I documenti PDF sono incredibilmente potenti, ma questo potere porta con sé intrinseci rischi per la sicurezza. Poiché i PDF supportano file incorporati, JavaScript interattivo e flussi binari complessi, vengono frequentemente utilizzati come vettori per la distribuzione di malware. Buffer overflow, letture fuori limite e integer overflow in parser PDF scritti male possono portare all'esecuzione di codice remoto (RCE).
Se stai sviluppando un'applicazione in Delphi che accetta PDF caricati dagli utenti (ad esempio, un portale di acquisizione documenti), garantire un'analisi PDF sicura per la memoria è un requisito di sicurezza critico.
Vettori di Attacco PDF Comuni
I PDF dannosi di solito prendono di mira le vulnerabilità nel parser stesso piuttosto che nel sistema operativo. Le tecniche più comuni includono:
- Tabelle di Riferimenti Incrociati (XRef) Malformate: creazione di offset di puntatori che conducono fuori limite, mandando in crash il parser o consentendo la divulgazione della memoria.
- Cicli Infiniti: creazione di riferimenti circolari tra gli oggetti PDF (ad es. l'Oggetto A fa riferimento all'Oggetto B, che a sua volta fa riferimento all'Oggetto A) portando all'esaurimento dello stack.
- Decompressione Esplosiva (Zip Bomb): flussi FlateDecode che da pochi kilobyte si decomprimono in gigabyte, esaurendo la memoria di sistema.
Strategie di Parsing Difensive in Delphi
Quando si analizzano i PDF nativamente in Delphi, è necessario programmare sulla difensiva. Non puoi fidarti dei metadati forniti nei dizionari PDF.
1. Interrompere i Riferimenti Circolari
Quando si percorre in modo ricorsivo l'albero degli oggetti PDF, è necessario mantenere una cronologia degli oggetti visitati per prevenire cicli infiniti.
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. Protezione Contro le Zip Bomb
Quando si applica il filtro FlateDecode per decomprimere un flusso, è necessario limitare rigorosamente la dimensione massima di espansione. Non allocare mai la memoria ciecamente in base alla chiave del dizionario /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;
Sfruttare Motori Rinforzati e Componenti Sicuri
Scrivere da zero un parser PDF completamente sicuro è un'impresa titanica. L'approccio standard del settore consiste nell'utilizzare un motore rinforzato e ampiamente testato tramite fuzzing come PDFium, oppure affidarsi a librerie native rigorosamente testate.
PDFium è il motore di rendering principale utilizzato da Google Chrome. Poiché Chrome elabora quotidianamente milioni di PDF non attendibili, PDFium è sottoposto a un fuzzing aggressivo e continuo da parte del Project Zero di Google. Gestisce XRef malformati, flussi interrotti e riferimenti ciclici in modo impeccabile.
Allo stesso modo, componenti nativi come l'HotPDF Component e la Delphi PDF Library integrano di default solide strategie di parsing difensivo. Implementano controlli rigorosi dei limiti, limitatori di profondità ricorsiva e meccanismi di prevenzione delle perdite di memoria progettati specificamente per gli ambienti Delphi e C++Builder.
Sia che tu scelga di consumare PDFium tramite un wrapper Delphi per il rendering, sia che tu utilizzi componenti nativi come HotPDF per la generazione e l'elaborazione di documenti, erediti un perimetro di sicurezza di livello enterprise, proteggendo i tuoi utenti e i tuoi server da payload dannosi senza dover scrivere tu stesso parser difensivi.
Nota: Funzionalità di parsing sicure e testate tramite fuzzing sono disponibili in tutta la nostra suite, inclusi l'HotPDF Component, la Delphi PDF Library e il PDFium Component.