Lewati ke konten
getnextpdf.com

Membersihkan PDF tak tepercaya: content disarm and reconstruction

Spec: ISO 32000-2, §12.6.4

Sebuah PDF yang tiba dari dunia luar adalah kode sebanyak ia adalah sebuah dokumen. Ia dapat membawa JavaScript, sebuah Launch action, sebuah eksekutabel tersemat, dan sebuah struktur yang dirancang untuk menjebak sebuah parser. Content Disarm & Reconstruction (CDR) memperlakukan berkas itu sebagai tak tepercaya, menyimpan hanya apa yang aman, dan membangun ulang sebuah PDF bersih dari yang selamat.

Halaman ini menjelaskan bagaimana CdrEngine NextPDF Enterprise melakukan itu — dan satu hal jujur yang harus dikatakan dengan lantang oleh setiap vendor CDR: berkas yang dibangun ulang adalah sebuah proyeksi keamanan dari aslinya, bukan sebuah salinan yang setia darinya.

Bagian berbahaya dari sebuah PDF tidaklah eksotis. Mereka adalah fitur standar. Spesifikasi mendefinisikan sebuah katalog utuh berisi action — apa yang terjadi saat sebuah dokumen dibuka, saat sebuah halaman ditampilkan, saat sebuah field berubah — dan katalog itu mencakup JavaScript dan Launch action (Spec: ISO 32000-2, §12.6.4). Sebuah viewer yang menghormati format akan dengan senang menjalankannya. Itulah pijakan kaki penyerang: sebuah berkas yang sepenuhnya valid dan sepenuhnya jahat pada saat yang sama.

Menyaring berdasarkan ekstensi berkas tidak melakukan apa pun di sini. Ancamannya ada di dalam sebuah PDF yang berbentuk-baik, jadi satu-satunya pertahanan nyata adalah membukanya, memahaminya, dan melepaskan mesin aktifnya sebelum ia pernah mencapai sebuah renderer. Ini adalah postur validasi-input yang dideskripsikan oleh panduan file-upload dan validasi-input OWASP: jangan pernah memercayai byte-nya, dan lebih utamakan membangun ulang sebuah artefak yang diketahui-baik daripada memindai yang berbahaya untuk mencari signature yang diketahui-buruk.

  • CDR mengasumsikan input bersifat berbahaya dan menghasilkan sebuah berkas baru alih-alih menambal yang lama.
  • CdrEngine::sanitize() menjalankan enam fase: parse, admission control, threat detection, filter, reference scrub, rebuild.
  • Ia mengembalikan sebuah CdrResult yang memberi tahu Anda apa yang dihapus, apakah dokumennya bahkan diterima, dan — jika tidak — mengapa ia ditolak.
  • Keluarannya adalah sebuah proyeksi keamanan. Ia secara eksplisit bukan sebuah salinan bukti, sebuah kecocokan hash, atau sebuah artefak arsip. Itu adalah sebuah kontrak, bukan sebuah peringatan.
  • Ini Enterprise saja. NextPDF core tidak melakukan CDR.

Dokumentasi mesin itu sendiri menyatakan garis merah rancangan dalam tiga kata: Security Projection Layer. sanitize() adalah sebuah transformasi yang destruktif dan tidak dapat dibalik. Ia diizinkan membuang byte. Yang tidak diizinkan ia lakukan adalah berpura-pura hasilnya adalah dokumen yang sama.

Pipeline-nya sengaja diurutkan. Setiap fase mempersempit kepercayaan sebelum fase berikutnya bertindak atasnya.

  1. ParsePdfReader builds the object graph from the raw bytes. A parse failure is a rejection, not a best-effort guess.
  2. Admission controlResource limits are checked first — object count, page count, decoded-stream size, per-stream inflation ratio. Over-budget input is rejected, never sanitised.
  3. DetectThreatDetector walks the graph and records each dangerous feature as a DetectedThreat with its object number and type.
  4. FilterObjects are partitioned into safe and removed. Catalog-level keys are stripped in place so the document catalog itself survives.
  5. Reference scrubPointers to removed objects are cleaned so the rebuilt file has no dangling references.
  6. RebuildCdrRebuilder serialises only the safe objects into a new PDF. The output is fresh structure, not an edited original.
Enam fase dari CdrEngine::sanitize(), secara berurutan. Dokumen di-parse, lalu diterima atau ditolak terhadap batas sumber daya, lalu dipindai untuk ancaman; objek berbahaya disaring keluar, referensi menggantung di-scrub, dan hanya objek aman yang selamat yang diserialisasi ke dalam sebuah PDF yang benar-benar baru. Byte asli tidak pernah terbawa.

Penerimaan sebelum disarm. Sebelum satu pun ancaman dihapus, mesin bertanya apakah dokumennya bahkan layak diproses. CdrPolicy membawa batas-batasnya — maxObjects, maxPageCount, maxDecodedStreamBytes, dan sebuah maxInflationRatio yang bertahan terhadap bom dekompresi. Sebuah dokumen yang melampaui batas itu ditolak, dan CdrResult mengatakannya dengan admitted: false dan sebuah rejectionReason. Perbedaan ini menanggung beban: “kami membersihkannya” dan “kami menolaknya” adalah hasil yang berbeda, dan tipe hasilnya menjaga keduanya tetap terpisah sehingga pelaporan kesalahan Anda pun bisa.

Ancaman dinamai, bukan ditebak. ThreatDetector::detect() memetakan setiap konstruksi berbahaya ke sebuah ThreatTypeJavaScript, LaunchAction, OpenAction, AdditionalActions, RemoteGoTo, SubmitForm, ImportData, EmbeddedFiles, RichMedia, NamedJavaScript, dan lainnya — masing-masing terikat ke sebuah fitur PDF spesifik. Sebuah objek yang tidak dapat di-parse sama sekali menjadi tipe ancamannya sendiri, UnparseableObject, karena sebuah objek yang tidak dapat dibaca sanitiser adalah sebuah objek yang tidak dapat ia jamin. Setiap temuan adalah sebuah DetectedThreat yang membawa nomor objek yang melanggar, sehingga penghapusan bersifat presisi.

Penghapusan melindungi dokumen, bukan hanya payload-nya. Beberapa key berbahaya hidup di document catalog (Root) — sebuah /OpenAction yang menyala saat dibuka, misalnya. Menghapus seluruh objek Root untuk membunuh satu key akan menghancurkan catalog dan diam-diam merusak berkas. Mesin menangani ini sebagai in-place key strip pada catalog sebagai gantinya, dan sebagai sebuah penjaga gagal-tertutup ia menolak memancarkan sebuah dokumen yang dibangun ulang yang telah kehilangan /Root-nya sama sekali. Sebuah sanitiser yang menghasilkan sebuah berkas yang rusak secara struktural sambil melaporkan keberhasilan adalah persis mode kegagalan yang keberadaan penjaga ini untuk mencegahnya.

Bentuk di bawah ini adalah titik masuk yang sebenarnya. Anda menyerahkan byte mentah dan sebuah policy kepada mesin; Anda mendapat kembali sebuah CdrResult yang jujur tentang apa yang terjadi.

<?php
declare(strict_types=1);
use NextPDF\Enterprise\Security\Cdr\CdrEngine;
use NextPDF\Enterprise\Security\Cdr\CdrPolicy;
$engine = new CdrEngine();
// Standard policy removes the known active threats — JavaScript, Launch
// actions, remote go-to, form submit/import, and the rest — while leaving
// the lossy opt-in "Strip*" cases off by default.
$result = $engine->sanitize($untrustedPdfBytes, CdrPolicy::standard());
if (!$result->admitted) {
// Rejected by admission control (e.g. object/page limit, zip bomb).
// This is NOT a sanitised document. Do not serve it; report the reason.
throw new \RuntimeException($result->rejectionReason);
}
if ($result->hadThreats()) {
// The disarmed bytes are safe to render. Each removed threat carries its
// type and object number for your audit log — never silently.
foreach ($result->removedThreats as $threat) {
error_log(\sprintf(
'CDR removed %s in object %d',
$threat->type->value,
$threat->objectNumber,
));
}
}
$cleanBytes = $result->sanitizedPdf; // The security projection. Not the original.

Tidak ada jalur di mana kode ini diam-diam menyerahkan kembali sebuah berkas yang masih berbahaya. Entah dokumennya diterima dan dilucuti, atau ia ditolak dengan sebuah alasan yang dinyatakan. Daftar removedThreats berarti pelucutan itu dapat diaudit, bukan ajaib.

“CDR hanyalah redaksi dengan langkah ekstra.”

Bukan, dan mencampuradukkan keduanya berbahaya. Redaksi menghapus informasi — nama, nomor rekening, konten yang tidak boleh dilihat seorang manusia. CDR menghapus kapabilitas — JavaScript, Launch action, payload tersemat yang tidak boleh dijalankan sebuah mesin. Keduanya punya kriteria keberhasilan yang berlawanan. Sebuah redaksi benar ketika konten sensitif telah hilang dan sisanya dipertahankan kata-demi-kata. Sebuah disarm benar ketika ancaman telah hilang, dan ia sepenuhnya rela mengubah struktur yang jinak untuk mencapainya. Gunakan alat yang cocok dengan maksud Anda; jangan menjangkau satu sambil mengharapkan jaminan dari yang lain.

Sebuah kesalahpahaman kedua adalah bahwa sebuah rebuild yang bersih membuktikan aslinya bersih. Ia tidak membuktikan apa pun tentang aslinya. Ia hanya membuktikan bahwa keluarannya tidak mengandung ancaman yang terdeteksi. Input-nya bisa saja sebuah senjata; tugas CDR adalah memastikan apa yang Anda teruskan ke hilir bukan.

Ini adalah bagian yang dilewati brosur, jadi kami akan mengatakannya dengan jelas.

  • Keluarannya adalah sebuah proyeksi keamanan, bukan sebuah salinan bukti. Sumber CdrEngine membawa ini sebagai sebuah garis merah arsitektur. PDF yang dibersihkan tidak boleh digunakan untuk pelestarian bukti hukum, untuk perbandingan hash terhadap aslinya, atau sebagai sebuah salinan arsip. Transformasinya bersifat destruktif dan tidak dapat dibalik menurut desainnya.
  • Deteksi punya cakupan. CDR menghapus ancaman yang ia tahu cara menamainya. Ia adalah lapisan yang kuat dan dapat diaudit dalam sebuah tumpukan defense-in-depth — bukan sebuah jaminan bahwa sebuah berkas bebas dari setiap kemungkinan teknik masa depan. Jaga ia di belakang validasi unggahan, pemeriksaan content-type, dan penanganan least-privilege yang sama yang dideskripsikan oleh panduan file-upload OWASP.
  • Beberapa policy sengaja bersifat lossy. Kasus Strip* opt-in menghapus berkas tersemat, tanda tangan, field formulir, layer, dan media 3D. Itu semua bertenaga dan mereka akan menghapus konten yang sah — sebuah payload faktur ZUGFeRD/Factur-X, misalnya. Mereka mati secara bawaan justru untuk alasan itu. Nyalakan mereka dengan sadar.
  • Tanda tangan tidak bertahan dari sebuah rebuild. Merekonstruksi berkas mengubah byte-nya, sehingga tanda tangan digital asli mana pun tidak lagi cocok dengan rentang byte-nya. Sebuah dokumen yang dilucuti tidak ditandatangani terhadap sumbernya. Jika Anda membutuhkan sebuah artefak yang ditandatangani, tandatangani keluaran yang bersih sebagai sebuah tindakan baru.
Content Disarm & Reconstruction (CDR) — edition availability
EditionAvailability
Core

Tidak tersedia. NextPDF core tidak melakukan CDR. Ia mem-parse, merender, dan menulis PDF; ia tidak mendeteksi-ancaman atau membangun ulang input tak tepercaya.

Pro

Tidak tersedia di edisi Pro.

Enterprise

Tersedia via CdrEngine. Keluaran yang dilucuti adalah sebuah proyeksi keamanan dari sumbernya — ia tidak boleh diperlakukan sebagai sebuah salinan bukti, salinan yang dapat-dibandingkan-hash, atau salinan arsip dari aslinya.

  • How PDF encryption really works — paruh lain dari penanganan PDF sensitif: melindungi konten versus menghapus kapabilitas.
  • Errors as a feature — filosofi gagal-tertutup yang diwujudkan oleh penolakan admission-control CDR dan penjaga /Root.
  • An API that refuses to guess — mengapa sebuah tipe hasil yang membedakan dibersihkan dari ditolak mengalahkan sebuah upaya-terbaik yang senyap.
  • CDR (Content Disarm & Reconstruction) — sebuah strategi sanitasi yang mem-parse sebuah berkas tak tepercaya, menghapus komponen aktif atau berbahaya, dan membangun ulang sebuah berkas bersih dari sisa yang aman, alih-alih memindai untuk mencari signature yang diketahui-buruk.
  • Security projection — sebuah keluaran yang dibersihkan yang mempertahankan cukup dari sumbernya agar berguna sambil menjamin penghapusan ancaman. Ia sengaja tidak setia-byte dan tidak cocok untuk bukti, hashing, atau pengarsipan.
  • Admission control — gerbang pra-sanitasi yang menolak dokumen yang melampaui batas sumber daya (jumlah objek, jumlah halaman, ukuran decoded-stream, rasio inflasi) sebelum pekerjaan disarm apa pun dimulai.
  • Action — sebuah konstruksi PDF yang membuat sesuatu terjadi pada sebuah pemicu seperti dokumen-dibuka atau sebuah perubahan field; katalog tipe-action (Spec: ISO 32000-2, §12.6.4) mencakup JavaScript dan Launch action, permukaan ancaman CDR yang kanonis.
  • Dangling reference — sebuah pointer ke sebuah objek yang tidak lagi ada setelah penyaringan. Fase reference-scrub menghapus ini sehingga berkas yang dibangun ulang tetap konsisten secara struktural.