#!/usr/bin/perl -w # # $Id: ssh_scan.pl,v 1.9 2003/01/13 05:28:42 jmates Exp $ # # Copyright (c) 2001, Jeremy Mates. This script is free software; # you can redistribute it and/or modify it under the same terms as # Perl itself. # # Run perldoc(1) on this file for additional documentation. # ###################################################################### # # REQUIREMENTS require 5; use strict; ###################################################################### # # MODULES use Carp; # better error reporting use Getopt::Std; # command line option processing use Socket qw(:DEFAULT :crlf); # low-level connection handling ###################################################################### # # VARIABLES my $service = 'ssh'; my $protoname = 'tcp'; my $port = getservbyname($service, $protoname); my $proto = getprotobyname($protoname); my $VERSION; ($VERSION = '$Revision: 1.9 $ ') =~ s/[^0-9.]//g; my (%opts); ###################################################################### # # MAIN # parse command-line options getopts('h?', \%opts); help() if exists $opts{'h'} or exists $opts{'?'}; while () { # skip non-open/non-relevant data next unless m!$port/open/$protoname!o; # extract ip and (optional) hostname from matching lines my ($ip, $hostname) = $_ =~ /^Host: (\S+) \(([^\(]+)?\)/; $hostname = "UNKNOWN" unless $hostname; # skip invalid IPv4 addresses (network & broadcast) next unless $ip; next if $ip =~ /\.(0|255)$/; # nab reply from SSH server and move on... my $ret = do_connect($ip); if ((!defined $ret) || ($ret <= 0)) { print $ip, "\t", $hostname, "\tCouldn't connect()\n"; next; } my $output; eval { local $SIG{ALRM} = sub { die "timed out\n" }; alarm(3); recv(SOCK, $output, 9999, 0); alarm(0); }; if ($@) { print $ip, "\t", $hostname, "\ttimeout\n"; } shutdown(SOCK, 2); # grab SSH version tag e.g. "SSH-1.99-OpenSSH_2.9" if ($output =~ /$service/io) { chomp($output); print $ip, "\t", $hostname, "\t", $output, "\n"; } } exit; ###################################################################### # # SUBROUTINES sub do_connect { my $ip = shift || return (0); my $o = undef; socket(SOCK, PF_INET, SOCK_STREAM, $proto); my $sin = sockaddr_in($port, inet_aton("$ip")); eval { local $SIG{ALRM} = sub { die "timed out\n" }; alarm(3); $o = connect(SOCK, $sin); alarm(0); }; return ($o); } # a generic help blarb sub help { print <<"HELP"; Usage: $0 < nmap-scan-output nmap(1) output should be in -oG or -oM format. Options for version $VERSION: -h/-? Display this message Run perldoc(1) on this script for additional documentation. HELP exit; } ###################################################################### # # DOCUMENTATION =head1 NAME ssh_scan.pl - helps map SSH server versions =head1 SYNOPSIS Simply pipe in nmap(1) output of the B<-oG> or B<-oM> format: # nmap -sS -p 22 -oG - 10.0.0.1/24 | ssh_scan.pl 10.0.0.1 example.org SSH-1.99-OpenSSH_2.9 ... =head1 DESCRIPTION This script takes nmap output, extracts out what look like open SSH servers, and attempts to connect to the IP Address in quetion to obtain the SSH version string (via the Socket module). Network and broadcast addresses will be skipped. Output consists of the IP Address, hostname, and server version for each running SSH daemon found, in tab-separated value format. The server version can also be "timeout" or a similar error message, depending on various failures to extract any meaningful data. Errors will crop up when there exist connectivity problems between the scanner and the target, or when a nmap stealth scan reports the port as being open, but tcp_wrappers on the target host denies the full socket connection. =head2 Normal Usage $ ssh_scan.pl < nmap-scan-output The nmap output must be in the B<-oG> or B<-oM> format, and is accepted on STDIN. All results are written to STDOUT. =head1 OPTIONS This script currently supports the following command line switches: =over 4 =item B<-h>, B<-?> Prints a brief usage note about the script. =back =head1 BUGS =head2 Reporting Bugs Newer versions of this script may be available from: http://sial.org/code/perl/ If the bug is in the latest version, send a report to the author. Patches that fix problems or add new features are welcome. =head2 Known Issues No known bugs. =head1 SEE ALSO nmap(1), perl(1) http://www.monkey.org/~provos/scanssh/ http://www.google.com/search?q=nmap+service+detection =head1 AUTHOR Jeremy Mates, http://sial.org/contact/ Socket code contributed by Michael Hornung, hornung@u.washington.edu. =head1 COPYRIGHT Copyright (c) 2001, Jeremy Mates. This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 VERSION $Id: ssh_scan.pl,v 1.9 2003/01/13 05:28:42 jmates Exp $ =cut