Zum Inhalt springen
getnextpdf.com

Nicht vertrauenswürdige PDFs bereinigen: Content Disarm and Reconstruction

Spec: ISO 32000-2, §12.6.4

Ein PDF, das aus der Außenwelt eintrifft, ist ebenso sehr Code wie es ein Dokument ist. Es kann JavaScript, eine Launch-Aktion, eine eingebettete ausführbare Datei und eine Struktur tragen, die darauf ausgelegt ist, einen Parser zu Fall zu bringen. Content Disarm & Reconstruction (CDR) behandelt diese Datei als nicht vertrauenswürdig, behält nur, was sicher ist, und baut aus den Überlebenden ein sauberes PDF neu auf.

Diese Seite erklärt, wie die CdrEngine von NextPDF Enterprise das tut – und das eine ehrliche Ding, das jeder CDR-Anbieter laut aussprechen sollte: Die neu aufgebaute Datei ist eine Sicherheitsprojektion des Originals, keine getreue Kopie davon.

Die gefährlichen Teile eines PDF sind nicht exotisch. Sie sind Standardfunktionen. Die Spezifikation definiert einen ganzen Katalog von Aktionen – was passiert, wenn ein Dokument geöffnet wird, wenn eine Seite angezeigt wird, wenn sich ein Feld ändert –, und dieser Katalog umfasst JavaScript- und Launch-Aktionen (Spec: ISO 32000-2, §12.6.4). Ein Reader, der das Format respektiert, wird sie bereitwillig ausführen. Das ist der Standfuß des Angreifers: eine Datei, die zugleich vollkommen gültig und vollkommen bösartig ist.

Das Filtern nach Dateierweiterung bewirkt hier nichts. Die Bedrohung steckt in einem wohlgeformten PDF, also ist die einzige echte Verteidigung, es zu öffnen, es zu verstehen und die aktive Maschinerie zu entfernen, bevor sie je einen Renderer erreicht. Dies ist die Haltung der Eingabevalidierung, die der Leitfaden von OWASP zu Datei-Upload und Eingabevalidierung beschreibt: traue den Bytes nie und ziehe es vor, ein bekanntermaßen gutes Artefakt neu aufzubauen, statt ein feindseliges nach bekanntermaßen schlechten Signaturen zu durchsuchen.

  • CDR nimmt an, dass die Eingabe feindselig ist, und erzeugt eine neue Datei, statt die alte zu flicken.
  • CdrEngine::sanitize() durchläuft sechs Phasen: parsen, Zulassungskontrolle, Bedrohungserkennung, filtern, Referenz-Schrubben, neu aufbauen.
  • Es gibt ein CdrResult zurück, das Ihnen sagt, was entfernt wurde, ob das Dokument überhaupt zugelassen wurde und – falls nicht – warum es abgelehnt wurde.
  • Die Ausgabe ist eine Sicherheitsprojektion. Sie ist ausdrücklich keine beweistaugliche Kopie, keine Hash-Übereinstimmung und kein Archivartefakt. Das ist ein Vertrag, kein Vorbehalt.
  • Dies ist nur Enterprise. Der NextPDF-Core führt kein CDR durch.

Die eigene Dokumentation der Engine formuliert die rote Designlinie in drei Worten: Security Projection Layer. sanitize() ist eine zerstörende, nicht umkehrbare Transformation. Sie darf Bytes wegwerfen. Was sie nicht darf, ist vorzutäuschen, dass das Ergebnis dasselbe Dokument ist.

Die Pipeline ist bewusst geordnet. Jede Phase verengt das Vertrauen, bevor die nächste Phase darauf einwirkt.

  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.
The six phases of CdrEngine::sanitize(), in order. The document is parsed, then admitted or rejected against resource limits, then scanned for threats; dangerous objects are filtered out, dangling references are scrubbed, and only the surviving safe objects are serialised into a brand-new PDF. The original bytes never carry through.

Zulassung vor Entschärfung. Bevor auch nur eine einzige Bedrohung entfernt wird, fragt die Engine, ob das Dokument überhaupt der Verarbeitung wert ist. CdrPolicy trägt die Grenzen – maxObjects, maxPageCount, maxDecodedStreamBytes und ein maxInflationRatio, das gegen Dekompressionsbomben verteidigt. Ein Dokument, das über sie hinausschießt, wird abgelehnt, und das CdrResult sagt das mit admitted: false und einem rejectionReason. Diese Unterscheidung ist tragend: „Wir haben es bereinigt” und „Wir haben es abgelehnt” sind unterschiedliche Ergebnisse, und der Ergebnistyp hält sie auseinander, sodass es auch Ihre Fehlerberichterstattung kann.

Bedrohungen werden benannt, nicht geraten. ThreatDetector::detect() ordnet jede gefährliche Konstruktion einem ThreatType zu – JavaScript, LaunchAction, OpenAction, AdditionalActions, RemoteGoTo, SubmitForm, ImportData, EmbeddedFiles, RichMedia, NamedJavaScript und mehr –, jede an eine bestimmte PDF-Funktion gebunden. Ein Objekt, das sich überhaupt nicht parsen lässt, wird zu seinem eigenen Bedrohungstyp, UnparseableObject, denn ein Objekt, das der Sanitizer nicht lesen kann, ist ein Objekt, für das er nicht bürgen kann. Jeder Fund ist ein DetectedThreat, der die anstößige Objektnummer trägt, sodass die Entfernung präzise ist.

Entfernung schützt das Dokument, nicht nur die Nutzlast. Manche gefährlichen Schlüssel liegen am Dokumentkatalog (dem Root) – ein /OpenAction etwa, das beim Öffnen feuert. Das ganze Root-Objekt zu entfernen, um einen Schlüssel zu töten, würde den Katalog zerstören und die Datei klammheimlich beschädigen. Die Engine behandelt diese stattdessen als An-Ort-und-Stelle-Schlüsselentfernungen am Katalog, und als ein Fail-closed-Schutz weigert sie sich, ein neu aufgebautes Dokument auszugeben, das sein /Root überhaupt verloren hat. Ein Sanitizer, der eine strukturell beschädigte Datei erzeugt und dabei Erfolg meldet, ist genau der Fehlermodus, den dieser Schutz verhindern soll.

Die Form unten ist der echte Einstiegspunkt. Sie übergeben der Engine rohe Bytes und eine Richtlinie; Sie erhalten ein CdrResult zurück, das ehrlich darüber ist, was geschehen ist.

<?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.

Es gibt keinen Pfad, auf dem dieser Code klammheimlich eine immer noch gefährliche Datei zurückgibt. Entweder wird das Dokument zugelassen und entschärft, oder es wird mit einem angegebenen Grund abgelehnt. Die removedThreats-Liste bedeutet, dass die Entschärfung prüfbar ist, nicht magisch.

„CDR ist nur Schwärzung mit zusätzlichen Schritten.”

Das ist es nicht, und die beiden zu vermengen ist gefährlich. Schwärzung entfernt Informationen – Namen, Kontonummern, den Inhalt, den ein Mensch nicht sehen darf. CDR entfernt Fähigkeit – das JavaScript, die Launch-Aktion, die eingebettete Nutzlast, die eine Maschine nicht ausführen darf. Sie haben entgegengesetzte Erfolgskriterien. Eine Schwärzung ist korrekt, wenn sensibler Inhalt weg ist und der Rest wortwörtlich erhalten bleibt. Eine Entschärfung ist korrekt, wenn die Bedrohung weg ist, und sie ist durchaus bereit, gutartige Struktur zu verändern, um dorthin zu gelangen. Verwenden Sie das Werkzeug, das Ihrer Absicht entspricht; greifen Sie nicht zu dem einen und erwarten Sie die Zusicherungen des anderen.

Ein zweites Missverständnis ist, dass ein sauberer Neuaufbau beweist, dass das Original sauber war. Es beweist nichts über das Original. Es beweist nur, dass die Ausgabe keine erkannte Bedrohung enthält. Die Eingabe mag eine Waffe gewesen sein; CDRs Aufgabe ist es, sicherzustellen, dass das, was Sie weiter unten in die Kette weiterleiten, es nicht ist.

Dies ist der Teil, den die Broschüren auslassen, also sagen wir es klar.

  • Die Ausgabe ist eine Sicherheitsprojektion, keine beweistaugliche Kopie. Der CdrEngine-Quellcode trägt dies als architektonische rote Linie. Das bereinigte PDF darf nicht zur juristischen Beweissicherung, zum Hash-Vergleich gegen das Original oder als Archivkopie verwendet werden. Die Transformation ist von Natur aus zerstörend und nicht umkehrbar.
  • Erkennung hat einen Geltungsbereich. CDR entfernt die Bedrohungen, die es zu benennen weiß. Es ist eine starke, prüfbare Schicht in einem Defense-in-Depth-Stapel – keine Garantie, dass eine Datei frei von jeder möglichen künftigen Technik ist. Halten Sie es hinter derselben Upload-Validierung, denselben Content-Type-Prüfungen und derselben Behandlung mit geringsten Rechten, die der Datei-Upload-Leitfaden von OWASP beschreibt.
  • Manche Richtlinien sind absichtlich verlustbehaftet. Die optionalen Strip*-Fälle entfernen eingebettete Dateien, Signaturen, Formularfelder, Ebenen und 3D-Medien. Diese sind mächtig, und sie werden legitimen Inhalt löschen – etwa eine ZUGFeRD/Factur-X-Rechnungsnutzlast. Sie sind genau aus diesem Grund standardmäßig ausgeschaltet. Schalten Sie sie wissentlich ein.
  • Signaturen überleben einen Neuaufbau nicht. Die Datei neu aufzubauen ändert ihre Bytes, sodass jede ursprüngliche digitale Signatur nicht mehr zu ihrem Byte-Bereich passt. Ein entschärftes Dokument ist in Bezug auf die Quelle unsigniert. Wenn Sie ein signiertes Artefakt brauchen, signieren Sie die saubere Ausgabe als einen neuen Akt.
Content Disarm & Reconstruction (CDR) — edition availability
EditionAvailability
Core

Nicht verfügbar. Der NextPDF-Core führt kein CDR durch. Er parst, rendert und schreibt PDFs; er erkennt keine Bedrohungen und baut keine nicht vertrauenswürdige Eingabe neu auf.

Pro

In der Pro-Edition nicht verfügbar.

Enterprise

Verfügbar über CdrEngine. Die entschärfte Ausgabe ist eine Sicherheitsprojektion der Quelle – sie darf nicht als beweistaugliche, hash-vergleichbare oder Archivkopie des Originals behandelt werden.

  • CDR (Content Disarm & Reconstruction) – eine Bereinigungsstrategie, die eine nicht vertrauenswürdige Datei parst, aktive oder gefährliche Komponenten entfernt und aus dem sicheren Rest eine saubere Datei neu aufbaut, statt nach bekanntermaßen schlechten Signaturen zu suchen.
  • Sicherheitsprojektion – eine bereinigte Ausgabe, die genug von der Quelle bewahrt, um nützlich zu sein, und zugleich die Entfernung von Bedrohungen garantiert. Sie ist bewusst nicht byte-getreu und nicht für Beweise, Hashing oder Archivierung geeignet.
  • Zulassungskontrolle – das vorgeschaltete Tor vor der Bereinigung, das Dokumente ablehnt, die Ressourcengrenzen überschreiten (Objektanzahl, Seitenanzahl, Größe des dekodierten Streams, Inflationsverhältnis), bevor irgendeine Entschärfungsarbeit beginnt.
  • Aktion – eine PDF-Konstruktion, die bei einem Auslöser wie Dokument-Öffnen oder einer Feldänderung etwas geschehen lässt; der Aktionstyp-Katalog (Spec: ISO 32000-2, §12.6.4) umfasst JavaScript- und Launch-Aktionen, die kanonische CDR-Bedrohungsoberfläche.
  • Hängende Referenz – ein Zeiger auf ein Objekt, das nach dem Filtern nicht mehr existiert. Die Referenz-Schrubb-Phase entfernt diese, sodass die neu aufgebaute Datei strukturell konsistent bleibt.