Re: Apache Vulnerability through a Proxy?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ulf Bahrenfuss wrote:
 > Hi!
 >
 > Does anyone know, if the chunk handling vulnerability carries through
 > a proxy i.e. Squid or Webcache? (Updating is currently not possible,
 > because it is not the plain apache, but the Oracle IAS flavour...)
 >
 > Or has anyone further information how this vulnerabilty really works?

Here's an analysis I wrote for iternal use at the ASF - it doesn't go 
into detail on the shellcode (which is just the usual shellcode), but 
does explain how the expected SEGV from overrunning the stack is 
avoided. Note that someone (sorry, forgotten who) posted a similar 
generic analyis a day or two ago - this one was independently arrived at 
  and refers to the Gobbles attack specifically.

First, the exploit code puts stuff on the stack (legitimately, in 
buffers). It then arranges a negative offset, as previously described, 
to be handed to memcpy. Here's where it gets cute. memcpy has memmove 
semantics (i.e., it copies in the correct direction to handle 
overlapping source/dest) on both OpenBSD and FreeBSD (in fact, I believe 
this is a requirement for this exploit to work on any system where the 
stack grows downwards). As a result, when the memcpy is attempted, it is 
done backwards (i.e. the copy starts at source+length-1 -> dest+length-1 
and downwards for length bytes). Now, here's the cute bit. memmove (et 
al) are optimised to copy in 4 byte chunks, for speed. This means that 
they have to copy the leftover bytes separately. This is handled by 
copying the odd 0-3 bytes before the remaining bytes.

So, if you arrange for the negative offset of the buffer to point at 
where the length is stored on the stack, then when these odd bytes are 
copied, you can modify the length. What they do is modify an initial 
length of 0xffffxxxx to 0x0000xxxx - note that the length is also the 
offset, so there is also a certain amount of luck involved, but all that 
is needed is for the offset to be small enough that the length remains 
big enough to zap enough stack (since the offset is a few hundred, that 
leaves the length at near to 64k, which is plenty to zap a few return 
addresses). Then, when the length is reloaded to do the second copy, it 
is miraculously smaller (I boggled first time I saw this in the 
debugger), and doesn't cause the expected SEGV, just nice corruption of 
the stack, as required![1]

So, to illustrate with source:

0x400f9d6c <memcpy>:    push   %esi
0x400f9d6d <memcpy+1>:  push   %edi
0x400f9d6e <memcpy+2>:  mov    0xc(%esp,1),%edi
0x400f9d72 <memcpy+6>:  mov    0x10(%esp,1),%esi
0x400f9d76 <memcpy+10>: mov    0x14(%esp,1),%ecx
0x400f9d7a <memcpy+14>: cmp    %esi,%edi
0x400f9d7c <memcpy+16>: jae    0x400f9d94 <memcpy+40>
...

at this point, we've decided to go backwards, edi is dest, esi is source 
and ecx is count (aka -146 aka ffffff6e)

0x400f9d94 <memcpy+40>: add    %ecx,%edi
0x400f9d96 <memcpy+42>: add    %ecx,%esi

Now we are pointing at the "end" of the buffers (i.e. somewhere down the 
stack from them, and, lo and behold, edi now points at the two MS bytes 
of the count)

0x400f9d98 <memcpy+44>: std
0x400f9d99 <memcpy+45>: and    $0x3,%ecx

calculate spare bytes (2 in this case)

0x400f9d9c <memcpy+48>: dec    %edi
0x400f9d9d <memcpy+49>: dec    %esi
0x400f9d9e <memcpy+50>: repz movsb %ds:(%esi),%es:(%edi)

and copy them - in fact two zeroes are copied, so the length is now 
0000ff6e.

0x400f9da0 <memcpy+52>: mov    0x14(%esp,1),%ecx

load the length again (now ff6e)

0x400f9da4 <memcpy+56>: shr    $0x2,%ecx

divide by 4

0x400f9da7 <memcpy+59>: sub    $0x3,%esi
0x400f9daa <memcpy+62>: sub    $0x3,%edi
0x400f9dad <memcpy+65>: repz movsl %ds:(%esi),%es:(%edi)

and copy that many longs (i.e. just shy of 64k bytes). Here is where we 
would have gone bang with a SEGV, but don't coz of the cunningness.

0x400f9daf <memcpy+67>: mov    0xc(%esp,1),%eax
0x400f9db3 <memcpy+71>: pop    %edi
0x400f9db4 <memcpy+72>: pop    %esi
0x400f9db5 <memcpy+73>: cld
0x400f9db6 <memcpy+74>: ret

return to a corrupted return address (or is it the next one up that's 
corrupted? not sure, don't care). And hey presto, remote shell.

Note that glibc is _not_ vulnerable in this way, so I have no idea how 
the Linux attack works. I have not examined Solaris.

Cheers,

Ben.

[1] For those not familiar with this class of exploit, the stack is 
corrupted such that the return address for some function call points to 
code which spawns a shell, which is then used by the attacker to have 
his or her evil way with your machine.

-- 
http://www.apache-ssl.org/ben.html       http://www.thebunker.net/

"There is no limit to what a man can do or how far he can go if he
doesn't mind who gets the credit." - Robert Woodruff


[Index of Archives]     [Linux Security]     [Netfilter]     [PHP]     [Yosemite News]     [Linux Kernel]

  Powered by Linux