Updates to parse_modsec.pl

This commit is contained in:
Robert Paprocki 2015-12-07 22:15:28 -08:00 committed by Felipe Zimmerle
parent 2307a8b55b
commit 374871e10e

View File

@ -22,7 +22,7 @@ Parse ModSecurity logs generated as JSON
=head1 USAGE =head1 USAGE
Usage: $0 [h] [Gtsrfdbalspj] Usage: $0 [h] [Htsrfdbalspjv]
-H|--host Search rules based on the Host request header -H|--host Search rules based on the Host request header
-t|--transaction-id Search rules based on the unique transaction ID -t|--transaction-id Search rules based on the unique transaction ID
-s|--source-ip Search rules based on the client IP address (can be presented as an address or CIDR block) -s|--source-ip Search rules based on the client IP address (can be presented as an address or CIDR block)
@ -35,7 +35,7 @@ Usage: $0 [h] [Gtsrfdbalspj]
-S|--stdin Read rules from stdin instead of an on-disk file -S|--stdin Read rules from stdin instead of an on-disk file
-p|--partial-chains Do not prune partial chain matches -p|--partial-chains Do not prune partial chain matches
-j|--json Print rule entries as a JSON blob, rather than nice formatting -j|--json Print rule entries as a JSON blob, rather than nice formatting
-v|--verbose Be verbose about various details such as JSON parse failures -v|--verbose Be verbose about various details such as JSON parse failures and log data
=head2 FILTERS =head2 FILTERS
@ -129,6 +129,10 @@ Print all log entries from the default log location:
parse_modsec.pl parse_modsec.pl
Print all log entries and show more detailed information, such as response data and matched rule details
parse_modsec.pl -v
Print entries matching a specific source IP: Print entries matching a specific source IP:
parse_modsec.pl -s 1.2.3.4 parse_modsec.pl -s 1.2.3.4
@ -161,7 +165,7 @@ Print entries that contain an HTTP GET request with a 'Content-Length' header
sub usage { sub usage {
print <<"_EOF"; print <<"_EOF";
Usage: $0 [h] [Gtsrfdbalspj] Usage: $0 [h] [Htsrfdbalspjv]
-h|--help Print this help -h|--help Print this help
-H|--host Search rules based on the Host request header -H|--host Search rules based on the Host request header
-t|--transaction-id Search rules based on the unique transaction ID -t|--transaction-id Search rules based on the unique transaction ID
@ -175,7 +179,7 @@ Usage: $0 [h] [Gtsrfdbalspj]
-S|--stdin Read rules from stdin instead of an on-disk file -S|--stdin Read rules from stdin instead of an on-disk file
-p|--partial-chains Do not prune partial chain matches -p|--partial-chains Do not prune partial chain matches
-j|--json Print rule entries as a JSON blob, rather than nice formatting -j|--json Print rule entries as a JSON blob, rather than nice formatting
-v|--verbose Be verbose about various details such as JSON parse failures -v|--verbose Be verbose about various details such as JSON parse failures and log data
For detailed explanations of various options and example usages, see 'perldoc $0' For detailed explanations of various options and example usages, see 'perldoc $0'
@ -339,22 +343,44 @@ sub print_matches {
} else { } else {
printf "\n%s\n", '=' x 80; printf "\n%s\n", '=' x 80;
# request my $transaction = $entry->{transaction};
my $transaction = $entry->{transaction}; my $request = $entry->{request};
my $request = $entry->{request}; my $response = $entry->{response};
my $audit_data = $entry->{audit_data};
my $matched_rules = $entry->{matched_rules};
printf "%s\nTransaction ID: %s\nIP: %s\n\n%s\n", if ($transaction) {
parse_modsec_timestamp($transaction->{time}), printf "%s\nTransaction ID: %s\nIP: %s\n\n",
$transaction->{transaction_id}, parse_modsec_timestamp($transaction->{time}),
$transaction->{remote_address}, $transaction->{transaction_id},
$request->{request_line}; $transaction->{remote_address};
for my $header (sort keys %{$request->{headers}}) {
printf "%s: %s\n", $header, $request->{headers}->{$header};
} }
# matched rules printf "%s\n", $request->{request_line}
for my $chain (@{$entry->{matched_rules}}) { if $request->{request_line};
if ($request->{headers}) {
for my $header (sort keys %{$request->{headers}}) {
printf "%s: %s\n", $header, $request->{headers}->{$header};
}
}
if ($verbose) {
print join ("\n", @{$request->{body}}) . "\n"
if $request->{body};
printf "\n%s %s\n", $response->{protocol}, $response->{status}
if $response->{protocol} && $response->{status};
for my $header (sort keys %{$response->{headers}}) {
printf "%s: %s\n", $header, $response->{headers}->{$header};
}
printf "\n%s\n", $response->{body}
if $response->{body};
}
for my $chain (@{$matched_rules}) {
print "\n"; print "\n";
my @extra_data; my @extra_data;
my $ctr = 0; my $ctr = 0;
@ -365,11 +391,12 @@ sub print_matches {
push @extra_data, $rule->{actionset}->{logdata} if $rule->{actionset}->{logdata}; push @extra_data, $rule->{actionset}->{logdata} if $rule->{actionset}->{logdata};
} }
printf "\n-- %s\n", join "\n-- ", @extra_data if @extra_data && $verbose; printf "\n-- %s\n", join "\n-- ", @extra_data
if @extra_data && $verbose;
} }
# audit message printf "\n-- %s\n\n", $audit_data->{action}->{message}
printf "\n-- %s\n\n", $entry->{audit_data}->{action}->{message} if $verbose; if $audit_data->{action}->{message} && $verbose;
printf "%s\n", '=' x 80; printf "%s\n", '=' x 80;
} }
@ -531,7 +558,7 @@ sub main {
$after = build_datetime($after); $after = build_datetime($after);
# figure where we're reading from # figure where we're reading from
$logpath ||= '/var/log/modsec_audit.log'; $logpath ||= '/var/log/mod_sec/modsec_audit.log';
$fh = get_input({ $fh = get_input({
logpath => $logpath, logpath => $logpath,
stdin => $stdin, stdin => $stdin,
@ -551,7 +578,7 @@ sub main {
delim => $delim, delim => $delim,
}); });
# walk through our input, getting an arrayref of entries valid based on filters and timeframe # walk through our input, getting an arrayref of valid entries based on filters and timeframe
$parsed_ref = grok_input({ $parsed_ref = grok_input({
fh => $fh, fh => $fh,
filters => \%filters, filters => \%filters,