Perl分析Nmap结果之二
作者:云舒
很久之前写过一个简单的分析nmap结果的perl脚本,http://icylife.net/yunshu/show.php?id=446,似乎是07年夏天吧。这几天因为一点小需求做了个稍微复杂一点的,可对端口的服务以及版本做一个简单的判断。
代码很简单,就是用hash保存了端口和服务的对应,服务和最新版本的对应,然后判断扫描的结果是否符合预定义的情况。因为没几行,所以就没什么注释了,看看就明白了。
代码:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my $version = "1.0.1";
# allow port-service mapping.
my %port_service = ( 21 => "ftp",
22 => "ssh",
23 => "telnet",
25 => "smtp",
53 => "domain",
80 => "http",
443 => "ssl",
2222 => "ssh",
3306 => "mysql",
8080 => "http",
);
# allow service-banner mapping.
my %service_banner = ( http => [ "Apache httpd 2.2.8",
"Apache httpd 2.0.63",
"Apache httpd 1.3.41"
],
php => [ "PHP/5.2.6",
"PHP/4.4.8"
],
);
if( @ARGV != 1 )
{
&Usage( $0 );
exit(0);
}
my $host;
my %nmap_results;
&LoadNmapResult( $ARGV[0] );
#print Dumper( %nmap_results );
&AnalyseResult( );
sub LoadNmapResult( )
{
my $result_file = shift;
open( RH, "<$result_file" ) || die "Open $result_file error...\n";
my @ports_array;
while( <RH> )
{
chomp;
my $line = $_;
# IP line, find a new host
if( $line =~ /[\s|\(](\d+\.\d+\.\d+\.\d+)\)?(\sare)?:/ )
{
$host = $1;
@ports_array = ( );
next;
}
# Blank line, finish a host
if( $line =~ /^\s*$/ )
{
if( @ports_array != 0 )
{
$nmap_results = [ @ports_array ];
}
next;
}
# An open tcp port
if( $line =~ /^(\d+)\/tcp\s+open/ )
{
my @tmp_array = split( /\s+/, $_, 4 );
my $port = $1;
my $service = (@tmp_array >= 3 ? $tmp_array[2] : "none");
my $banner = (@tmp_array >= 4 ? $tmp_array[3] : "none");
# remove last ? from service
if( $service =~ /\?$/ )
{
chop( $service );
}
undef @tmp_array;
push( @ports_array, $port."|".$service."|".$banner );
}
}
}
sub AnalyseResult( )
{
foreach my $host( sort keys(%nmap_results) )
{
#print "$host:\n";
#print Dumper( @{ $nmap_results } );
foreach my $port_detail( @{ $nmap_results } )
{
#print "$port_detail\n";
my( $port, $service, $version ) = split( /\|/, $port_detail );
# Check port-service mapping!
if( exists( $port_service ) )
{
if( $port_service ne $service )
{
print "[HOLE!!!!] $host: tcp $port run $service demon!\n";
}
}
# Check service-banner mapping!
if( exists( $service_banner ) )
{
# if it has version info?
if( $version !~ /\d+/ )
{
#print "[WARNING!] $host: tcp $port run a unknow version $version.\n";
next;
}
# http is especial, we should test apache version and php version
if( $service eq "http" )
{
#if not apache
if( $version !~ /apache/i )
{
print "[HOLE!!!!] $host: tcp $port is http server, but run $version, not apache!\n";
next;
}
#check php version
if( $version =~ /(php[^\)])/i )
{
my $php_version = $1;
my $check_result = &CheckVersion( "php", $php_version );
if( $check_result ne "ok" )
{
print "[HOLE!!!!] $host: tcp $port run with wrong php version, $php_version!\n"
}
}
#check apache version
if( $version =~ /(Apache httpd [^\s])/i )
{
my $apache_version = $1;
my $check_result = &CheckVersion( "http", $apache_version );
if( $check_result ne "ok" )
{
print "[HOLE!!!!] $host: tcp $port run with wrong apache version, $apache_version!\n"
}
}
next;
}
}
}
}
}
sub CheckVersion( )
{
my $product_name = shift;
my $check_version = shift;
my $check_result = "not_ok";
foreach my $right_version ( @{ $service_banner } )
{
if( $check_version =~ /$right_version/i )
{
$check_result = "ok";
last;
}
}
return $check_result;
}
sub Usage( )
{
my $program = shift;
print "\nAnalyse banner from nmap's report, version $version, good luck!\n";
print "Code by xingguo.weixg\@alibaba-inc.com, please mail me if any problem.\n";
print "\nUse nmap first: nmap -sT -sV --version-all -A -iL ip.txt -oN result.txt\n";
print "\nUsage: $program <nmap_report>\n";
print "Example: $program result.txt\n";
exit(-1);
}