Skip to content

Commit 0c34e46

Browse files
committed
modsecurity: do not process headers added by nginx
This code need to be kept in sync with nginx, otherwise modsecurity would be checking incorrect headers. In documentation [1] is mentioned that header added by Apache is not checked. Therefore the code was removed completely. [1] https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-%28v3.x%29#Phase_Response_Headers
1 parent 9d96617 commit 0c34e46

File tree

2 files changed

+12
-338
lines changed

2 files changed

+12
-338
lines changed

src/ngx_http_modsecurity_common.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,6 @@ typedef struct {
9797
} ngx_http_modsecurity_conf_t;
9898

9999

100-
typedef ngx_int_t (*ngx_http_modsecurity_resolv_header_pt)(ngx_http_request_t *r, ngx_str_t name, off_t offset);
101-
102-
typedef struct {
103-
ngx_str_t name;
104-
ngx_uint_t offset;
105-
ngx_http_modsecurity_resolv_header_pt resolver;
106-
} ngx_http_modsecurity_header_out_t;
107-
108-
109100
extern ngx_module_t ngx_http_modsecurity_module;
110101

111102
/* ngx_http_modsecurity_module.c */

src/ngx_http_modsecurity_header_filter.c

Lines changed: 12 additions & 329 deletions
Original file line numberDiff line numberDiff line change
@@ -26,302 +26,6 @@ static ngx_int_t ngx_http_modsecurity_header_filter(ngx_http_request_t *r);
2626

2727
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
2828

29-
static ngx_int_t ngx_http_modsecurity_resolv_header_server(ngx_http_request_t *r, ngx_str_t name, off_t offset);
30-
static ngx_int_t ngx_http_modsecurity_resolv_header_date(ngx_http_request_t *r, ngx_str_t name, off_t offset);
31-
static ngx_int_t ngx_http_modsecurity_resolv_header_content_length(ngx_http_request_t *r, ngx_str_t name, off_t offset);
32-
static ngx_int_t ngx_http_modsecurity_resolv_header_content_type(ngx_http_request_t *r, ngx_str_t name, off_t offset);
33-
static ngx_int_t ngx_http_modsecurity_resolv_header_last_modified(ngx_http_request_t *r, ngx_str_t name, off_t offset);
34-
static ngx_int_t ngx_http_modsecurity_resolv_header_connection(ngx_http_request_t *r, ngx_str_t name, off_t offset);
35-
static ngx_int_t ngx_http_modsecurity_resolv_header_transfer_encoding(ngx_http_request_t *r, ngx_str_t name, off_t offset);
36-
static ngx_int_t ngx_http_modsecurity_resolv_header_vary(ngx_http_request_t *r, ngx_str_t name, off_t offset);
37-
38-
ngx_http_modsecurity_header_out_t ngx_http_modsecurity_headers_out[] = {
39-
40-
{ ngx_string("Server"),
41-
offsetof(ngx_http_headers_out_t, server),
42-
ngx_http_modsecurity_resolv_header_server },
43-
44-
{ ngx_string("Date"),
45-
offsetof(ngx_http_headers_out_t, date),
46-
ngx_http_modsecurity_resolv_header_date },
47-
48-
{ ngx_string("Content-Length"),
49-
offsetof(ngx_http_headers_out_t, content_length_n),
50-
ngx_http_modsecurity_resolv_header_content_length },
51-
52-
{ ngx_string("Content-Type"),
53-
offsetof(ngx_http_headers_out_t, content_type),
54-
ngx_http_modsecurity_resolv_header_content_type },
55-
56-
{ ngx_string("Last-Modified"),
57-
offsetof(ngx_http_headers_out_t, last_modified),
58-
ngx_http_modsecurity_resolv_header_last_modified },
59-
60-
{ ngx_string("Connection"),
61-
0,
62-
ngx_http_modsecurity_resolv_header_connection },
63-
64-
{ ngx_string("Transfer-Encoding"),
65-
0,
66-
ngx_http_modsecurity_resolv_header_transfer_encoding },
67-
68-
{ ngx_string("Vary"),
69-
0,
70-
ngx_http_modsecurity_resolv_header_vary },
71-
72-
#if 0
73-
{ ngx_string("Content-Encoding"),
74-
offsetof(ngx_http_headers_out_t, content_encoding),
75-
NGX_TABLE },
76-
77-
{ ngx_string("Cache-Control"),
78-
offsetof(ngx_http_headers_out_t, cache_control),
79-
NGX_ARRAY },
80-
81-
{ ngx_string("Location"),
82-
offsetof(ngx_http_headers_out_t, location),
83-
NGX_TABLE },
84-
85-
{ ngx_string("Content-Range"),
86-
offsetof(ngx_http_headers_out_t, content_range),
87-
NGX_TABLE },
88-
89-
{ ngx_string("Accept-Ranges"),
90-
offsetof(ngx_http_headers_out_t, accept_ranges),
91-
NGX_TABLE },
92-
93-
returiders_out[i].name 1;
94-
{ ngx_string("WWW-Authenticate"),
95-
offsetof(ngx_http_headers_out_t, www_authenticate),
96-
NGX_TABLE },
97-
98-
{ ngx_string("Expires"),
99-
offsetof(ngx_http_headers_out_t, expires),
100-
NGX_TABLE },
101-
#endif
102-
{ ngx_null_string, 0, 0 }
103-
};
104-
105-
106-
static ngx_int_t
107-
ngx_http_modsecurity_resolv_header_server(ngx_http_request_t *r, ngx_str_t name, off_t offset)
108-
{
109-
static char ngx_http_server_full_string[] = NGINX_VER;
110-
static char ngx_http_server_string[] = "nginx";
111-
112-
ngx_http_core_loc_conf_t *clcf = NULL;
113-
ngx_http_modsecurity_ctx_t *ctx = NULL;
114-
ngx_str_t value;
115-
116-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
117-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
118-
119-
if (r->headers_out.server == NULL) {
120-
if (clcf->server_tokens) {
121-
value.data = (u_char *)ngx_http_server_full_string;
122-
value.len = sizeof(ngx_http_server_full_string);
123-
} else {
124-
value.data = (u_char *)ngx_http_server_string;
125-
value.len = sizeof(ngx_http_server_string);
126-
}
127-
} else {
128-
ngx_table_elt_t *h = r->headers_out.server;
129-
value.data = h->value.data;
130-
value.len = h->value.len;
131-
}
132-
133-
return msc_add_n_response_header(ctx->modsec_transaction,
134-
(const unsigned char *) name.data,
135-
name.len,
136-
(const unsigned char *) value.data,
137-
value.len);
138-
}
139-
140-
141-
static ngx_int_t
142-
ngx_http_modsecurity_resolv_header_date(ngx_http_request_t *r, ngx_str_t name, off_t offset)
143-
{
144-
ngx_http_modsecurity_ctx_t *ctx = NULL;
145-
ngx_str_t date;
146-
147-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
148-
149-
if (r->headers_out.date == NULL) {
150-
date.data = ngx_cached_http_time.data;
151-
date.len = ngx_cached_http_time.len;
152-
} else {
153-
ngx_table_elt_t *h = r->headers_out.date;
154-
date.data = h->value.data;
155-
date.len = h->value.len;
156-
}
157-
158-
return msc_add_n_response_header(ctx->modsec_transaction,
159-
(const unsigned char *) name.data,
160-
name.len,
161-
(const unsigned char *) date.data,
162-
date.len);
163-
}
164-
165-
166-
static ngx_int_t
167-
ngx_http_modsecurity_resolv_header_content_length(ngx_http_request_t *r, ngx_str_t name, off_t offset)
168-
{
169-
ngx_http_modsecurity_ctx_t *ctx = NULL;
170-
ngx_str_t value;
171-
char buf[NGX_INT64_LEN+2];
172-
173-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
174-
175-
if (r->headers_out.content_length_n > 0)
176-
{
177-
ngx_sprintf((u_char *)buf, "%O%Z", r->headers_out.content_length_n);
178-
value.data = (unsigned char *)buf;
179-
value.len = strlen(buf);
180-
181-
return msc_add_n_response_header(ctx->modsec_transaction,
182-
(const unsigned char *) name.data,
183-
name.len,
184-
(const unsigned char *) value.data,
185-
value.len);
186-
}
187-
188-
return 1;
189-
}
190-
191-
192-
static ngx_int_t
193-
ngx_http_modsecurity_resolv_header_content_type(ngx_http_request_t *r, ngx_str_t name, off_t offset)
194-
{
195-
ngx_http_modsecurity_ctx_t *ctx = NULL;
196-
197-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
198-
199-
if (r->headers_out.content_type.len > 0)
200-
{
201-
return msc_add_n_response_header(ctx->modsec_transaction,
202-
(const unsigned char *) name.data,
203-
name.len,
204-
(const unsigned char *) r->headers_out.content_type.data,
205-
r->headers_out.content_type.len);
206-
}
207-
208-
return 1;
209-
}
210-
211-
212-
static ngx_int_t
213-
ngx_http_modsecurity_resolv_header_last_modified(ngx_http_request_t *r, ngx_str_t name, off_t offset)
214-
{
215-
ngx_http_modsecurity_ctx_t *ctx = NULL;
216-
u_char buf[1024], *p;
217-
ngx_str_t value;
218-
219-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
220-
221-
if (r->headers_out.last_modified_time == -1) {
222-
return 1;
223-
}
224-
225-
p = ngx_http_time(buf, r->headers_out.last_modified_time);
226-
227-
value.data = buf;
228-
value.len = (int)(p-buf);
229-
230-
return msc_add_n_response_header(ctx->modsec_transaction,
231-
(const unsigned char *) name.data,
232-
name.len,
233-
(const unsigned char *) value.data,
234-
value.len);
235-
}
236-
237-
238-
static ngx_int_t
239-
ngx_http_modsecurity_resolv_header_connection(ngx_http_request_t *r, ngx_str_t name, off_t offset)
240-
{
241-
ngx_http_modsecurity_ctx_t *ctx = NULL;
242-
ngx_http_core_loc_conf_t *clcf = NULL;
243-
char *connection = NULL;
244-
ngx_str_t value;
245-
246-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
247-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
248-
249-
if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
250-
connection = "upgrade";
251-
} else if (r->keepalive) {
252-
connection = "keep-alive";
253-
if (clcf->keepalive_header)
254-
{
255-
u_char buf[1024];
256-
ngx_sprintf(buf, "timeout=%T%Z", clcf->keepalive_header);
257-
ngx_str_t name2 = ngx_string("Keep-Alive");
258-
259-
value.data = buf;
260-
value.len = strlen((char *)buf);
261-
262-
msc_add_n_response_header(ctx->modsec_transaction,
263-
(const unsigned char *) name2.data,
264-
name2.len,
265-
(const unsigned char *) value.data,
266-
value.len);
267-
}
268-
} else {
269-
connection = "close";
270-
}
271-
272-
value.data = (u_char *) connection;
273-
value.len = strlen(connection);
274-
275-
return msc_add_n_response_header(ctx->modsec_transaction,
276-
(const unsigned char *) name.data,
277-
name.len,
278-
(const unsigned char *) value.data,
279-
value.len);
280-
}
281-
282-
static ngx_int_t
283-
ngx_http_modsecurity_resolv_header_transfer_encoding(ngx_http_request_t *r, ngx_str_t name, off_t offset)
284-
{
285-
ngx_http_modsecurity_ctx_t *ctx = NULL;
286-
287-
if (r->chunked) {
288-
ngx_str_t value = ngx_string("chunked");
289-
290-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
291-
292-
return msc_add_n_response_header(ctx->modsec_transaction,
293-
(const unsigned char *) name.data,
294-
name.len,
295-
(const unsigned char *) value.data,
296-
value.len);
297-
}
298-
299-
return 1;
300-
}
301-
302-
static ngx_int_t
303-
ngx_http_modsecurity_resolv_header_vary(ngx_http_request_t *r, ngx_str_t name, off_t offset)
304-
{
305-
#if (NGX_HTTP_GZIP)
306-
ngx_http_modsecurity_ctx_t *ctx = NULL;
307-
ngx_http_core_loc_conf_t *clcf = NULL;
308-
309-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
310-
if (r->gzip_vary && clcf->gzip_vary) {
311-
ngx_str_t value = ngx_string("Accept-Encoding");
312-
313-
ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module);
314-
315-
return msc_add_n_response_header(ctx->modsec_transaction,
316-
(const unsigned char *) name.data,
317-
name.len,
318-
(const unsigned char *) value.data,
319-
value.len);
320-
}
321-
#endif
322-
323-
return 1;
324-
}
32529

32630
void
32731
ngx_http_modsecurity_header_filter_init(void)
@@ -334,14 +38,13 @@ ngx_http_modsecurity_header_filter_init(void)
33438
static ngx_int_t
33539
ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
33640
{
337-
ngx_http_modsecurity_ctx_t *ctx;
338-
ngx_list_part_t *part = &r->headers_out.headers.part;
339-
ngx_table_elt_t *data = part->elts;
340-
ngx_uint_t i = 0;
341-
int ret = 0;
342-
ngx_uint_t status;
343-
char *http_response_ver;
344-
ngx_pool_t *old_pool;
41+
int rc;
42+
char *http_response_ver;
43+
ngx_uint_t i, status;
44+
ngx_pool_t *old_pool;
45+
ngx_list_part_t *part;
46+
ngx_table_elt_t *data;
47+
ngx_http_modsecurity_ctx_t *ctx;
34548

34649

34750
/* XXX: if NOT_MODIFIED, do we need to process it at all? see xslt_header_filter() */
@@ -354,29 +57,9 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
35457
}
35558

35659
ctx->processed = 1;
357-
/*
358-
*
359-
* Assuming ModSecurity module is running immediately before the
360-
* ngx_http_header_filter, we will be able to populate ModSecurity with
361-
* headers from the headers_out structure.
362-
*
363-
* As ngx_http_header_filter place a direct call to the
364-
* ngx_http_write_filter_module, we cannot hook between those two. In order
365-
* to enumerate all headers, we first look at the headers_out structure,
366-
* and later we look into the ngx_list_part_t. The ngx_list_part_t must be
367-
* checked. Other module(s) in the chain may added some content to it.
368-
*
369-
*/
370-
for (i = 0; ngx_http_modsecurity_headers_out[i].name.len; i++)
371-
{
372-
dd(" Sending header to ModSecurity - header: `%.*s'.",
373-
(int) ngx_http_modsecurity_headers_out[i].name.len,
374-
ngx_http_modsecurity_headers_out[i].name.data);
37560

376-
ngx_http_modsecurity_headers_out[i].resolver(r,
377-
ngx_http_modsecurity_headers_out[i].name,
378-
ngx_http_modsecurity_headers_out[i].offset);
379-
}
61+
part = &r->headers_out.headers.part;
62+
data = part->elts;
38063

38164
for (i = 0 ;; i++)
38265
{
@@ -422,12 +105,12 @@ ngx_http_modsecurity_header_filter(ngx_http_request_t *r)
422105
old_pool = ngx_http_modsecurity_pcre_malloc_init(r->pool);
423106
msc_process_response_headers(ctx->modsec_transaction, status, http_response_ver);
424107
ngx_http_modsecurity_pcre_malloc_done(old_pool);
425-
ret = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
108+
rc = ngx_http_modsecurity_process_intervention(ctx->modsec_transaction, r, 0);
426109
if (r->error_page) {
427110
return ngx_http_next_header_filter(r);
428111
}
429-
if (ret > 0) {
430-
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity_module, ret);
112+
if (rc > 0) {
113+
return ngx_http_filter_finalize_request(r, &ngx_http_modsecurity_module, rc);
431114
}
432115

433116
return ngx_http_next_header_filter(r);

0 commit comments

Comments
 (0)