fellow monks,

In my current position I'm required to write network reports. To make this process less tedious, I've put together several scripts that will build certain components of a standard report for me. One such script will generate a table that maps services and available service banners to each available IP. I was able to do this by taking the style sections from a previous report and incorporating these into my script...which is as follows.

#!perlenv -w #--------------------------------------------------------- # nessus-stable - nessus service table # David J Kyger - April 27, 2003 # Used to create a table that provides service and banner # information for each IP in a NessusWX export file. #--------------------------------------------------------- use strict; my $style = "<style> p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:\"\"\; margin-top:0in\; margin-right:32.0pt\; margin-bottom:12.0pt\; margin-left:32.0pt\; mso-pagination:widow-orphan\; mso-hyphenate:none\; font-size:12.0pt\; mso-bidi-font-size:10.0pt\; font-family:\"Times New Roman\"\; mso-fareast-font-family:\"Times New Roman\"\;} p.tabletxt0, li.tabletxt0, div.tabletxt0 {mso-style-name:tabletxt\; mso-style-parent:\"\"\; margin:0in\; margin-bottom:.0001pt\; mso-pagination:widow-orphan\; font-size:10.0pt\; font-family:\"Times New Roman\"\; mso-fareast-font-family:\"Times New Roman\"\;} \@page Section1 {size:8.5in 11.0in\; margin:1.0in 1.0in 1.0in 1.0in\; mso-header-margin:.5in\; mso-footer-margin:.5in\; mso-page-numbers:1\; mso-paper-source:0\;} </style>"; my $header = "<table border=1 cellspacing=0 cellpadding=0 width=720 st +yle='width:6.0in\; margin-left:37.45pt\;border-collapse:collapse\;border:none\;mso-borde +r-alt:solid windowtext .5pt\; mso-padding-alt:0in 1.45pt 0in 1.45pt'> <thead> <tr style='height:.1in'> <td width=225 style='width:135.0pt\;border:solid windowtext .5pt\;b +ackground: \#CCCCCC\;padding:0in 1.45pt 0in 1.45pt\;height:.1in'> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>IP Addr +ess/</span></p> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>Hostnam +e</span></p> </td> <span style='mso-bookmark:_Toc523573038'></span> <td width=210 style='width:1.75in\;border:solid windowtext .5pt\;bo +rder-left: none\;mso-border-left-alt:solid windowtext .5pt\;background:\#CCCCC +C\; padding:0in 1.45pt 0in 1.45pt\;height:.1in'> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>Ports I +dentified</span></p> </td> <span style='mso-bookmark:_Toc523573038'></span> <td width=285 style='width:171.0pt\;border:solid windowtext .5pt\;b +order-left: none\;mso-border-left-alt:solid windowtext .5pt\;background:\#CCCCC +C\; padding:0in 1.45pt 0in 1.45pt\;height:.1in'> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>System/ +Services Identification</span></p> </td> <span style='mso-bookmark:_Toc523573038'></span> </tr> </thead>"; my $tablecolumn1astart = "<tr style='height:12.35pt'> <td width=225 rowspan="; my $tablecolumn1bstart = " valign=top style='width:135.0pt\;border:sol +id windowtext .5pt\; border-top:none\;mso-border-top-alt:solid windowtext .5pt\;padding:0 +in 1.45pt 0in 1.45pt\; height:12.35pt'> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>"; my $tablecolumn1end = "</span></p> </td> <span style='mso-bookmark:_Toc523573038'></span>"; my $tablecolumn2start = "<td width=210 valign=top style='width:1.75in\ +;border-top:none\;border-left: none\;border-bottom:solid windowtext .5pt\;border-right:solid window +text .5pt\; mso-border-top-alt:solid windowtext .5pt\;mso-border-left-alt:solid +windowtext .5pt\; padding:0in 1.45pt 0in 1.45pt\;height:8.5pt'> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>"; my $tablecolumn2end = "</span></p> </td> <span style='mso-bookmark:_Toc523573038'></span>"; my $tablecolumn3start = " <td width=285 valign=top style='width:171.0p +t\;border-top:none\;border-left: none\;border-bottom:solid windowtext .5pt\;border-right:solid window +text .5pt\; mso-border-top-alt:solid windowtext .5pt\;mso-border-left-alt:solid +windowtext .5pt\; padding:0in 1.45pt 0in 1.45pt\;height:8.5pt'> <p class=tabletxt0><span style='mso-bookmark:_Toc523573038'>"; my $tablecolumn3end = "</span></p> </td> <span style='mso-bookmark:_Toc523573038'></span> </tr>"; my $servicestart = "<tr style='height:12.35pt'> <td width=210 valign=top style='width:1.75in\;border-top:none\;borde +r-left: none\;border-bottom:solid windowtext .5pt\;border-right:solid window +text .5pt\; mso-border-top-alt:solid windowtext .5pt\;mso-border-left-alt:solid +windowtext .5pt\; padding:0in 1.45pt 0in 1.45pt\;height:12.35pt'> <p class=tabletxt0>"; my $serviceend = "</p> </td> "; my $bannerstart = "<td width=285 valign=top style='width:171.0pt\;bord +er-top:none\;border-left: none\;border-bottom:solid windowtext .5pt\;border-right:solid window +text .5pt\; mso-border-top-alt:solid windowtext .5pt\;mso-border-left-alt:solid +windowtext .5pt\; padding:0in 1.45pt 0in 1.45pt\;height:12.35pt'> <p class=tabletxt0>"; my $bannerend = "</p> </td> </tr>"; my ( $port, $uniqip, $longip ); my ( @nessusdata, @ports, @ips, @uniqip, @splitip, @rearranged ); my %longips; my $nessusdata = $ARGV[0]; my $num = 256; my $count = 0; my $bannerplace = 0; my $allbanners; my @allbanners; my @osreport; my $os; if ( $#ARGV < 1 ) { print "usage: stable <NessusWX Export File> <output file name>"; exit; } my $htmlreport = $ARGV[1] . "\.html"; open( HTML, "> $htmlreport" ) || die "Could not open file: $! \n"; print HTML $style; print HTML $header; open( NESSUSDATA, "< $nessusdata" ) || die "Could not open file: $! \n +"; @nessusdata = <NESSUSDATA>; close(NESSUSDATA); if ( $nessusdata[0] !~ m/\[NessusWX Export File\]/ ) { print "File $ARGV[0] does not appear to be a valid NessusWX Export + File\n"; exit 0; } foreach $nessusdata (@nessusdata) { my @result = split ( /\|/, $nessusdata ); if ( $result[0] =~ /(NessusWX|DATA)/ ) { next; } elsif ( !$result[2] ) { chomp $nessusdata; push @ports, $nessusdata; push @ips, $result[0]; } elsif ($nessusdata =~ m/10336\|INFO/) { $result[4] =~ s/Nmap(.*)running //; $result[4] =~ s/\;//; push(@osreport, $result[0] . "|" . $result[4]); } elsif ($nessusdata =~ m/10337\|INFO/) { $result[4] =~ s/QueSO(.*)host OS is//; $result[4] =~ s/(\;\;\;(.*)$| \;\* )//g; push(@osreport, $result[0] . "|" . $result[4]); } elsif ($nessusdata =~ m/10107(.*)web server/) { $result[4] =~ s/The remote(.*):\;\;//; $result[4] =~ s/\;\;Solution(.*)$//; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10281(.*)telnet banner/) { $result[4] =~ s/Remote telnet banner ://; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10267(.*)SSH version/) { $result[4] =~ s/Remote SSH version : //; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10185(.*)POP server/) { push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10092(.*)FTP server banner/) { $result[4] =~ s/Remote FTP server banner :\;//; $result[4] =~ s/\;//; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10330(.*)SMTP server/) { $result[4] =~ s/An SMTP server(.*)banner : \;//; $result[4] =~ s/ready at(.*)$//; $result[4] =~ s/\;(.*)$//; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10159(.*)NNTP server version/) { $result[4] =~ s/Remote(.*)version ://; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10622(.*)PPTP server/) { $result[4] =~ s/A PPTP(.*)port\;//; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10658(.*)Oracle tnslsnr/) { $result[4] =~ s/This host is running(.*)tnslsnr: //; $result[4] =~ s/- Production(.*)$//; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } elsif ($nessusdata =~ m/10785(.*)lan manager/) { $result[4] =~ s/The remote(.*)manager is ://; $result[4] =~ s/\;The remote Operating (.*)$//; push(@allbanners,$result[0] . "|" . $result[1] . "|" . $result[4]) +; } } @uniqip = keys %{ { @ips, reverse @ips } }; foreach $uniqip (@uniqip) { @splitip = split ( /\./, $uniqip ); $longip = ( $splitip[0] * ( $num * $num * $num ) ) + ( $splitip[1] * ( $num * $num ) ) + ( $splitip[2] * $num ) + ( $splitip[3] ); $longips{$longip} = $uniqip; } @rearranged = sort { $a <=> $b } keys %longips; foreach (@rearranged) { my $osmarker = 0; my $rowspan = 1; foreach $port (@ports) { my @result = split ( /\|/, $port ); if ( $result[1] =~ m/general/ ) { next; } elsif ( $longips{$_} eq $result[0] ) { $rowspan = $rowspan + 1; } } print HTML $tablecolumn1astart . $rowspan . $tablecolumn1bstart . +$longips{$_} . $tablecolumn1end; foreach $os (@osreport) { my @result = split ( /\|/, $os ); if ( $longips{$_} eq $result[0] ) { print HTML $tablecolumn2start . "OS" . $tablecolumn2end; print HTML $tablecolumn3start . $result[1] . $tablecolumn3end; $osmarker = 1; } } if ($osmarker != 1) { print HTML $tablecolumn2start . "OS" . $tablecolumn2end; print HTML $tablecolumn3start . "n/a" . $tablecolumn3end; $osmarker = 0; } foreach $port (@ports) { my $bannermarker = 0; my @result = split ( /\|/, $port ); if ( $result[1] =~ m/general/ ) { next; } elsif ( $longips{$_} eq $result[0] ) { print HTML $servicestart . $result[1] . $serviceend; foreach $allbanners (@allbanners) { my @resultban = split ( /\|/, $allbanners ); if ( $longips{$_} eq $resultban[0] && $resultban[1] eq $resul +t[1] ) { chomp $resultban[2]; print HTML $bannerstart . $resultban[2] . $bannerend; $bannermarker = 1; } } if ($bannermarker != 1) { print HTML $bannerstart . "n/a" . $bannerend; } } } } print HTML "</table>";
If interested, you can see sample output from this script here.
I'm interested in hearing opinions on this approach as well as other ways to solve this problem, module recommendations, etc. Of course, code critiques are very welcome.

cheers, -semio

Edit by tye, add READMORE tags


In reply to creating report tables by semio

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.