PDF-documenten zijn ongelooflijk krachtig, maar die kracht brengt inherente veiligheidsrisico's met zich mee. Omdat PDF's ingesloten bestanden, interactieve JavaScript en complexe binaire streams ondersteunen, worden ze vaak gebruikt als vectoren voor de distributie van malware. Buffer overflows, out-of-bounds reads en integer overflows in slecht geschreven PDF-parsers kunnen leiden tot uitvoering van externe code (RCE).
Als u een applicatie in Delphi bouwt die door gebruikers geüploade PDF's accepteert (bijv. een portaal voor documentopname), is het garanderen van geheugenveilig PDF-parsen een cruciale beveiligingsvereiste.
Veelvoorkomende PDF-aanvalsvectoren
Kwaadaardige PDF's richten zich doorgaans op kwetsbaarheden in de parser zelf in plaats van in het besturingssysteem. Veelvoorkomende technieken zijn onder meer:
- Misvormde kruisverwijzingstabellen (XRef): Het maken van pointer-offsets die buiten de grenzen (out-of-bounds) leiden, waardoor de parser crasht of geheugenblootlegging mogelijk wordt.
- Oneindige lussen: Het creëren van circulaire referenties tussen PDF-objecten (bijv. Object A verwijst naar Object B, dat verwijst naar Object A), wat leidt tot uitputting van de stack.
- Exploderende decompressie (Zip-bommen): FlateDecode-streams die decomprimeren van een paar kilobytes naar gigabytes, waardoor het systeemgeheugen uitgeput raakt.
Defensieve parsingstrategieën in Delphi
Bij het native parsen van PDF's in Delphi moet u defensief programmeren. U kunt de metadata in de PDF-dictionaries niet vertrouwen.
1. Circulaire referenties doorbreken
Wanneer u recursief een PDF-objectboom doorloopt, moet u een geschiedenis bijhouden van bezochte objecten om oneindige lussen te voorkomen.
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. Beschermen tegen zip-bommen
Wanneer u het FlateDecode-filter toepast om een stream te decomprimeren, moet u de maximale uitbreidingsgrootte strikt beperken. Wijs nooit blindelings geheugen toe op basis van de dictionariesleutel /Length.
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;
Gebruikmaken van Geharde Engines en Veilige Componenten
Het schrijven van een volledig veilige PDF-parser vanaf nul is een enorme taak. De standaardbenadering in de industrie is het gebruik van een geharde, zwaar met fuzzing geteste engine zoals PDFium, of het vertrouwen op streng geteste native bibliotheken.
PDFium is de kern-renderingengine die wordt gebruikt door Google Chrome. Omdat Chrome dagelijks miljoenen onbetrouwbare PDF's verwerkt, wordt PDFium onderworpen aan agressieve, continue fuzzing door Google's Project Zero. Het verwerkt misvormde XRefs, kapotte streams en cyclische verwijzingen op een elegante manier.
Evenzo bevatten native componenten zoals het HotPDF Component en de Delphi PDF Library standaard robuuste defensieve parsingstrategieën. Ze implementeren strikte grenscontroles, recursieve dieptebeperkingen en mechanismen ter voorkoming van geheugenlekken die speciaal zijn ontworpen voor Delphi- en C++Builder-omgevingen.
Of u er nu voor kiest om PDFium via een Delphi-wrapper te gebruiken voor rendering, of native componenten zoals HotPDF gebruikt voor het genereren en verwerken van documenten, u erft een beveiligingsperimeter op ondernemingsniveau, waardoor uw gebruikers en uw servers worden beschermd tegen schadelijke payloads zonder dat u zelf defensieve parsers hoeft te schrijven.
Opmerking: Veilige, met fuzzing geteste parsingmogelijkheden zijn beschikbaar in onze hele suite, inclusief het HotPDF Component, de Delphi PDF Library en het PDFium Component.