At work I was tasked to see if any of our servers are running SSH which allow passwords instead of strictly only allowing SSH keys. You can tell if they allow passwords when you get a password prompt like this:
$ ssh user@example.com user@example.com's password: |
Of course we’ll use nmap to scan for open SSH ports. I suspect I should have have used nmap NSE to do scripting, but we’ll plod ahead with out it. Here’s the call I used to scan each subnet for open SSH ports and append it to ‘open.raw.txt’. Run this for each of your subnets:
nmap -PN -p 22 --open -oG - 1.2.3.0/24 >> open.raw.txt |
Here’s an example line from open.raw.txt:
Host: 1.2.3.1 () Status: Up Host: 1.2.3.1 () Ports: 22/open/tcp//ssh/// |
To get that all formatted nice for the next phase, we’ll just cut out dupe and grab just the IPs:
grep 'Up' open.raw.txt |cut -d' ' -f2 > open.ips.txt |
Finally, taking much inspiration from this script on StackOverflow, I wrote a bash script to check for servers with a password prompt on SSH called ssh.test.sh:
#!/usr/bin/expect proc isHostAlive {host} { set timeout 5 spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=QUIET -o PasswordAuthentication=yes ssh-testing@$host expect { timeout {puts "Timeout happened"; return 'TIMEOUT'} eof {return 'NO'} -nocase "password:" {send "exit\r";return 'YES' } } } # Lists to maintain the each host's information set serverList {1.2.3.1 1.2.3.2 1.2.3.3 1.2.3.4 1.2.3.5} # Looping through all the servers and checking it's availability foreach server $serverList { puts "\n$server : [isHostAlive $server]\n" } |
To execute and log the results, call:
ssh.test.sh > password.accepted.raw.txt |
And finally, to clean up those results into a file with “YES”, “NO” or “TIMEOUT” for each IP, just use this final grep
egrep 'YES|NO|TIMEOUT' password.accepted.raw.txt > password.accepted.txt |
The final results will look like this:
1.2.3.1 : 'YES' 1.2.3.2 : 'NO' 1.2.3.3 : 'YES' 1.2.3.4 : 'YES' 1.2.3.5 : 'TIMEOUT' |
Happy SSH testing!