Imported Upstream version 2.5.11
[libapache-mod-security.git] / apache2 / t / regression / config / 10-request-directives.t
1 ### Tests for directives altering how a request is handled
2
3 # SecArgumentSeparator
4 {
5         type => "config",
6         comment => "SecArgumentSeparator (get-pos)",
7         conf => q(
8                 SecRuleEngine On
9                 SecArgumentSeparator ";"
10                 SecRule ARGS:a "@streq 1" "phase:1,deny,chain"
11                 SecRule ARGS:b "@streq 2"
12         ),
13         match_log => {
14                 error => [ qr/Access denied with code 403 \(phase 1\)\. String match "2" at ARGS:b\./, 1 ],
15         },
16         match_response => {
17                 status => qr/^403$/,
18         },
19         request => new HTTP::Request(
20                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt?a=1;b=2",
21         ),
22 },
23 {
24         type => "config",
25         comment => "SecArgumentSeparator (get-neg)",
26         conf => q(
27                 SecRuleEngine On
28                 SecRule ARGS:a "@streq 1" "phase:1,deny,chain"
29                 SecRule ARGS:b "@streq 2"
30         ),
31         match_log => {
32                 -error => [ qr/Access denied/, 1 ],
33         },
34         match_response => {
35                 status => qr/^200$/,
36         },
37         request => new HTTP::Request(
38                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt?a=1;b=2",
39         ),
40 },
41 {
42         type => "config",
43         comment => "SecArgumentSeparator (post-pos)",
44         conf => q(
45                 SecRuleEngine On
46                 SecRequestBodyAccess On
47                 SecArgumentSeparator ";"
48                 SecRule ARGS:a "@streq 1" "phase:2,deny,chain"
49                 SecRule ARGS:b "@streq 2"
50         ),
51         match_log => {
52                 error => [ qr/Access denied with code 403 \(phase 2\)\. String match "2" at ARGS:b\./, 1 ],
53         },
54         match_response => {
55                 status => qr/^403$/,
56         },
57         request => new HTTP::Request(
58                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
59                 [
60                         "Content-Type" => "application/x-www-form-urlencoded",
61                 ],
62                 "a=1;b=2",
63         ),
64 },
65 {
66         type => "config",
67         comment => "SecArgumentSeparator (post-neg)",
68         conf => q(
69                 SecRuleEngine On
70                 SecRequestBodyAccess On
71                 SecRule ARGS:a "@streq 1" "phase:2,deny"
72                 SecRule ARGS:b "@streq 2" "phase:2,deny"
73         ),
74         match_log => {
75                 -error => [ qr/Access denied/, 1 ],
76         },
77         match_response => {
78                 status => qr/^200$/,
79         },
80         request => new HTTP::Request(
81                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
82                 [
83                         "Content-Type" => "application/x-www-form-urlencoded",
84                 ],
85                 "a=1;b=2",
86         ),
87 },
88
89 # SecRequestBodyAccess
90 {
91         type => "config",
92         comment => "SecRequestBodyAccess (pos)",
93         conf => qq(
94                 SecRuleEngine On
95                 SecRequestBodyAccess On
96                 SecRule ARGS:a "\@streq 1" "phase:2,deny,chain"
97                 SecRule ARGS:b "\@streq 2"
98         ),
99         match_log => {
100                 error => [ qr/Access denied with code 403 \(phase 2\)\. String match "2" at ARGS:b\./, 1 ],
101         },
102         match_response => {
103                 status => qr/^403$/,
104         },
105         request => new HTTP::Request(
106                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
107                 [
108                         "Content-Type" => "application/x-www-form-urlencoded",
109                 ],
110                 "a=1&b=2",
111         ),
112 },
113 {
114         type => "config",
115         comment => "SecRequestBodyAccess (neg)",
116         conf => qq(
117                 SecRuleEngine On
118                 SecRequestBodyAccess Off
119                 SecRule ARGS:a "\@streq 1" "phase:2,deny"
120                 SecRule ARGS:b "\@streq 2" "phase:2,deny"
121         ),
122         match_log => {
123                 -error => [ qr/Access denied/, 1 ],
124         },
125         match_response => {
126                 status => qr/^200$/,
127         },
128         request => new HTTP::Request(
129                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
130                 [
131                         "Content-Type" => "application/x-www-form-urlencoded",
132                 ],
133                 "a=1&b=2",
134         ),
135 },
136
137 # SecRequestBodyLimit
138 {
139         type => "config",
140         comment => "SecRequestBodyLimit (equal)",
141         conf => qq(
142                 SecRuleEngine On
143                 SecRequestBodyAccess On
144                 SecRequestBodyLimit 7
145         ),
146         match_log => {
147                 -error => [ qr/Request body is larger than the configured limit/, 1 ],
148         },
149         match_response => {
150                 status => qr/^200$/,
151         },
152         request => new HTTP::Request(
153                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
154                 [
155                         "Content-Type" => "application/x-www-form-urlencoded",
156                 ],
157                 "a=1&b=2",
158         ),
159 },
160 {
161         type => "config",
162         comment => "SecRequestBodyLimit (greater)",
163         conf => qq(
164                 SecRuleEngine On
165                 SecRequestBodyAccess On
166                 SecRequestBodyLimit 5
167         ),
168         match_log => {
169                 error => [ qr/Request body .*is larger than the configured limit \(5\)\./, 1 ],
170         },
171         match_response => {
172                 status => qr/^413$/,
173         },
174         request => new HTTP::Request(
175                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
176                 [
177                         "Content-Type" => "application/x-www-form-urlencoded",
178                 ],
179                 "a=1&b=2",
180         ),
181 },
182 {
183         type => "config",
184         comment => "SecRequestBodyLimit (equal - chunked)",
185         conf => qq(
186                 SecRuleEngine On
187                 SecRequestBodyAccess On
188                 SecRequestBodyLimit 276
189         ),
190         match_log => {
191                 -error => [ qr/Request body is larger than the configured limit/, 1 ],
192         },
193         match_response => {
194                 status => qr/^200$/,
195         },
196         request => normalize_raw_request_data(
197                 qq(
198                         POST /test.txt HTTP/1.1
199                         Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
200                         User-Agent: $ENV{USER_AGENT}
201                         Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
202                         Transfer-Encoding: chunked
203
204                 ),
205         )
206         .encode_chunked(
207                 normalize_raw_request_data(
208                         q(
209                                 -----------------------------69343412719991675451336310646
210                                 Content-Disposition: form-data; name="a"
211
212                                 1
213                                 -----------------------------69343412719991675451336310646
214                                 Content-Disposition: form-data; name="b"
215
216                                 2
217                                 -----------------------------69343412719991675451336310646--
218                         )
219                 ),
220                 1024
221         ),
222 },
223 {
224         type => "config",
225         comment => "SecRequestBodyLimit (greater - chunked)",
226         conf => qq(
227                 SecRuleEngine On
228                 SecRequestBodyAccess On
229                 SecRequestBodyLimit 256
230         ),
231         match_log => {
232                 error => [ qr/Request body .*is larger than the configured limit \(256\)\./, 1 ],
233         },
234         match_response => {
235                 status => qr/^413$/,
236         },
237         request => normalize_raw_request_data(
238                 qq(
239                         POST /test.txt HTTP/1.1
240                         Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
241                         User-Agent: $ENV{USER_AGENT}
242                         Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
243                         Transfer-Encoding: chunked
244
245                 ),
246         )
247         .encode_chunked(
248                 normalize_raw_request_data(
249                         q(
250                                 -----------------------------69343412719991675451336310646
251                                 Content-Disposition: form-data; name="a"
252
253                                 1
254                                 -----------------------------69343412719991675451336310646
255                                 Content-Disposition: form-data; name="b"
256
257                                 2
258                                 -----------------------------69343412719991675451336310646--
259                         )
260                 ),
261                 1024
262         ),
263 },
264 {
265         type => "config",
266         comment => "SecRequestBodyLimit (ctl:ruleEngine=off)",
267         conf => qq(
268                 SecRuleEngine On
269                 SecRequestBodyAccess On
270                 SecRequestBodyLimit 5
271
272                 SecAction "phase:1,pass,nolog,ctl:ruleEngine=off"
273                 SecRule REQUEST_BODY "." "phase:2,deny"
274         ),
275         match_log => {
276                 -error => [ qr/Request body .*is larger than the configured limit/, 1 ],
277         },
278         match_response => {
279                 status => qr/^200$/,
280         },
281         request => new HTTP::Request(
282                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
283                 [
284                         "Content-Type" => "application/x-www-form-urlencoded",
285                 ],
286                 "a=1&b=2",
287         ),
288 },
289 {
290         type => "config",
291         comment => "SecRequestBodyLimit (ctl:requestBodyAccess=off)",
292         conf => qq(
293                 SecRuleEngine On
294                 SecRequestBodyAccess On
295                 SecRequestBodyLimit 5
296
297                 SecAction "phase:1,pass,nolog,ctl:requestBodyAccess=off"
298                 SecRule REQUEST_BODY "." "phase:2,deny"
299         ),
300         match_log => {
301                 -error => [ qr/Request body .*is larger than the configured limit/, 1 ],
302         },
303         match_response => {
304                 status => qr/^200$/,
305         },
306         request => new HTTP::Request(
307                 POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
308                 [
309                         "Content-Type" => "application/x-www-form-urlencoded",
310                 ],
311                 "a=1&b=2",
312         ),
313 },
314 {
315         type => "config",
316         comment => "SecRequestBodyLimit (ctl:ruleEngine=off - chunked)",
317         conf => qq(
318                 SecRuleEngine On
319                 SecRequestBodyAccess On
320                 SecRequestBodyLimit 256
321
322                 SecAction "phase:1,pass,nolog,ctl:ruleEngine=off"
323                 SecRule REQUEST_BODY "." "phase:2,deny"
324         ),
325         match_log => {
326                 -error => [ qr/Request body .*is larger than the configured limit/, 1 ],
327         },
328         match_response => {
329                 status => qr/^200$/,
330         },
331         request => normalize_raw_request_data(
332                 qq(
333                         POST /test.txt HTTP/1.1
334                         Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
335                         User-Agent: $ENV{USER_AGENT}
336                         Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
337                         Transfer-Encoding: chunked
338
339                 ),
340         )
341         .encode_chunked(
342                 normalize_raw_request_data(
343                         q(
344                                 -----------------------------69343412719991675451336310646
345                                 Content-Disposition: form-data; name="a"
346
347                                 1
348                                 -----------------------------69343412719991675451336310646
349                                 Content-Disposition: form-data; name="b"
350
351                                 2
352                                 -----------------------------69343412719991675451336310646--
353                         )
354                 ),
355                 1024
356         ),
357 },
358 {
359         type => "config",
360         comment => "SecRequestBodyLimit (ctl:requestBodyAccess=off - chunked)",
361         conf => qq(
362                 SecRuleEngine On
363                 SecRequestBodyAccess On
364                 SecRequestBodyLimit 256
365
366                 SecAction "phase:1,pass,nolog,ctl:requestBodyAccess=off"
367                 SecRule REQUEST_BODY "." "phase:2,deny"
368         ),
369         match_log => {
370                 -error => [ qr/Request body .*is larger than the configured limit \(256\)\./, 1 ],
371         },
372         match_response => {
373                 status => qr/^200$/,
374         },
375         request => normalize_raw_request_data(
376                 qq(
377                         POST /test.txt HTTP/1.1
378                         Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
379                         User-Agent: $ENV{USER_AGENT}
380                         Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
381                         Transfer-Encoding: chunked
382
383                 ),
384         )
385         .encode_chunked(
386                 normalize_raw_request_data(
387                         q(
388                                 -----------------------------69343412719991675451336310646
389                                 Content-Disposition: form-data; name="a"
390
391                                 1
392                                 -----------------------------69343412719991675451336310646
393                                 Content-Disposition: form-data; name="b"
394
395                                 2
396                                 -----------------------------69343412719991675451336310646--
397                         )
398                 ),
399                 1024
400         ),
401 },
402
403 # SecRequestBodyInMemoryLimit
404 {
405         type => "config",
406         comment => "SecRequestBodyInMemoryLimit (equal)",
407         conf => qq(
408                 SecRuleEngine On
409                 SecDebugLog $ENV{DEBUG_LOG}
410                 SecDebugLogLevel 9
411                 SecRequestBodyAccess On
412                 SecRequestBodyLimit 1000
413                 SecRequestBodyInMemoryLimit 276
414         ),
415         match_log => {
416                 -debug => [ qr/Input filter: Request too large to store in memory, switching to disk\./, 1 ],
417         },
418         match_response => {
419                 status => qr/^200$/,
420         },
421         request => normalize_raw_request_data(
422                 qq(
423                         POST /test.txt HTTP/1.1
424                         Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
425                         User-Agent: $ENV{USER_AGENT}
426                         Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
427                         Transfer-Encoding: chunked
428
429                 ),
430         )
431         .encode_chunked(
432                 normalize_raw_request_data(
433                         q(
434                                 -----------------------------69343412719991675451336310646
435                                 Content-Disposition: form-data; name="a"
436
437                                 1
438                                 -----------------------------69343412719991675451336310646
439                                 Content-Disposition: form-data; name="b"
440
441                                 2
442                                 -----------------------------69343412719991675451336310646--
443                         )
444                 ),
445                 1024
446         ),
447 },
448 {
449         type => "config",
450         comment => "SecRequestBodyInMemoryLimit (greater)",
451         conf => qq(
452                 SecRuleEngine On
453                 SecDebugLog $ENV{DEBUG_LOG}
454                 SecDebugLogLevel 9
455                 SecRequestBodyAccess On
456                 SecRequestBodyLimit 1000
457                 SecRequestBodyInMemoryLimit 16
458         ),
459         match_log => {
460                 debug => [ qr/Input filter: Request too large to store in memory, switching to disk\./, 1 ],
461         },
462         match_response => {
463                 status => qr/^200$/,
464         },
465         request => normalize_raw_request_data(
466                 qq(
467                         POST /test.txt HTTP/1.1
468                         Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
469                         User-Agent: $ENV{USER_AGENT}
470                         Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
471                         Transfer-Encoding: chunked
472
473                 ),
474         )
475         .encode_chunked(
476                 normalize_raw_request_data(
477                         q(
478                                 -----------------------------69343412719991675451336310646
479                                 Content-Disposition: form-data; name="a"
480
481                                 1
482                                 -----------------------------69343412719991675451336310646
483                                 Content-Disposition: form-data; name="b"
484
485                                 2
486                                 -----------------------------69343412719991675451336310646--
487                         )
488                 ),
489                 1024
490         ),
491 },
492
493 # SecCookieFormat
494 {
495         type => "config",
496         comment => "SecCookieFormat (pos)",
497         conf => qq(
498                 SecRuleEngine On
499                 SecDebugLog $ENV{DEBUG_LOG}
500                 SecDebugLogLevel 5
501                 SecCookieFormat 1
502                 SecRule REQUEST_COOKIES_NAMES "\@streq SESSIONID" "phase:1,deny,chain"
503                 SecRule REQUEST_COOKIES:\$SESSIONID_PATH "\@streq /" "chain"
504                 SecRule REQUEST_COOKIES:SESSIONID "\@streq cookieval"
505         ),
506         match_log => {
507                 error => [ qr/Access denied with code 403 \(phase 1\)\. String match "cookieval" at REQUEST_COOKIES:SESSIONID\./, 1 ],
508                 debug => [ qr(Adding request cookie: name "\$SESSIONID_PATH", value "/"), 1 ],
509         },
510         match_response => {
511                 status => qr/^403$/,
512         },
513         request => new HTTP::Request(
514                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
515                 [
516                         "Cookie" => q($Version="1"; SESSIONID="cookieval"; $PATH="/"),
517                 ],
518                 undef,
519         ),
520 },
521 {
522         type => "config",
523         comment => "SecCookieFormat (neg)",
524         conf => qq(
525                 SecRuleEngine On
526                 SecDebugLog $ENV{DEBUG_LOG}
527                 SecDebugLogLevel 5
528                 SecCookieFormat 0
529                 SecRule REQUEST_COOKIES_NAMES "\@streq SESSIONID" "phase:1,deny,chain"
530                 SecRule REQUEST_COOKIES:\$SESSIONID_PATH "\@streq /" "chain"
531                 SecRule REQUEST_COOKIES:SESSIONID "\@streq cookieval"
532         ),
533         match_log => {
534                 -error => [ qr/Access denied/, 1 ],
535                 -debug => [ qr(Adding request cookie: name "\$SESSIONID_PATH", value "/"), 1 ],
536         },
537         match_response => {
538                 status => qr/^200$/,
539         },
540         request => new HTTP::Request(
541                 GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
542                 [
543                         "Cookie" => q($Version="1"; SESSIONID="cookieval"; $PATH="/"),
544                 ],
545                 undef,
546         ),
547 },
548