A PDF-dokumentumok hihetetlenül nagy tudásúak, de ez az erő eredendő biztonsági kockázatokkal jár. Mivel a PDF-ek támogatják a beágyazott fájlokat, az interaktív JavaScriptet és a komplex bináris streameket, gyakran használják őket kártevők bejuttatására (malware delivery vector). A rosszul megírt PDF-elemzőkben (parsers) a puffer-túlcsordulások (buffer overflows), a határokon kívüli olvasások (out-of-bounds reads) és az egész-túlcsordulások (integer overflows) távoli kódvégrehajtáshoz (RCE - Remote Code Execution) vezethetnek.
Ha olyan alkalmazást épít Delphiben, amely felhasználók által feltöltött PDF-eket fogad be (pl. egy dokumentumbeviteli portál), a memóriabiztonságos PDF-elemzés biztosítása kritikus biztonsági követelmény.
Gyakori PDF támadási vektorok
A rosszindulatú PDF-ek általában magában az elemzőben lévő sebezhetőségeket célozzák meg, nem pedig az operációs rendszert. A gyakori technikák a következők:
- Hibásan formázott kereszthivatkozási (XRef) táblák: Olyan mutatóeltolások (pointer offsets) készítése, amelyek a memóriahatárokon kívülre mutatnak, összeomlasztva az elemzőt vagy lehetővé téve a memóriatartalom kiszivárogtatását.
- Végtelen ciklusok (Infinite Loops): Körkörös hivatkozások létrehozása PDF-objektumok között (pl. az 'A' objektum hivatkozik a 'B' objektumra, ami pedig visszahivatkozik az 'A' objektumra), ami veremkimerüléshez (stack exhaustion) vezet.
- Robbanó kicsomagolás (Zip bombák): Olyan FlateDecode streamek, amelyek néhány kilobájtról gigabájtokra bomlanak ki, kimerítve a rendszermemóriát.
Védekező elemzési stratégiák Delphiben
Amikor natívan elemez PDF-eket Delphiben, védekező (defensive) módon kell programoznia. Nem bízhat meg a PDF szótárakban megadott metaadatokban.
1. Körkörös hivatkozások megszakítása
Amikor rekurzívan bejár egy PDF-objektumfát, a végtelen ciklusok elkerülése érdekében fenn kell tartania a már meglátogatott objektumok előzményeit.
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. Védekezés a Zip bombák ellen
Amikor a FlateDecode szűrőt (filter) alkalmazza egy stream kicsomagolására, szigorúan korlátoznia kell a maximális kiterjedési méretet (expansion size). Soha ne foglaljon memóriát vakon a /Length szótárkulcs alapján.
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;
Megerősített motorok és biztonságos komponensek kiaknázása
Egy teljesen biztonságos PDF értelmező nulláról történő megírása monumentális feladat. Az iparági szabvány szerinti megközelítés egy megerősített, intenzíven fuzz-tesztelt motor, például a PDFium használata, vagy pedig szigorúan tesztelt natív könyvtárakra való támaszkodás.
A PDFium a Google Chrome által használt alapvető renderelő motor. Mivel a Chrome naponta több millió nem megbízható PDF-et dolgoz fel, a PDFiumot a Google Project Zero csapata agresszív, folyamatos fuzzingnak veti alá. Elegánsan kezeli a hibás XRef-eket, a megszakadt streameket és a ciklikus hivatkozásokat.
Hasonlóképpen, az olyan natív komponensek, mint a HotPDF Component és a Delphi PDF Library már a dobozból kivéve robusztus defenzív értelmezési stratégiákat tartalmaznak. Szigorú határellenőrzést, rekurzív mélységkorlátozókat és memóriaszivárgást megelőző mechanizmusokat implementálnak, amelyeket kifejezetten Delphi és C++Builder környezetekhez terveztek.
Akár a PDFiumot választja egy Delphi wrapperen keresztül történő rendereléshez, akár olyan natív komponenseket használ dokumentumgenerálásra és -feldolgozásra, mint a HotPDF, nagyvállalati szintű biztonsági perimetert örököl, megvédve felhasználóit és szervereit a rosszindulatú rakományoktól anélkül, hogy önmagának kellene defenzív értelmezőket írnia.
Megjegyzés: A biztonságos, fuzz-tesztelt értelmezési képességek a teljes termékcsaládunkban elérhetők, beleértve a HotPDF Component-et, a Delphi PDF Library-t és a PDFium Component-et.