1 minute, 25 seconds
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!