Les documents PDF sont incroyablement puissants, mais cette puissance s'accompagne de risques de sécurité inhérents. Étant donné que les PDF prennent en charge les fichiers intégrés, le JavaScript interactif et les flux binaires complexes, ils sont fréquemment utilisés comme vecteurs de diffusion de logiciels malveillants. Les dépassements de mémoire tampon, les lectures hors limites et les dépassements d'entiers dans les analyseurs PDF mal écrits peuvent entraîner l'exécution de code à distance (RCE).
Si vous créez une application dans Delphi qui accepte des PDF téléchargés par les utilisateurs (par exemple, un portail d'ingestion de documents), garantir une analyse de PDF sécurisée en mémoire est une exigence de sécurité critique.
Vecteurs d'attaque PDF courants
Les PDF malveillants ciblent généralement des vulnérabilités dans l'analyseur lui-même plutôt que dans le système d'exploitation. Les techniques courantes incluent :
- Tables de références croisées (XRef) mal formées : Création de décalages de pointeur qui mènent hors limites, ce qui fait planter l'analyseur ou permet la divulgation de mémoire.
- Boucles infinies : Création de références circulaires entre des objets PDF (par exemple, l'objet A fait référence à l'objet B, qui fait référence à l'objet A) entraînant l'épuisement de la pile.
- Décompression explosive (Bombes Zip) : Flux FlateDecode qui se décompressent de quelques kilo-octets à plusieurs gigaoctets, épuisant la mémoire système.
Stratégies d'analyse défensive dans Delphi
Lors de l'analyse native de PDF dans Delphi, vous devez programmer de manière défensive. Vous ne pouvez pas faire confiance aux métadonnées fournies dans les dictionnaires PDF.
1. Briser les références circulaires
Lors du parcours récursif d'une arborescence d'objets PDF, vous devez conserver un historique des objets visités pour éviter les boucles infinies.
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. Protection contre les bombes Zip
Lors de l'application du filtre FlateDecode pour décompresser un flux, vous devez limiter strictement la taille d'extension maximale. N'allouez jamais de mémoire à l'aveugle en vous basant sur la clé de dictionnaire `/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;
Exploitation de moteurs renforcés et de composants sécurisés
Écrire un analyseur syntaxique PDF complètement sécurisé à partir de zéro est une tâche monumentale. L'approche standard de l'industrie consiste à utiliser un moteur renforcé et intensément testé par fuzzing comme PDFium, ou à s'appuyer sur des bibliothèques natives rigoureusement testées.
PDFium est le principal moteur de rendu utilisé par Google Chrome. Parce que Chrome traite quotidiennement des millions de PDF non fiables, PDFium est soumis à un fuzzing agressif et continu par le Project Zero de Google. Il gère gracieusement les XRefs malformés, les flux rompus et les références cycliques.
De même, les composants natifs tels que le HotPDF Component et la Delphi PDF Library intègrent par défaut de robustes stratégies d'analyse défensive. Ils mettent en œuvre des vérifications de limites strictes, des limiteurs de profondeur récursive et des mécanismes de prévention des fuites de mémoire conçus spécifiquement pour les environnements Delphi et C++Builder.
Que vous choisissiez de consommer PDFium via un wrapper Delphi pour le rendu, ou d'utiliser des composants natifs comme HotPDF pour la génération et le traitement de documents, vous héritez d'un périmètre de sécurité de niveau entreprise, protégeant vos utilisateurs et vos serveurs contre les charges utiles malveillantes sans avoir à écrire vous-même des analyseurs défensifs.
Remarque : Des capacités d'analyse sécurisées et testées par fuzzing sont disponibles dans l'ensemble de notre suite, y compris le HotPDF Component, la Delphi PDF Library et le PDFium Component.