
إثبات مفهوم (PoC) للتحقق فقط من CVE-2026-98432، وهو ثغرة use-after-free في Linux IPv4/TCP ضمن ireq_opt: محفّز حالة تسابق (race) وأداة استدلال لإعادة استخدام الكومة (heap-reuse oracle) تؤكد وجود UAF دون تنفيذ تعليمات برمجية.
ireq_opt لـ IPv4/TCP في Linuxإثبات مفهوم للتحقق فقط من CVE-2026-98432 (CVSS 9.8): ثغرة use-after-free قابلة للتشغيل عن بُعد في حزمة IPv4/TCP في Linux.
لاختبارات الأمان المصرّح بها فقط. شغّله ضد أنظمة تملكها أو لديك إذن صريح باختبارها.
يُفعّل إثبات المفهوم حالة التسابق (race) ويكتشف عندما ينسخ النواة بايتات من كائن ip_options_rcu محرَّر إلى حزمة SYN-ACK. وهو لا ينشئ مستخدمين أو ملفات، ولا ينفّذ سلسلة تنفيذ كود.
تعني الإصابة أن الخادم أعاد علامة تخصيص آخر داخل حزمة SYN-ACK الخاصة به — وهو ما لا تستطيع نواة سليمة فعله. في اختبار مُتحكَّم به على Ubuntu 24.04.5 بنواة 6.8.0-147-generic (المُدرجة كمعرّضة للثغرة من قِبل Ubuntu؛ الإصلاح مُجدول في 6.8.0-149)، أنتج تشغيل على الواجهة المحلية لمدة 180 ثانية 21 إصابة في 320,829 محاولة، وأنتج تشغيل لمدة 300 ثانية 22 إصابة في 616,911 محاولة. بقيت النواة نظيفة (tainted=0، دون oops).
لا تتضمن هذه الوثيقة أي التقاطات حزم أو سجلات من ذلك المضيف؛ مخرجات إثبات المفهوم نفسها هي الدليل.
حزمة SYN تحمل خيارات IPv4 تجعل النواة تبني كائن ip_options_rcu (بحجم 72 بايت، kmalloc-96) لمقبس الطلب. عند اكتمال المصافحة، يسلّم tcp_v4_syn_recv_sock() ذلك الكائن إلى المقبس الابن دون نسخه، ثم يمسح المؤشر في مقبس الطلب. أي وحدة معالجة ثانية كانت قد بحثت عن مقبس الطلب مسبقًا قد تكون لا تزال داخل tcp_check_req() → tcp_v4_send_synack() → ip_build_and_send_pkt() → ip_options_build()، وتقرأ الكائن نفسه. مقابس الأبناء ليست SOCK_RCU_FREE، وinet_sock_destruct() يحرّر inet_opt باستخدام kfree() عادي، لذا إذا تم تفكيك الابن في تلك النافذة فإن القارئ يصل إلى ذاكرة محرَّرة.
يوجد متغيّر ثانٍ مع ترحيل مقبس الطلب (net.ipv4.tcp_migrate_req=1 أو برنامج BPF reuseport)؛ يستخدم الإصلاح kfree_rcu() في كلٍّ من inet_sock_destruct() وtcp_v4_reqsk_destructor().
أُدخل الخلل في Linux 4.4 (079096f103fa)؛ وأُصلح في mainline 7.3 وأُعيد نقله إلى 5.10.272 و5.15.223 و6.1.190 و6.6.159 و6.12.113 و6.18.56 و7.2.10. المتأثر: Linux 4.4 وما بعده، غير المُرقَّع.
يتراوح التأثير من تعطّل عن بُعد (DoS) إلى كشف ذاكرة النواة، ومع سلسلة استغلال كاملة، تنفيذ كود. يتوقف هذا المستودع عند إثبات use-after-free.
لكل محاولة:
ireq_opt؛ يعكس الهدف الخيار في حزمة SYN-ACK الخاصة به.inet_opt، ويُسقط مقبس الطلب مؤشره.المُتحقِّق (Oracle). كل محاولة تُضمّن قيمة سحرية فريدة 32-بت مع وسم تحقّق عند إزاحات الخيار 16..23. تحدث ثلاث عمليات إعادة كتابة قبل أن يرى قارئ في مساحة المستخدم الخيار:
| المرحلة | الفتحة |
|---|---|
ip_options_compile() على الخادم لحزمة SYN | 4..7 (TS) / 3..6 (RR) |
ip_options_build() على الخادم لحزمة SYN-ACK | 8..11 (TS) / 7..10 (RR) |
ip_options_compile() على المضيف المستقبِل لحزمة SYN-ACK | 12..15 (TS) / 11..14 (RR) |
تقع العلامة بعد الثلاث جميعًا. حزمة SYN-ACK تعكس القيمة السحرية لتخصيص مختلف (مع tag == magic ^ 0x5a5a5a5a) تُثبت أن القارئ نسخ من كائن محرَّر وأُعيد استخدامه.
CAP_NET_RAW؛ يحتاج مرشّح RST التلقائي إلى CAP_NET_ADMIN (root).accept().iptables/nftables لمرشّح RST المجرّد.--proof مكتفٍ ذاتيًا على مضيف واحد: يبدأ مستمعًا على الواجهة المحلية ويسابقه.
python3 poc_cve_2026_98432.py --selftest
sudo python3 poc_cve_2026_98432.py --check
يطبع النواة قيد التشغيل، وجدول الإصدارات المُصلحة، ومعاملات sysctl ذات الصلة.
sudo python3 poc_cve_2026_98432.py --proof 9000 \
--duration 180 --workers 6 --spray 2 --spray-rate 1000 \
--pcap /tmp/proof.pcap
يبدأ مستمعًا على 127.0.0.1:9000، ويشغّل السباق، ويطبع الحكم، ويوقف
المستمع، ويزيل قاعدة جدار الحماية المؤقتة. لا يتم إنشاء أي شيء على
المضيف — فقط حالة TCP عابرة.
sudo python3 poc_cve_2026_98432.py --probe <TARGET>:<PORT>
فحص SYN واحد: يُبلّغ عمّا إذا كان الهدف مستمع MPTCP وما إذا كان يعيد خيار IPv4 (المطلوب من قِبل الأوراكل).
sudo python3 poc_cve_2026_98432.py <TARGET>:<PORT> \
--workers 16 --spray 4 --duration 600 --pcap hits.pcap
تُرفض العناوين العامة ما لم يُمرَّر --allow-public. يُثبَّت مرشِّح RST المجرَّد تلقائيًا ويُزال عند الخروج.
python3 poc_cve_2026_98432.py --listen 9000 --mptcp
يُربط بـ 127.0.0.1؛ أضف --listen-any فقط لمضيف مهاجم بعيد. يقبل المستمع كل اتصال ويغلقه فورًا باستخدام SO_LINGER(0)، مما يحرّر العملية الفرعية بسرعة.
| الحقل | المعنى |
|---|---|
attempts | عمليات المصافحة التي بدأت |
synacks | حزم SYN-ACK التي لوحظت (حوالي اثنتين لكل محاولة) |
hits | حمل SYN-ACK علامة تخصيص آخر → تأكّد وجود UAF |
anomalies | تم تحليل العلامة لكن الوسم غير مطابق (تلف جزئي) |
leaks | قيمة تشبه مؤشر النواة في البايتات المعكوسة |
noopt | SYN-ACK بدون الخيار المعكوس (syncookies/الطابور ممتلئ/الإزالة) |
stale | تمت تصفية إعادة إرسال SYN-ACK المتأخرة (ليست إصابة) |
malformed | SYN-ACK مع ihl < 5 (بصمة underflow لـ optlen القديمة) |
timeouts | لا يوجد SYN-ACK خلال --timeout |
spray | حزم SYN الخاصة برشّ الكومة التي أُرسلت |
نموذج إصابة:
[!] UAF ORACLE HIT #1 at attempt sport=63042 (expected magic f815ca68 tag a24f9032)
tcp <TARGET>:9000 -> <CLIENT>:63042 seq=c20ed8ef ack=d212b2b1 flags=0x12
SYN-ACK echoed magic d4bcdcc7 tag 8ee6869d, belongs to another allocation
ip options:
44 28 11 00 03 71 b0 b5 03 71 cc 73 03 71 cc 73
d4 bc dc c7 8e e6 86 9d 00 00 00 00 00 00 00 00
0x8ee6869d == 0xd4bcdcc7 ^ 0x5a5a5a5a: تُثبت علاقة الوسم أن البايتات المعكوسة هي علامة صالحة من تخصيص مختلف.
رموز الخروج: 0 = تمت ملاحظة الدليل، 3 = لا شيء، 2 = خطأ في الإعداد،
1 = خطأ في الاستخدام/وقت التشغيل.
السباق احتمالي. على مضيف الاختبار، أعاد إنتاج السباق استخدام --workers 6 --spray 2 --spray-rate 1000 لمدة 3 دقائق على الأقل؛ بينما أنتج تشغيل لمدة 60 ثانية مع
--workers 4 --spray 1 --spray-rate 500 صفر إصابات على المضيف نفسه.
لا تستنتج "غير معرّض للثغرة" من تشغيل قصير.
--duration — مزيد من المحاولات؛ استغرق البحث المنشور عشرات الدقائق.--workers — مزيد من المحاولات المتزامنة (8–16 على شبكة محلية).--spray / --spray-rate — يُبقي kmalloc-96 في حالة تقليب مستمر حتى يُعاد استخدام كائنات الخيارات المحرَّرة.--lead / --rst-delta / --jitter — مسح توقيتي بالميكروثانية؛ ابدأ بـ
20/40/10 وامسح lead من 0–40، وdelta من 0–80.آلة افتراضية قابلة للتخلص منها أكثر أمانًا للتطوير. ابنِ نواة 6.12.112 معرّضة للثغرة عن طريق عكس سطري الإصلاح:
curl -LO https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.112.tar.xz
tar xf linux-6.12.112.tar.xz && cd linux-6.12.112
sed -i 's/kfree_rcu(rcu_dereference_protected(inet->inet_opt, 1), rcu);/kfree(rcu_dereference_protected(inet->inet_opt, 1));/' net/ipv4/af_inet.c
sed -i 's/kfree_rcu(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1), rcu);/kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));/' net/ipv4/tcp_ipv4.c
make defconfig
make -j"$(nproc)"
شغّله في QEMU ونفّذ --proof داخل الضيف، أو --race من المضيف
مقابل المنفذ المُعاد توجيهه.
يتطلب المُشغِّل ترويسة IPv4 مع خيارات (ihl > 5). وإسقاطها عند
الحافة يجعل الثغرة غير قابلة للوصول حتى يتم ترقيع النواة. باستخدام nftables: