Los documentos PDF son increíblemente potentes, pero esa potencia conlleva riesgos de seguridad inherentes. Debido a que los PDF admiten archivos integrados, JavaScript interactivo y flujos binarios complejos, se utilizan con frecuencia como vectores para la entrega de malware. Los desbordamientos de búfer, las lecturas fuera de límites y los desbordamientos de enteros en analizadores PDF mal escritos pueden llevar a la ejecución remota de código (RCE).
Si está creando una aplicación en Delphi que acepta archivos PDF subidos por usuarios (por ejemplo, un portal de recepción de documentos), garantizar un análisis de PDF seguro para la memoria es un requisito de seguridad crítico.
Vectores comunes de ataque a PDF
Los PDF maliciosos suelen atacar vulnerabilidades en el propio analizador en lugar de en el sistema operativo. Las técnicas comunes incluyen:
- Tablas de referencias cruzadas (XRef) malformadas: Creación de compensaciones de punteros (pointer offsets) que conducen fuera de los límites, bloqueando el analizador o permitiendo la divulgación de memoria.
- Bucles infinitos: Creación de referencias circular entre objetos PDF (por ejemplo, el Objeto A hace referencia al Objeto B, que hace referencia al Objeto A), lo que lleva al agotamiento de la pila (stack exhaustion).
- Descompresión explosiva (Bombas Zip): Flujos FlateDecode que se descomprimen de unos pocos kilobytes a gigabytes, agotando la memoria del sistema.
Estrategias de análisis defensivo en Delphi
Al analizar PDF de forma nativa en Delphi, debe programar a la defensiva. No puede confiar en los metadatos proporcionados en los diccionarios del PDF.
1. Romper referencias circulares
Al recorrer de forma recursiva un árbol de objetos PDF, debe mantener un historial de los objetos visitados para evitar bucles infinitos.
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. Protección contra bombas Zip
Al aplicar el filtro FlateDecode para descomprimir un flujo, debe limitar estrictamente el tamaño máximo de expansión. Nunca asigne memoria a ciegas en base a la clave de diccionario /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;
Aprovechamiento de motores reforzados y componentes seguros
Escribir un analizador sintáctico de PDF completamente seguro desde cero es una tarea monumental. El enfoque estándar de la industria es utilizar un motor reforzado y sometido a pruebas intensivas de fuzzing como PDFium, o depender de bibliotecas nativas rigurosamente probadas.
PDFium es el motor de renderizado principal utilizado por Google Chrome. Debido a que Chrome procesa millones de PDF no confiables diariamente, PDFium es sometido a un fuzzing continuo y agresivo por parte de Project Zero de Google. Maneja de manera elegante XRefs mal formados, flujos rotos y referencias cíclicas.
De manera similar, componentes nativos como el HotPDF Component y Delphi PDF Library incorporan de fábrica estrategias robustas de análisis sintáctico defensivo. Implementan una estricta comprobación de límites, limitadores de profundidad recursiva y mecanismos de prevención de fugas de memoria diseñados específicamente para entornos Delphi y C++Builder.
Ya sea que elija consumir PDFium a través de un contenedor Delphi para el renderizado, o utilice componentes nativos como HotPDF para la generación y procesamiento de documentos, heredará un perímetro de seguridad de nivel empresarial, protegiendo a sus usuarios y servidores de cargas maliciosas sin tener que escribir analizadores defensivos usted mismo.
Nota: Las capacidades de análisis sintáctico seguro y sometido a fuzzing están disponibles en toda nuestra suite, incluyendo el HotPDF Component, la Delphi PDF Library y el PDFium Component.