Skip to content

Commit 15c3390

Browse files
defanatorFelipe Zimmerle
authored and
Felipe Zimmerle
committed
Tests: added request body tests for HTTP/2
Note that auth_request related bits are marked as TODO.
1 parent 395305a commit 15c3390

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed

tests/modsecurity-request-body-h2.t

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Andrei Belov
4+
5+
# Tests for ModSecurity-nginx connector (request body operations, HTTP/2).
6+
7+
###############################################################################
8+
9+
use warnings;
10+
use strict;
11+
12+
use Test::More;
13+
use Socket qw/ CRLF /;
14+
15+
BEGIN { use FindBin; chdir($FindBin::Bin); }
16+
17+
use lib 'lib';
18+
use Test::Nginx;
19+
use Test::Nginx::HTTP2;
20+
21+
###############################################################################
22+
23+
select STDERR; $| = 1;
24+
select STDOUT; $| = 1;
25+
26+
my $t = Test::Nginx->new()->has(qw/http http_v2 proxy auth_request/);
27+
28+
$t->write_file_expand('nginx.conf', <<'EOF');
29+
30+
%%TEST_GLOBALS%%
31+
32+
daemon off;
33+
34+
events {
35+
}
36+
37+
http {
38+
%%TEST_GLOBALS_HTTP%%
39+
40+
server {
41+
listen 127.0.0.1:8081;
42+
location / {
43+
return 200 "TEST-OK-IF-YOU-SEE-THIS";
44+
}
45+
}
46+
47+
server {
48+
listen 127.0.0.1:8080 http2;
49+
server_name localhost;
50+
51+
modsecurity on;
52+
client_header_buffer_size 1024;
53+
54+
location /bodyaccess {
55+
modsecurity_rules '
56+
SecRuleEngine On
57+
SecRequestBodyAccess On
58+
SecRule REQUEST_BODY "@rx BAD BODY" "id:11,phase:request,deny,log,status:403"
59+
';
60+
proxy_pass http://127.0.0.1:8081;
61+
}
62+
63+
location /nobodyaccess {
64+
modsecurity_rules '
65+
SecRuleEngine On
66+
SecRequestBodyAccess Off
67+
SecRule REQUEST_BODY "@rx BAD BODY" "id:21,phase:request,deny,log,status:403"
68+
SecRule ARGS_POST|ARGS_POST_NAMES "@rx BAD ARG" "id:22,phase:request,deny,log,status:403"
69+
';
70+
proxy_pass http://127.0.0.1:8081;
71+
}
72+
73+
location /bodylimitreject {
74+
modsecurity_rules '
75+
SecRuleEngine On
76+
SecRequestBodyAccess On
77+
SecRequestBodyLimit 128
78+
SecRequestBodyLimitAction Reject
79+
SecRule REQUEST_BODY "@rx BAD BODY" "id:31,phase:request,deny,log,status:403"
80+
';
81+
proxy_pass http://127.0.0.1:8081;
82+
}
83+
84+
location /bodylimitprocesspartial {
85+
modsecurity_rules '
86+
SecRuleEngine On
87+
SecRequestBodyAccess On
88+
SecRequestBodyLimit 128
89+
SecRequestBodyLimitAction ProcessPartial
90+
SecRule REQUEST_BODY "@rx BAD BODY" "id:41,phase:request,deny,log,status:403"
91+
';
92+
proxy_pass http://127.0.0.1:8081;
93+
}
94+
95+
location = /auth {
96+
return 200;
97+
}
98+
99+
location = /useauth {
100+
modsecurity on;
101+
modsecurity_rules '
102+
SecRuleEngine On
103+
SecRequestBodyAccess On
104+
';
105+
auth_request /auth;
106+
proxy_pass http://127.0.0.1:8081;
107+
}
108+
}
109+
}
110+
EOF
111+
112+
$t->run();
113+
114+
$t->plan(36);
115+
116+
###############################################################################
117+
118+
my ($s, $sid, $frames, $frame);
119+
120+
foreach my $method (('GET', 'POST', 'PUT', 'DELETE')) {
121+
122+
$s = Test::Nginx::HTTP2->new();
123+
$sid = $s->new_stream({ method => $method, path => '/bodyaccess', 'body_more' => 1 });
124+
$s->h2_body('GOOD BODY');
125+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
126+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
127+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body access on, pass");
128+
129+
$s = Test::Nginx::HTTP2->new();
130+
$sid = $s->new_stream({ method => $method, path => '/bodyaccess', 'body_more' => 1 });
131+
$s->h2_body('VERY BAD BODY');
132+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
133+
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
134+
is($frame->{headers}->{':status'}, 403, "${method} request body access on, block");
135+
136+
$s = Test::Nginx::HTTP2->new();
137+
$sid = $s->new_stream({ method => $method, path => '/nobodyaccess', 'body_more' => 1 });
138+
$s->h2_body('VERY BAD BODY');
139+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
140+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
141+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body access off, pass");
142+
143+
$s = Test::Nginx::HTTP2->new();
144+
$sid = $s->new_stream({ 'body_more' => 1,
145+
headers => [
146+
{name => ':method', value => "${method}" },
147+
{name => ':scheme', value => 'http' },
148+
{name => ':path', value => '/nobodyaccess' },
149+
{name => 'host', value => 'localhost' },
150+
{name => 'content-type', value => 'application/x-www-form-urlencoded' }
151+
] });
152+
$s->h2_body('test=VERY BAD BODY');
153+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
154+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
155+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body access off (ARGS_POST), pass");
156+
157+
$s = Test::Nginx::HTTP2->new();
158+
$sid = $s->new_stream({ method => $method, path => '/bodylimitreject', 'body_more' => 1 });
159+
$s->h2_body('BODY' x 32);
160+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
161+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
162+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body limit reject, pass");
163+
164+
$s = Test::Nginx::HTTP2->new();
165+
$sid = $s->new_stream({ method => $method, path => '/bodylimitreject', 'body_more' => 1 });
166+
$s->h2_body('BODY' x 33);
167+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
168+
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
169+
is($frame->{headers}->{':status'}, 403, "${method} request body limit reject, block");
170+
171+
$s = Test::Nginx::HTTP2->new();
172+
$sid = $s->new_stream({ method => $method, path => '/bodylimitprocesspartial', 'body_more' => 1 });
173+
$s->h2_body('BODY' x 32 . 'BAD BODY');
174+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
175+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
176+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body limit process partial, pass");
177+
178+
$s = Test::Nginx::HTTP2->new();
179+
$sid = $s->new_stream({ method => $method, path => '/bodylimitprocesspartial', 'body_more' => 1 });
180+
$s->h2_body('BODY' x 30 . 'BAD BODY' x 32);
181+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
182+
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
183+
is($frame->{headers}->{':status'}, 403, "${method} request body limit process partial, block");
184+
185+
}
186+
187+
TODO: {
188+
local $TODO = 'not yet';
189+
190+
$s = Test::Nginx::HTTP2->new();
191+
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body' => 'BODY' x 16 });
192+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
193+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
194+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size < client_header_buffer_size)");
195+
196+
$s = Test::Nginx::HTTP2->new();
197+
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body' => 'BODY' x 257 });
198+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
199+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
200+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size > client_header_buffer_size)");
201+
202+
$s = Test::Nginx::HTTP2->new();
203+
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body_more' => 1 });
204+
$s->h2_body('BODY' x 15);
205+
select undef, undef, undef, 0.1;
206+
$s->h2_body('BODY');
207+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
208+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
209+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size < client_header_buffer_size), no preread");
210+
211+
$s = Test::Nginx::HTTP2->new();
212+
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body_more' => 1 });
213+
$s->h2_body('BODY' x 256);
214+
select undef, undef, undef, 0.1;
215+
$s->h2_body('BODY');
216+
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
217+
($frame) = grep { $_->{type} eq "DATA" } @$frames;
218+
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size > client_header_buffer_size), no preread");
219+
220+
}
221+
222+
###############################################################################

0 commit comments

Comments
 (0)