Skip to content

Commit 1ff2259

Browse files
committed
Try to address the response headers in the right place
This is the very first attempt to address the response headers in the right place.
1 parent ee7cd5e commit 1ff2259

6 files changed

+451
-3
lines changed

config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ if test -n "$ngx_module_link"; then
9292
ngx_module_libs="$ngx_feature_libs"
9393
ngx_module_incs="$ngx_feature_path"
9494

95+
ngx_module_order="$ngx_module_name ngx_http_chunked_filter_module"
96+
9597
. auto/module
9698
else
9799
CFLAGS="$ngx_modsecurity_opt_I $CFLAGS"

src/ddebug.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@
1717

1818

1919
#define DDEBUG 0
20+
/*
21+
* Setting MODSECURITY_SANITY_CHECKS will help you in the debug process. By
22+
* defining MODSECURITY_SANITY_CHECKS a set of functions will be executed in
23+
* order to make sure the well behavior of ModSecurity, letting you know (via
24+
* debug_logs) if something unexpected happens.
25+
*
26+
* If performance is not a concern, it is safe to keep it set.
27+
*
28+
*/
29+
#define MODSECURITY_SANITY_CHECKS 1
2030

2131
#if defined(DDEBUG) && (DDEBUG)
2232

src/ngx_http_modsecurity_body_filter.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ ngx_int_t ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *i
4141
int buffer_fully_loadead = 0;
4242
ngx_chain_t *chain = in;
4343
ngx_http_modsecurity_ctx_t *ctx = NULL;
44+
ngx_list_part_t *part = &r->headers_out.headers.part;
45+
ngx_table_elt_t *data = part->elts;
46+
ngx_uint_t i = 0;
4447

4548
if (in == NULL) {
4649
return ngx_http_next_body_filter(r, in);
@@ -54,6 +57,63 @@ ngx_int_t ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *i
5457
return ngx_http_next_body_filter(r, in);
5558
}
5659

60+
#ifdef MODSECURITY_SANITY_CHECKS
61+
/*
62+
* Identify if there is a header that was not inspected by ModSecurity.
63+
*
64+
*/
65+
for (i = 0; ; i++) {
66+
int found = 0;
67+
ngx_uint_t j = 0;
68+
ngx_table_elt_t *s1;
69+
ngx_http_modsecurity_header_t *vals;
70+
71+
if (i >= part->nelts)
72+
{
73+
if (part->next == NULL)
74+
{
75+
break;
76+
}
77+
78+
part = part->next;
79+
data = part->elts;
80+
i = 0;
81+
}
82+
83+
vals = ctx->headers_out->elts;
84+
s1 = &data[i];
85+
/*
86+
* Headers that were inspected by ModSecurity.
87+
*
88+
*/
89+
while (j < ctx->headers_out->nelts)
90+
{
91+
ngx_str_t *s2 = &vals[j].name;
92+
ngx_str_t *s3 = &vals[j].value;
93+
94+
if (s1->key.len == s2->len && ngx_strncmp(s1->key.data, s2->data, s1->key.len) == 0)
95+
{
96+
if (s1->value.len == s3->len && ngx_strncmp(s1->value.data, s3->data, s1->value.len) == 0)
97+
{
98+
found = 1;
99+
break;
100+
}
101+
}
102+
j++;
103+
}
104+
if (!found) {
105+
dd("header: `%.*s' with value: `%.*s' was not inpected by ModSecurity",
106+
(int) s1->key.len,
107+
(const char *) s1->key.data,
108+
(int) s1->value.len,
109+
(const char *) s1->value.data);
110+
111+
return ngx_http_filter_finalize_request(r,
112+
&ngx_http_modsecurity, NGX_HTTP_INTERNAL_SERVER_ERROR);
113+
}
114+
}
115+
#endif
116+
57117
for (; chain != NULL; chain = chain->next)
58118
{
59119
if (chain->buf->last_buf)

src/ngx_http_modsecurity_common.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,29 @@
2525
#include <modsecurity/transaction.h>
2626
#include <modsecurity/rules.h>
2727

28+
typedef struct {
29+
ngx_str_t name;
30+
ngx_str_t value;
31+
} ngx_http_modsecurity_header_t;
32+
33+
2834
typedef struct {
2935
ngx_http_request_t *r;
3036
Transaction *modsec_transaction;
3137
ModSecurityIntervention *delayed_intervention;
3238

39+
#ifdef MODSECURITY_SANITY_CHECKS
40+
/*
41+
* Should be filled with the headers that were sent to ModSecurity.
42+
*
43+
* The idea is to compare this set of headers with the headers that were
44+
* sent to the client. This check was placed because we don't have control
45+
* over other modules, thus, we may partially inspect the headers.
46+
*
47+
*/
48+
ngx_array_t *headers_out;
49+
#endif
50+
3351
unsigned waiting_more_body:1;
3452
unsigned body_requested:1;
3553
unsigned processed:1;
@@ -55,6 +73,16 @@ typedef struct {
5573
} ngx_http_modsecurity_main_conf_t;
5674

5775

76+
typedef ngx_int_t (*ngx_http_modsecurity_resolv_header_pt)(ngx_http_request_t *r, ngx_str_t name, off_t offset);
77+
78+
79+
typedef struct {
80+
ngx_str_t name;
81+
ngx_uint_t offset;
82+
ngx_http_modsecurity_resolv_header_pt resolver;
83+
} ngx_http_modsecurity_header_out_t;
84+
85+
5886
extern ngx_module_t ngx_http_modsecurity;
5987
extern ngx_http_output_header_filter_pt ngx_http_modsecurity_next_header_filter;
6088
extern ngx_http_output_body_filter_pt ngx_http_modsecurity_next_body_filter;
@@ -64,5 +92,7 @@ extern int ngx_http_modsecurity_process_intervention (Transaction *transaction,
6492
extern ngx_http_modsecurity_ctx_t *ngx_http_modsecurity_create_ctx(ngx_http_request_t *r);
6593
extern char *ngx_str_to_char(ngx_str_t a, ngx_pool_t *p);
6694

95+
typedef ngx_str_t (*ngx_http_modsecurity_get_header_pt)(ngx_http_request_t *r, void *value);
96+
6797

6898
#endif

0 commit comments

Comments
 (0)