]> 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)
committerSergey Kandaurov <s.kandaurov@f5.com>
Fri, 22 May 2026 15:07:28 +0000 (19:07 +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 2ea6113735b543c7c4eaf04f0840665764da8ed8..8a28e23a6729b44db21e78f3460e1ca705152fa0 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 {