More regression testing updates.

This commit is contained in:
brectanus
2008-06-02 23:13:45 +00:00
parent 6cd8459bc8
commit e209cb7688
6 changed files with 477 additions and 36 deletions

View File

@@ -135,7 +135,7 @@
),
match_log => {
-error => [ qr/ModSecurity: /, 1 ],
# ENH: No message, but should have data. Is this intended?
# No message, but should have data. This may need changed
audit => [ qr/-H--\s+Stopwatch: /s, 1 ],
},
match_response => {

View File

@@ -190,7 +190,7 @@
SecDebugLogLevel 9
SecRequestBodyAccess On
SecRequestBodyLimit 1000
SecRequestBodyInMemoryLimit 266
SecRequestBodyInMemoryLimit 276
),
match_log => {
-debug => [ qr/Input filter: Request too large to store in memory, switching to disk\./, 1 ],
@@ -198,22 +198,32 @@
match_response => {
status => qr/^200$/,
},
request => qq(
POST /test.txt HTTP/1.1
Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
User-Agent: $ENV{USER_AGENT}
Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
Transfer-Encoding: chunked
request => normalize_raw_request_data(
qq(
POST /test.txt HTTP/1.1
Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
User-Agent: $ENV{USER_AGENT}
Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
Transfer-Encoding: chunked
) . encode_chunked(q(-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
),
)
.encode_chunked(
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
2
-----------------------------69343412719991675451336310646--), 1024),
2
-----------------------------69343412719991675451336310646--
)
),
1024
),
},
{
type => "config",
@@ -232,22 +242,32 @@ Content-Disposition: form-data; name="b"
match_response => {
status => qr/^200$/,
},
request => qq(
POST /test.txt HTTP/1.1
Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
User-Agent: $ENV{USER_AGENT}
Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
Transfer-Encoding: chunked
request => normalize_raw_request_data(
qq(
POST /test.txt HTTP/1.1
Host: $ENV{SERVER_NAME}:$ENV{SERVER_PORT}
User-Agent: $ENV{USER_AGENT}
Content-Type: multipart/form-data; boundary=---------------------------69343412719991675451336310646
Transfer-Encoding: chunked
) . encode_chunked(q(-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
),
)
.encode_chunked(
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
2
-----------------------------69343412719991675451336310646--), 1024),
2
-----------------------------69343412719991675451336310646--
)
),
1024
),
},
# SecCookieFormat

View File

@@ -0,0 +1,361 @@
### Multipart parser tests
# Final CRLF or not, we should still work
{
type => "misc",
comment => "multipart parser (final CRLF)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecRule MULTIPART_STRICT_ERROR "\@eq 1" "phase:2,deny"
SecRule MULTIPART_UNMATCHED_BOUNDARY "\@eq 1" "phase:2,deny"
SecRule REQBODY_PROCESSOR_ERROR "\@eq 1" "phase:2,deny"
),
match_log => {
debug => [ qr/Adding request argument \(BODY\): name "a", value "1".*Adding request argument \(BODY\): name "b", value "2"/s, 1 ],
-debug => [ qr/Multipart error:/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
2
-----------------------------69343412719991675451336310646--
),
),
),
},
{
type => "misc",
comment => "multipart parser (no final CRLF)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecRule MULTIPART_STRICT_ERROR "\@eq 1" "phase:2,deny"
SecRule MULTIPART_UNMATCHED_BOUNDARY "\@eq 1" "phase:2,deny"
SecRule REQBODY_PROCESSOR_ERROR "\@eq 1" "phase:2,deny"
),
match_log => {
debug => [ qr/Adding request argument \(BODY\): name "a", value "1".*Adding request argument \(BODY\): name "b", value "2"/s, 1 ],
-debug => [ qr/Multipart error:/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
2
-----------------------------69343412719991675451336310646--),
),
),
},
# Should work with a boundary of "boundary"
{
type => "misc",
comment => "multipart parser (boundary contains \"boundary\")",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecRule MULTIPART_STRICT_ERROR "\@eq 1" "phase:2,deny"
SecRule MULTIPART_UNMATCHED_BOUNDARY "\@eq 1" "phase:2,deny"
SecRule REQBODY_PROCESSOR_ERROR "\@eq 1" "phase:2,deny"
),
match_log => {
debug => [ qr/Adding request argument \(BODY\): name "a", value "1".*Adding request argument \(BODY\): name "b", value "2"/s, 1 ],
-debug => [ qr/Multipart error:/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=------------------------------------------------boundary",
],
normalize_raw_request_data(
q(
--------------------------------------------------boundary
Content-Disposition: form-data; name="a"
1
--------------------------------------------------boundary
Content-Disposition: form-data; name="b"
2
--------------------------------------------------boundary--
),
),
),
},
{
type => "misc",
comment => "multipart parser (boundary contains \"BoUnDaRy\")",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecRule MULTIPART_STRICT_ERROR "\@eq 1" "phase:2,deny"
SecRule MULTIPART_UNMATCHED_BOUNDARY "\@eq 1" "phase:2,deny"
SecRule REQBODY_PROCESSOR_ERROR "\@eq 1" "phase:2,deny"
),
match_log => {
debug => [ qr/Adding request argument \(BODY\): name "a", value "1".*Adding request argument \(BODY\): name "b", value "2"/s, 1 ],
-debug => [ qr/Multipart error:/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=------------------------------------------------BoUnDaRy",
],
normalize_raw_request_data(
q(
--------------------------------------------------BoUnDaRy
Content-Disposition: form-data; name="a"
1
--------------------------------------------------BoUnDaRy
Content-Disposition: form-data; name="b"
2
--------------------------------------------------BoUnDaRy--
),
),
),
},
# We should handle data starting with a "--"
{
type => "misc",
comment => "multipart parser (data contains \"--\")",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecRule MULTIPART_STRICT_ERROR "\@eq 1" "phase:2,deny"
SecRule REQBODY_PROCESSOR_ERROR "\@eq 1" "phase:2,deny"
),
match_log => {
debug => [ qr/Adding request argument \(BODY\): name "a", value "--test".*Adding request argument \(BODY\): name "b", value "--"/s, 1 ],
-debug => [ qr/Multipart error:/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
--test
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
--
-----------------------------69343412719991675451336310646--),
),
),
},
# We should emit warnings for parsing errors
{
type => "misc",
comment => "multipart parser error (no final boundary)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecAuditLog "$ENV{AUDIT_LOG}"
SecAuditEngine RelevantOnly
),
match_log => {
audit => [ qr/Final boundary missing/, 1 ],
debug => [ qr/Final boundary missing/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="a"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data; name="b"
2
),
),
),
},
{
type => "misc",
comment => "multipart parser error (no disposition)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecAuditLog "$ENV{AUDIT_LOG}"
SecAuditEngine RelevantOnly
),
match_log => {
-debug => [ qr/Multipart error:/, 1 ],
audit => [ qr/Part missing Content-Disposition header/, 1 ],
debug => [ qr/Part missing Content-Disposition header/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
1
-----------------------------69343412719991675451336310646
2
-----------------------------69343412719991675451336310646--
),
),
),
},
{
type => "misc",
comment => "multipart parser error (bad disposition)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecAuditLog "$ENV{AUDIT_LOG}"
SecAuditEngine RelevantOnly
),
match_log => {
audit => [ qr/Invalid Content-Disposition header/, 1 ],
debug => [ qr/Invalid Content-Disposition header/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data name="a"
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data name="b"
2
-----------------------------69343412719991675451336310646--
),
),
),
},
{
type => "misc",
comment => "multipart parser error (no disposition name)",
conf => qq(
SecRuleEngine On
SecDebugLog $ENV{DEBUG_LOG}
SecDebugLogLevel 9
SecRequestBodyAccess On
SecAuditLog "$ENV{AUDIT_LOG}"
SecAuditEngine RelevantOnly
),
match_log => {
-debug => [ qr/Multipart error:/, 1 ],
audit => [ qr/Content-Disposition header missing name field/, 1 ],
debug => [ qr/Content-Disposition header missing name field/, 1 ],
},
match_response => {
status => qr/^200$/,
},
request => new HTTP::Request(
POST => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
[
"Content-Type" => "multipart/form-data; boundary=---------------------------69343412719991675451336310646",
],
normalize_raw_request_data(
q(
-----------------------------69343412719991675451336310646
Content-Disposition: form-data;
1
-----------------------------69343412719991675451336310646
Content-Disposition: form-data;
2
-----------------------------69343412719991675451336310646--
),
),
),
},

View File

@@ -2,7 +2,7 @@
# SecAction
{
type => "config",
type => "rule",
comment => "SecAction (override default)",
conf => qq(
SecRuleEngine On

View File

@@ -370,7 +370,51 @@
),
},
# TODO: AUTH_TYPE
# AUTH_TYPE
#{
# type => "target",
# comment => "AUTH_TYPE",
# conf => qq(
# <IfVersion >= 2.2>
# <IfModule !mod_authn_file.c>
# LoadModule authn_file_module modules/mod_authn_file.so
# </IfModule>
# </IfVersion>
## <IfVersion ~ ^2.0.>
## <IfModule !mod_auth.c>
## LoadModule auth_module modules/mod_auth.so
## </IfModule>
## </IfVersion>
# <Location />
# AuthType Basic
# AuthName Test
# AuthUserFile "$ENV{CONF_DIR}/htpasswd"
# Require user nobody
# </Location>
# SecRuleEngine On
# SecRequestBodyAccess On
# SecResponseBodyAccess On
# SecResponseBodyMimeType null
## SecDebugLog $ENV{DEBUG_LOG}
## SecDebugLogLevel 9
# SecRule REQUEST_HEADERS:Authorization "Basic (.*)" "phase:2,log,pass,capture,chain"
# SecRule TX:1 "nobody:test" "t:none,t:base64Decode,chain"
# SecRule AUTH_TYPE "Basic"
# ),
# match_log => {
# error => [ qr/Pattern match "Basic" at AUTH_TYPE/s, 1 ],
# },
# match_response => {
# status => qr/^200$/,
# },
# request => new HTTP::Request(
# GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
# [
# "Authorization" => "Basic bm9ib2R5OnRlc3Q="
# ],
# ),
#},
# TODO: ENV
# TODO: FILES
# TODO: FILES_COMBINED_SIZE

View File

@@ -21,7 +21,7 @@ use Data::Dumper;
use IO::Socket;
use LWP::UserAgent;
my @TYPES = qw(config action target rule);
my @TYPES = qw(config misc action target rule);
my $SCRIPT = basename($0);
my $SCRIPT_DIR = File::Spec->rel2abs(dirname($0));
my $REG_DIR = "$SCRIPT_DIR/regression";
@@ -324,6 +324,23 @@ sub runfile {
msg(sprintf("Passed: %2d; Failed: %2d", $pass, $testnum ? (1 - $pass) : ($n - $pass)));
}
# Take out any indenting and translate LF -> CRLF
sub normalize_raw_request_data {
my $r = $_[0];
# Allow for indenting in test file
$r =~ s/^[ \t]*\x0d?\x0a//s;
my($indention) = ($r =~ m/^([ \t]*)/s); # indention taken from first line
$r =~ s/^$indention//mg;
$r =~ s/(\x0d?\x0a)[ \t]+$/$1/s;
# Translate LF to CRLF
$r =~ s/^\x0a/\x0d\x0a/mg;
$r =~ s/([^\x0d])\x0a/$1\x0d\x0a/mg;
return $r;
}
sub do_raw_request {
my $sock = new IO::Socket::INET(
Proto => "tcp",
@@ -332,15 +349,14 @@ sub do_raw_request {
) or msg("Failed to connect to localhost:$opt{p}: $@");
return unless ($sock);
my $r = "@_";
$r =~ s/^[^A-Z]+//s;
$r =~ s/^[ \t]+//mg;
$r =~ s/^\x0a/\x0d\x0a/mg;
$r =~ s/([^\x0d])\x0a/$1\x0d\x0a/mg;
# Join togeather the request
my $r = join("", @_);
# Write to socket
print $sock "$r";
$sock->shutdown(1);
# Read from socket
my @resp = <$sock>;
$sock->close();