]> git.kaiwu.me - nginx.git/commitdiff
Rewrite: fix buffer overflow with overlapping captures
authorRoman Arutyunyan <arut@nginx.com>
Thu, 14 May 2026 14:42:18 +0000 (18:42 +0400)
committerRoman Arutyunyan <arutyunyan.roman@gmail.com>
Fri, 22 May 2026 14:55:09 +0000 (18:55 +0400)
When the rewrite replacement string had no variables, but had
overlapping captures, the length of the allocated buffer could be
smaller than the replacement string.  This could happen either
when the "redirect" parameter is specified, or when arguments are
present in the replacement string.

The following configurations resulted in heap buffer overflow when
using URI "/++++++++++++++++++++++++++++++":

    location / {
        rewrite ^/((.*))$ http://127.0.0.1:8080/$1$2 redirect;
        return 200 foo;
    }

    location / {
        rewrite ^/((.*))$ http://127.0.0.1:8080/?$1$2;
        return 200 foo;
    }

Reported by Mufeed VH of Winfunc Research.

src/http/ngx_http_script.c

index 3018efe1343f77e638dbfb0d0cda44f816d7ab95..8f7b548cc6686ea0b59aee141a8497ff912ff67d 100644 (file)
@@ -1037,6 +1037,8 @@ ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
 void
 ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
 {
+    int                           *cap;
+    u_char                        *p;
     size_t                         len;
     ngx_int_t                      rc;
     ngx_uint_t                     n;
@@ -1143,15 +1145,19 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
     if (code->lengths == NULL) {
         e->buf.len = code->size;
 
-        if (code->uri) {
-            if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
-                e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
-                                                 NGX_ESCAPE_ARGS);
-            }
-        }
+        cap = r->captures;
+        p = r->captures_data;
 
         for (n = 2; n < r->ncaptures; n += 2) {
-            e->buf.len += r->captures[n + 1] - r->captures[n];
+            e->buf.len += cap[n + 1] - cap[n];
+
+            if (code->uri) {
+                if (r->quoted_uri || r->plus_in_uri) {
+                    e->buf.len += 2 * ngx_escape_uri(NULL, &p[cap[n]],
+                                                     cap[n + 1] - cap[n],
+                                                     NGX_ESCAPE_ARGS);
+                }
+            }
         }
 
     } else {