mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Remove unused test files and scripts from ModSecurity Nginx integration
This commit is contained in:
parent
3a7a25b568
commit
ba242318bd
16 changed files with 0 additions and 2603 deletions
10
src/deps/src/modsecurity-nginx/tests/README.md
vendored
10
src/deps/src/modsecurity-nginx/tests/README.md
vendored
|
|
@ -1,10 +0,0 @@
|
|||
# Tests
|
||||
|
||||
Those are nginx test files. You can copy those files into yours nginx test
|
||||
tree, to perform the tests using the "prove" utility.
|
||||
|
||||
For more information about those tests, read the subsection "Testing your
|
||||
patch" on the project's README file.
|
||||
|
||||
For more about nginx tests, check their repository:
|
||||
http://hg.nginx.org/nginx-tests/
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# ModSecurity, http://www.modsecurity.org/
|
||||
# Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
#
|
||||
# You may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# If any of the files related to licensing are missing or if you have any
|
||||
# other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
# directly using the email address security@modsecurity.org.
|
||||
#
|
||||
|
||||
|
||||
# Tests for ModSecurity module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq whee" "id:10,phase:2"
|
||||
SecRule ARGS "@streq whee" "id:11,phase:2"
|
||||
';
|
||||
|
||||
location / {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq root" "id:21,phase:1,auditlog,status:302,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-root.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLogParts AB
|
||||
SecAuditLog %%TESTDIR%%/auditlog-root.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
}
|
||||
|
||||
location /subfolder1/subfolder2 {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq subfolder2" "id:41,phase:1,status:302,auditlog,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq subfolder1" "id:42,phase:1,status:302,auditlog,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-subfolder2.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLogParts AB
|
||||
SecResponseBodyAccess On
|
||||
SecAuditLog %%TESTDIR%%/auditlog-subfolder2.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
}
|
||||
|
||||
location /subfolder1 {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq subfolder1" "id:31,phase:1,status:302,auditlog,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-subfolder1.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditLogParts AB
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLog %%TESTDIR%%/auditlog-subfolder1.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
}
|
||||
|
||||
location /subfolder3/subfolder4 {
|
||||
modsecurity_rules '
|
||||
SecResponseBodyAccess On
|
||||
SecRule ARGS "@streq subfolder4" "id:61,phase:1,status:302,auditlog,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq subfolder3" "id:62,phase:1,status:302,auditlog,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq subfolder4withE" "id:63,phase:1,ctl:auditLogParts=+E,auditlog"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-subfolder4.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLogParts AB
|
||||
SecAuditLog %%TESTDIR%%/auditlog-subfolder4.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
}
|
||||
|
||||
location /subfolder3 {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq subfolder3" "id:51,phase:1,status:302,auditlog,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-subfolder3.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditLogParts AB
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLog %%TESTDIR%%/auditlog-subfolder3.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder1');
|
||||
$t->write_file("/subfolder1/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder1/subfolder2');
|
||||
$t->write_file("/subfolder1/subfolder2/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder3');
|
||||
$t->write_file("/subfolder3/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder3/subfolder4');
|
||||
$t->write_file("/subfolder3/subfolder4/index.html", "should be moved/blocked before this.");
|
||||
|
||||
$t->run();
|
||||
$t->plan(9);
|
||||
|
||||
###############################################################################
|
||||
|
||||
my $d = $t->testdir();
|
||||
|
||||
my $r;
|
||||
# Performing requests at root
|
||||
$r = http_get('/index.html?what=root');
|
||||
$r = http_get('/index.html?what=subfolder1');
|
||||
$r = http_get('/index.html?what=subfolder2');
|
||||
$r = http_get('/index.html?what=subfolder3');
|
||||
$r = http_get('/index.html?what=subfolder4');
|
||||
|
||||
# Performing requests at subfolder1
|
||||
$r = http_get('/subfolder1/index.html?what=root');
|
||||
$r = http_get('/subfolder1/index.html?what=subfolder1');
|
||||
$r = http_get('/subfolder1/index.html?what=subfolder2');
|
||||
$r = http_get('/subfolder1/index.html?what=subfolder3');
|
||||
$r = http_get('/subfolder1/index.html?what=subfolder4');
|
||||
|
||||
# Performing requests at subfolder2
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=root');
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=subfolder1');
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=subfolder2');
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=subfolder3');
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=subfolder4');
|
||||
|
||||
# Performing requests at subfolder3
|
||||
$r = http_get('/subfolder3/index.html?what=root');
|
||||
$r = http_get('/subfolder3/index.html?what=subfolder1');
|
||||
$r = http_get('/subfolder3/index.html?what=subfolder2');
|
||||
$r = http_get('/subfolder3/index.html?what=subfolder3');
|
||||
$r = http_get('/subfolder3/index.html?what=subfolder4');
|
||||
|
||||
# Performing requests at subfolder4
|
||||
$r = http_get('/subfolder3/subfolder4/index.html?what=root');
|
||||
$r = http_get('/subfolder3/subfolder4/index.html?what=subfolder1');
|
||||
$r = http_get('/subfolder3/subfolder4/index.html?what=subfolder2');
|
||||
$r = http_get('/subfolder3/subfolder4/index.html?what=subfolder3');
|
||||
$r = http_get('/subfolder3/subfolder4/index.html?what=subfolder4');
|
||||
$r = http_get('/subfolder3/subfolder4/index.html?what=subfolder4withE');
|
||||
|
||||
my $root = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-root.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
my $subfolder1 = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-subfolder1.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
my $subfolder2 = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-subfolder2.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
my $subfolder3 = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-subfolder3.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
my $subfolder4 = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-subfolder4.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
|
||||
|
||||
like($root, qr/what=root/, 'root');
|
||||
like($subfolder1, qr/what=subfolder1/, 'subfolder1');
|
||||
like($subfolder2, qr/what=subfolder2/, 'subfolder2');
|
||||
like($subfolder2, qr/what=subfolder1/, 'subfolder2 / subfolder1');
|
||||
|
||||
like($subfolder3, qr/what=subfolder3/, 'subfolder3');
|
||||
like($subfolder4, qr/what=subfolder4/, 'subfolder4');
|
||||
like($subfolder4, qr/what=subfolder3/, 'subfolder4 / subfolder3');
|
||||
|
||||
like($subfolder4, qr/what=subfolder4withE/, 'subfolder4');
|
||||
like($subfolder4, qr/---E--/, 'subfolder4');
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# ModSecurity, http://www.modsecurity.org/
|
||||
# Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
#
|
||||
# You may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# If any of the files related to licensing are missing or if you have any
|
||||
# other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
# directly using the email address security@modsecurity.org.
|
||||
#
|
||||
|
||||
|
||||
# Tests for ModSecurity module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name s1;
|
||||
|
||||
error_page 403 /403.html;
|
||||
|
||||
location /403.html {
|
||||
root %%TESTDIR%%/http;
|
||||
internal;
|
||||
}
|
||||
|
||||
location / {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq root" "id:10,phase:1,auditlog,status:403,deny"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-local.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLogParts ABIJDEFHZ
|
||||
SecAuditLog %%TESTDIR%%/auditlog-local.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name s2;
|
||||
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq root" "id:10,phase:1,auditlog,status:403,deny"
|
||||
SecDebugLog %%TESTDIR%%/auditlog-debug-global.txt
|
||||
SecDebugLogLevel 9
|
||||
SecAuditEngine RelevantOnly
|
||||
SecAuditLogParts ABIJDEFHZ
|
||||
SecAuditLog %%TESTDIR%%/auditlog-global.txt
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
';
|
||||
|
||||
error_page 403 /403.html;
|
||||
|
||||
location /403.html {
|
||||
modsecurity off;
|
||||
root %%TESTDIR%%/http;
|
||||
internal;
|
||||
}
|
||||
|
||||
location / {
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
my $index_txt = "This is the index page.";
|
||||
my $custom_txt = "This is a custom error page.";
|
||||
|
||||
$t->write_file("/index.html", $index_txt);
|
||||
mkdir($t->testdir() . '/http');
|
||||
$t->write_file("/http/403.html", $custom_txt);
|
||||
|
||||
$t->run();
|
||||
$t->plan(10);
|
||||
|
||||
###############################################################################
|
||||
|
||||
my $d = $t->testdir();
|
||||
|
||||
my $t1;
|
||||
my $t2;
|
||||
my $t3;
|
||||
my $t4;
|
||||
|
||||
# Performing requests to a server with ModSecurity enabled at location context
|
||||
$t1 = http_get_host('s1', '/index.html?what=root');
|
||||
$t2 = http_get_host('s1', '/index.html?what=other');
|
||||
|
||||
# Performing requests to a server with ModSecurity enabled at server context
|
||||
$t3 = http_get_host('s2', '/index.html?what=root');
|
||||
$t4 = http_get_host('s2', '/index.html?what=other');
|
||||
|
||||
my $local = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-local.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
|
||||
my $global = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/auditlog-global.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
|
||||
like($t1, qr/$custom_txt/, 'ModSecurity at location / root');
|
||||
like($t2, qr/$index_txt/, 'ModSecurity at location / other');
|
||||
like($local, qr/what=root/, 'ModSecurity at location / root present in auditlog');
|
||||
unlike($local, qr/what=other/, 'ModSecurity at location / other not present in auditlog');
|
||||
|
||||
like($t3, qr/$custom_txt/, 'ModSecurity at server / root');
|
||||
like($t4, qr/$index_txt/, 'ModSecurity at server / other');
|
||||
like($global, qr/what=root/, 'ModSecurity at server / root present in auditlog');
|
||||
unlike($global, qr/what=other/, 'ModSecurity at server / other not present in auditlog');
|
||||
|
||||
like($local, qr/Access denied with code 403/, 'ModSecurity at location / 403 in auditlog');
|
||||
like($global, qr/Access denied with code 403/, 'ModSecurity at server / 403 in auditlog');
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub http_get_host {
|
||||
my ($host, $url) = @_;
|
||||
return http(<<EOF);
|
||||
GET $url HTTP/1.0
|
||||
Host: $host
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# ModSecurity, http://www.modsecurity.org/
|
||||
# Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
#
|
||||
# You may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# If any of the files related to licensing are missing or if you have any
|
||||
# other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
# directly using the email address security@modsecurity.org.
|
||||
#
|
||||
|
||||
|
||||
# Tests for ModSecurity module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq whee" "id:10,phase:2"
|
||||
SecRule ARGS "@streq whee" "id:11,phase:2"
|
||||
';
|
||||
|
||||
location / {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq root" "id:21,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/debuglog-root.txt
|
||||
SecDebugLogLevel 9
|
||||
';
|
||||
}
|
||||
|
||||
location /subfolder1 {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq subfolder1" "id:31,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/debuglog-subfolder1.txt
|
||||
SecDebugLogLevel 9
|
||||
';
|
||||
location /subfolder1/subfolder2 {
|
||||
modsecurity_rules '
|
||||
SecRule ARGS "@streq subfolder2" "id:41,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecDebugLog %%TESTDIR%%/debuglog-subfolder2.txt
|
||||
SecDebugLogLevel 9
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder1');
|
||||
$t->write_file("/subfolder1/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder1/subfolder2');
|
||||
$t->write_file("/subfolder1/subfolder2/index.html", "should be moved/blocked before this.");
|
||||
|
||||
$t->run();
|
||||
$t->plan(3);
|
||||
|
||||
###############################################################################
|
||||
|
||||
my $d = $t->testdir();
|
||||
|
||||
my $r;
|
||||
# Performing requests at root
|
||||
$r = http_get('/index.html?what=root');
|
||||
$r = http_get('/index.html?what=subfolder1');
|
||||
$r = http_get('/index.html?what=subfolder2');
|
||||
|
||||
# Performing requests at subfolder1
|
||||
$r = http_get('/subfolder1/index.html?what=root');
|
||||
$r = http_get('/subfolder1/index.html?what=subfolder1');
|
||||
$r = http_get('/subfolder1/index.html?what=subfolder2');
|
||||
|
||||
# Performing requests at subfolder2
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=root');
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=subfolder1');
|
||||
$r = http_get('/subfolder1/subfolder2/index.html?what=subfolder2');
|
||||
|
||||
my $root = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/debuglog-root.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
my $subfolder1 = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/debuglog-subfolder1.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
my $subfolder2 = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", "$d/debuglog-subfolder2.txt"
|
||||
or die "could not open: $!";
|
||||
<$fh>;
|
||||
};
|
||||
|
||||
like($root, qr/"what", value "root"/, 'root');
|
||||
like($subfolder1, qr/"what", value "subfolder1"/, 'subfolder1');
|
||||
like($subfolder2, qr/"what", value "subfolder2"/, 'subfolder2');
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity-nginx connector (configuration merge).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
use Socket qw/ CRLF /;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http proxy/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRequestBodyLimit 128
|
||||
SecRequestBodyLimitAction Reject
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:11,phase:request,deny,log,status:403"
|
||||
';
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:%%PORT_8080%%;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /modsec-disabled {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine Off
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /nobodyaccess {
|
||||
modsecurity_rules '
|
||||
SecRequestBodyAccess Off
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /bodylimitprocesspartial {
|
||||
modsecurity_rules '
|
||||
SecRequestBodyLimitAction ProcessPartial
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /bodylimitincreased {
|
||||
modsecurity_rules '
|
||||
SecRequestBodyLimit 512
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /server {
|
||||
modsecurity off;
|
||||
|
||||
location /server/modsec-disabled {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8082%%;
|
||||
}
|
||||
|
||||
location /server/nobodyaccess {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8083%%;
|
||||
}
|
||||
|
||||
location /server/bodylimitprocesspartial {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8084%%;
|
||||
}
|
||||
|
||||
location /server/bodylimitincreased {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8085%%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:%%PORT_8082%%;
|
||||
|
||||
modsecurity_rules '
|
||||
SecRuleEngine Off
|
||||
';
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:%%PORT_8083%%;
|
||||
|
||||
modsecurity_rules '
|
||||
SecRequestBodyAccess Off
|
||||
';
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:%%PORT_8084%%;
|
||||
|
||||
modsecurity_rules '
|
||||
SecRequestBodyLimitAction ProcessPartial
|
||||
';
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:%%PORT_8085%%;
|
||||
|
||||
modsecurity_rules '
|
||||
SecRequestBodyLimit 512
|
||||
';
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->run_daemon(\&http_daemon);
|
||||
$t->run()->waitforsocket('127.0.0.1:' . port(8081));
|
||||
|
||||
$t->plan(10);
|
||||
|
||||
###############################################################################
|
||||
|
||||
like(http_get_body('/', 'GOOD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "http level defaults, pass");
|
||||
like(http_get_body('/', 'VERY BAD BODY'), qr/^HTTP.*403/, "http level defaults, block");
|
||||
|
||||
like(http_get_body('/modsec-disabled', 'VERY BAD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "location override for SecRuleEngine, pass");
|
||||
like(http_get_body('/nobodyaccess', 'VERY BAD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "location override for SecRequestBodyAccess, pass");
|
||||
like(http_get_body('/bodylimitprocesspartial', 'BODY' x 33), qr/TEST-OK-IF-YOU-SEE-THIS/, "location override for SecRequestBodyLimitAction, pass");
|
||||
like(http_get_body('/bodylimitincreased', 'BODY' x 64), qr/TEST-OK-IF-YOU-SEE-THIS/, "location override for SecRequestBodyLimit, pass");
|
||||
|
||||
like(http_get_body('/server/modsec-disabled', 'VERY BAD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "server override for SecRuleEngine, pass");
|
||||
like(http_get_body('/server/nobodyaccess', 'VERY BAD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "server override for SecRequestBodyAccess, pass");
|
||||
like(http_get_body('/server/bodylimitprocesspartial', 'BODY' x 33), qr/TEST-OK-IF-YOU-SEE-THIS/, "server override for SecRequestBodyLimitAction, pass");
|
||||
like(http_get_body('/server/bodylimitincreased', 'BODY' x 64), qr/TEST-OK-IF-YOU-SEE-THIS/, "server override for SecRequestBodyLimit, pass");
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub http_daemon {
|
||||
my $server = IO::Socket::INET->new(
|
||||
Proto => 'tcp',
|
||||
LocalHost => '127.0.0.1:' . port(8081),
|
||||
Listen => 5,
|
||||
Reuse => 1
|
||||
)
|
||||
or die "Can't create listening socket: $!\n";
|
||||
|
||||
local $SIG{PIPE} = 'IGNORE';
|
||||
|
||||
while (my $client = $server->accept()) {
|
||||
$client->autoflush(1);
|
||||
|
||||
my $headers = '';
|
||||
my $uri = '';
|
||||
|
||||
while (<$client>) {
|
||||
$headers .= $_;
|
||||
last if (/^\x0d?\x0a?$/);
|
||||
}
|
||||
|
||||
$uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
|
||||
|
||||
print $client <<'EOF';
|
||||
HTTP/1.1 200 OK
|
||||
Connection: close
|
||||
|
||||
EOF
|
||||
print $client "TEST-OK-IF-YOU-SEE-THIS"
|
||||
unless $headers =~ /^HEAD/i;
|
||||
|
||||
close $client;
|
||||
}
|
||||
}
|
||||
|
||||
sub http_get_body {
|
||||
my $uri = shift;
|
||||
my $last = pop;
|
||||
return http( join '', (map {
|
||||
my $body = $_;
|
||||
"GET $uri HTTP/1.1" . CRLF
|
||||
. "Host: localhost" . CRLF
|
||||
. "Content-Length: " . (length $body) . CRLF . CRLF
|
||||
. $body
|
||||
} @_),
|
||||
"GET $uri HTTP/1.1" . CRLF
|
||||
. "Host: localhost" . CRLF
|
||||
. "Connection: close" . CRLF
|
||||
. "Content-Length: " . (length $last) . CRLF . CRLF
|
||||
. $last
|
||||
);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# ModSecurity, http://www.modsecurity.org/
|
||||
# Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
#
|
||||
# You may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# If any of the files related to licensing are missing or if you have any
|
||||
# other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
# directly using the email address security@modsecurity.org.
|
||||
#
|
||||
|
||||
|
||||
# Tests for ModSecurity module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq whee" "id:10,phase:2"
|
||||
SecRule ARGS "@streq whee" "id:11,phase:2"
|
||||
';
|
||||
|
||||
location / {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq root" "id:21,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
';
|
||||
}
|
||||
|
||||
location /subfolder1 {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq subfolder1" "id:31,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
';
|
||||
location /subfolder1/subfolder2 {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq subfolder2" "id:41,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder1');
|
||||
$t->write_file("/subfolder1/index.html", "should be moved/blocked before this.");
|
||||
mkdir($t->testdir() . '/subfolder1/subfolder2');
|
||||
$t->write_file("/subfolder1/subfolder2/index.html", "should be moved/blocked before this.");
|
||||
|
||||
$t->run();
|
||||
$t->plan(9);
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Performing requests at root
|
||||
like(http_get('/index.html?what=root'), qr/^HTTP.*302/, 'redirect 302 - root');
|
||||
like(http_get('/index.html?what=subfolder1'), qr/should be moved\/blocked before this./, 'nothing - requested subfolder1 at root');
|
||||
like(http_get('/index.html?what=subfolder2'), qr/should be moved\/blocked before this./, 'nothing - requested subfolder2 at root');
|
||||
|
||||
# Performing requests at subfolder1
|
||||
like(http_get('/subfolder1/index.html?what=root'), qr/should be moved\/blocked before this./, 'nothing - requested root at subfolder 1');
|
||||
like(http_get('/subfolder1/index.html?what=subfolder1'), qr/^HTTP.*302/, 'redirect 302 - subfolder 1');
|
||||
like(http_get('/subfolder1/index.html?what=subfolder2'), qr/should be moved\/blocked before this./, 'nothing - requested subfolder2 at subfolder1');
|
||||
|
||||
# Performing requests at subfolder2
|
||||
like(http_get('/subfolder1/subfolder2/index.html?what=root'), qr/should be moved\/blocked before this./, 'nothing - requested root at subfolder 2');
|
||||
like(http_get('/subfolder1/subfolder2/index.html?what=subfolder1'), qr/^HTTP.*302/, 'redirect 302 - subfolder 2');
|
||||
like(http_get('/subfolder1/subfolder2/index.html?what=subfolder2'), qr/^HTTP.*302/, 'redirect 302 - subfolder 2');
|
||||
|
||||
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity module (HTTP/2).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
use Test::Nginx::HTTP2;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http http_v2/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080 http2;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq whee" "id:10,phase:2"
|
||||
SecRule ARGS "@streq whee" "id:11,phase:2"
|
||||
';
|
||||
}
|
||||
location /phase1 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:1,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:1,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
location /phase2 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:2,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:2,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:2,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:2,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:2,status:403,block"
|
||||
';
|
||||
}
|
||||
location /phase3 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:3,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:3,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:3,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:3,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:3,status:403,block"
|
||||
';
|
||||
}
|
||||
location /phase4 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecResponseBodyAccess On
|
||||
SecDefaultAction "phase:4,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:4,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:4,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:4,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:4,status:403,block"
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/phase1", "should be moved/blocked before this.");
|
||||
$t->write_file("/phase2", "should be moved/blocked before this.");
|
||||
$t->write_file("/phase3", "should be moved/blocked before this.");
|
||||
$t->write_file("/phase4", "should not be moved/blocked, headers delivered before phase 4.");
|
||||
$t->run();
|
||||
$t->plan(20);
|
||||
|
||||
###############################################################################
|
||||
|
||||
my ($phase, $s, $sid, $frames, $frame);
|
||||
|
||||
# Redirect (302)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=redirect302" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 302, "redirect 302 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=redirect302' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'redirect 302 - phase 4');
|
||||
}
|
||||
|
||||
# Redirect (301)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=redirect301" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 301, "redirect 301 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=redirect301' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'redirect 301 - phase 4');
|
||||
}
|
||||
|
||||
# Block (401)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=block401" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 401, "block 401 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=block401' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'block 401 - phase 4');
|
||||
}
|
||||
|
||||
# Block (403)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=block403" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 403, "block 403 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=block403' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'block 403 - phase 4');
|
||||
}
|
||||
|
||||
# Nothing to detect
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=nothing" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame->{data}, "should be moved\/blocked before this.", "nothing phase ${phase}");
|
||||
}
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase4?what=nothing" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame->{data}, "should not be moved\/blocked, headers delivered before phase 4.", 'nothing phase 4');
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity over the http proxy module (HTTP/2).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
use Test::Nginx::HTTP2;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http http_v2 proxy/)->plan(23);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080 http2;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
|
||||
location /phase1 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:1,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:1,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
location /phase2 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:2,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:2,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:2,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:2,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:2,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
location /phase3 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:3,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:3,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:3,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:3,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:3,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
location /phase4 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecResponseBodyAccess On
|
||||
SecDefaultAction "phase:4,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:4,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:4,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:4,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:4,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
$t->run_daemon(\&http_daemon);
|
||||
$t->run()->waitforsocket('127.0.0.1:' . port(8081));
|
||||
|
||||
###############################################################################
|
||||
|
||||
my ($phase, $s, $sid, $frames, $frame);
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/SEE-THIS/, "proxy request");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/multi' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/AND-THIS/, "proxy request with multiple packets");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/', method => 'HEAD' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
unlike($frame->{data}, qr/SEE-THIS/, "proxy head request");
|
||||
|
||||
# Redirect (302)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=redirect302" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 302, "redirect 302 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=redirect302' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'redirect 302 - phase 4');
|
||||
}
|
||||
|
||||
# Redirect (301)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=redirect301" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 301, "redirect 301 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=redirect301' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'redirect 301 - phase 4');
|
||||
}
|
||||
|
||||
# Block (401)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=block401" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 401, "block 401 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=block401' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'block 401 - phase 4');
|
||||
}
|
||||
|
||||
|
||||
# Block (403)
|
||||
|
||||
for $phase (1 .. 3) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=block403" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 403, "block 403 - phase ${phase}");
|
||||
}
|
||||
|
||||
SKIP: {
|
||||
skip 'long test', 1 unless $ENV{TEST_NGINX_UNSAFE};
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => '/phase4?what=block403' });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
is($frame, undef, 'block 403 - phase 4');
|
||||
}
|
||||
|
||||
# Nothing to detect
|
||||
#like(http_get('/phase1?what=nothing'), qr/phase1\?what=nothing\' not found/, 'nothing phase 1');
|
||||
#like(http_get('/phase2?what=nothing'), qr/phase2\?what=nothing\' not found/, 'nothing phase 2');
|
||||
#like(http_get('/phase3?what=nothing'), qr/phase3\?what=nothing\' not found/, 'nothing phase 3');
|
||||
#like(http_get('/phase4?what=nothing'), qr/phase4\?what=nothing\' not found/, 'nothing phase 4');
|
||||
|
||||
for $phase (1 .. 4) {
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ path => "/phase${phase}?what=nothing" });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/phase${phase}\?what=nothing\' not found/, "nothing phase ${phase}");
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub http_daemon {
|
||||
my $server = IO::Socket::INET->new(
|
||||
Proto => 'tcp',
|
||||
LocalHost => '127.0.0.1:' . port(8081),
|
||||
Listen => 5,
|
||||
Reuse => 1
|
||||
)
|
||||
or die "Can't create listening socket: $!\n";
|
||||
|
||||
local $SIG{PIPE} = 'IGNORE';
|
||||
|
||||
while (my $client = $server->accept()) {
|
||||
$client->autoflush(1);
|
||||
|
||||
my $headers = '';
|
||||
my $uri = '';
|
||||
|
||||
while (<$client>) {
|
||||
$headers .= $_;
|
||||
last if (/^\x0d?\x0a?$/);
|
||||
}
|
||||
|
||||
$uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
|
||||
|
||||
if ($uri eq '/') {
|
||||
print $client <<'EOF';
|
||||
HTTP/1.1 200 OK
|
||||
Connection: close
|
||||
|
||||
EOF
|
||||
print $client "TEST-OK-IF-YOU-SEE-THIS"
|
||||
unless $headers =~ /^HEAD/i;
|
||||
|
||||
} elsif ($uri eq '/multi') {
|
||||
|
||||
print $client <<"EOF";
|
||||
HTTP/1.1 200 OK
|
||||
Connection: close
|
||||
|
||||
TEST-OK-IF-YOU-SEE-THIS
|
||||
EOF
|
||||
|
||||
select undef, undef, undef, 0.1;
|
||||
print $client 'AND-THIS';
|
||||
|
||||
} else {
|
||||
|
||||
print $client <<"EOF";
|
||||
HTTP/1.1 404 Not Found
|
||||
Connection: close
|
||||
|
||||
Oops, '$uri' not found
|
||||
EOF
|
||||
}
|
||||
|
||||
close $client;
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
|
||||
# Tests for ModSecurity over the http proxy module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(23);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
|
||||
location /phase1 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:1,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:1,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
location /phase2 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:2,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:2,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:2,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:2,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:2,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
location /phase3 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:3,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:3,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:3,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:3,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:3,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
location /phase4 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecResponseBodyAccess On
|
||||
SecDefaultAction "phase:4,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:4,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:4,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:4,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:4,status:403,block"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_read_timeout 1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
$t->todo_alerts();
|
||||
$t->run_daemon(\&http_daemon);
|
||||
$t->run()->waitforsocket('127.0.0.1:' . port(8081));
|
||||
|
||||
###############################################################################
|
||||
|
||||
like(http_get('/'), qr/SEE-THIS/, 'proxy request');
|
||||
like(http_get('/multi'), qr/AND-THIS/, 'proxy request with multiple packets');
|
||||
|
||||
unlike(http_head('/'), qr/SEE-THIS/, 'proxy head request');
|
||||
|
||||
|
||||
# Redirect (302)
|
||||
like(http_get('/phase1?what=redirect302'), qr/^HTTP.*302/, 'redirect 302 - phase 1');
|
||||
like(http_get('/phase2?what=redirect302'), qr/^HTTP.*302/, 'redirect 302 - phase 2');
|
||||
like(http_get('/phase3?what=redirect302'), qr/^HTTP.*302/, 'redirect 302 - phase 3');
|
||||
is(http_get('/phase4?what=redirect302'), '', 'redirect 302 - phase 4');
|
||||
|
||||
# Redirect (301)
|
||||
like(http_get('/phase1?what=redirect301'), qr/^HTTP.*301/, 'redirect 301 - phase 1');
|
||||
like(http_get('/phase2?what=redirect301'), qr/^HTTP.*301/, 'redirect 301 - phase 2');
|
||||
like(http_get('/phase3?what=redirect301'), qr/^HTTP.*301/, 'redirect 301 - phase 3');
|
||||
is(http_get('/phase4?what=redirect301'), '', 'redirect 301 - phase 4');
|
||||
|
||||
# Block (401)
|
||||
like(http_get('/phase1?what=block401'), qr/^HTTP.*401/, 'block 401 - phase 1');
|
||||
like(http_get('/phase2?what=block401'), qr/^HTTP.*401/, 'block 401 - phase 2');
|
||||
like(http_get('/phase3?what=block401'), qr/^HTTP.*401/, 'block 401 - phase 3');
|
||||
is(http_get('/phase4?what=block401'), '', 'block 401 - phase 4');
|
||||
|
||||
# Block (403)
|
||||
like(http_get('/phase1?what=block403'), qr/^HTTP.*403/, 'block 403 - phase 1');
|
||||
like(http_get('/phase2?what=block403'), qr/^HTTP.*403/, 'block 403 - phase 2');
|
||||
like(http_get('/phase3?what=block403'), qr/^HTTP.*403/, 'block 403 - phase 3');
|
||||
is(http_get('/phase4?what=block403'), '', 'block 403 - phase 4');
|
||||
|
||||
# Nothing to detect
|
||||
like(http_get('/phase1?what=nothing'), qr/phase1\?what=nothing\' not found/, 'nothing phase 1');
|
||||
like(http_get('/phase2?what=nothing'), qr/phase2\?what=nothing\' not found/, 'nothing phase 2');
|
||||
like(http_get('/phase3?what=nothing'), qr/phase3\?what=nothing\' not found/, 'nothing phase 3');
|
||||
like(http_get('/phase4?what=nothing'), qr/phase4\?what=nothing\' not found/, 'nothing phase 4');
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub http_daemon {
|
||||
my $server = IO::Socket::INET->new(
|
||||
Proto => 'tcp',
|
||||
LocalHost => '127.0.0.1:' . port(8081),
|
||||
Listen => 5,
|
||||
Reuse => 1
|
||||
)
|
||||
or die "Can't create listening socket: $!\n";
|
||||
|
||||
local $SIG{PIPE} = 'IGNORE';
|
||||
|
||||
while (my $client = $server->accept()) {
|
||||
$client->autoflush(1);
|
||||
|
||||
my $headers = '';
|
||||
my $uri = '';
|
||||
|
||||
while (<$client>) {
|
||||
$headers .= $_;
|
||||
last if (/^\x0d?\x0a?$/);
|
||||
}
|
||||
|
||||
$uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
|
||||
|
||||
if ($uri eq '/') {
|
||||
print $client <<'EOF';
|
||||
HTTP/1.1 200 OK
|
||||
Connection: close
|
||||
|
||||
EOF
|
||||
print $client "TEST-OK-IF-YOU-SEE-THIS"
|
||||
unless $headers =~ /^HEAD/i;
|
||||
|
||||
} elsif ($uri eq '/multi') {
|
||||
|
||||
print $client <<"EOF";
|
||||
HTTP/1.1 200 OK
|
||||
Connection: close
|
||||
|
||||
TEST-OK-IF-YOU-SEE-THIS
|
||||
EOF
|
||||
|
||||
select undef, undef, undef, 0.1;
|
||||
print $client 'AND-THIS';
|
||||
|
||||
} else {
|
||||
|
||||
print $client <<"EOF";
|
||||
HTTP/1.1 404 Not Found
|
||||
Connection: close
|
||||
|
||||
Oops, '$uri' not found
|
||||
EOF
|
||||
}
|
||||
|
||||
close $client;
|
||||
}
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity-nginx connector (request body operations, HTTP/2).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
use Socket qw/ CRLF /;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
use Test::Nginx::HTTP2;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http http_v2 proxy auth_request/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8081;
|
||||
location / {
|
||||
return 200 "TEST-OK-IF-YOU-SEE-THIS";
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080 http2;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
client_header_buffer_size 1024;
|
||||
|
||||
location /bodyaccess {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:11,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
}
|
||||
|
||||
location /nobodyaccess {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess Off
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:21,phase:request,deny,log,status:403"
|
||||
SecRule ARGS_POST|ARGS_POST_NAMES "@rx BAD ARG" "id:22,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
}
|
||||
|
||||
location /bodylimitreject {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRequestBodyLimit 128
|
||||
SecRequestBodyLimitAction Reject
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:31,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
}
|
||||
|
||||
location /bodylimitprocesspartial {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRequestBodyLimit 128
|
||||
SecRequestBodyLimitAction ProcessPartial
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:41,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
}
|
||||
|
||||
location = /auth {
|
||||
return 200;
|
||||
}
|
||||
|
||||
location = /useauth {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
';
|
||||
auth_request /auth;
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->run();
|
||||
|
||||
$t->plan(36);
|
||||
|
||||
###############################################################################
|
||||
|
||||
my ($s, $sid, $frames, $frame);
|
||||
|
||||
foreach my $method (('GET', 'POST', 'PUT', 'DELETE')) {
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/bodyaccess', 'body_more' => 1 });
|
||||
$s->h2_body('GOOD BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body access on, pass");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/bodyaccess', 'body_more' => 1 });
|
||||
$s->h2_body('VERY BAD BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 403, "${method} request body access on, block");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/nobodyaccess', 'body_more' => 1 });
|
||||
$s->h2_body('VERY BAD BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body access off, pass");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ 'body_more' => 1,
|
||||
headers => [
|
||||
{name => ':method', value => "${method}" },
|
||||
{name => ':scheme', value => 'http' },
|
||||
{name => ':path', value => '/nobodyaccess' },
|
||||
{name => 'host', value => 'localhost' },
|
||||
{name => 'content-type', value => 'application/x-www-form-urlencoded' }
|
||||
] });
|
||||
$s->h2_body('test=VERY BAD BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body access off (ARGS_POST), pass");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/bodylimitreject', 'body_more' => 1 });
|
||||
$s->h2_body('BODY' x 32);
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body limit reject, pass");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/bodylimitreject', 'body_more' => 1 });
|
||||
$s->h2_body('BODY' x 33);
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 403, "${method} request body limit reject, block");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/bodylimitprocesspartial', 'body_more' => 1 });
|
||||
$s->h2_body('BODY' x 32 . 'BAD BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "${method} request body limit process partial, pass");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => $method, path => '/bodylimitprocesspartial', 'body_more' => 1 });
|
||||
$s->h2_body('BODY' x 30 . 'BAD BODY' x 32);
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
|
||||
is($frame->{headers}->{':status'}, 403, "${method} request body limit process partial, block");
|
||||
|
||||
}
|
||||
|
||||
TODO: {
|
||||
# https://github.com/SpiderLabs/ModSecurity-nginx/issues/163
|
||||
# https://github.com/nginx/nginx/commit/6c89d752c8ab3a3cc0832927484808b68153f8c4
|
||||
local $TODO = 'not yet' unless $t->has_version('1.19.3');
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body' => 'BODY' x 16 });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size < client_header_buffer_size)");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body' => 'BODY' x 257 });
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size > client_header_buffer_size)");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body_more' => 1 });
|
||||
$s->h2_body('BODY' x 15, { 'body_more' => 1 });
|
||||
select undef, undef, undef, 0.1;
|
||||
$s->h2_body('BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size < client_header_buffer_size), no preread");
|
||||
|
||||
$s = Test::Nginx::HTTP2->new();
|
||||
$sid = $s->new_stream({ method => 'POST', path => '/useauth', 'body_more' => 1 });
|
||||
$s->h2_body('BODY' x 256, { 'body_more' => 1 });
|
||||
select undef, undef, undef, 0.1;
|
||||
$s->h2_body('BODY');
|
||||
$frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
|
||||
($frame) = grep { $_->{type} eq "DATA" } @$frames;
|
||||
like($frame->{data}, qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size > client_header_buffer_size), no preread");
|
||||
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity-nginx connector (request body operations).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
use Socket qw/ CRLF /;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http proxy auth_request/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
client_header_buffer_size 1024;
|
||||
|
||||
location /bodyaccess {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:11,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /nobodyaccess {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess Off
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:21,phase:request,deny,log,status:403"
|
||||
SecRule ARGS_POST|ARGS_POST_NAMES "@rx BAD ARG" "id:22,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /bodylimitreject {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRequestBodyLimit 128
|
||||
SecRequestBodyLimitAction Reject
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:31,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location /bodylimitrejectserver {
|
||||
modsecurity off;
|
||||
proxy_pass http://127.0.0.1:%%PORT_8082%%;
|
||||
}
|
||||
|
||||
location /bodylimitprocesspartial {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRequestBodyLimit 128
|
||||
SecRequestBodyLimitAction ProcessPartial
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:41,phase:request,deny,log,status:403"
|
||||
';
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
|
||||
location = /auth {
|
||||
return 200;
|
||||
}
|
||||
|
||||
location = /useauth {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
';
|
||||
auth_request /auth;
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:%%PORT_8082%%;
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecRequestBodyLimit 128
|
||||
SecRequestBodyLimitAction Reject
|
||||
SecRule REQUEST_BODY "@rx BAD BODY" "id:31,phase:request,deny,log,status:403"
|
||||
';
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:%%PORT_8081%%;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->run_daemon(\&http_daemon);
|
||||
$t->run()->waitforsocket('127.0.0.1:' . port(8081));
|
||||
|
||||
$t->plan(40);
|
||||
|
||||
###############################################################################
|
||||
|
||||
foreach my $method (('GET', 'POST', 'PUT', 'DELETE')) {
|
||||
like(http_req_body($method, '/bodyaccess', 'GOOD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "$method request body access on, pass");
|
||||
like(http_req_body($method, '/bodyaccess', 'VERY BAD BODY'), qr/^HTTP.*403/, "$method request body access on, block");
|
||||
like(http_req_body($method, '/nobodyaccess', 'VERY BAD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "$method request body access off, pass");
|
||||
like(http_req_body_postargs($method, '/nobodyaccess', 'BAD ARG'), qr/TEST-OK-IF-YOU-SEE-THIS/, "$method request body access off (ARGS_POST), pass");
|
||||
like(http_req_body($method, '/bodylimitreject', 'BODY' x 32), qr/TEST-OK-IF-YOU-SEE-THIS/, "$method request body limit reject, pass");
|
||||
like(http_req_body($method, '/bodylimitreject', 'BODY' x 33), qr/^HTTP.*403/, "$method request body limit reject, block");
|
||||
like(http_req_body($method, '/bodylimitprocesspartial', 'BODY' x 32 . 'BAD BODY'), qr/TEST-OK-IF-YOU-SEE-THIS/, "$method request body limit process partial, pass");
|
||||
like(http_req_body($method, '/bodylimitprocesspartial', 'BODY' x 30 . 'BAD BODY' x 32), qr/^HTTP.*403/, "$method request body limit process partial, block");
|
||||
}
|
||||
|
||||
like(http_req_body('POST', '/useauth', 'BODY' x 16), qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size < client_header_buffer_size)");
|
||||
like(http_req_body('POST', '/useauth', 'BODY' x 257), qr/TEST-OK-IF-YOU-SEE-THIS/, "POST with auth_request (request size > client_header_buffer_size)");
|
||||
|
||||
like(
|
||||
http(
|
||||
'POST /useauth HTTP/1.0' . CRLF
|
||||
. 'Content-Length: 1028' . CRLF . CRLF
|
||||
. 'BODY' x 256,
|
||||
sleep => 0.1,
|
||||
body => 'BODY'
|
||||
),
|
||||
qr/TEST-OK-IF-YOU-SEE-THIS/,
|
||||
'POST with auth_request (request size > client_header_buffer_size), no preread'
|
||||
);
|
||||
|
||||
like(
|
||||
http(
|
||||
'POST /useauth HTTP/1.0' . CRLF
|
||||
. 'Content-Length: 64' . CRLF . CRLF
|
||||
. 'BODY' x 15,
|
||||
sleep => 0.1,
|
||||
body => 'BODY'
|
||||
),
|
||||
qr/TEST-OK-IF-YOU-SEE-THIS/,
|
||||
'POST with auth_request (request size < client_header_buffer_size), no preread'
|
||||
);
|
||||
|
||||
foreach my $method (('GET', 'POST', 'PUT', 'DELETE')) {
|
||||
like(http_req_body($method, '/bodylimitrejectserver', 'BODY' x 33), qr/^HTTP.*403/, "$method request body limit reject, block (inherited SecRequestBodyLimit)");
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub http_daemon {
|
||||
my $server = IO::Socket::INET->new(
|
||||
Proto => 'tcp',
|
||||
LocalHost => '127.0.0.1:' . port(8081),
|
||||
Listen => 5,
|
||||
Reuse => 1
|
||||
)
|
||||
or die "Can't create listening socket: $!\n";
|
||||
|
||||
local $SIG{PIPE} = 'IGNORE';
|
||||
|
||||
while (my $client = $server->accept()) {
|
||||
$client->autoflush(1);
|
||||
|
||||
my $headers = '';
|
||||
my $uri = '';
|
||||
|
||||
while (<$client>) {
|
||||
$headers .= $_;
|
||||
last if (/^\x0d?\x0a?$/);
|
||||
}
|
||||
|
||||
$uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i;
|
||||
|
||||
print $client <<'EOF';
|
||||
HTTP/1.1 200 OK
|
||||
Connection: close
|
||||
|
||||
EOF
|
||||
print $client "TEST-OK-IF-YOU-SEE-THIS"
|
||||
unless $headers =~ /^HEAD/i;
|
||||
|
||||
close $client;
|
||||
}
|
||||
}
|
||||
|
||||
sub http_req_body {
|
||||
my $method = shift;
|
||||
my $uri = shift;
|
||||
my $last = pop;
|
||||
return http( join '', (map {
|
||||
my $body = $_;
|
||||
"$method $uri HTTP/1.1" . CRLF
|
||||
. "Host: localhost" . CRLF
|
||||
. "Content-Length: " . (length $body) . CRLF . CRLF
|
||||
. $body
|
||||
} @_),
|
||||
"$method $uri HTTP/1.1" . CRLF
|
||||
. "Host: localhost" . CRLF
|
||||
. "Connection: close" . CRLF
|
||||
. "Content-Length: " . (length $last) . CRLF . CRLF
|
||||
. $last
|
||||
);
|
||||
}
|
||||
|
||||
sub http_req_body_postargs {
|
||||
my $method = shift;
|
||||
my $uri = shift;
|
||||
my $last = pop;
|
||||
return http( join '', (map {
|
||||
my $body = $_;
|
||||
"$method $uri HTTP/1.1" . CRLF
|
||||
. "Host: localhost" . CRLF
|
||||
. "Content-Type: application/x-www-form-urlencoded" . CRLF
|
||||
. "Content-Length: " . (length "test=" . $body) . CRLF . CRLF
|
||||
. "test=" . $body
|
||||
} @_),
|
||||
"$method $uri HTTP/1.1" . CRLF
|
||||
. "Host: localhost" . CRLF
|
||||
. "Connection: close" . CRLF
|
||||
. "Content-Type: application/x-www-form-urlencoded" . CRLF
|
||||
. "Content-Length: " . (length "test=" . $last) . CRLF . CRLF
|
||||
. "test=" . $last
|
||||
);
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity-nginx connector (response body operations).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
|
||||
location /body1 {
|
||||
default_type text/plain;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecResponseBodyAccess On
|
||||
SecResponseBodyLimit 128
|
||||
SecRule RESPONSE_BODY "@rx BAD BODY" "id:11,phase:response,deny,log,status:403"
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/body1", "BAD BODY");
|
||||
$t->run();
|
||||
$t->todo_alerts();
|
||||
$t->plan(1);
|
||||
|
||||
###############################################################################
|
||||
|
||||
TODO: {
|
||||
local $TODO = 'not yet';
|
||||
|
||||
like(http_get('/body1'), qr/^HTTP.*403/, 'response body (block)');
|
||||
}
|
||||
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity-nginx connector (scoring).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
modsecurity on;
|
||||
|
||||
location /absolute {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq badarg1" "id:11,phase:2,setvar:tx.score=1"
|
||||
SecRule ARGS "@streq badarg2" "id:12,phase:2,setvar:tx.score=2"
|
||||
SecRule TX:SCORE "@ge 2" "id:199,phase:request,deny,log,status:403"
|
||||
';
|
||||
}
|
||||
|
||||
location /iterative {
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq badarg1" "id:21,phase:2,setvar:tx.score=+1"
|
||||
SecRule ARGS "@streq badarg2" "id:22,phase:2,setvar:tx.score=+1"
|
||||
SecRule ARGS "@streq badarg3" "id:23,phase:2,setvar:tx.score=+1"
|
||||
SecRule TX:SCORE "@ge 3" "id:299,phase:request,deny,log,status:403"
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/absolute", "should be moved/blocked before this.");
|
||||
$t->write_file("/iterative", "should be moved/blocked before this.");
|
||||
$t->run();
|
||||
$t->plan(5);
|
||||
|
||||
###############################################################################
|
||||
|
||||
like(http_get('/absolute?what=badarg1'), qr/should be moved\/blocked before this./, 'absolute scoring 1 (pass)');
|
||||
like(http_get('/absolute?what=badarg2'), qr/^HTTP.*403/, 'absolute scoring 2 (block)');
|
||||
|
||||
like(http_get('/iterative?arg1=badarg1'), qr/should be moved\/blocked before this./, 'iterative scoring 1 (pass)');
|
||||
like(http_get('/iterative?arg1=badarg1&arg2=badarg2'), qr/should be moved\/blocked before this./, 'iterative scoring 2 (pass)');
|
||||
like(http_get('/iterative?arg1=badarg1&arg2=badarg2&arg3=badarg3'), qr/^HTTP.*403/, 'iterative scoring 3 (block)');
|
||||
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# (C) Andrei Belov
|
||||
|
||||
# Tests for ModSecurity-nginx connector (modsecurity_transaction_id).
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->plan(5)->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
modsecurity_transaction_id "tid-HTTP-DEFAULT-$request_id";
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name server1;
|
||||
|
||||
location / {
|
||||
error_log %%TESTDIR%%/e_s1l1.log info;
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name server2;
|
||||
|
||||
modsecurity_transaction_id "tid-SERVER-DEFAULT-$request_id";
|
||||
|
||||
location / {
|
||||
error_log %%TESTDIR%%/e_s2l1.log info;
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
|
||||
location /specific {
|
||||
error_log %%TESTDIR%%/e_s2l2.log info;
|
||||
modsecurity on;
|
||||
modsecurity_transaction_id "tid-LOCATION-SPECIFIC-$request_id";
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
|
||||
location /debuglog {
|
||||
modsecurity on;
|
||||
modsecurity_transaction_id "tid-DEBUG-$request_id";
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDebugLog %%TESTDIR%%/modsec_debug.log
|
||||
SecDebugLogLevel 4
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
|
||||
location /auditlog {
|
||||
modsecurity on;
|
||||
modsecurity_transaction_id "tid-AUDIT-$request_id";
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecAuditEngine On
|
||||
SecAuditLogParts A
|
||||
SecAuditLog %%TESTDIR%%/modsec_audit.log
|
||||
SecAuditLogType Serial
|
||||
SecAuditLogStorageDir %%TESTDIR%%/
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->run();
|
||||
|
||||
###############################################################################
|
||||
|
||||
# charge limit_req
|
||||
|
||||
http(<<EOF);
|
||||
GET /?what=block403 HTTP/1.0
|
||||
Host: server1
|
||||
|
||||
EOF
|
||||
|
||||
isnt(lines($t, 'e_s1l1.log', 'unique_id "tid-HTTP-DEFAULT-'), 0, 'http default');
|
||||
|
||||
http(<<EOF);
|
||||
GET /?what=block403 HTTP/1.0
|
||||
Host: server2
|
||||
|
||||
EOF
|
||||
|
||||
isnt(lines($t, 'e_s2l1.log', 'unique_id "tid-SERVER-DEFAULT-'), 0, 'server default');
|
||||
|
||||
http(<<EOF);
|
||||
GET /specific/?what=block403 HTTP/1.0
|
||||
Host: server2
|
||||
|
||||
EOF
|
||||
|
||||
isnt(lines($t, 'e_s2l2.log', 'unique_id "tid-LOCATION-SPECIFIC-'), 0, 'location specific');
|
||||
|
||||
http(<<EOF);
|
||||
GET /debuglog/?what=block403 HTTP/1.0
|
||||
Host: server2
|
||||
|
||||
EOF
|
||||
|
||||
isnt(lines($t, 'modsec_debug.log', 'tid-DEBUG-'), 0, 'libmodsecurity debug log');
|
||||
|
||||
http(<<EOF);
|
||||
GET /auditlog/?what=block403 HTTP/1.0
|
||||
Host: server2
|
||||
|
||||
EOF
|
||||
|
||||
isnt(lines($t, 'modsec_audit.log', 'tid-AUDIT-'), 0, 'libmodsecurity audit log');
|
||||
|
||||
###############################################################################
|
||||
|
||||
sub lines {
|
||||
my ($t, $file, $pattern) = @_;
|
||||
my $path = $t->testdir() . '/' . $file;
|
||||
open my $fh, '<', $path or return "$!";
|
||||
my $value = map { $_ =~ /\Q$pattern\E/ } (<$fh>);
|
||||
close $fh;
|
||||
return $value;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
172
src/deps/src/modsecurity-nginx/tests/modsecurity.t
vendored
172
src/deps/src/modsecurity-nginx/tests/modsecurity.t
vendored
|
|
@ -1,172 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# ModSecurity, http://www.modsecurity.org/
|
||||
# Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
#
|
||||
# You may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# If any of the files related to licensing are missing or if you have any
|
||||
# other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
# directly using the email address security@modsecurity.org.
|
||||
#
|
||||
|
||||
|
||||
# Tests for ModSecurity module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http/);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecRule ARGS "@streq whee" "id:10,phase:2"
|
||||
SecRule ARGS "@streq whee" "id:11,phase:2"
|
||||
';
|
||||
}
|
||||
location /phase1 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:1,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:1,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:1,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:1,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:1,status:403,block"
|
||||
';
|
||||
}
|
||||
location /phase2 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:2,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:2,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:2,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:2,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:2,status:403,block"
|
||||
';
|
||||
}
|
||||
location /phase3 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDefaultAction "phase:3,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:3,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:3,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:3,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:3,status:403,block"
|
||||
';
|
||||
}
|
||||
location /phase4 {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecResponseBodyAccess On
|
||||
SecDefaultAction "phase:4,log,deny,status:403"
|
||||
SecRule ARGS "@streq redirect301" "id:1,phase:4,status:301,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq redirect302" "id:2,phase:4,status:302,redirect:http://www.modsecurity.org"
|
||||
SecRule ARGS "@streq block401" "id:3,phase:4,status:401,block"
|
||||
SecRule ARGS "@streq block403" "id:4,phase:4,status:403,block"
|
||||
';
|
||||
}
|
||||
location /early-block {
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecResponseBodyAccess On
|
||||
SecDefaultAction "phase:1,log,auditlog,pass"
|
||||
SecDefaultAction "phase:2,log,auditlog,pass"
|
||||
SecAction "id:900101,phase:1,nolog,pass,t:none,setvar:tx.trigger_phase1=1"
|
||||
SecAction "id:900103,phase:1,nolog,pass,t:none,setvar:tx.trigger_phase3=1"
|
||||
SecAction "id:900105,phase:1,nolog,pass,t:none,setvar:tx.trigger_phase5=1"
|
||||
SecRule TX:TRIGGER_PHASE1 "@eq 1" "id:901111,phase:1,t:none,deny,log"
|
||||
SecRule REQUEST_BODY "@rx attack" "id:901121,phase:2,t:none,deny,log"
|
||||
SecRule TX:TRIGGER_PHASE3 "@eq 1" "id:901131,phase:3,t:none,deny,log"
|
||||
SecRule RESPONSE_BODY "@rx ok" "id:901141,phase:4,t:none,deny,log"
|
||||
SecRule TX:TRIGGER_PHASE5 "@eq 1" "id:901151,phase:5,t:none,pass,log,msg:\'This is the phase 5.\'"
|
||||
';
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
$t->write_file("/phase1", "should be moved/blocked before this.");
|
||||
$t->write_file("/phase2", "should be moved/blocked before this.");
|
||||
$t->write_file("/phase3", "should be moved/blocked before this.");
|
||||
$t->write_file("/phase4", "should not be moved/blocked, headers delivered before phase 4.");
|
||||
$t->write_file("/early-block", "should be moved/blocked before this.");
|
||||
$t->run();
|
||||
$t->todo_alerts();
|
||||
$t->plan(21);
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Redirect (302)
|
||||
like(http_get('/phase1?what=redirect302'), qr/^HTTP.*302/, 'redirect 302 - phase 1');
|
||||
like(http_get('/phase2?what=redirect302'), qr/^HTTP.*302/, 'redirect 302 - phase 2');
|
||||
like(http_get('/phase3?what=redirect302'), qr/^HTTP.*302/, 'redirect 302 - phase 3');
|
||||
is(http_get('/phase4?what=redirect302'), '', 'redirect 302 - phase 4');
|
||||
|
||||
# Redirect (301)
|
||||
like(http_get('/phase1?what=redirect301'), qr/^HTTP.*301/, 'redirect 301 - phase 1');
|
||||
like(http_get('/phase2?what=redirect301'), qr/^HTTP.*301/, 'redirect 301 - phase 2');
|
||||
like(http_get('/phase3?what=redirect301'), qr/^HTTP.*301/, 'redirect 301 - phase 3');
|
||||
is(http_get('/phase4?what=redirect301'), '', 'redirect 301 - phase 4');
|
||||
|
||||
# Block (401)
|
||||
like(http_get('/phase1?what=block401'), qr/^HTTP.*401/, 'block 401 - phase 1');
|
||||
like(http_get('/phase2?what=block401'), qr/^HTTP.*401/, 'block 401 - phase 2');
|
||||
like(http_get('/phase3?what=block401'), qr/^HTTP.*401/, 'block 401 - phase 3');
|
||||
is(http_get('/phase4?what=block401'), '', 'block 401 - phase 4');
|
||||
|
||||
# Block (403)
|
||||
like(http_get('/phase1?what=block403'), qr/^HTTP.*403/, 'block 403 - phase 1');
|
||||
like(http_get('/phase2?what=block403'), qr/^HTTP.*403/, 'block 403 - phase 2');
|
||||
like(http_get('/phase3?what=block403'), qr/^HTTP.*403/, 'block 403 - phase 3');
|
||||
is(http_get('/phase4?what=block403'), '', 'block 403 - phase 4');
|
||||
|
||||
# Nothing to detect
|
||||
like(http_get('/phase1?what=nothing'), qr/should be moved\/blocked before this./, 'nothing phase 1');
|
||||
like(http_get('/phase2?what=nothing'), qr/should be moved\/blocked before this./, 'nothing phase 2');
|
||||
like(http_get('/phase3?what=nothing'), qr/should be moved\/blocked before this./, 'nothing phase 3');
|
||||
like(http_get('/phase4?what=nothing'), qr/should not be moved\/blocked, headers delivered before phase 4./, 'nothing phase 4');
|
||||
|
||||
# early block (https://github.com/SpiderLabs/ModSecurity-nginx/issues/238)
|
||||
like(http_get('/early-block'), qr/^HTTP.*403/, 'early block 403 (https://github.com/SpiderLabs/ModSecurity-nginx/issues/238)');
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# Script to adjust nginx tests to include ModSecurity directives. It enables
|
||||
# us to passively test nginx functionality with ModSecurity module enabled.
|
||||
#
|
||||
|
||||
# sh command line variations:
|
||||
#
|
||||
# for i in *.t; do cp -n $i $i.orig; perl nginx-tests-cvt.pl < $i.orig > $i; done
|
||||
# for i in *.t; do perl nginx-tests-cvt.pl < $i.orig > $i; done
|
||||
# for i in *.t; do cp $i.orig $i; done
|
||||
|
||||
my $ignore = 0;
|
||||
while (<STDIN>) {
|
||||
print $_;
|
||||
|
||||
$ignore = 1 if (/^mail {/); # skip mail_*.t mail blocks
|
||||
$ignore = 0 if (/^http {/);
|
||||
|
||||
next if ($ignore);
|
||||
|
||||
if (/^ *server_name .*;$/) {
|
||||
|
||||
next if (/^ *server_name *below;/); # skip duplication on refresh.t
|
||||
next if (/^ *server_name *many4.example.com;/); # skip duplication on http_server_name.t
|
||||
|
||||
print "
|
||||
modsecurity on;
|
||||
modsecurity_rules '
|
||||
SecRuleEngine On
|
||||
SecDebugLogLevel 9
|
||||
SecRule ARGS \"\@streq whee\" \"id:10,phase:2\"
|
||||
SecRule ARGS \"\@streq whee\" \"id:11,phase:2\"
|
||||
';
|
||||
";
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue