]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/CRITICAL: http_ana: Fix parsing of malformed cookies which start by a delimiter
authorOlivier Houchard <ohouchard@haproxy.com>
Mon, 22 Jul 2019 15:43:46 +0000 (17:43 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 23 Jul 2019 12:58:32 +0000 (14:58 +0200)
When client-side or server-side cookies are parsed, HAProxy enters in an
infinite loop if a Cookie/Set-Cookie header value starts by a delimiter (a colon
or a semicolon). Depending on the operating system, the service may become
degraded, unresponsive, or may trigger haproxy's watchdog causing a service stop
or automatic restart.

To fix this bug, in the loop parsing the attributes, we must be sure to always
skip delimiters once the first attribute-value pair was parsed, empty or
not. The credit for the fix goes to Olivier.

CVE-2019-14241 was assigned to this bug. This patch fixes the Github issue #181.

This patch must be backported to 2.0 and 1.9. However, the patch will have to be
adapted.

src/http_ana.c

index a0507a3c1d0e75089ad9fa36764799698d220e24..3f681c0f59d4e7d211ac891578f3bd24b7d8e538 100644 (file)
@@ -3448,6 +3448,7 @@ static void http_manage_client_side_cookies(struct stream *s, struct channel *re
        htx = htxbuf(&req->buf);
        ctx.blk = NULL;
        while (http_find_header(htx, ist("Cookie"), &ctx, 1)) {
+               int is_first = 1;
                del_from = NULL;  /* nothing to be deleted */
                preserve_hdr = 0; /* assume we may kill the whole header */
 
@@ -3505,8 +3506,9 @@ static void http_manage_client_side_cookies(struct stream *s, struct channel *re
 
                        /* find att_beg */
                        att_beg = prev;
-                       if (prev > hdr_beg)
+                       if (!is_first)
                                att_beg++;
+                       is_first = 0;
 
                        while (att_beg < hdr_end && HTTP_IS_SPHT(*att_beg))
                                att_beg++;
@@ -3848,6 +3850,8 @@ static void http_manage_server_side_cookies(struct stream *s, struct channel *re
 
        ctx.blk = NULL;
        while (1) {
+               int is_first = 1;
+
                if (!http_find_header(htx, ist("Set-Cookie"), &ctx, 1)) {
                        if (!http_find_header(htx, ist("Set-Cookie2"), &ctx, 1))
                                break;
@@ -3911,8 +3915,9 @@ static void http_manage_server_side_cookies(struct stream *s, struct channel *re
 
                        /* find att_beg */
                        att_beg = prev;
-                       if (prev > hdr_beg)
+                       if (!is_first)
                                att_beg++;
+                       is_first = 0;
 
                        while (att_beg < hdr_end && HTTP_IS_SPHT(*att_beg))
                                att_beg++;