From a6c2d867f40338401d8010e1a426bb7720897520 Mon Sep 17 00:00:00 2001 From: brectanus Date: Fri, 30 Nov 2007 21:31:12 +0000 Subject: [PATCH] Improvements to audit logging matching rules. See #93. --- CHANGES | 4 ++- apache2/msc_logging.c | 41 +++++++++++++++++---------- apache2/msc_logging.h | 4 ++- apache2/re.c | 10 ++++++- doc/modsecurity2-apache-reference.xml | 5 ++++ 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 7764ec22..397d7206 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,9 @@ 29 Nov 2007 - 2.5.0-dev3 ------------------------ - * Added matching rules to audit log data. + * The invoked rule is now logged in the debug log at level 5. + + * New audit log part 'K' logs all matching rules. * Implemented SecRequestBodyNoFilesLimit. diff --git a/apache2/msc_logging.c b/apache2/msc_logging.c index 71e216c2..0110d61b 100644 --- a/apache2/msc_logging.c +++ b/apache2/msc_logging.c @@ -463,7 +463,7 @@ void sec_audit_logger(modsec_rec *msr) { /* AUDITLOG_PART_HEADER */ - text = apr_psprintf(msr->mp, "--%s-A--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_HEADER); sec_auditlog_write(msr, text, strlen(text)); /* Format: time transaction_id remote_addr remote_port local_addr local_port */ @@ -477,7 +477,7 @@ void sec_audit_logger(modsec_rec *msr) { /* AUDITLOG_PART_REQUEST_HEADERS */ if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_REQUEST_HEADERS) != NULL) { - text = apr_psprintf(msr->mp, "\n--%s-B--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_REQUEST_HEADERS); sec_auditlog_write(msr, text, strlen(text)); sanitise_request_line(msr); @@ -581,7 +581,7 @@ void sec_audit_logger(modsec_rec *msr) { unsigned int sanitise_offset = 0; unsigned int sanitise_length = 0; - text = apr_psprintf(msr->mp, "\n--%s-C--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_REQUEST_BODY); sec_auditlog_write(msr, text, strlen(text)); for(;;) { @@ -669,7 +669,7 @@ void sec_audit_logger(modsec_rec *msr) { if (buffer == NULL) { msr_log(msr, 1, "Audit log: Failed to reconstruct request body."); } else { - text = apr_psprintf(msr->mp, "\n--%s-I--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_FAKE_REQUEST_BODY); sec_auditlog_write(msr, text, strlen(text)); sec_auditlog_write(msr, buffer, strlen(buffer)); } @@ -679,7 +679,7 @@ void sec_audit_logger(modsec_rec *msr) { /* AUDITLOG_PART_A_RESPONSE_HEADERS */ if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_A_RESPONSE_HEADERS) != NULL) { - text = apr_psprintf(msr->mp, "\n--%s-F--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_A_RESPONSE_HEADERS); sec_auditlog_write(msr, text, strlen(text)); /* There are no response headers (or the status line) in HTTP 0.9 */ @@ -713,7 +713,7 @@ void sec_audit_logger(modsec_rec *msr) { if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_RESPONSE_BODY) != NULL) { if (msr->resbody_data != NULL) { - text = apr_psprintf(msr->mp, "\n--%s-E--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_RESPONSE_BODY); sec_auditlog_write(msr, text, strlen(text)); sec_auditlog_write(msr, msr->resbody_data, msr->resbody_length); wrote_response_body = 1; @@ -725,7 +725,7 @@ void sec_audit_logger(modsec_rec *msr) { if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_TRAILER) != NULL) { apr_time_t now = apr_time_now(); - text = apr_psprintf(msr->mp, "\n--%s-H--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_TRAILER); sec_auditlog_write(msr, text, strlen(text)); /* Messages */ @@ -734,13 +734,6 @@ void sec_audit_logger(modsec_rec *msr) { sec_auditlog_write(msr, text, strlen(text)); } - /* Matched Rules */ - for(i = 0; i < msr->matched_rules->nelts; i++) { - rule = ((msre_rule **)msr->matched_rules->elts)[i]; - text = apr_psprintf(msr->mp, "MatchedRule: %s\n", rule->unparsed); - sec_auditlog_write(msr, text, strlen(text)); - } - /* Apache error messages */ for(i = 0; i < msr->error_messages->nelts; i++) { error_message *em = (((error_message**)msr->error_messages->elts)[i]); @@ -880,10 +873,28 @@ void sec_audit_logger(modsec_rec *msr) { } } + /* AUDITLOG_PART_UPLOADS */ + // TODO: Implement + + + /* AUDITLOG_PART_MATCHEDRULES */ + + if (strchr(msr->txcfg->auditlog_parts, AUDITLOG_PART_MATCHEDRULES) != NULL) { + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_MATCHEDRULES); + sec_auditlog_write(msr, text, strlen(text)); + + /* Matched Rules */ + for(i = 0; i < msr->matched_rules->nelts; i++) { + rule = ((msre_rule **)msr->matched_rules->elts)[i]; + text = apr_psprintf(msr->mp, "%s\n", rule->unparsed); + sec_auditlog_write(msr, text, strlen(text)); + } + } + /* AUDITLOG_PART_ENDMARKER */ - text = apr_psprintf(msr->mp, "\n--%s-Z--\n", msr->new_auditlog_boundary); + text = apr_psprintf(msr->mp, "\n--%s-%c--\n", msr->new_auditlog_boundary, AUDITLOG_PART_ENDMARKER); sec_auditlog_write(msr, text, strlen(text)); /* Return here if we were writing to a serial log diff --git a/apache2/msc_logging.h b/apache2/msc_logging.h index 6cfaa181..83496960 100644 --- a/apache2/msc_logging.h +++ b/apache2/msc_logging.h @@ -28,7 +28,9 @@ #define AUDITLOG_PART_A_RESPONSE_BODY 'G' #define AUDITLOG_PART_TRAILER 'H' #define AUDITLOG_PART_FAKE_REQUEST_BODY 'I' -#define AUDITLOG_PART_LAST 'I' +#define AUDITLOG_PART_UPLOADS 'J' +#define AUDITLOG_PART_MATCHEDRULES 'K' +#define AUDITLOG_PART_LAST 'K' #define AUDITLOG_PART_ENDMARKER 'Z' #include "modsecurity.h" diff --git a/apache2/re.c b/apache2/re.c index e84bb5d2..a8added5 100644 --- a/apache2/re.c +++ b/apache2/re.c @@ -790,6 +790,7 @@ apr_status_t msre_ruleset_process_phase(msre_ruleset *ruleset, modsec_rec *msr) } msr_log(msr, 4, "Recipe: Invoking rule %pp;%s%s%s.", rule, (fn ? fn : ""), (id ? id : ""), (rev ? rev : "")); + msr_log(msr, 5, "Rule %pp: %s", rule, rule->unparsed); } #if defined(PERFORMANCE_MEASUREMENT) @@ -1214,10 +1215,17 @@ msre_rule *msre_rule_create(msre_ruleset *ruleset, rule->ruleset = ruleset; rule->targets = apr_array_make(ruleset->mp, 10, sizeof(const msre_var *)); rule->p1 = apr_pstrdup(ruleset->mp, targets); - rule->unparsed = apr_pstrcat(ruleset->mp, ((strcmp(SECACTION_TARGETS, targets) || strcmp(SECACTION_TARGETS, args)) ? "SecRule" : "SecAction"), " ", targets, " ", args, " ", actions, NULL); rule->filename = apr_pstrdup(ruleset->mp, fn); rule->line_num = line; + /* Add the unparsed rule */ + if ((strcmp(SECACTION_TARGETS, targets) == 0) && (strcmp(SECACTION_ARGS, args) == 0)) { + rule->unparsed = apr_pstrcat(ruleset->mp, "SecAction", " \"", actions, "\"", NULL); + } + else { + rule->unparsed = apr_pstrcat(ruleset->mp, "SecRule", " \"", targets, "\" \"", args, "\"", (actions != NULL ? " \"" : ""), (actions != NULL ? actions : ""), (actions != NULL ? "\"" : ""), NULL); + } + /* Parse targets */ rc = msre_parse_targets(ruleset, targets, rule->targets, &my_error_msg); if (rc < 0) { diff --git a/doc/modsecurity2-apache-reference.xml b/doc/modsecurity2-apache-reference.xml index d210f087..86121ac6 100644 --- a/doc/modsecurity2-apache-reference.xml +++ b/doc/modsecurity2-apache-reference.xml @@ -676,6 +676,11 @@ SecAuditLogStorageDir logs/audit using multipart/form-data encoding. + + K - This part contains a + full list of every rule that matched (one per line) in the order they were matched. + + Z - final boundary, signifies the end of the entry (mandatory)