PDF-dokument är otroligt kraftfulla, men den kraften kommer med inneboende säkerhetsrisker. Eftersom PDF-filer stöder inbäddade filer, interaktivt JavaScript och komplexa binära strömmar används de ofta som vektorer för leverans av skadlig kod. Buffertöverskridningar, läsningar utanför gränserna och heltalsöverskridningar i dåligt skrivna PDF-tolkare kan leda till fjärrkörning av kod (RCE).
Om du bygger en applikation i Delphi som accepterar användaruppladdade PDF-filer (t.ex. en portal för inmatning av dokument), är minnessäker PDF-tolkning ett kritiskt säkerhetskrav.
Vanliga attackvektorer för PDF
Skadliga PDF-filer riktar sig vanligtvis in på sårbarheter i själva tolkaren snarare än operativsystemet. Vanliga tekniker inkluderar:
- Felaktigt utformade korsreferenstabeller (XRef): Att skapa pekarförskjutningar som leder utanför gränserna, vilket kraschar tolkaren eller tillåter avslöjande av minne.
- Oändliga loopar: Att skapa cirkulära referenser mellan PDF-objekt (t.ex. Objekt A refererar till Objekt B, som refererar till Objekt A) vilket leder till stackutmattning.
- Exploderande dekomprimering (Zip-bomber): FlateDecode-strömmar som dekomprimerar från några kilobyte till gigabyte, vilket tömmer systemminnet.
Defensiva tolkningsstrategier i Delphi
När du tolkar PDF-filer inbyggt i Delphi måste du programmera defensivt. Du kan inte lita på metadatan som tillhandahålls i PDF-ordböckerna.
1. Bryta cirkulära referenser
När du rekursivt går igenom ett PDF-objektträd måste du upprätthålla en historik över besökta objekt för att förhindra oändliga loopar.
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. Skydda mot Zip-bomber
När du tillämpar FlateDecode-filtret för att dekomprimera en ström måste du strikt begränsa den maximala expansionsstorleken. Allokera aldrig minne blint baserat på ordboksnyckeln /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;
Utnyttjande av härdade motorer och säkra komponenter
Att skriva en helt säker PDF-parser från grunden är en monumental uppgift. Branschstandarden är att använda en härdad, kraftigt fuzz-testad motor som PDFium, eller förlita sig på rigoröst testade inbyggda bibliotek.
PDFium är kärnmotorn för rendering som används av Google Chrome. Eftersom Chrome dagligen bearbetar miljontals opålitliga PDF-filer utsätts PDFium för aggressiv, kontinuerlig fuzzing av Googles Project Zero. Den hanterar felaktigt utformade XRef-filer, trasiga strömmar och cykliska referenser smidigt.
På liknande sätt integrerar inbyggda komponenter som HotPDF Component och Delphi PDF Library robusta, defensiva parsningsstrategier direkt. De implementerar strikta gränskontroller, rekursiva djupbegränsare och mekanismer för att förhindra minnesläckor utformade specifikt för Delphi- och C++Builder-miljöer.
Oavsett om du väljer att konsumera PDFium via en Delphi-wrapper för rendering, eller utnyttjar inbyggda komponenter som HotPDF för dokumentgenerering och -bearbetning, ärver du en säkerhetsperimeter på företagsnivå, som skyddar dina användare och dina servrar från skadlig nyttolast utan att du själv behöver skriva defensiva parsrar.
Obs! Säkra, fuzz-testade parsningsfunktioner är tillgängliga i hela vår svit, inklusive HotPDF Component, Delphi PDF Library och PDFium Component.