1 |
blueness 13/06/05 20:45:45 |
2 |
|
3 |
Added: monkeyd-fix-DoS-headers-parser.patch |
4 |
Log: |
5 |
Fix DoS bug on headers parser, bug #472400, CVE-2013-3843 |
6 |
|
7 |
(Portage version: 2.1.11.62/cvs/Linux x86_64, signed Manifest commit with key 0xF52D4BBA) |
8 |
|
9 |
Revision Changes Path |
10 |
1.1 www-servers/monkeyd/files/monkeyd-fix-DoS-headers-parser.patch |
11 |
|
12 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/www-servers/monkeyd/files/monkeyd-fix-DoS-headers-parser.patch?rev=1.1&view=markup |
13 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/www-servers/monkeyd/files/monkeyd-fix-DoS-headers-parser.patch?rev=1.1&content-type=text/plain |
14 |
|
15 |
Index: monkeyd-fix-DoS-headers-parser.patch |
16 |
=================================================================== |
17 |
From 95d646e5de252bfaa8b68c39d0f48e5d82965d41 Mon Sep 17 00:00:00 2001 |
18 |
From: Eduardo Silva <edsiper@×××××.com> |
19 |
Date: Wed, 5 Jun 2013 12:18:39 -0600 |
20 |
Subject: [PATCH] Fix #182: DoS bug on headers parser |
21 |
|
22 |
This patch fix the root cause for a problem described in Ticket #182, |
23 |
actually if a header is malformed like a Header Key without a value, the |
24 |
ToC parser used to continue processing the next header line. |
25 |
|
26 |
The solution applied is to improve the ToC generator where it adds extra |
27 |
validations for at least one colon and forcing each header line to contain |
28 |
a value or empty space, otherwise the server will trigger a Bad Request |
29 |
response to the client and close the connection. |
30 |
|
31 |
Signed-off-by: Eduardo Silva <edsiper@×××××.com> |
32 |
--- |
33 |
src/mk_method.c | 11 ++++++++++- |
34 |
src/mk_request.c | 36 +++++++++++++++++++++++++++++------- |
35 |
2 files changed, 39 insertions(+), 8 deletions(-) |
36 |
|
37 |
diff --git a/src/mk_method.c b/src/mk_method.c |
38 |
index 4a0698a..b35e893 100644 |
39 |
--- a/src/mk_method.c |
40 |
+++ b/src/mk_method.c |
41 |
@@ -45,16 +45,25 @@ |
42 |
|
43 |
long int mk_method_validate_content_length(const char *body, int body_len) |
44 |
{ |
45 |
+ int crlf; |
46 |
struct headers_toc toc; |
47 |
long int len; |
48 |
mk_pointer tmp; |
49 |
|
50 |
+ crlf = mk_string_search(body, MK_CRLF, MK_STR_INSENSITIVE); |
51 |
+ if (crlf < 0) { |
52 |
+ return -1; |
53 |
+ } |
54 |
+ |
55 |
/* |
56 |
* obs: Table of Content (toc) is created when the full |
57 |
* request has arrived, this function cannot be used from |
58 |
* mk_http_pending_request(). |
59 |
*/ |
60 |
- mk_request_header_toc_parse(&toc, body, body_len); |
61 |
+ if (mk_request_header_toc_parse(&toc, body + crlf + mk_crlf.len, |
62 |
+ body_len - mk_crlf.len - crlf) < 0) { |
63 |
+ return -1; |
64 |
+ } |
65 |
tmp = mk_request_header_get(&toc, |
66 |
mk_rh_content_length.data, |
67 |
mk_rh_content_length.len); |
68 |
diff --git a/src/mk_request.c b/src/mk_request.c |
69 |
index 5c1f07e..083aba8 100644 |
70 |
--- a/src/mk_request.c |
71 |
+++ b/src/mk_request.c |
72 |
@@ -121,13 +121,32 @@ static void mk_request_free(struct session_request *sr) |
73 |
|
74 |
int mk_request_header_toc_parse(struct headers_toc *toc, const char *data, int len) |
75 |
{ |
76 |
- int i; |
77 |
+ int i = 0; |
78 |
+ int header_len; |
79 |
+ int colon; |
80 |
+ char *q; |
81 |
char *p = (char *) data; |
82 |
- char *l = 0; |
83 |
+ char *l = p; |
84 |
|
85 |
toc->length = 0; |
86 |
+ |
87 |
+ if (*p == '\r') goto out; |
88 |
for (i = 0; l < (data + len) && p && i < MK_HEADERS_TOC_LEN; i++) { |
89 |
- l = strstr(p, MK_CRLF); |
90 |
+ if (*p == '\r') goto out; |
91 |
+ |
92 |
+ colon = -1; |
93 |
+ for (q = p; *q != '\r'; ++q) { |
94 |
+ if (*q == ':') { |
95 |
+ colon = (q - p); |
96 |
+ } |
97 |
+ } |
98 |
+ |
99 |
+ l = (q); |
100 |
+ header_len = (l - p) - mk_crlf.len; |
101 |
+ if ((colon == -1) || (header_len == colon) || (*++q != '\n')) { |
102 |
+ return -1; |
103 |
+ } |
104 |
+ |
105 |
if (l) { |
106 |
toc->rows[i].init = p; |
107 |
toc->rows[i].end = l; |
108 |
@@ -140,6 +159,7 @@ int mk_request_header_toc_parse(struct headers_toc *toc, const char *data, int l |
109 |
} |
110 |
} |
111 |
|
112 |
+ out: |
113 |
return toc->length; |
114 |
} |
115 |
|
116 |
@@ -237,13 +257,15 @@ static int mk_request_header_process(struct session_request *sr) |
117 |
|
118 |
/* Creating Table of Content (index) for HTTP headers */ |
119 |
sr->headers_len = sr->body.len - (prot_end + mk_crlf.len); |
120 |
- mk_request_header_toc_parse(&sr->headers_toc, headers, sr->headers_len); |
121 |
+ if (mk_request_header_toc_parse(&sr->headers_toc, headers, sr->headers_len) < 0) { |
122 |
+ MK_TRACE("Invalid headers"); |
123 |
+ return -1; |
124 |
+ } |
125 |
|
126 |
/* Host */ |
127 |
host = mk_request_header_get(&sr->headers_toc, |
128 |
mk_rh_host.data, |
129 |
mk_rh_host.len); |
130 |
- |
131 |
if (host.data) { |
132 |
if ((pos_sep = mk_string_char_search_r(host.data, ':', host.len)) >= 0) { |
133 |
/* TCP port should not be higher than 65535 */ |
134 |
@@ -321,8 +343,8 @@ static int mk_request_header_process(struct session_request *sr) |
135 |
sr->keep_alive = MK_TRUE; |
136 |
sr->close_now = MK_FALSE; |
137 |
} |
138 |
- else if(mk_string_search_n(sr->connection.data, "Close", |
139 |
- MK_STR_INSENSITIVE, sr->connection.len) >= 0) { |
140 |
+ else if (mk_string_search_n(sr->connection.data, "Close", |
141 |
+ MK_STR_INSENSITIVE, sr->connection.len) >= 0) { |
142 |
sr->keep_alive = MK_FALSE; |
143 |
sr->close_now = MK_TRUE; |
144 |
} |
145 |
-- |
146 |
1.7.4.1 |