Статья Среди ублюдков шел артист. PoC CVE-2023-2663

1687799885640.png

Ку, киберрекруты. Данная статья посвящена уязвимости CVE-2023-31554, которая найдена в xpdf v4.04 . Тоже неплохая практика в ПыВНе - реальные кейсы, а именно для прокачки скиллов в фаззинге. Данная уязвимость приводит к отказу работы. На протяжении всей работы опирался на эти данные в статьях:

Описание уязвимости примерно такое:

Код:
В Xpdf 4.04 (и более ранних версиях) цикл объекта PDF в дереве меток страниц приводит к бесконечной рекурсии и переполнению стека.

Для нахождения уязвимости придется профаззить это произведение искусства, поэтому большое внимание уделю фаззингу.

Дисклеймер: Все данные, предоставленные в данной статье, взяты из открытых источников, не призывают к действию и являются только лишь данными для ознакомления, и изучения механизмов используемых технологий.

Развертка стенда

Опять же, стендом это назвать сложно, но как есть. Необходимая версия xpdf 4.04, но по факту подойдет и старше версия. Старшие версии можно найти на сайте

1687800052981.png


Там нашел и xpdf v4.04. На сайте нашел инфу о версии и видимо еще не обновляли версию:

Код:
Current version: 4.04
Released: 2022 Apr 18

Скачиваю для 32-bit версии:

1687800100121.png


После скачивания просто запускаю XpdfReader-linux64-4.04.run, куда и распакуется сам бинарь. В результате распаковки этого мяса видим следующее:

1687800127408.png


Если не запустилась, то на этом же сайте есть исходники и можно собрать проект командами ниже(очевидно, что нужно сначала распаковать и все дела). Все, что соберется будет находиться в директории /xpdf.

Код:
cmake -DCMAKE_BUILD_TYPE=Release
make

Уязвимость содержится в бинаре pdfimages, поэтому и буду с ним играться. Для этого подготовил pdf файл, в котором содержится картинка:

1687800248159.png


И пока что просто проверим работу программы:

Код:
./pdfimages test.pdf img

Выхлоп проги выразился в получении картинки img-0000.ppm . Значит, он принимает два параметра на вход:

  1. пдфку
  2. куда и как сохранять
Эта инфа важа для фаззинга. Думаю, что сохранять ничего не будем, поэтому вторым аргументом укажу /dev/null . Сделаю еще пару тест-кейсов и запущю фаззер AFL++.

Установка 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 картинки выводятся сюда

Получил такое мясо

1687800692456.png


После получения крашей, решил проверить как они отрабатывают (переименовал его в crash1):

1687800713889.png


Теперь с помощью 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*) ()

И в самом деле похоже на рекурсию из-за чего и происходит переполение.
 
Последнее редактирование модератором:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!