Vulnerability Development mailing list archives

OpenSSH Vulnerability


From: "Adam Gilmore" <adam () zeusinternet net>
Date: Thu, 18 Sep 2003 12:57:01 +1000

I've been working on exploiting the recent OpenSSH vulnerability and have
run into a few errors - thought someone might be able to shed some light on
how they could be overcome - or any other ideas.

First off, the bug is in buffer_append_space() which sets the buffer's
allocated int when it isn't allocated yet, so when fatal() gets called and
does the cleanup, it tries to null out too much data.

Now, I've been hacking at the 3.6p1 source all day and it comes down to a
few things. OpenSSH refuses packets > 256kb in size. Also,
buffer_append_space() will only let you append 1mb of data at a time. It
needs >10mb allocated to successfully error and null out too much data. So
that's the big obstacle so far, obercoming the limits.

When a packet is being received, it fills up a buffer (input) then calls a
few functions for parsing. It ends up at packet_read_poll2() which does most
of the checking. Firstly, when it receives a fresh packet, it'll check the
first dword of the packet for the length (always the length). If it's >256kb
it rejects the packet. So we always have to send <= 256kb as our packet
length. It's then stored in a static int for that function packet_length.

If it hasn't received the whole packet yet (it receives into the buffer
named "input" at 8kb per read), it returns SSH2_MSG_NONE - telling our read
function to keep reading - the packet's not finished yet. The input buffer
is the one we're hoping to overflow as it's the only one that has a looped
buffer_append() (which then calls buffer_append_space). Because it reads 8kb
at a time, it only allocates an extra 8kb each time - which overcomes the
1mb buffer_append_space problem.

But, we can't seem to get a packet >256kb to be continued to be read. The
minute it reaches 256kb, the packet is deemed complete, decrypted and it's
all over.

The lines that do this are:

        if (buffer_len(&input) < need + maclen)
                return SSH_MSG_NONE;

need is declared as:

need = 4 + packet_length - block_size;

So to get around this, somehow we need to make need + maclen >= 10mb. We
can't force packet_length to be >256kb so we're left with block_size and
maclen. Both are declared as:

maclen = mac && mac->enabled ? mac->mac_len : 0;
block_size = enc ? enc->block_size : 8;

It would seem, that the maclen/block_size are uncontrollable and are server
specific.

Removing the if statement yields the overflow and successfully crashes the
child. So to even reach the overflow, we need to somehow bypass that line.

As of yet, I can't think of any way to do this - we can't control
packet_length, block_size or maclen from what I can see. But possibly
someone else will be able to shed some light on the issue.

-Adam



***************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you are not the intended recipient any use,
distribution, disclosure or copying of this information is prohibited.
If you have received this email in error please notify the sender
immediately and delete it and any attachments from your system
***************************************************************


Current thread: