Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploit not working in 6.6.p1 #1

Closed
monstercode opened this issue Sep 16, 2018 · 6 comments
Closed

Exploit not working in 6.6.p1 #1

monstercode opened this issue Sep 16, 2018 · 6 comments

Comments

@monstercode
Copy link

Hello,

I was researching about vulnerabilities to protect our production environment and found the CVE https://www.cvedetails.com/cve/CVE-2016-8858/

I setuped a VM with ubuntu 14.04 with openssh 6.6.1p1, bridged connection and tried to test this vulnerability, but with no success. No memory consumption (checking with htop from the VM...no more than 10MB increase).
I can ssh to the VM.

Tried with different maxconn (-n)
./kexkill -v -n 100 192.168.0.69

Has anyone exploited this vulnerability with success? Under some other conditions, openssh-server version? I couldn't find much info online.

Thanks!

@dag-erling
Copy link
Owner

dag-erling commented Sep 17, 2018

It's been so long, I barely even remembered I'd written this. I just tested it against FreeBSD 9.3-STABLE and confirmed that it has no effect. Here's a clue as to why:

# /usr/sbin/sshd -Dd
debug1: HPN Buffer Size: 65536
debug1: sshd version OpenSSH_6.6.1p1_hpn13v11 FreeBSD-20160314, OpenSSL 0.9.8zh-freebsd 3 Dec 2015
[...]
debug1: expecting SSH2_MSG_KEXDH_INIT [preauth]
Disconnecting: Protocol error: expected packet type 30, got 20 [preauth]
debug1: do_cleanup [preauth]
debug1: monitor_read_log: child log fd closed
debug1: do_cleanup
debug1: Killing privsep child 47315

After the first SSH2_MSG_KEXINIT, OpenSSH expects SSH2_MSG_KEXDH_INIT and closes the connection when it gets a second SSH2_MSG_KEXINIT instead. This is confirmed by reading the code. First, this line in server_init_dispatch_20() (called by server_init_dispatch(), called by server_loop()) in serverloop.c sets kex_input_kexinit() to be the handler for SSH2_MSG_KEXINIT packets:

        /* rekeying */
        dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);

That function is in kex.c. It parses the KEX proposal, then calls kex_kexinit_finish() in the same file, which calls the KEX handler for the requested algorithm:

        if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
            kex->kex[kex->kex_type] != NULL) {
                (kex->kex[kex->kex_type])(kex);
        } else {
                fatal("Unsupported key exchange %d", kex->kex_type);
        }

These handlers are initialized by do_ssh2_kex() in sshd.c:

        kex = kex_setup(myproposal);
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;

If you look at kexdh_server() in kexdhs.c, you'll see that it first generates a DH key and then immediately waits for a SSH2_MSG_KEXDH_INIT packet:

        dh_gen_key(dh, kex->we_need * 8);

        debug("expecting SSH2_MSG_KEXDH_INIT");
        packet_read_expect(SSH2_MSG_KEXDH_INIT);

Unsurprisingly, if packet_read_expect() gets anything else than SSH2_MSG_KEXDH_INIT, it prints an error message and kills the connection.

However, this code was significantly rewritten between 6.7 and 6.8. Instead of having the KEX code actively request and validate the next packet, it simply sets a handler for the packet it expects (SSH2_MSG_KEXDH_INIT) and returns to the server loop:

        if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
                goto out;

        debug("expecting SSH2_MSG_KEXDH_INIT");
        ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init);
        r = 0;
 out:
        return r;

If the correct packet is received, the correct handler is called, but the server loop now also accepts and dispatches other types of packets. This is what kexkill takes advantage of. The bug was fixed between 7.3 and 7.4 by having kex_input_kexinit() immediately deregister the SSH2_MSG_KEXINIT handler:

        ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);

The server loop no longer knows what to do with it and throws a fatal error instead.

To summarize: the bug is real and kexkill works (which I verified by taking a 10.4-STABLE VM and rolling back OpenSSH to an unpatched 7.2p1), but only OpenSSH 6.8 through 7.3 are vulnerable. The precise impact of the bug varies, but in theory, especially on a small system, it can trigger the OOM killer and completely kill sshd or other services.

Note that I also found and fixed a bug while working on this, so be sure to grab the latest version.

@dag-erling
Copy link
Owner

Update: I notified NIST, and they have updated the NVD entry to reflect this information.

@monstercode
Copy link
Author

monstercode commented Sep 29, 2018

Hi!

Thanks for the detailed explanation!

I tried the same with version OpenSSH-6.8p1 with the latest version of kexkill but still no luck, but it may be some mis-configuration.

If I get some free time (actually, a lot as it is not trivial to me) to delve into this CVE, I'll ping you back.

Thanks for your time! =)

@dag-erling
Copy link
Owner

Did you build it yourself or did you use your OS vendor's package? If the latter, it's quite likely patched. Either try to revert it to an unpatched version or just build it yourself from source.

@zhanglGitHub
Copy link

i can not exploited this vulnerability with success too

@dag-erling
Copy link
Owner

i can not exploited this vulnerability with success too

Please open a new issue with detailed information about your problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants