PDF-документи є неймовірно потужними, але ця потужність супроводжується притаманними ризиками безпеки. Оскільки PDF-файли підтримують вбудовані файли, інтерактивний JavaScript і складні двійкові потоки, вони часто використовуються як вектори для доставки шкідливого програмного забезпечення. Переповнення буфера, читання за межами пам'яті (out-of-bounds) та цілочисельні переповнення в погано написаних аналізаторах PDF можуть призвести до віддаленого виконання коду (RCE).
Якщо ви створюєте додаток на Delphi, який приймає завантажені користувачами PDF-файли (наприклад, портал для прийому документів), забезпечення безпечного для пам'яті аналізу PDF є критичною вимогою безпеки.
Поширені вектори атак на PDF
Зловмисні PDF-файли зазвичай націлені на вразливості в самому аналізаторі, а не в операційній системі. Поширені методи включають:
- Неправильно сформовані таблиці перехресних посилань (XRef): Створення зміщень вказівників, які виходять за межі, що призводить до збою аналізатора або дозволяє розкрити вміст пам'яті.
- Нескінченні цикли: Створення циклічних посилань між об'єктами PDF (наприклад, об'єкт A посилається на об'єкт B, який посилається на об'єкт A), що призводить до вичерпання стека.
- Вибухова декомпресія (Zip Bombs): Потоки FlateDecode, які розпаковуються з кількох кілобайт у гігабайти, вичерпуючи системну пам'ять.
Стратегії захисного аналізу в Delphi
Під час нативного аналізу PDF-файлів у Delphi ви повинні програмувати з урахуванням захисту. Ви не можете довіряти метаданим, наданим у словниках PDF.
1. Розрив циклічних посилань
При рекурсивному обході дерева об'єктів PDF ви повинні підтримувати історію відвіданих об'єктів, щоб запобігти нескінченним циклам.
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. Захист від Zip Bombs
Застосовуючи фільтр FlateDecode для розпакування потоку, ви повинні суворо обмежити максимальний розмір розширення. Ніколи не виділяйте пам'ять наосліп на основі ключа словника /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;
Використання посилених рушіїв та безпечних компонентів
Написання повністю безпечного парсера PDF з нуля є монументальним завданням. Стандартним галузевим підходом є використання посиленого рушія, що пройшов ретельне фаззинг-тестування, такого як PDFium, або покладання на суворо перевірені нативні бібліотеки.
PDFium є основним рушієм рендерингу, який використовується в Google Chrome. Оскільки Chrome щодня обробляє мільйони ненадійних PDF-файлів, PDFium піддається агресивному, безперервному фаззингу з боку Project Zero від Google. Він витончено обробляє неправильно сформовані XRef, пошкоджені потоки та циклічні посилання.
Аналогічно, нативні компоненти, такі як HotPDF Component та Delphi PDF Library, включають надійні стратегії захисного парсингу "з коробки". Вони реалізують сувору перевірку меж, обмежувачі глибини рекурсії та механізми запобігання витоку пам'яті, спеціально розроблені для середовищ Delphi та C++Builder.
Незалежно від того, чи виберете ви використання PDFium через оболонку Delphi для рендерингу, чи застосуєте нативні компоненти, такі як HotPDF, для генерації та обробки документів, ви успадковуєте периметр безпеки корпоративного рівня, захищаючи ваших користувачів і сервери від шкідливих навантажень без необхідності самостійно писати захисні парсери.
Примітка: Безпечні можливості парсингу, перевірені фаззингом, доступні в усьому нашому наборі, включаючи HotPDF Component, Delphi PDF Library та PDFium Component.