1#VERSION,2.00
2###############################################################################
3#  Copyright (C) 2013 CIRT, Inc.
4#
5#  This program is free software; you can redistribute it and/or
6#  modify it under the terms of the GNU General Public License
7#  as published by the Free Software Foundation; version 2
8#  of the License only.
9#
10#  This program is distributed in the hope that it will be useful,
11#  but WITHOUT ANY WARRANTY; without even the implied warranty of
12#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#  GNU General Public License for more details.
14#
15#  You should have received a copy of the GNU General Public License
16#  along with this program; if not, write to
17#  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18###############################################################################
19# PURPOSE:
20# SQL Reporting
21# Sample table create (mysql):
22#	create table nikto_table (testid varchar(6) not null, ip varchar(15),
23#	hostname text, port int(5), usessl tinyint(1), osvdb int, httpmethod text,
24#	uri text, message text, request blob, response blob);
25###############################################################################
26sub nikto_report_sqlg_init {
27    my $id = { name              => "report_sqlg",
28               full_name         => "Generic SQL reports",
29               author            => "Sullo",
30               description       => "Produces SQL inserts into a generic database.",
31               report_head       => \&sqlg_open,
32               report_host_start => \&sqlg_host_start,
33               report_item       => \&sqlg_item,
34               report_format     => 'sql',
35               copyright         => "2013 CIRT Inc."
36               };
37    return $id;
38}
39
40###############################################################################
41# open output file
42sub sqlg_open {
43    my ($file) = @_;
44
45    # Open file and produce header
46    open(OUT, ">>$file") || die print STDERR "+ ERROR: Unable to open '$file' for write: $@\n";
47
48    # Write header
49    my $opt = $CLI{'all_options'};
50    $opt =~ s/'/\\'/g;
51    print OUT "# $VARIABLES{'name'} - v$VARIABLES{'version'}/$VARIABLES{'core_version'}\n";
52    print OUT "# Options:       $opt\n";
53	print OUT "# Start Time:    " . localtime($COUNTERS{'scan_start'}) . "\n";
54	print OUT "# End Time:      " . localtime($COUNTERS{'scan_end'}) . "\n";
55	print OUT "\n";
56
57    return OUT;
58}
59
60###############################################################################
61# start output
62sub sqlg_host_start {
63    my ($handle, $mark) = @_;
64    my $banner = $mark->{'banner'};
65    $banner =~ s/"/\\'/g;
66    my $ssl=0;
67    if (defined $mark->{'ssl_cipher'}) { $ssl=1; }
68    my $hostname = $mark->{'hostname'};
69    if ($mark->{'vhost'} ne '') { $hostname=$mark->{'hostname'}; }
70    my $sql="insert into nikto_table (testid, ip, hostname, port, usessl, osvdb, httpmethod, uri, message) values(";
71    $sql .= "'999958','$mark->{'ip'}','$hostname','$mark->{'port'}','$ssl','0','GET','/','$banner');\n";
72	print $handle $sql;
73
74    if (defined $mark->{'ssl_cipher'}) {
75    	my $ciphers = $mark->{'ssl_cipher'};
76    	my $issuer = $mark->{'ssl_cert_issuer'};
77    	my $subj = $mark->{'ssl_cert_subject'};
78    	my $alt = $mark->{'ssl_cert_altnames'};
79    	$ciphers =~ s/'/\\'/g;
80    	$issuer =~ s/'/\\'/g;
81    	$subj =~ s/'/\\'/g;
82    	$alt =~ s/'/\\'/g;
83	print OUT "# SSL Ciphers: $ciphers\n";
84	print OUT "# SSL Altnames: $alt\n";
85	print OUT "# SSL Issuer:  $issuer\n";
86	print OUT "# SSL Info:    $subj\n";
87    }
88
89    return;
90}
91
92###############################################################################
93# print an item
94sub sqlg_item {
95    my ($handle, $mark, $item) = @_;
96    foreach my $uri (split(' ', $item->{'uri'})) {
97 	my $hostname = quotemeta($item->{'mark'}->{'hostname'});
98    	my $httpmethod = quotemeta($item->{'method'});
99	my $msg = quotemeta($item->{'message'});
100        my $root = quotemeta($mark->{'root'});
101	my $rootq = quotemeta($mark->{'root'});  # temporary, just for regex
102        $uri = quotemeta($uri);
103	if ($item->{'mark'}->{'vhost'} ne '') { $hostname=$item->{'mark'}->{'vhost'}; }
104        my $ssl = $mark->{'ssl_cipher'} ? 1 : 0;
105
106    	my $sql="insert into nikto_table (testid, ip, hostname, port, usessl, osvdb, httpmethod, uri, message, request, response) values(";
107		$sql .= "'$item->{'nikto_id'}','$item->{'mark'}->{'ip'}','$hostname','$item->{'mark'}->{'port'}','$ssl',";
108		$sql .= "'$item->{'osvdb'}','$httpmethod',";
109
110        if (($uri ne '') && ($root ne '') && ($uri !~ /^$rootq/)) {
111		$sql .= "'" . $root . $uri . "',"; }
112	else {
113		$sql .= "'$uri',";
114		}
115
116	$msg =~ s/^$uri:\s//;
117	$msg =~ s/^$rootq$uri:\s//;
118        $sql .= "'$msg',";
119
120        # Rebuild the request from the hash -- no need to escape as it's base64 encoded
121        my $req = $$item{'request'};
122    	if ($req->{'whisker'}{'method'} eq '') {
123		$sql .= "'',";
124		}
125    	else {
126    		my $rstring = $req->{'whisker'}{'method'} . " "
127      			. $req->{'whisker'}{'uri'} . " "
128      			. $req->{'whisker'}{'protocol'} . "/"
129				. $req->{'whisker'}{'version'} . "\n";
130
131    		foreach my $header (keys %{$req}) {
132        		next if $header eq 'whisker';
133        		$rstring .= $header . ": " . $req->{$header} . "\n";
134    			}
135        	$sql .= "'" . LW2::encode_base64($rstring,'') . "',";
136			}
137
138	# response content
139        my $response = $$item{'response'};
140	$rstring='';
141    	if ($response->{'whisker'}{'protocol'} ne '') {
142    		$rstring = $response->{'whisker'}{'protocol'} . "/"
143      		. $response->{'whisker'}{'version'} . " "
144      		. $response->{'whisker'}{'code'} . " "
145      		. $response->{'whisker'}{'message'} . "\n";
146    		foreach my $header (@{ $response->{'whisker'}{'header_order'} }) {
147        		$rstring .= $header . ": " . $response->{$header} . "\n";
148    			}
149    		$rstring .= "\n" . $response->{'whisker'}{'data'} . "\n";
150    		}
151
152        $sql .= "'" . LW2::encode_base64($rstring,'') . "');";
153        print $handle "$sql\n";
154    }
155}
156
1571;
158