[nginx] HTTP: just one empty line now accepted when parsing requ...

Maxim Dounin mdounin at mdounin.ru
Sat Mar 30 04:59:47 UTC 2024


details:   http://freenginx.org/hg/nginx/rev/ddcedfa3a809
branches:  
changeset: 9242:ddcedfa3a809
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Sat Mar 30 05:10:40 2024 +0300
description:
HTTP: just one empty line now accepted when parsing request line.

This ensures that multiple CRLFs cannot be used as a DoS vector, and also
in line with RFC 9112 ("SHOULD ignore at least one empty line").  Further,
bare CRs are no longer accepted.

diffstat:

 src/http/ngx_http_parse.c   |  29 ++++++++++++++++++++++++++++-
 src/http/ngx_http_request.c |  10 ----------
 2 files changed, 28 insertions(+), 11 deletions(-)

diffs (73 lines):

diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -106,6 +106,8 @@ ngx_http_parse_request_line(ngx_http_req
     u_char  c, ch, *p, *m;
     enum {
         sw_start = 0,
+        sw_newline,
+        sw_method_start,
         sw_method,
         sw_spaces_before_uri,
         sw_schema,
@@ -143,7 +145,13 @@ ngx_http_parse_request_line(ngx_http_req
         case sw_start:
             r->request_start = p;
 
-            if (ch == CR || ch == LF) {
+            if (ch == CR) {
+                state = sw_newline;
+                break;
+            }
+
+            if (ch == LF) {
+                state = sw_method_start;
                 break;
             }
 
@@ -154,6 +162,25 @@ ngx_http_parse_request_line(ngx_http_req
             state = sw_method;
             break;
 
+        case sw_newline:
+
+            if (ch == LF) {
+                state = sw_method_start;
+                break;
+            }
+
+            return NGX_HTTP_PARSE_INVALID_REQUEST;
+
+        case sw_method_start:
+            r->request_start = p;
+
+            if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+
+            state = sw_method;
+            break;
+
         case sw_method:
             if (ch == ' ') {
                 r->method_end = p - 1;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1623,16 +1623,6 @@ ngx_http_alloc_large_header_buffer(ngx_h
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http alloc large header buffer");
 
-    if (request_line && r->state == 0) {
-
-        /* the client fills up the buffer with "\r\n" */
-
-        r->header_in->pos = r->header_in->start;
-        r->header_in->last = r->header_in->start;
-
-        return NGX_OK;
-    }
-
     old = request_line ? r->request_start : r->header_name_start;
 
     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);



More information about the nginx-devel mailing list