
يكتشف نمط rewrite الخاص بـ CVE-2026-42945 في إعدادات nginx: rewrite مع ? في جزء الاستبدال بالإضافة إلى التقاط غير مسمّى يُستهلك في نفس location
يكتشف الإعدادات المعرّضة للثغرة CVE-2026-42945، وهي تجاوز سعة المخزن المؤقت في كومة الذاكرة (heap buffer overflow) في وحدة nginx ngx_http_rewrite_module.
مجرد تشغيل إصدار nginx متأثر (من 0.6.27 حتى 1.30.0) لا يكفي ليكون قابلاً للاستغلال. يجب أن تحتوي الإعدادات على زوج محدد من التوجيهات، وهذا الزوج نادر: عمليتا مسح مستقلتان لإعدادات حقيقية من الواقع عثرتا على صفر إعدادات قابلة للاستغلال من أصل 1465، وواحدة من أصل 35633. يخبرك هذا السكريبت أي جانب من هذا الخط تقف فيه.
توجيه rewrite يحتوي استبداله على ? متبوعة بوسائط (arguments)، يليه التقاط غير مسمّى ($1 إلى $9) يُقرأ في نفس location:
location / {
rewrite ^(.*) /new?c=1; # the ? here raises the internal is_args flag
set $myvar $1; # ...which was never cleared, and leaks into this
return 200 $myvar;
}
تمريرة واحدة تحدد حجم المخزن المؤقت للخيط الخام (raw string)، والتمريرة التالية تنسخ نسخة مهربة (escaped) داخله. كلا الجزأين يبدوان صحيحين كلٌ على حدة.
كل قاعدة أدناه قيست على nginx 1.30.0 بدلاً من استنتاجها، لأن الأوصاف المنشورة تخطئ في اثنتين منها.
| الإعداد داخل location واحد | ينهار |
|---|---|
rewrite ^(.*) /new?c=1; + set $x $1; | نعم |
rewrite ^/old/(.*)$ /new?x=1; + set $x $1; | نعم |
rewrite ^/old/(.*)$ /new/$1?; + set $x $1; | لا |
rewrite ... /mid?c=1; ثم rewrite ... /new; ثم set $x $1; | لا |
rewrite ^(.*) /new?c=1 break; + set $x $1; | لا |
rewrite ^(?<tail>.*) /new?c=1; + set $x $1; | نعم |
rewrite ^(?<tail>.*) /new?c=1; + set $x $tail; | لا |
نتيجتان جديرتان بالتوضيح:
علامة ? الزائدة في النهاية ليست خطيرة. فالصيغة /new/$1? هي طريقة إسقاط سلسلة الاستعلام الموروثة، وهي تظهر في نسبة كبيرة من إعدادات الترحيل. وضع علامة على كل ? سيصرخ في وجه نصف الإنترنت.
العبارة «الالتقاطات المسماة آمنة» غير صحيحة. المهم هو كيفية قراءة الالتقاط، لا كيفية تعريفه. مجموعة مسماة تُقرأ كـ $1 تنهار تمامًا كمجموعة غير مسماة.
وكذلك يُتجاهل، لنفس الأسباب المقاسة: ? داخل الـ regex نفسه (كمحدد كمية)، وتوجيهات redirect / permanent / break، التي تنهي المعالجة قبل أن يعمل المستهلك.
nginx -T | python3 check_rewrite.py
python3 check_rewrite.py /path/to/dump.txt
python3 check_rewrite.py --json /path/to/dump.txt
بايثون 3، المكتبة القياسية فقط.
رموز الخروج: 0 نظيف، 1 تم العثور على زوج، 2 تعذّرت قراءة الإعدادات أو تحليلها. الثالث هو المقصود: علامة اقتباس غير مغلقة أو أقواس غير متوازنة تقطع التحليل، والفاحص الذي يجيب بـ «لا شيء موجود» لملف فشل في قراءته أسوأ من الذي ينهار. وعند حدوث ذلك يخبرك ويعيد 2.
أعطه مخرَج nginx -T، لا ملفات فردية: فملفات include قد تكون في أي مكان، والإعدادات المولَّدة تكون صحيحة فقط على الخادم الفعلي. تُبلغ النتائج عن الملف والسطر الذي يعيش فيه التوجيه فعليًا، لا عن الإزاحة في المخرَج.
$ python3 check_rewrite.py samples/vuln-nginx-T.txt
[HIGH] находка #1
location: location / (/etc/nginx/nginx.conf:14)
rewrite: rewrite ^(.*) /new?c=1 (/etc/nginx/nginx.conf:15)
захват $N: set -> set $myvar $1 (/etc/nginx/nginx.conf:16)
почему: обработка продолжается в этом же location без редиректа
Итого находок: 1
تُطبع أيضًا في نهاية كل تقرير، حتى لا يظن أحد أن الأداة ضمانة:
location;rewrite و set الموجودة مباشرة في server وليس داخل location لا تُتتبع;set $tmp $1; ثم استخدام $tmp) لا تُتبَع;try_files و error_page والمواقع المسماة لا تُتبَع;if لا يعمل أبدًا يظل مُبلغًا عنه.التحديث أكثر موثوقية من أي فحص إعدادات. خذ الإصدار المستقر أو الرئيسي الحالي من nginx.org.
python3 -m unittest test_check_rewrite -v
29 اختبارًا. معظمها حالات سلبية، لأن الخطر في أداة كهذه هو الصراخ في وجه إعدادات سليمة. كما شُغِّلت على إعداد إنتاجي من 250 سطرًا موزعة على أحد عشر ملف include، مع regex في map ورأس CSP مليء بفواصل منقوطة داخل علامات اقتباس: صفر نتائج، صفر شكاوى تحليل، ونتيجة واحدة بالضبط بعد حقن زوج حقيقي فيها.
MIT