Ку, киберрекруты. Данная статья посвящена уязвимости CVE-2023-31554, которая найдена в xpdf v4.04 . Тоже неплохая практика в ПыВНе - реальные кейсы, а именно для прокачки скиллов в фаззинге. Данная уязвимость приводит к отказу работы. На протяжении всей работы опирался на эти данные в статьях:
-
Ссылка скрыта от гостей
-
Ссылка скрыта от гостей
Описание уязвимости примерно такое:
Код:
В Xpdf 4.04 (и более ранних версиях) цикл объекта PDF в дереве меток страниц приводит к бесконечной рекурсии и переполнению стека.
Для нахождения уязвимости придется профаззить это произведение искусства, поэтому большое внимание уделю фаззингу.
Дисклеймер: Все данные, предоставленные в данной статье, взяты из открытых источников, не призывают к действию и являются только лишь данными для ознакомления, и изучения механизмов используемых технологий.
Развертка стенда
Опять же, стендом это назвать сложно, но как есть. Необходимая версия xpdf 4.04, но по факту подойдет и старше версия. Старшие версии можно найти на сайте
Ссылка скрыта от гостей
Там нашел и xpdf v4.04. На сайте нашел инфу о версии и видимо еще не обновляли версию:
Код:
Current version: 4.04
Released: 2022 Apr 18
Скачиваю для 32-bit версии:
После скачивания просто запускаю XpdfReader-linux64-4.04.run, куда и распакуется сам бинарь. В результате распаковки этого мяса видим следующее:
Если не запустилась, то на этом же сайте есть исходники и можно собрать проект командами ниже(очевидно, что нужно сначала распаковать и все дела). Все, что соберется будет находиться в директории
/xpdf
.
Код:
cmake -DCMAKE_BUILD_TYPE=Release
make
Уязвимость содержится в бинаре pdfimages, поэтому и буду с ним играться. Для этого подготовил pdf файл, в котором содержится картинка:
И пока что просто проверим работу программы:
Код:
./pdfimages test.pdf img
Выхлоп проги выразился в получении картинки img-0000.ppm . Значит, он принимает два параметра на вход:
- пдфку
- куда и как сохранять
Установка AFL++
Установите зависимости:
Код:
sudo apt-get update
sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
Проверка и сборка AFL++ :
Код:
cd $HOME
git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
export LLVM_CONFIG="llvm-config-11"
make distrib
sudo make install
Теперь, если все прошло хорошо, вы должны быть в состоянии запустить afl-fuzz. Просто введите
afl-fuzz
и вы должны увидеть что-то вроде этого:
Код:
afl-fuzz++4.06a based on afl by Michal Zalewski and a large online community
afl-fuzz [ options ] -- /path/to/fuzzed_app [ ... ]
Required parameters:
-i dir - input directory with test cases
-o dir - output directory for fuzzer findings
Execution control settings:
-p schedule - power schedules compute a seed's performance score:
fast(default), explore, exploit, seek, rare, mmopt, coe, lin
quad -- see docs/FAQ.md for more information
-f file - location read by the fuzzed program (default: stdin or @@)
-t msec - timeout for each run (auto-scaled, default 1000 ms). Add a '+'
to auto-calculate the timeout, the value being the maximum.
-m megs - memory limit for child process (0 MB, 0 = no limit [default])
-O - use binary-only instrumentation (FRIDA mode)
-Q - use binary-only instrumentation (QEMU mode)
-U - use unicorn-based instrumentation (Unicorn mode)
-W - use qemu-based instrumentation with Wine (Wine mode)
-X - use VM fuzzing (NYX mode - standalone mode)
-Y - use VM fuzzing (NYX mode - multiple instances mode)
Запуск AFL++
У нас уже скомпиленный бинарь, то есть типо блэкбокс, если понимаете о чем я. Для фаззинга этих коробок нужно использовать qemu. В папке, куда установили afl++ есть директория, которая называется qemu_mode или что-то в этом духе. Там необходимо запустить скрипт build_qemu_support.sh и запустится QemuAFL build script.
Дальше сделал два экспорта:
Код:
export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
export AFL_SKIP_CPUFREQ=1
Запустил фаззер так:
Код:
afl-fuzz -Q -D -i $PWD/in -o $PWD/out $PWD/pdfimages @@ $PWD/in /dev/null
-Q обозначает, что используем qemu afl
-i входной каталог с тестовыми кейсами
-o выходной каталог для результатов работы фаззера
@@ аргументы программы
$PWD/in на вход пдфки/тесткейсы
/dev/null картинки выводятся сюда
Получил такое мясо
После получения крашей, решил проверить как они отрабатывают (переименовал его в crash1):
Теперь с помощью gdb, можно определить где именно произошел краш.
Разбор полета
Для выявления места падения использовал GDB и запускал его так:
Код:
gdb --args ./pdfimages crash1 /dev/null
Внутри GDB пишу команду run и увидел следующее:
Код:
...
Syntax Error (2384): Illegal character '>'
Program received signal SIGSEGV, Segmentation fault.
0x0000555555671cd4 in XRef::fetch(int, int, Object*, int) ()
(gdb)
Затем прописал команду bt, что означает backtrace и было много вызовов функции Catalog::readPageLabelTree2(Object*):
Код:
#0 0x0000555555671cd4 in XRef::fetch(int, int, Object*, int) ()
#1 0x00005555555f17c2 in Catalog::readPageLabelTree2(Object*) ()
#2 0x00005555555f17cd in Catalog::readPageLabelTree2(Object*) ()
...
...
...
#?? 0x00005555555f17cd in Catalog::readPageLabelTree2(Object*) ()
И в самом деле похоже на рекурсию из-за чего и происходит переполение.
Последнее редактирование модератором: