diff --git a/CHANGES b/CHANGES index 8df030bb..4da6f6a7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -03 Feb 2010 - 2.5.12 +04 Feb 2010 - 2.5.12 -------------------- + * Fixed nolog,auditlog/noauditlog/nolog controls for disruptive actions. + * Added additional file info definitions introduced in APR 0.9.5 so that build will work with older APRs (IBM HTTP Server v6). diff --git a/apache2/mod_security2.c b/apache2/mod_security2.c index 043f5a2b..1d00e9c3 100644 --- a/apache2/mod_security2.c +++ b/apache2/mod_security2.c @@ -228,9 +228,24 @@ int perform_interception(modsec_rec *msr) { break; } + /* If the level is not high enough to add an alert message, but "auditlog" + * is enabled, then still add the message. */ + if ((log_level > 3) && (actionset->auditlog != 0)) { + *(const char **)apr_array_push(msr->alerts) = msc_alert_message(msr, actionset, NULL, message); + } + /* Log the message now. */ msc_alert(msr, log_level, actionset, message, msr->intercept_message); + /* However, this will mark the txn relevant again if it is <= 3, + * which will mess up noauditlog. We need to compensate for this + * so that we do not increment twice when auditlog is enabled and + * prevent incrementing when auditlog is disabled. + */ + if ((actionset->auditlog == 0) && (log_level <= 3)) { + msr->is_relevant--; + } + return status; } diff --git a/apache2/t/regression/action/10-logging.t b/apache2/t/regression/action/10-logging.t index 0a199eab..3c1d42b2 100644 --- a/apache2/t/regression/action/10-logging.t +++ b/apache2/t/regression/action/10-logging.t @@ -1,17 +1,21 @@ ### Logging tests -# log/nolog +# log/nolog (pass) { type => "action", - comment => "log", + comment => "log (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,log" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: Warning\. Unconditional match in SecAction\./, 1 ], }, match_response => { status => qr/^200$/, @@ -22,9 +26,12 @@ }, { type => "action", - comment => "nolog", + comment => "nolog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,nolog" @@ -41,19 +48,70 @@ ), }, -# auditlog/noauditlog +# log/nolog (deny) { type => "action", - comment => "auditlog", + comment => "log (deny)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,log" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: 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 => "action", + comment => "nolog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,nolog" + ), + match_log => { + -error => [ qr/ModSecurity: /, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, + +# auditlog/noauditlog (pass) +{ + type => "action", + comment => "auditlog (pass)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,auditlog" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], - audit => [ qr/Message: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: Warning\. Unconditional match in SecAction\./, 1 ], }, match_response => { status => qr/^200$/, @@ -64,15 +122,18 @@ }, { type => "action", - comment => "noauditlog", + comment => "noauditlog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,noauditlog" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], -audit => [ qr/./, 1 ], }, match_response => { @@ -83,19 +144,70 @@ ), }, -# All log/nolog auditlog/noauditlog combos +# auditlog/noauditlog (deny) { type => "action", - comment => "log,auditlog", + comment => "auditlog (deny)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,auditlog" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: 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 => "action", + comment => "noauditlog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,noauditlog" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, + +# All log/nolog auditlog/noauditlog combos (pass) +{ + type => "action", + comment => "log,auditlog (pass)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,log,auditlog" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], - audit => [ qr/Message: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: Warning\. Unconditional match in SecAction\./, 1 ], }, match_response => { status => qr/^200$/, @@ -106,15 +218,18 @@ }, { type => "action", - comment => "log,noauditlog", + comment => "log,noauditlog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,log,noauditlog" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], -audit => [ qr/./, 1 ], }, match_response => { @@ -126,9 +241,12 @@ }, { type => "action", - comment => "nolog,auditlog", + comment => "nolog,auditlog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,nolog,auditlog" @@ -145,9 +263,12 @@ }, { type => "action", - comment => "nolog,noauditlog", + comment => "nolog,noauditlog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,nolog,noauditlog" @@ -165,16 +286,19 @@ }, { type => "action", - comment => "auditlog,log", + comment => "auditlog,log (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,auditlog,log" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], - audit => [ qr/Message: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: Warning\. Unconditional match in SecAction\./, 1 ], }, match_response => { status => qr/^200$/, @@ -185,9 +309,12 @@ }, { type => "action", - comment => "auditlog,nolog", + comment => "auditlog,nolog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,auditlog,nolog" @@ -205,15 +332,18 @@ }, { type => "action", - comment => "noauditlog,log", + comment => "noauditlog,log (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,noauditlog,log" ), match_log => { - error => [ qr/ModSecurity: Warning. Unconditional match in SecAction\./, 1 ], + error => [ qr/ModSecurity: Warning\. Unconditional match in SecAction\./, 1 ], -audit => [ qr/./, 1 ], }, match_response => { @@ -225,9 +355,12 @@ }, { type => "action", - comment => "noauditlog,nolog", + comment => "noauditlog,nolog (pass)", conf => qq( SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx SecAuditEngine RelevantOnly SecAuditLog "$ENV{AUDIT_LOG}" SecAction "phase:1,pass,noauditlog,nolog" @@ -244,3 +377,188 @@ ), }, +# All log/nolog auditlog/noauditlog combos (deny) +{ + type => "action", + comment => "log,auditlog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,log,auditlog" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: 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 => "action", + comment => "log,noauditlog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,log,noauditlog" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, +{ + type => "action", + comment => "nolog,auditlog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,nolog,auditlog" + ), + match_log => { + audit => [ qr/-H--\s+Message: .*Stopwatch: /s, 1 ], + }, + match_response => { + -error => [ qr/ModSecurity: /, 1 ], + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, +{ + type => "action", + comment => "nolog,noauditlog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,nolog,noauditlog" + ), + match_log => { + -error => [ qr/ModSecurity: /, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, +{ + type => "action", + comment => "auditlog,log (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,auditlog,log" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + audit => [ qr/Message: 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 => "action", + comment => "auditlog,nolog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,auditlog,nolog" + ), + match_log => { + -error => [ qr/ModSecurity: /, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, +{ + type => "action", + comment => "noauditlog,log (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,noauditlog,log" + ), + match_log => { + error => [ qr/ModSecurity: Access denied with code 403 \(phase 1\)\. Unconditional match in SecAction\./, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +}, +{ + type => "action", + comment => "noauditlog,nolog (deny)", + conf => qq( + SecRuleEngine On + SecDebugLog "$ENV{DEBUG_LOG}" + SecDebugLogLevel 9 + SecAuditLogRelevantStatus xxx + SecAuditEngine RelevantOnly + SecAuditLog "$ENV{AUDIT_LOG}" + SecAction "phase:1,deny,status:403,noauditlog,nolog" + ), + match_log => { + -error => [ qr/ModSecurity: /, 1 ], + -audit => [ qr/./, 1 ], + }, + match_response => { + status => qr/^403$/, + }, + request => new HTTP::Request( + GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt", + ), +},