PDF-Dokumente sind unglaublich leistungsfähig, aber diese Leistungsfähigkeit bringt inhärente Sicherheitsrisiken mit sich. Da PDFs eingebettete Dateien, interaktives JavaScript und komplexe binäre Streams unterstützen, werden sie häufig als Vektoren für die Verbreitung von Malware verwendet. Pufferüberläufe, Out-of-Bounds-Lesevorgänge und Integer-Überläufe in schlecht geschriebenen PDF-Parsern können zur Remotecodeausführung (RCE) führen.
Wenn Sie eine Anwendung in Delphi erstellen, die von Benutzern hochgeladene PDFs akzeptiert (z. B. ein Dokumentenerfassungsportal), ist die Gewährleistung eines speichersicheren PDF-Parsings eine kritische Sicherheitsanforderung.
Häufige PDF-Angriffsvektoren
Bösartige PDFs zielen in der Regel auf Schwachstellen im Parser selbst ab und nicht auf das Betriebssystem. Gängige Techniken umfassen:
- Fehlerhafte Kreuzreferenztabellen (XRef): Erstellung von Zeiger-Offsets, die über die Grenzen hinausführen und den Parser zum Absturz bringen oder die Offenlegung des Speichers ermöglichen.
- Endlosschleifen: Erstellung von zirkulären Referenzen zwischen PDF-Objekten (z. B. referenziert Objekt A das Objekt B, welches wiederum Objekt A referenziert), was zur Erschöpfung des Stacks (Stack Exhaustion) führt.
- Explodierende Dekomprimierung (Zip-Bomben): FlateDecode-Streams, die von wenigen Kilobyte auf Gigabyte anwachsen und den Systemspeicher erschöpfen.
Defensive Parsing-Strategien in Delphi
Beim nativen Parsen von PDFs in Delphi müssen Sie defensiv programmieren. Sie können den in den PDF-Wörterbüchern bereitgestellten Metadaten nicht vertrauen.
1. Unterbrechen von zirkulären Referenzen
Wenn Sie einen PDF-Objektbaum rekursiv durchlaufen, müssen Sie einen Verlauf der besuchten Objekte führen, um Endlosschleifen zu vermeiden.
uses
System.Generics.Collections, System.SysUtils;
// A safe recursive function to walk the PDF tree
procedure ParsePDFDictionary(DictObj: TPDFDictionary; Visited: TList<Integer>);
var
ObjID: Integer;
begin
ObjID := DictObj.ObjectID;
if Visited.Contains(ObjID) then
begin
Writeln('Warning: Circular reference detected. Aborting branch.');
Exit;
end;
Visited.Add(ObjID);
try
// Process child objects safely...
finally
// Allow siblings to traverse, but prevent vertical recursion loops
Visited.Remove(ObjID);
end;
end;
2. Schutz vor Zip-Bomben
Wenn Sie den Filter FlateDecode zum Dekomprimieren eines Streams anwenden, müssen Sie die maximale Expansionsgröße strikt begrenzen. Weisen Sie niemals blind Speicher basierend auf dem Wörterbuchschlüssel `/Length` zu.
const
MAX_DECOMPRESSED_SIZE = 1024 * 1024 * 50; // 50 MB safety limit
procedure DecompressPDFStream(CompressedStream, OutputTarget: TStream);
var
ZLibStream: TZDecompressionStream;
Buffer: array[0..8191] of Byte;
BytesRead, TotalRead: Integer;
begin
ZLibStream := TZDecompressionStream.Create(CompressedStream);
try
TotalRead := 0;
repeat
BytesRead := ZLibStream.Read(Buffer[0], SizeOf(Buffer));
if BytesRead > 0 then
begin
TotalRead := TotalRead + BytesRead;
if TotalRead > MAX_DECOMPRESSED_SIZE then
raise Exception.Create('Security Exception: Decompression bomb detected!');
OutputTarget.WriteBuffer(Buffer[0], BytesRead);
end;
until BytesRead = 0;
finally
ZLibStream.Free;
end;
end;
Nutzung gehärteter Engines und sicherer Komponenten
Einen vollständig sicheren PDF-Parser von Grund auf neu zu schreiben, ist eine monumentale Aufgabe. Der branchenübliche Ansatz besteht darin, eine gehärtete, stark fuzz-getestete Engine wie PDFium zu verwenden oder sich auf streng getestete native Bibliotheken zu verlassen.
PDFium ist die von Google Chrome verwendete Kern-Rendering-Engine. Da Chrome täglich Millionen nicht vertrauenswürdiger PDFs verarbeitet, wird PDFium von Googles Project Zero aggressivem und kontinuierlichem Fuzzing unterzogen. Es geht elegant mit fehlerhaften XRefs, beschädigten Streams und zyklischen Referenzen um.
Ebenso integrieren native Komponenten wie die HotPDF Component und die Delphi PDF Library von Haus aus robuste defensive Parsing-Strategien. Sie implementieren strenge Grenzwertprüfungen, rekursive Tiefenbegrenzer und Mechanismen zur Vermeidung von Speicherlecks, die speziell für Delphi- und C++Builder-Umgebungen entwickelt wurden.
Unabhängig davon, ob Sie PDFium über einen Delphi-Wrapper für das Rendering nutzen oder native Komponenten wie HotPDF für die Dokumentengenerierung und -verarbeitung verwenden, erben Sie einen Sicherheitsperimeter auf Unternehmensniveau, der Ihre Benutzer und Server vor schädlichen Payloads schützt, ohne dass Sie selbst defensive Parser schreiben müssen.
Hinweis: Sichere, fuzz-getestete Parsing-Funktionen sind in unserer gesamten Suite verfügbar, einschließlich der HotPDF Component, der Delphi PDF Library und der PDFium Component.