ข้ามไปยังเนื้อหา
getnextpdf.com

Enterprise รุ่น

Content Disarm and Reconstruction — เอกสารอ้างอิงเชิงลึก

หน้านี้เป็นการอ้างอิงเชิงลึกสำหรับโมดูล NextPDF\Enterprise\Security\Cdr โมดูลนี้ปลดอาวุธ PDF ที่ไม่น่าเชื่อถือและสร้างไฟล์สะอาดขึ้นใหม่จากอ็อบเจกต์ที่ปลอดภัยของมัน ไปป์ไลน์คือ: แจงส่วน ควบคุมการรับเข้า ตรวจจับภัยคุกคาม กรอง ขัดล้างการอ้างอิง สร้างใหม่ ผลลัพธ์เป็นการฉายด้านความปลอดภัยของอินพุต ไม่ใช่สำเนาเชิงหลักฐานเลย สำหรับคำแนะนำด้านเวิร์กโฟลว์ ให้อ่านหน้าความสามารถ CDRก่อน

ความสามารถนี้จัดส่งใน NextPDF Enterprise (nextpdf/enterprise) และเปิดใช้งานด้วยซองใบอนุญาตระดับ Enterprise การนำไปใช้งานที่ไม่มีสิทธิ์ดังกล่าวจะไม่โหลดคลาสของความสามารถนี้ เปรียบเทียบรุ่นและรับใบอนุญาต

สัญลักษณ์พารามิเตอร์พฤติกรรมเริ่มต้นค่าที่คืนโยนหรือล้มเหลวด้วยหมายเหตุ
CdrEngine::__constructไม่มีสร้างตัวตรวจจับและตัวสร้างใหม่ภายในCdrEngineไม่ประกาศอะไรไว้ไม่มีผู้ร่วมงานที่ฉีดเข้าได้
CdrEngine::sanitizestring $pdfData, ?CdrPolicy $policy = nullรันไปป์ไลน์เต็มภายใต้ CdrPolicy::standard()CdrResultไม่โยนบนอินพุตที่เป็นภัย การล้มเหลวในการแจงส่วนและการรับเข้าจะคืนผลลัพธ์ที่ถูกปฏิเสธผลลัพธ์รายงานการปฏิเสธแยกจากการชำระล้างอย่างชัดเจน
CdrPolicy::__constructพารามิเตอร์แบบมีชื่อที่เลือกได้เจ็ดตัว ดูที่เฟนซ์ชุดกำจัดว่างเปล่า; allowUriActions เป็น false; flattenIncrementalUpdates เป็น true; ขีดจำกัด 100000 อ็อบเจกต์, 256 MiB ที่ถอดรหัสแล้ว, 10000 หน้า, อัตรา 1000.0CdrPolicyไม่ประกาศอะไรไว้final readonly; รายการ removeThreatTypes ที่ว่างเปล่าจะไม่ตรวจจับอะไรเลย
CdrPolicy::standardไม่มีชุดภัยคุกคามแบบเดิม; กำจัด URI actions; ขีดจำกัดเริ่มต้นselfไม่ประกาศอะไรไว้ยกเว้นเคส Strip* ที่สูญเสียข้อมูลทั้งเจ็ด
CdrPolicy::paranoidไม่มีชุดภัยคุกคามแบบเดิมพร้อมขีดจำกัดที่เข้มขึ้น: 50000 อ็อบเจกต์, 128 MiB, 5000 หน้า, อัตรา 100.0selfไม่ประกาศอะไรไว้ยกเว้นเคส Strip* ที่สูญเสียข้อมูลทั้งเจ็ด
CdrPolicy::permissiveไม่มีกำจัดเฉพาะ JavaScript, LaunchAction, NamedJavaScript, SubmitForm, ImportData; คงไว้ซึ่ง URI actionsselfไม่ประกาศอะไรไว้มีไว้สำหรับแหล่งที่น่าเชื่อถือ
CdrPolicy::allThreatTypesไม่มีคืนทุกเคสของ ThreatType รวมถึงเคส Strip* ที่สูญเสียข้อมูลlist<ThreatType>ไม่ประกาศอะไรไว้การเลือกเข้าใช้แบบ strip สูงสุดอย่างชัดแจ้ง
CdrPolicy::legacyThreatTypesไม่มีคืนทุกเคสยกเว้นเคส Strip* ทั้งเจ็ดlist<ThreatType>ไม่ประกาศอะไรไว้ชุดกำจัดเริ่มต้นสำหรับ standard() และ paranoid()
CdrPolicy::shouldRemoveThreatType $typeทดสอบความเป็นสมาชิกกับ removeThreatTypesboolไม่ประกาศอะไรไว้คืน false สำหรับ UriAction เมื่อ allowUriActions เป็น true
ThreatDetector::detectPdfReader $reader, CdrPolicy $policyสแกนทุกอ็อบเจกต์และแคตาล็อกในเทรลเลอร์เพื่อหาชนิดภัยคุกคามของนโยบายlist<DetectedThreat>ไม่โยน; อ็อบเจกต์ที่แจงส่วนไม่ได้จะกลายเป็นภัยคุกคาม UnparseableObjectการสแกนแคตาล็อกครอบคลุมทรี /Names/JavaScript
CdrRebuilder::rebuildPdfReader $reader, list<int> $safeObjNums, list<int> $removedObjNums, CdrPolicy $policyทำให้อ็อบเจกต์ที่ปลอดภัยเป็นอนุกรมลงในไฟล์ %PDF-2.0 รีวิชันเดียวstringไม่ประกาศอะไรไว้; อ็อบเจกต์ที่อ่านซ้ำไม่ผ่านหรือตรวจสอบ /Length ไม่ผ่านจะถูกข้าม$policy สงวนไว้สำหรับการปรับแต่งการทำอนุกรมในอนาคต
DetectedThreat::__constructThreatType $type, int $objectNumber, string $description, string $location = ''อ็อบเจกต์ค่าของสิ่งที่ตรวจพบซึ่งไม่เปลี่ยนแปลงDetectedThreatไม่ประกาศอะไรไว้คุณสมบัติทั้งสี่เป็น public readonly
ThreatTypeenum ที่หนุนด้วย stringยี่สิบเคส: สิบสามเคสแบบเดิมบวกเจ็ดเคส Strip* แบบเลือกเข้าใช้ไม่มีไม่มีดูรายการเคสด้านล่าง
final class CdrEngine
{
public function __construct()
public function sanitize(string $pdfData, ?CdrPolicy $policy = null): CdrResult
}
final readonly class CdrPolicy
{
public function __construct(
public array $removeThreatTypes = [],
public bool $allowUriActions = false,
public bool $flattenIncrementalUpdates = true,
public int $maxObjects = 100_000,
public int $maxDecodedStreamBytes = 268_435_456,
public int $maxPageCount = 10_000,
public float $maxInflationRatio = 1000.0,
)
public static function standard(): self
public static function paranoid(): self
public static function permissive(): self
public static function allThreatTypes(): array
public static function legacyThreatTypes(): array
public function shouldRemove(ThreatType $type): bool
}
final class ThreatDetector
{
public function detect(PdfReader $reader, CdrPolicy $policy): array
}
final class CdrRebuilder
{
public function rebuild(PdfReader $reader, array $safeObjNums, array $removedObjNums, CdrPolicy $policy): string
}
final readonly class DetectedThreat
{
public function __construct(
public ThreatType $type,
public int $objectNumber,
public string $description,
public string $location = '',
)
}
enum ThreatType: string

เคสแบบเดิมสิบสามเคสประกอบเป็นชุดกำจัดเริ่มต้น เคส Strip* สูญเสียข้อมูลโดยการออกแบบและจะไม่เข้าสู่นโยบายเริ่มต้นเลย

เคสค่าที่หนุนพื้นผิวการตรวจจับ
ThreatType::JavaScriptjavascriptคีย์ /JS บนอ็อบเจกต์ใดๆ หรือ action /S /JavaScript
ThreatType::AdditionalActionsadditional-actionsดิกชันนารี /AA บนอ็อบเจกต์ใดๆ
ThreatType::OpenActionopen-actionคีย์ /OpenAction บนอ็อบเจกต์ใดๆ
ThreatType::LaunchActionlaunch-actionaction /S /Launch
ThreatType::RemoteGoToremote-gotoaction /S /GoToR หรือ /S /GoToE
ThreatType::SubmitFormsubmit-formaction /S /SubmitForm
ThreatType::ImportDataimport-dataaction /S /ImportData
ThreatType::EmbeddedFilesembedded-filesทรีชื่อ /EmbeddedFiles หรือดิกชันนารี /EF
ThreatType::RichMediarich-media/Subtype /RichMedia
ThreatType::NamedJavaScriptnamed-javascriptทรีชื่อ /Names/JavaScript ในแคตาล็อก
ThreatType::UriActionuri-actionaction /S /URI; ระงับเมื่อ allowUriActions เป็น true
ThreatType::Xfaxfaคีย์ /XFA
ThreatType::UnparseableObjectunparseable-objectอ็อบเจกต์หรือแคตาล็อกใดๆ ที่แจงส่วนไม่สำเร็จ
ThreatType::StripJavaScriptstrip-javascriptซูเปอร์เซตแบบเลือกเข้าใช้: คีย์ /JS, /S /JavaScript, หรือ /Subtype /JavaScript
ThreatType::StripEmbeddedFilesstrip-embedded-filesเลือกเข้าใช้: /Type /EmbeddedFile, /Type /Filespec, /EmbeddedFiles, หรือ /EF
ThreatType::StripFormFieldsstrip-form-fieldsเลือกเข้าใช้: /Subtype /Widget, คีย์ /FT, หรือคีย์ /AcroForm
ThreatType::StripAnnotationsRichstrip-annotations-richsubtype แบบเลือกเข้าใช้: Movie, Sound, FileAttachment, 3D, RichMedia, Screen
ThreatType::StripOcgNonDefaultstrip-ocg-non-defaultเลือกเข้าใช้: /Type /OCG ที่มีคีย์ /Usage หรือ /Visibility
ThreatType::StripDigitalSignaturesAtRebuildstrip-digital-signatures-at-rebuildเลือกเข้าใช้: /Type /Sig, /FT /Sig, /DSS, /VRI, หรือ /ByteRange
ThreatType::Strip3dAndRichMediastrip-3d-and-rich-mediasubtype แบบเลือกเข้าใช้: 3D, U3D, PRC, RMF, RichMedia, Sound, Movie

CdrEngine::sanitize ดำเนินการหกเฟสตามลำดับและไม่เคยโยนสำหรับอินพุตที่เป็นภัย

  1. แจงส่วน การแจงส่วนล้มเหลวจะคืนผลลัพธ์ที่มี admitted เป็น false และเหตุผลการปฏิเสธแบบข้อผิดพลาดในการแจงส่วน ผลลัพธ์ที่ชำระล้างแล้วจะว่างเปล่าในกรณีนั้น
  2. ควบคุมการรับเข้า จำนวนอ็อบเจกต์ ผลรวมไบต์ของสตรีมที่ถอดรหัสแล้ว อัตราการขยายต่อสตรีม และจำนวนหน้าจะถูกตรวจสอบกับขีดจำกัดของนโยบาย เอกสารที่เกินขีดจำกัดจะถูกปฏิเสธ ไม่ใช่ถูกชำระล้าง การปฏิเสธและการชำระล้างถูกรายงานแยกจากกันอย่างชัดเจน
  3. ตรวจจับ ThreatDetector::detect สแกนทุกอ็อบเจกต์และแคตาล็อกในเทรลเลอร์เพื่อหาชนิดภัยคุกคามของนโยบาย อ็อบเจกต์ที่แจงส่วนไม่ได้จะถูกบันทึกเป็นสิ่งที่ตรวจพบชนิด ThreatType::UnparseableObject แทนที่จะถูกข้าม
  4. กรอง อ็อบเจกต์ที่มีสิ่งที่ตรวจพบจะถูกจัดคิวเพื่อกำจัด แคตาล็อกเอกสารจะไม่ถูกกำจัดในฐานะอ็อบเจกต์ทั้งก้อนเลย สิ่งที่ตรวจพบระดับแคตาล็อก (OpenAction, AdditionalActions, NamedJavaScript) จะได้รับการแก้ไขด้วยการลอกคีย์ออกแทน
  5. ขัดล้างการอ้างอิง ทุกการอ้างอิงทางอ้อมไปยังอ็อบเจกต์ที่ถูกกำจัดจะถูกแทนที่ด้วย null ระหว่างการทำอนุกรม
  6. สร้างใหม่ CdrRebuilder::rebuild ปล่อยไฟล์ %PDF-2.0 รีวิชันเดียวพร้อมอ็อบเจกต์ที่ถูกกำหนดหมายเลขใหม่ ตารางการอ้างอิงข้ามแบบคลาสสิก และเทรลเลอร์ใหม่ ไบต์ของสตรีมที่ปลอดภัยถูกคัดลอกแบบไบต์ต่อไบต์เหมือนกันทุกประการ แคตาล็อกที่สร้างใหม่ทิ้ง /OpenAction, /AA, และ /Names; /AA ถูกทิ้งจากทุกอ็อบเจกต์

CdrResult ที่คืนมาเปิดเผยไบต์ที่สร้างใหม่ รายการภัยคุกคามที่ถูกกำจัด ขนาดไบต์ทั้งสองด้าน ธงการรับเข้า และเหตุผลการปฏิเสธ หากต้นฉบับมี /Root ที่แก้ค่าได้และผลลัพธ์ที่สร้างใหม่สูญเสียมันไป เอนจินจะปฏิเสธผลลัพธ์แทนที่จะคืนไฟล์ที่เสียหายเชิงโครงสร้าง นี่คือการรับประกันแบบ fail-closed: admitted เป็น true บ่งชี้ว่าผลลัพธ์ยังคงมีการอ้างอิงแคตาล็อกเอกสารอยู่

การอัปเดตเชิงเพิ่มไม่เคยรอด: การสร้างใหม่ทำอนุกรมเพียงรีวิชันเดียวภายใต้ทุกนโยบาย ดังนั้นรีวิชันช่วงหลังแบบเงาจึงถูกทำให้แบนราบโดยโครงสร้าง ลายเซ็นดิจิทัลต้นฉบับไม่สามารถคงความถูกต้องข้ามการสร้างใหม่ได้ เพราะช่วงไบต์ไม่ตรงกับผลลัพธ์อีกต่อไป

เส้นแดงเชิงสถาปัตยกรรม CDR เป็นชั้นการฉายด้านความปลอดภัย ไม่ใช่ชั้นการเก็บรักษา ต้องไม่ใช้ผลลัพธ์เพื่อการเก็บรักษาหลักฐานทางกฎหมาย การเปรียบเทียบแฮชกับต้นฉบับ หรือสำเนาเพื่อการเก็บถาวร

  • นโยบาย null จะแก้ค่าเป็น CdrPolicy::standard() นโยบายที่สร้างด้วย removeThreatTypes ว่างเปล่าเริ่มต้นจะตรวจจับและกำจัดไม่ได้อะไรเลย
  • การตั้ง allowUriActions เป็น true จะระงับการกำจัด UriAction แม้เคสจะปรากฏอยู่ใน removeThreatTypes
  • flattenIncrementalUpdates เป็นเชิงประกาศในรีลีสนี้: การสร้างใหม่ปล่อยรีวิชันเดียวภายใต้ทุกนโยบาย รวมถึง permissive() ซึ่งตั้งธงเป็น false
  • การตรวจสอบอัตราการขยายถือว่าความยาวสตรีมดิบเป็นศูนย์นับเป็นหนึ่ง ดังนั้นสตรีมที่ขยายจากศูนย์ยังคงถูกกำหนดขอบเขต เมื่อไม่มีการเก็บรูปแบบที่ถอดรหัสไว้ ความยาวสตรีมดิบจะนับรวมเข้าในงบประมาณรวม
  • การตรวจสอบการรับเข้าด้วยจำนวนหน้าทำได้เท่าที่พยายาม: การอ่านแคตาล็อกหรือทรีหน้าล้มเหลวจะไม่ปฏิเสธเอกสารด้วยตัวมันเอง งบประมาณจำนวนอ็อบเจกต์และการคลายบีบอัดถูกบังคับใช้เสมอ
  • อ็อบเจกต์ที่ความยาวสตรีมดิบขัดแย้งกับรายการ /Length แบบจำนวนเต็มของมันจะถูกข้ามตอนสร้างใหม่ (การป้องกัน polyglot) การอ้างอิงไปยังอ็อบเจกต์ที่ถูกข้ามเช่นนั้นจะยังคงเลขอ็อบเจกต์ต้นทางไว้และอาจแก้ค่าไม่ได้ในผลลัพธ์ sanitize() ปฏิเสธผลลัพธ์ที่เสียหายอย่างตรวจพบได้ (/Root ที่หายไป) แต่ผู้เรียกที่ขับ CdrRebuilder::rebuild() ระดับต่ำโดยตรงต้องตรวจสอบโครงสร้างผลลัพธ์และความสมบูรณ์ของการอ้างอิงด้วยตนเอง
  • เมื่อเทรลเลอร์ต้นฉบับมี /ID เทรลเลอร์ที่สร้างใหม่จะมี /ID แบบสุ่มที่สร้างขึ้นใหม่ ไม่ใช่ตัวเดิม รายการเทรลเลอร์อื่นๆ รวมถึง /Info จะไม่ถูกนำมาด้วย; เทรลเลอร์ที่สร้างใหม่ถือ /Size, /Root เมื่อแก้ค่าได้ และ /ID ที่สร้างใหม่
  • ไบต์ของชื่อและคีย์ที่ถอดรหัสแล้วจะถูกปล่อยออกมาใหม่พร้อม escape แบบเลขฐานสิบหกสำหรับตัวคั่น ช่องว่าง และไบต์ที่พิมพ์ไม่ได้ ดังนั้นชื่อที่เป็นภัยจึงไม่สามารถฉีดไวยากรณ์ดิกชันนารีลงในผลลัพธ์ได้
  • ค่าสตริงภายใต้คีย์ดิกชันนารีนอกชุดที่มีค่าเป็นชื่อที่รู้จักจะถูกปล่อยออกมาเป็นสตริงตามตัวอักษรอย่างระมัดระวัง
  • CdrPolicy::legacyThreatTypes() ถือว่าเคส enum ในอนาคตใดๆ เป็นค่ากำจัดเริ่มต้นเว้นแต่จะลงทะเบียนเป็นเคส Strip* ดังนั้นเคสที่สูญเสียข้อมูลใหม่จึงไม่สามารถเข้าสู่นโยบายเริ่มต้นอย่างเงียบๆ ได้
  • CDR ไม่ใช่โมดูลการเข้ารหัส การใช้ความสุ่มเพียงอย่างเดียวของมันคือ /ID ในเทรลเลอร์ที่สร้างใหม่ การตรวจสอบลายเซ็นอยู่นอกขอบเขตที่นี่ ดูการอ้างอิงเชิงลึกของลายเซ็น
ข้ออ้างมาตรฐานข้อกำหนด
การเรียก action แบบ ECMAScript ทำให้ตัวประมวลผล PDF รันสคริปต์ที่ฝังอยู่ISO 32000-2§12.6.4.17
สคริปต์ระดับเอกสารในทรีชื่อ JavaScript ทั้งหมดจะรันเมื่อเอกสารเปิดขึ้นISO 32000-2§12.6.4.17
ดิกชันนารีชื่อในแคตาล็อกอาจถือทรีชื่อ JavaScript ของ action สคริปต์ระดับเอกสารISO 32000-2§7.7.4 (Table 32)
launch action เปิดใช้แอปพลิเคชัน หรือเปิดหรือพิมพ์เอกสารISO 32000-2§12.6.4.6
ดิกชันนารี additional-actions /AA ขยายเหตุการณ์ทริกเกอร์บน annotation หน้า ฟิลด์ และแคตาล็อกISO 32000-2§12.6.3
การรับไฟล์ที่ไม่น่าเชื่อถือต้องกำหนดขอบเขตการมีอยู่ ปริมาณ และเนื้อหาของไฟล์ที่เข้ามาOWASP ASVS 5.0§5.2
ระบบควรป้องกันการรันไฟล์ที่อัปโหลดอย่างไม่เหมาะสมและตรวจจับเนื้อหาอันตรายOWASP ASVS 5.0§5.3

ทุกข้อกำหนดถูกถอดความ; NextPDF ไม่ทำซ้ำข้อความเชิงบรรทัดฐาน NextPDF ไม่กล่าวอ้างการรับรองใดๆ CDR กำจัดพื้นผิวเนื้อหาที่ทำงานได้ซึ่งระบุโดย ThreatType ภายใต้นโยบายที่กำหนดค่าไว้; มันเป็นความสามารถ ไม่ใช่เครื่องมือชำระล้างที่ได้รับการรับรอง CDR ไม่ใช่โปรแกรมสแกนไวรัสและไม่ตรวจจับลายเซ็นมัลแวร์; มันเสริม และไม่ทำให้สมบูรณ์แทน การควบคุมอย่างเช่นการสแกนไวรัสตาม OWASP ASVS 5.4.3 ว่าไฟล์ที่ถูกปลดอาวุธจะยอมรับได้สำหรับไปป์ไลน์การรับใดหนึ่งหรือไม่ยังคงเป็นการตัดสินใจด้านความเสี่ยงของผู้ปฏิบัติการ

  • ซอร์สของโมดูลถือ @since 1.9.0; การอ้างอิงนี้บันทึกพื้นผิวตามที่จัดส่งใน nextpdf/enterprise 3.1.0
  • ทุกอย่างรันในกระบวนการบนโฮสต์ของคุณ ไม่มีการเข้าถึงเครือข่ายเกิดขึ้นระหว่างการชำระล้าง
  • CdrPolicy และ DetectedThreat เป็น final readonly; สร้างอินสแตนซ์นโยบายใหม่เพื่อเปลี่ยนขีดจำกัด
  • CdrEngine สร้างตัวตรวจจับและตัวสร้างใหม่ภายในของมัน ThreatDetector และ CdrRebuilder ยังคงใช้ได้โดยตรงสำหรับไปป์ไลน์แบบเป็นขั้นที่จัดหา PdfReader ของตัวเอง
  • พารามิเตอร์ $policy ของ CdrRebuilder::rebuild ปัจจุบันถูกสงวนไว้; ซอร์สบันทึกว่ามันถูกเก็บไว้เพื่อความเข้ากันได้ของจุดเรียกและการปรับแต่งการทำอนุกรมต่อนโยบายในอนาคต
  • ผลลัพธ์สามารถทำซ้ำได้เชิงโครงสร้าง ไม่ใช่เชิงบิต: /ID ที่สร้างใหม่แตกต่างกันทุกครั้งที่รันเมื่อต้นฉบับมีมัน
  • ชนิดผลลัพธ์ CdrResult (ค่าที่คืนของ sanitize()) ถูกครอบคลุมเชิงพฤติกรรมด้านบน; ฟิลด์ของมันเป็น public readonly โดยมี hadThreats() และ threatCount() เป็นตัวอำนวยความสะดวก

หน้านี้บันทึกพฤติกรรมที่สังเกตได้จากภายนอกและพื้นผิว Public API ที่รองรับเท่านั้น เส้นทาง namespace ภายใน คลาสตัวช่วย ตารางกลไก ชื่อไฟล์ runbook และคำนำหน้าตั๋วอยู่นอกขอบเขต