mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-15 23:55:03 +03:00
Added some basic regression tests.
This commit is contained in:
parent
f90ffeb970
commit
813127aa13
23
apache2/t/regression/config/00-load-modsec.t
Normal file
23
apache2/t/regression/config/00-load-modsec.t
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "module loaded",
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity for Apache.* configured\./, 10 ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "minimal config",
|
||||||
|
conf => sub {
|
||||||
|
# Open the minimal conf file, substituting the
|
||||||
|
# relative log paths with full paths.
|
||||||
|
open(C, "<$ENV{DIST_ROOT}/modsecurity.conf-minimal") or die "$!\n";
|
||||||
|
(my $conf = join('', <C>)) =~ s#Log logs/#Log $ENV{TEST_SERVER_ROOT}/logs/#g;
|
||||||
|
close C;
|
||||||
|
|
||||||
|
return $conf;
|
||||||
|
},
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity for Apache.* configured\./, 10 ],
|
||||||
|
},
|
||||||
|
},
|
144
apache2/t/regression/config/10-request-directives.t
Normal file
144
apache2/t/regression/config/10-request-directives.t
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
|
||||||
|
### SecArgumentSeparator
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "SecArgumentSeparator (get-pos)",
|
||||||
|
conf => q(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecArgumentSeparator ";"
|
||||||
|
SecRule ARGS:a "@streq 1" "phase:1,deny,chain"
|
||||||
|
SecRule ARGS:b "@streq 2"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 1\). String match "2" at ARGS:b./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt?a=1;b=2",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "SecArgumentSeparator (get-neg)",
|
||||||
|
conf => q(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule ARGS:a "@streq 1" "phase:1,deny,chain"
|
||||||
|
SecRule ARGS:b "@streq 2"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
-error => [ qr/Access denied/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt?a=1;b=2",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "SecArgumentSeparator (post-pos)",
|
||||||
|
conf => q(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecArgumentSeparator ";"
|
||||||
|
SecRule ARGS:a "@streq 1" "phase:2,deny,chain"
|
||||||
|
SecRule ARGS:b "@streq 2"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 2\). String match "2" at ARGS:b./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
[
|
||||||
|
"Content-Type" => "application/x-www-form-urlencoded",
|
||||||
|
],
|
||||||
|
"a=1;b=2",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "SecArgumentSeparator (post-neg)",
|
||||||
|
conf => q(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecRule ARGS:a "@streq 1" "phase:2,deny"
|
||||||
|
SecRule ARGS:b "@streq 2" "phase:2,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
-error => [ qr/Access denied/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
[
|
||||||
|
"Content-Type" => "application/x-www-form-urlencoded",
|
||||||
|
],
|
||||||
|
"a=1;b=2",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
### SecRequestBodyAccess
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "SecRequestBodyAccess (pos)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAuditEngine On
|
||||||
|
SecAuditLogParts ABCDEFGHIJKZ
|
||||||
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
|
SecDebugLogLevel 9
|
||||||
|
SecAuditLog $ENV{AUDIT_LOG}
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecRule ARGS:a "\@streq 1" "phase:2,deny,chain"
|
||||||
|
SecRule ARGS:b "\@streq 2"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 2\). String match "2" at ARGS:b./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
[
|
||||||
|
"Content-Type" => "application/x-www-form-urlencoded",
|
||||||
|
],
|
||||||
|
"a=1&b=2",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "config",
|
||||||
|
comment => "SecRequestBodyAccess (neg)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAuditEngine On
|
||||||
|
SecAuditLogParts ABCDEFGHIJKZ
|
||||||
|
SecDebugLog $ENV{DEBUG_LOG}
|
||||||
|
SecDebugLogLevel 9
|
||||||
|
SecAuditLog $ENV{AUDIT_LOG}
|
||||||
|
SecRequestBodyAccess Off
|
||||||
|
SecRule ARGS:a "\@streq 1" "phase:2,deny"
|
||||||
|
SecRule ARGS:b "\@streq 2" "phase:2,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
-error => [ qr/Access denied/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
[
|
||||||
|
"Content-Type" => "application/x-www-form-urlencoded",
|
||||||
|
],
|
||||||
|
"a=1&b=2",
|
||||||
|
),
|
||||||
|
},
|
427
apache2/t/regression/rule/00-disruptive-actions.t
Normal file
427
apache2/t/regression/rule/00-disruptive-actions.t
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
### Pass
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "pass action in phase:1",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:1,pass"
|
||||||
|
SecAction "phase:1,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "pass action in phase:2",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:2,pass"
|
||||||
|
SecAction "phase:2,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "pass action in phase:3",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:3,pass"
|
||||||
|
SecAction "phase:3,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "pass action in phase:4",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:4,pass"
|
||||||
|
SecAction "phase:4,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Warning. Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
### Allow
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "allow action in phase:1",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:1,allow"
|
||||||
|
SecAction "phase:1,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access allowed \(phase 1\). Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "allow action in phase:2",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:2,allow"
|
||||||
|
SecAction "phase:2,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access allowed \(phase 2\). Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "allow action in phase:3",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:3,allow"
|
||||||
|
SecAction "phase:3,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access allowed \(phase 3\). Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "allow action in phase:4",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:4,allow"
|
||||||
|
SecAction "phase:4,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access allowed \(phase 4\). Unconditional match in SecAction/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
### Deny
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "deny action in phase:1",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:1,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 1\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "deny action in phase:2",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:2,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 2\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "deny action in phase:3",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:3,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 3\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "deny action in phase:4",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:4,deny"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with code 403 \(phase 4\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^403$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
### Drop
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "drop action in phase:1",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:1,drop"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with connection close \(phase 1\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^500$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "drop action in phase:2",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:2,drop"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with connection close \(phase 2\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^500$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "drop action in phase:3",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:3,drop"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with connection close \(phase 3\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^500$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "drop action in phase:4",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecAction "phase:4,drop"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/Access denied with connection close \(phase 4\). Unconditional match in SecAction./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^500$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
### Redirect
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "redirect action in phase:1 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:1,redirect:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied with redirection to .* using status 302 \(phase 1\)/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "redirect action in phase:2 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:2,redirect:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied with redirection to .* using status 302 \(phase 2\)/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "redirect action in phase:3 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:3,redirect:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied with redirection to .* using status 302 \(phase 3\)/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "redirect action in phase:4 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:4,redirect:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied with redirection to .* using status 302 \(phase 4\)/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
### Proxy
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "proxy action in phase:1 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:1,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied using proxy to \(phase 1\)/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "proxy action in phase:2 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:2,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied using proxy to \(phase 2\)/, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^200$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "proxy action in phase:3 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:3,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied with code 500 \(phase 3\) \(Configuration Error: Proxy action requested but it does not work in output phases\)./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^500$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type => "rule",
|
||||||
|
comment => "proxy action in phase:4 (get)",
|
||||||
|
conf => qq(
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRule REQUEST_URI "\@streq /test2.txt" "phase:4,proxy:'http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt'"
|
||||||
|
),
|
||||||
|
match_log => {
|
||||||
|
error => [ qr/ModSecurity: Access denied with code 500 \(phase 4\) \(Configuration Error: Proxy action requested but it does not work in output phases\)./, 1 ],
|
||||||
|
},
|
||||||
|
match_response => {
|
||||||
|
status => qr/^500$/,
|
||||||
|
},
|
||||||
|
request => new HTTP::Request(
|
||||||
|
GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test2.txt",
|
||||||
|
),
|
||||||
|
},
|
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
#!@PERL@
|
#!@PERL@
|
||||||
#
|
#
|
||||||
# Run regression tests.
|
# Run regression tests.
|
||||||
@ -71,7 +70,7 @@ EOT
|
|||||||
usage() if ($opt{h});
|
usage() if ($opt{h});
|
||||||
|
|
||||||
### Check startup script
|
### Check startup script
|
||||||
$opt{a} = "apachectl" unless (defined $opt{a});
|
$opt{a} = "httpd" unless (defined $opt{a});
|
||||||
usage("Invalid Apache startup script: $opt{a}\n") unless (-e $opt{a});
|
usage("Invalid Apache startup script: $opt{a}\n") unless (-e $opt{a});
|
||||||
|
|
||||||
### Defaults
|
### Defaults
|
||||||
@ -181,7 +180,7 @@ sub runfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($httpd_up) {
|
if ($httpd_up) {
|
||||||
# Perform the request
|
# Perform the request and check response
|
||||||
if (exists $t{request}) {
|
if (exists $t{request}) {
|
||||||
my $resp = do_request($t{request});
|
my $resp = do_request($t{request});
|
||||||
if (!$resp) {
|
if (!$resp) {
|
||||||
@ -189,21 +188,45 @@ sub runfile {
|
|||||||
dbg("RESPONSE: ", $resp);
|
dbg("RESPONSE: ", $resp);
|
||||||
$rc = 1;
|
$rc = 1;
|
||||||
}
|
}
|
||||||
elsif (exists $t{match_response}{status}) {
|
else {
|
||||||
unless ($resp->code =~ m/$t{match_response}{status}/) {
|
for my $key (keys %{ $t{match_response} || {}}) {
|
||||||
msg("incorrect status code " . $resp->code . ": $t{match_response}{status}");
|
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
|
||||||
$rc = 1;
|
my $m = $t{match_response}{$key};
|
||||||
|
my $match = match_response($mtype, $resp, $m);
|
||||||
|
if ($neg and defined $match) {
|
||||||
|
$rc = 1;
|
||||||
|
msg("response $mtype matched: $m");
|
||||||
|
dbg("$LOG{$mtype}{buf}");
|
||||||
|
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
elsif (!$neg and !defined $match) {
|
||||||
|
$rc = 1;
|
||||||
|
msg("response $mtype no match: $m");
|
||||||
|
dbg("$LOG{$mtype}{buf}");
|
||||||
|
last;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Search for all log matches
|
# Search for all log matches
|
||||||
if ($rc == 0 and exists $t{match_log} and defined $t{match_log}) {
|
if ($rc == 0 and exists $t{match_log} and defined $t{match_log}) {
|
||||||
for my $mtype (keys %{ $t{match_log} || {}}) {
|
for my $key (keys %{ $t{match_log} || {}}) {
|
||||||
my $m = $t{match_log}{$mtype};
|
my($neg,$mtype) = ($key =~ m/^(-?)(.*)$/);
|
||||||
unless (defined log_read_match($mtype, @{$m || []})) {
|
my $m = $t{match_log}{$key};
|
||||||
|
my $match = match_log($mtype, @{$m || []});
|
||||||
|
if ($neg and defined $match) {
|
||||||
$rc = 1;
|
$rc = 1;
|
||||||
msg("$mtype log match failed: $m->[0]");
|
msg("$mtype log matched: $m->[0]");
|
||||||
|
dbg("$LOG{$mtype}{buf}");
|
||||||
|
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
elsif (!$neg and !defined $match) {
|
||||||
|
$rc = 1;
|
||||||
|
msg("$mtype log no match: $m->[0]");
|
||||||
|
dbg("$LOG{$mtype}{buf}");
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,12 +274,30 @@ sub do_request {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub log_read_match {
|
|
||||||
|
sub match_response {
|
||||||
|
my($name, $resp, $re) = @_;
|
||||||
|
|
||||||
|
msg("Warning: Empty regular expression.") if (!defined $re or $re eq "");
|
||||||
|
|
||||||
|
if ($name eq "status") {
|
||||||
|
return $@ if ($resp->code =~ m/$re/m);
|
||||||
|
}
|
||||||
|
elsif ($name eq "content") {
|
||||||
|
return $@ if ($resp->content =~ m/$re/m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub match_log {
|
||||||
my($name, $re, $timeout) = @_;
|
my($name, $re, $timeout) = @_;
|
||||||
my $t0 = gettimeofday();
|
my $t0 = gettimeofday();
|
||||||
my($fh,$rbuf) = ($LOG{$name}{fd}, \$LOG{$name}{buf});
|
my($fh,$rbuf) = ($LOG{$name}{fd}, \$LOG{$name}{buf});
|
||||||
my $n = length($$rbuf);
|
my $n = length($$rbuf);
|
||||||
|
|
||||||
|
msg("Warning: Empty regular expression.") if (!defined $re or $re eq "");
|
||||||
|
|
||||||
$timeout = 0 unless (defined $timeout);
|
$timeout = 0 unless (defined $timeout);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -267,7 +308,7 @@ sub log_read_match {
|
|||||||
sleep 0.1;
|
sleep 0.1;
|
||||||
} while (gettimeofday - $t0 < $timeout);
|
} while (gettimeofday - $t0 < $timeout);
|
||||||
|
|
||||||
return undef;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub escape {
|
sub escape {
|
||||||
@ -288,7 +329,11 @@ sub dbg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub msg {
|
sub msg {
|
||||||
print STDOUT "@_\n" if (@_);
|
return unless(@_);
|
||||||
|
my $out = join "", map {
|
||||||
|
(ref $_ ne "" ? Dumper($_) : $_)
|
||||||
|
} @_;
|
||||||
|
print STDOUT "$out\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub quit {
|
sub quit {
|
||||||
@ -321,7 +366,7 @@ sub httpd_start {
|
|||||||
-k => "start",
|
-k => "start",
|
||||||
);
|
);
|
||||||
|
|
||||||
#dbg("EXEC: ", \@p);
|
# dbg("EXEC: ", \@p);
|
||||||
# dbg("Httpd start");
|
# dbg("Httpd start");
|
||||||
|
|
||||||
my $httpd_out;
|
my $httpd_out;
|
||||||
@ -350,7 +395,7 @@ sub httpd_start {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Look for startup msg
|
# Look for startup msg
|
||||||
unless (defined log_read_match("error", qr/resuming normal operations/, 10)) {
|
unless (defined match_log("error", qr/resuming normal operations/, 10)) {
|
||||||
quit(1, "Httpd server failed to start.");
|
quit(1, "Httpd server failed to start.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +441,7 @@ sub httpd_stop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Look for startup msg
|
# Look for startup msg
|
||||||
unless (defined log_read_match("error", qr/caught SIG[A-Z]+, shutting down/, 10)) {
|
unless (defined match_log("error", qr/caught SIG[A-Z]+, shutting down/, 10)) {
|
||||||
quit(1, "Httpd server failed to shutdown.");
|
quit(1, "Httpd server failed to shutdown.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +487,7 @@ sub httpd_reload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Look for startup msg
|
# Look for startup msg
|
||||||
unless (defined log_read_match("error", qr/resuming normal operations/, 10)) {
|
unless (defined match_log("error", qr/resuming normal operations/, 10)) {
|
||||||
quit(1, "Httpd server failed to reload.");
|
quit(1, "Httpd server failed to reload.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user