PDF dokumenti su nevjerojatno moćni, ali ta moć donosi inherentne sigurnosne rizike. Budući da PDF-ovi podržavaju ugrađene datoteke, interaktivni JavaScript i složene binarne tokove, često se koriste kao vektori za isporuku zlonamjernog softvera. Prelijevanje međuspremnika, čitanja izvan granica i prelijevanja cijelih brojeva (integer overflows) u loše napisanim PDF parserima mogu dovesti do daljinskog izvršavanja koda (RCE).
Ako gradite aplikaciju u Delphiju koja prihvaća PDF-ove prenesene od strane korisnika (npr. portal za unos dokumenata), osiguranje memorijski sigurnog parsiranja PDF-a ključni je sigurnosni zahtjev.
Uobičajeni vektori PDF napada
Zlonamjerni PDF-ovi obično ciljaju na ranjivosti u samom parseru, a ne u operativnom sustavu. Uobičajene tehnike uključuju:
- Loše oblikovane tablice unakrsnih referenci (XRef): Stvaranje pomaka pokazivača koji vode izvan granica, što uzrokuje pad parsera ili omogućuje otkrivanje memorije.
- Beskonačne petlje: Stvaranje kružnih referenci između PDF objekata (npr. objekt A referencira objekt B, koji referencira objekt A) što dovodi do iscrpljivanja stoga.
- Eksplozivna dekompresija (Zip bombe): FlateDecode tokovi koji se dekomprimiraju s nekoliko kilobajta u gigabajte, iscrpljujući sistemsku memoriju.
Strategije defanzivnog parsiranja u Delphiju
Prilikom izvornog parsiranja PDF-ova u Delphiju, morate programirati defanzivno. Ne možete vjerovati metapodacima navedenima u PDF rječnicima.
1. Prekidanje kružnih referenci
Kada rekurzivno prolazite kroz stablo PDF objekata, morate održavati povijest posjećenih objekata kako biste spriječ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 primjenjujete filtar FlateDecode za dekompresiju toka, morate strogo ograničiti maksimalnu veličinu proširenja. Nikada nemojte slijepo dodjeljivati memoriju na temelju tipke rječ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štenje ojačanih mehanizama i sigurnih komponenti
Pisanje potpuno sigurnog PDF parsera od nule je monumentalan zadatak. Standardni pristup u industriji je korištenje ojačanog, snažno fuzz-testiranog mehanizma kao što je PDFium, ili oslanjanje na rigorozno testirane nativne biblioteke.
PDFium je osnovni mehanizam za iscrtavanje koji koristi Google Chrome. Budući da Chrome svakodnevno obrađuje milijune nepouzdanih PDF-ova, PDFium je podvrgnut agresivnom, kontinuiranom fuzzingu od strane Googleovog Project Zero tima. On se elegantno nosi s neispravno oblikovanim XRef-ovima, prekinutim tokovima i cikličkim referencama.
Slično tome, nativne komponente poput HotPDF Component i Delphi PDF Library unaprijed uključuju robusne strategije obrambenog parsiranja. One implementiraju strogu provjeru granica, ograničivače rekurzivne dubine i mehanizme za sprječavanje curenja memorije dizajnirane specifično za Delphi i C++Builder okruženja.
Bez obzira odaberete li konzumirati PDFium putem Delphi omotača (wrappera) za iscrtavanje ili koristiti nativne komponente poput HotPDF-a za generiranje i obradu dokumenata, nasljeđujete sigurnosni perimetar na razini poduzeća, štiteći svoje korisnike i servere od zlonamjernih opterećenja bez potrebe da sami pišete obrambene parsere.
Napomena: Sigurne mogućnosti parsiranja testirane fuzzingom dostupne su u cijelom našem paketu, uključujući HotPDF Component, Delphi PDF Library i PDFium Component.