PDF dokumenti su neverovatno moćni, ali ta moć nosi inherentne bezbednosne rizike. Zato što PDF-ovi podržavaju ugrađene datoteke, interaktivni JavaScript i složene binarne tokove, često se koriste kao vektori za isporuku zlonamernog softvera. Prelivanja bafera, čitanja van granica i prekoračenja celih brojeva u loše napisanim PDF parserima mogu dovesti do daljinskog izvršavanja koda (RCE).
Ako gradite aplikaciju u Delphiju koja prihvata PDF-ove koje otpremaju korisnici (npr. portal za unos dokumenata), obezbeđivanje memorijski bezbednog parsiranja PDF-a je kritičan bezbednosni zahtev.
Uobičajeni vektori PDF napada
Zlonamerni PDF-ovi obično ciljaju ranjivosti u samom parseru umesto u operativnom sistemu. Uobičajene tehnike uključuju:
- Loše formatirane tabele unakrsnih referenci (XRef): Kreiranje ofseta pokazivača koji vode van granica, uzrokujući pad parsera ili omogućavajući otkrivanje memorije.
- Beskonačne petlje: Stvaranje kružnih referenci između PDF objekata (npr. Objekat A referencira Objekat B, koji referencira Objekat A) što dovodi do iscrpljivanja steka.
- Eksplozivna dekompresija (Zip Bombe): Tokovi FlateDecode koji se dekompresuju od nekoliko kilobajta u gigabajte, iscrpljujući sistemsku memoriju.
Defanzivne strategije parsiranja u Delphiju
Kada izvorno parsirate PDF-ove u Delphiju, morate programirati defanzivno. Ne možete verovati metapodacima koji su navedeni u PDF rečnicima.
1. Razbijanje kružnih referenci
Kada rekurzivno prolazite kroz stablo PDF objekata, morate održavati istoriju posećenih objekata da biste sprečili beskonačne petlje.
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. Zaštita od Zip bombi
Kada primenjujete filter FlateDecode za dekompresiju toka, morate strogo ograničiti maksimalnu veličinu ekspanzije. Nikada ne alocirajte memoriju na slepo na osnovu ključa rečnika /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;
Korišćenje ojačanih mehanizama i bezbednih komponenti
Pisanje potpuno bezbednog PDF parsera od nule je monumentalan zadatak. Standardni pristup u industriji je korišćenje ojačanog, snažno fuzz-testiranog mehanizma kao što je PDFium, ili oslanjanje na rigorozno testirane nativne biblioteke.
PDFium je osnovni mehanizam za renderovanje koji koristi Google Chrome. Pošto Chrome svakodnevno obrađuje milione nepouzdanih PDF-ova, PDFium je podvrgnut agresivnom, kontinuiranom fuzzingu od strane Google-ovog Project Zero tima. On se elegantno nosi sa neispravno oblikovanim XRef-ovima, prekinutim tokovima i cikličnim referencama.
Slično tome, nativne komponente poput HotPDF Component i Delphi PDF Library unapred uključuju robusne strategije odbrambenog parsiranja. One implementiraju strogu proveru granica, graničnike rekurzivne dubine i mehanizme za sprečavanje curenja memorije dizajnirane specifično za Delphi i C++Builder okruženja.
Bilo da izaberete da koristite PDFium putem Delphi omotača (wrappera) za renderovanje ili da koristite nativne komponente poput HotPDF-a za generisanje i obradu dokumenata, nasleđujete bezbednosni perimetar na nivou preduzeća, štiteći svoje korisnike i servere od zlonamernih opterećenja bez potrebe da sami pišete odbrambene parsere.
Napomena: Bezbedne mogućnosti parsiranja testirane fuzzingom dostupne su u celom našem paketu, uključujući HotPDF Component, Delphi PDF Library i PDFium Component.