From e759b3300aace5314fe3d30800c8bd83c81c29f7 Mon Sep 17 00:00:00 2001 From: sullo Date: Thu, 31 May 2018 23:30:03 -0400 Subject: [PATCH] Fix CSV injection issue if server responds with a malicious Server string & CSV output is opened in Excel or other spreadsheet app. Potentially malicious cell start characters are now prefaced with a ' mark. Thanks to Adam (@bytesoverbombs) for letting me know! Also fixed a crash in the outdated plugin if the $sepr field ends up being something that triggers a panic in split(). --- program/plugins/nikto_outdated.plugin | 2 +- program/plugins/nikto_report_csv.plugin | 41 +++++++++++++++---------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/program/plugins/nikto_outdated.plugin b/program/plugins/nikto_outdated.plugin index 219505c..08562c5 100644 --- a/program/plugins/nikto_outdated.plugin +++ b/program/plugins/nikto_outdated.plugin @@ -88,7 +88,7 @@ sub nikto_outdated { $sepr = substr($sepr, (length($sepr) - 1), 1); # break up ID string on $sepr - my @T = split(/$sepr/, $mark->{'banner'}); + my @T = split(/\\$sepr/, $mark->{'banner'}); # assume last is version... for ($i = 0 ; $i < $#T ; $i++) { $MATCHSTRING .= "$T[$i] "; } diff --git a/program/plugins/nikto_report_csv.plugin b/program/plugins/nikto_report_csv.plugin index ce65cfe..76bdb3f 100644 --- a/program/plugins/nikto_report_csv.plugin +++ b/program/plugins/nikto_report_csv.plugin @@ -53,10 +53,11 @@ sub csv_host_start { my ($handle, $mark) = @_; $mark->{'banner'} =~ s/"/\\"/g; my $hostname = $mark->{'vhost'} ? $mark->{'vhost'} : $mark->{'hostname'}; - print $handle "\"$hostname\"," - . "\"$mark->{'ip'}\"," - . "\"$mark->{'port'}\"," . "\"\"," . "\"\"," . "\"\"," - . "\"$mark->{'banner'}\"\n"; + print $handle "\"" . csv_safecell($hostname) . "\"," + . "\"" . csv_safecell($mark->{'ip'}) . "\"," + . "\"" . csv_safecell($mark->{'port'}) . "\"," . "\"\"," . "\"\"," . "\"\"," + #. "\"" . $mark->{'banner'} . "\"\n"; + . "\"" . csv_safecell($mark->{'banner'}) . "\"\n"; return; } @@ -67,33 +68,41 @@ sub csv_item { foreach my $uri (split(' ', $item->{'uri'})) { my $line = ''; my $hostname = $item->{'mark'}->{'vhost'} ? $item->{'mark'}->{'vhost'} : $item->{'mark'}->{'hostname'}; - $line .= "\"$hostname\","; - $line .= "\"$item->{'mark'}->{'ip'}\","; - $line .= "\"$item->{'mark'}->{'port'}\","; + $line .= "\"" . csv_safecell($hostname) . "\","; + $line .= "\"" . csv_safecell($item->{'mark'}->{'ip'}) . \","; + $line .= "\"" . csv_safecell($item->{'mark'}->{'port'}) . "\","; $line .= "\""; if ($item->{'osvdb'} ne '') { $line .= "OSVDB-" . $item->{'osvdb'}; } $line .= "\","; $line .= "\""; - if ($item->{'method'} ne '') { $line .= $item->{'method'}; } + if ($item->{'method'} ne '') { $line .= csv_safecell($item->{'method'}); } $line .= "\","; $line .= "\""; if (($uri ne '') && ($mark->{'root'} ne '') && ($uri !~ /^$mark->{'root'}/)) - { $line .= $mark->{'root'} . $uri; } - else { $line .= $uri; } + { $line .= csv_safecell($mark->{'root'}) . $uri; } + else { $line .= csv_safecell($uri); } $line .= "\","; - my $msg = $item->{'message'}; - $uri=quotemeta($uri); - my $root = quotemeta($mark->{'root'}); - $msg =~ s/^$uri:\s//; - $msg =~ s/^$root$uri:\s//; + my $msg = $item->{'message'}; + $uri=quotemeta($uri); + my $root = quotemeta($mark->{'root'}); + $msg =~ s/^$uri:\s//; + $msg =~ s/^$root$uri:\s//; $msg =~ s/"/\\"/g; - $line .= "\"$msg\""; + $line .= "\"" . csv_safecell($msg) ."\""; print $handle "$line\n"; } } +############################################################################### +# prevent CSV injection attacks +sub csv_safecell { + my $celldata = $_[0] || return; + if ($celldata =~ /^[=+@-]/) { $celldata = "'" . $celldata; } + return $celldata; +} + 1; -- 2.19.1