
أداة اختبار موجّهة على مستوى الثنائيات متخصصة في اكتشاف ثغرات الاستخدام بعد التحرير (Use-After-Free) عبر مقاييس إدخال تراعي الترتيب وتحليل ثابت، مما يتيح إعادة إنتاج الأخطاء واختبار التصحيحات والتحقق من التقارير.
الاختبار العشوائي الموجه للصندوق الرمادي (DGF) مثل AFLGo يهدف إلى إجراء اختبار إجهاد على مواقع الهدف المحتملة الحساسة المحددة مسبقًا، مع تطبيقات في سياقات أمنية مختلفة: (1) إعادة إنتاج الثغرات، (2) اختبار التصحيحات، أو (3) التحقق من تقارير التحليل الثابت. هناك مؤخرًا المزيد من الأبحاث التي حسّنت فعالية وكفاءة الاختبار العشوائي الموجه (انظر awesome-directed-fuzzing).
نقترح UAFuzz وهو أداة اختبار عشوائي موجهة مخصصة لثغرات الاستخدام بعد التحرير (UAF) على مستوى البرنامج الثنائي من خلال ضبط المكونات الرئيسية للاختبار العشوائي الموجه بعناية لتلبية الخصائص المحددة لهذه الفئة من الثغرات. تظهر ثغرات UAF عندما يتم استخدام عنصر من الكومة بعد تحريره. اكتشاف ثغرات UAF صعب: (1) التعقيد لأن إدخال الإثبات (PoC) يحتاج إلى تشغيل سلسلة من ثلاثة أحداث – تخصيص وتحرير واستخدام – على نفس موقع الذاكرة، وذلك عبر عدة وظائف من البرنامج المختبر، و(2) الصمت دون حدوث خطأ تجزئة.
بشكل عام، لدى UAFuzz سير عمل مشابه لأدوات الاختبار العشوائي الموجهة مع تعديلاتنا الموضحة باللون البرتقالي على طول عملية الاختبار العشوائي بأكملها، كما هو موضح في الشكل التالي. نظرًا لأننا نركز على (1) إعادة إنتاج الثغرات و(2) تطبيقات اختبار التصحيحات، فمن المرجح أن يكون لدينا تتبعات مكدس (كاملة إلى حد كبير) لجميع أحداث UAF المتعلقة بالذاكرة. على عكس النهج الموجهة العامة الحالية حيث يمكن اختيار الأهداف بشكل مستقل، فإننا نأخذ في الاعتبار العلاقة بين الأهداف (مثل الترتيب الضروري لثغرات UAF) لتحسين التوجيه. أولاً، الحساب المسبق الثابت لـ UAFuzz سريع على مستوى البرنامج الثنائي. ثانيًا، نقدم مقاييس إدخال جديدة مراعية للترتيب لتوجيه الأداة نحو الأهداف أثناء التشغيل. أخيرًا، نقوم بفرز الإدخالات المحتملة فقط التي تغطي جميع الأهداف في التتبع المتوقع و الترشيح المسبق للإدخالات التي سيتم تحريرها التي تقل احتمالية تسببها في الثغرة.
مزيد من التفاصيل في ورقتنا العلمية في RAID'20 و مُحاضرتنا في Black Hat USA'20. شكرًا أيضًا لـ Sébastien Bardin و Matthieu Lemerre و البروفيسور Roland Groz وخاصة Richard Bonichon (@rbonichon) على مساعدته في Ocaml.
بيئة الاختبار لدينا هي Ubuntu 16.04 64-bit.
# Install Ocaml and prerequisite packages for BINSEC via OPAM
sudo apt update
sudo apt update
sudo apt install ocaml ocaml-native-compilers camlp4-extra opam emacs llvm-6.0-dev pkg-config protobuf-compiler libgmp-dev libzmq3-dev cmake valgrind
opam init
opam switch 4.05.0
opam depext conf-m4.1
opam install merlin ocp-indent caml-mode tuareg menhir ocamlgraph ocamlfind piqi zmq.5.0.0 zarith llvm.6.0.0
eval `opam config env`
# Install Python's packages (Python 2 for IDA's scripts)
sudo python -m pip install networkx pydot
sudo apt install graphviz
# Install Graph Easy
wget https://cpan.metacpan.org/authors/id/S/SH/SHLOMIF/Graph-Easy-0.76.tar.gz
tar xzf Graph-Easy-0.76.tar.gz
cd Graph-Easy-0.76
perl Makefile.PL; make test; sudo make install
export GRAPH_EASY_PATH=/usr/local/bin/graph-easy
# Checkout source code
git clone https://github.com/strongcourage/uafuzz.git
# Environment variables
export IDA_PATH = /path/to/ida-6.9/idaq
export GRAPH_EASY_PATH=/path/to/graph-easy
cd uafuzz; export UAFUZZ_PATH=`pwd`
# Compile source code
./scripts/build.sh uafuzz
# Help for IDA/UAFuzz interface
./binsec/src/binsec -ida-help
./binsec/src/binsec -uafuzz-help
أداة الاختبار العشوائي لدينا مبنية فوق AFL v2.52b في وضع QEMU للاختبار العشوائي و BINSEC للتحليل الثابت الخفيف (انظر uafuzz/README.md). نستخدم حاليًا IDA Pro v6.9 لاستخراج رسوم بيانية لتدفق التحكم (CFGs) ورسم بياني للاستدعاءات للبرنامج الثنائي المختبر (انظر ida/README.md).
uafuzz
├── binsec/src
│ └── ida: برنامج إضافي لاستيراد ومعالجة CFGs ورسم بياني للاستدعاءات من IDA
│ └── uafuzz: كود الاختبار العشوائي
│ │ └── afl-2.52b: الاختبار العشوائي الأساسي المبني فوق AFL-QEMU
│ │ └── uafuzz_*.ml(i): برنامج إضافي لحساب المعلومات الثابتة والتواصل مع AFL-QEMU
└── scripts: بعض النصوص البرمجية للبناء وفرز الثغرات
نأخذ أولاً ثغرة UAF بسيطة. كل من AFL-QEMU وحتى أداة الاختبار العشوائي الموجهة AFLGo مع أهداف على مستوى المصدر لا تستطيع اكتشاف هذه الثغرة خلال 6 ساعات، بينما يستطيع UAFuzz اكتشافها في دقائق بمساعدة تقرير UAF من Valgrind.
# Run AFL-QEMU
$UAFUZZ_PATH/tests/example.sh aflqemu 360
# Run AFLGo given targets at source-level
$UAFUZZ_PATH/tests/example.sh aflgo 360
# Run UAFuzz
$UAFUZZ_PATH/tests/example.sh uafuzz 360 $UAFUZZ_PATH/tests/example/example.valgrind
بالنسبة للبرامج الواقعية، نستخدم معيار UAF Fuzzing Benchmark لتقييماتنا.
# Checkout the benchmark
git clone https://github.com/strongcourage/uafbench.git
cd uafbench; export UAFBENCH_PATH=`pwd`
نعرض بالتفصيل كيفية تشغيل UAFuzz لتطبيق إعادة إنتاج ثغرات CVE-2018-20623 في readelf (Binutils). تتبعات المكدس لهذه الثغرة UAF التي تم الحصول عليها عبر Valgrind هي كالتالي:
// stack trace for the bad Use
==5358== Invalid read of size 1
==5358== at 0x40A9393: vfprintf (vfprintf.c:1632)
==5358== by 0x40A9680: buffered_vfprintf (vfprintf.c:2320)
==5358== by 0x40A72E0: vfprintf (vfprintf.c:1293)
[6] ==5358== by 0x80AB881: error (elfcomm.c:43)
[5] ==5358== by 0x8086217: process_archive (readelf.c:19409)
[1] ==5358== by 0x80868EA: process_file (readelf.c:19588)
[0] ==5358== by 0x8086B01: main (readelf.c:19664)
// stack trace for the Free
==5358== Address 0x4221dc0 is 0 bytes inside a block of size 80 free'd
==5358== at 0x402D358: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
[4] ==5358== by 0x8086647: process_archive (readelf.c:19524)
[1] ==5358== by 0x80868EA: process_file (readelf.c:19588)
[0] ==5358== by 0x8086B01: main (readelf.c:19664)
// stack trace for the Alloc
==5358== Block was alloc'd at
==5358== at 0x402C17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
[3] ==5358== by 0x80AD97E: make_qualified_name (elfcomm.c:906)
[2] ==5358== by 0x8086350: process_archive (readelf.c:19435)
[1] ==5358== by 0x80868EA: process_file (readelf.c:19588)
[0] ==5358== by 0x8086B01: main (readelf.c:19664)