Dokumenty PDF jsou neuvěřitelně výkonné, ale tato síla s sebou nese inherentní bezpečnostní rizika. Vzhledem k tomu, že soubory PDF podporují vložené soubory, interaktivní JavaScript a složité binární streamy, často se používají jako vektory pro šíření malwaru. Přetečení vyrovnávací paměti, čtení mimo hranice a přetečení celých čísel ve špatně napsaných analyzátorech PDF mohou vést ke vzdálenému spuštění kódu (RCE).
Pokud v Delphi vytváříte aplikaci, která přijímá soubory PDF nahrané uživateli (např. portál pro příjem dokumentů), je zajištění paměťově bezpečné analýzy PDF kritickým bezpečnostním požadavkem.
Běžné vektory útoků na PDF
Škodlivá PDF se obvykle zaměřují na zranitelnosti v samotném analyzátoru, nikoli v operačním systému. Mezi běžné techniky patří:
- Poškozené tabulky křížových odkazů (XRef): Vytváření posunů ukazatelů, které vedou mimo stanovené hranice, což způsobí pád analyzátoru nebo umožní odhalení obsahu paměti.
- Nekonečné smyčky: Vytváření cyklických odkazů mezi objekty PDF (např. objekt A odkazuje na objekt B, který odkazuje zpět na objekt A), což vede k vyčerpání zásobníku.
- Explodující dekomprese (Zip Bombs): Streamy FlateDecode, které se dekomprimují z několika kilobajtů na gigabajty a vyčerpají tak systémovou paměť.
Strategie defenzivní analýzy v Delphi
Při nativní analýze PDF v Delphi musíte programovat defenzivně. Nemůžete důvěřovat metadatům poskytnutým v PDF slovnících.
1. Přerušení cyklických odkazů
Při rekurzivním procházení stromu objektů PDF musíte udržovat historii navštívených objektů, abyste zabránili nekonečným smyčkám.
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. Ochrana proti Zip bombám
Při použití filtru FlateDecode pro dekompresi streamu musíte striktně omezit maximální velikost expanze. Nikdy nealokujte paměť slepě na základě klíče `/Length` ve slovníku.
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;
Využití posílených enginů a bezpečných komponent
Napsat zcela bezpečný PDF parser od nuly je monumentální úkol. Standardním průmyslovým přístupem je použití posíleného enginu, který je silně testován metodou fuzzing, jako je PDFium, nebo spoléhání na přísně testované nativní knihovny.
PDFium je hlavní renderovací engine používaný prohlížečem Google Chrome. Protože Chrome denně zpracovává miliony nedůvěryhodných PDF, je PDFium vystaveno agresivnímu a neustálému fuzzingu od týmu Project Zero společnosti Google. Elegantně si poradí s poškozenými XRef tabulkami, rozbitými streamy a cyklickými odkazy.
Podobně i nativní komponenty jako HotPDF Component a Delphi PDF Library obsahují robustní defenzivní parsovací strategie již v základu. Implementují přísnou kontrolu mezí, omezovače hloubky rekurze a mechanismy pro prevenci úniku paměti navržené speciálně pro prostředí Delphi a C++Builder.
Ať už se rozhodnete konzumovat PDFium přes Delphi wrapper pro renderování, nebo využijete nativní komponenty jako HotPDF pro generování a zpracování dokumentů, zdědíte bezpečnostní perimetr na podnikové úrovni, který ochrání vaše uživatele a servery před škodlivým obsahem, aniž byste museli sami psát defenzivní parsery.
Poznámka: Bezpečné parsovací schopnosti prověřené fuzzingem jsou dostupné napříč celou naší sadou, včetně HotPDF Component, Delphi PDF Library a PDFium Component.