PDF-dokumenter er utrolig kraftige, men den kraften kommer med iboende sikkerhetsrisikoer. Fordi PDF-filer støtter innebygde filer, interaktiv JavaScript og komplekse binærstrømmer, blir de ofte brukt som vektorer for spredning av skadelig programvare. Bufferoverflyt, lesing utenfor grenser og heltallsoverflyt i dårlig skrevne PDF-parsere kan føre til ekstern kodekjøring (RCE).
Hvis du bygger en applikasjon i Delphi som aksepterer PDF-filer lastet opp av brukere (for eksempel en portal for innhenting av dokumenter), er det et kritisk sikkerhetskrav å sikre minnesikker PDF-parsing.
Vanlige angrepsvektorer for PDF
Ondsinnede PDF-filer retter seg vanligvis mot sårbarheter i selve parseren fremfor operativsystemet. Vanlige teknikker inkluderer:
- Misdannede Cross-Reference (XRef) tabeller: Utforming av pekerforskyvninger som fører utenfor grenser, får parseren til å krasje eller tillater minneavsløring.
- Uendelige løkker: Oppretting av sirkulære referanser mellom PDF-objekter (f.eks. Objekt A refererer til Objekt B, som refererer til Objekt A) som fører til at stakken tømmes.
- Eksploderende dekomprimering (zip-bomber): FlateDecode-strømmer som dekomprimeres fra noen få kilobyte til gigabyte og tømmer systemminnet.
Defensive parsestrategier i Delphi
Når du parser PDF-filer nativt i Delphi, må du programmere defensivt. Du kan ikke stole på metadataene som er gitt i PDF-ordbøkene.
1. Bryte sirkulære referanser
Når du rekursivt går gjennom et PDF-objekttre, må du opprettholde en historikk over besøkte objekter for å forhindre uendelige løkker.
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. Beskytte mot zip-bomber
Når du bruker FlateDecode-filteret for å dekomprimere en strøm, må du strengt begrense den maksimale utvidelsesstørrelsen. Du må aldri tildele minne blindt basert på /Length-ordboknøkkelen.
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;
Utnyttelse av herdede motorer og sikre komponenter
Å skrive en fullstendig sikker PDF-parser fra bunnen av er en enorm oppgave. Bransjestandarden er å bruke en herdet, sterkt fuzz-testet motor som PDFium, eller stole på grundig testede native-biblioteker.
PDFium er kjerne-rendringsmotoren som brukes av Google Chrome. Fordi Chrome behandler millioner av upålitelige PDF-filer daglig, blir PDFium utsatt for aggressiv, kontinuerlig fuzzing av Googles Project Zero. Den håndterer misdannede XRef-er, ødelagte strømmer og sykliske referanser på en elegant måte.
På samme måte har native-komponenter som HotPDF Component og Delphi PDF Library robuste defensive parsestrategier innebygd. De implementerer streng grensekontroll, rekursive dybdebegrensere og mekanismer for å forhindre minnelekkasje designet spesielt for Delphi- og C++Builder-miljøer.
Enten du velger å bruke PDFium via en Delphi-wrapper for gjengivelse, eller benytte native-komponenter som HotPDF for dokumentgenerering og -behandling, arver du en sikkerhetssone i bedriftsklasse som beskytter brukerne dine og serverne dine mot ondsinnede nyttelaster uten at du trenger å skrive defensive parsere selv.
Merk: Sikre, fuzz-testede parsing-funksjoner er tilgjengelige over hele pakken vår, inkludert HotPDF Component, Delphi PDF Library og PDFium Component.