Bekijk Volledige Versie : [ANNOUNCE] glibc heap protection patch
William Robertson
01/12/03, 21:31
Hi all,
I'd just like to announce that we have a heap protection system for
glibc available for download. The system detects and prevents all heap
overflow exploits that modify inline control information from
succeeding against a protected application, can be installed
system-wide or on a per-process basis using LD_PRELOAD, and is
transparent to existing applications.
We would definitely appreciate any feedback and bug reports on the
code. The patch and some additional information is available at:
http://www.cs.ucsb.edu/~wkr/projects/heap_protection/
Enjoy!
--
William Robertson
Reliable Software Group, UC Santa Barbara
http://www.cs.ucsb.edu/~wkr/
Eugene Tsyrklevich
02/12/03, 17:45
Hello,
Your heap protection scheme is based on checking the validity of the chunk
structure magic value that is calculated as
(chunk)->magic = (((int) chunk) ^ *__heap_magic ^ (chunk)->size)
I believe that "chunk" and "(chunk)->size" can be considered to be known
to attackers and thus contain no entropy. Thus the security of your scheme
is based on the randomness of the "__heap_magic" value which is calculated
as
+#ifdef __HEAP_PROTECTION
[snip]
+ srand(time(NULL));
+ *__heap_magic = rand();
[snip]
+ if (mprotect(__heap_magic, sizeof(*__heap_magic), PROT_READ))
+ fprintf(stderr, "glibc: WARNING: unable to protect heap magic!\n");
+#endif /* __HEAP_PROTECTION */
With such a poor random number generator you only raise a bar slightly
higher whereby attackers have to predict your "random" canary in their
exploits.
Also, since you initialize "__heap_magic" once per process, an attacker
might be able to use nmap to determine the uptime of the victim machine
which will quite precisely determine when a process was started (a valid
assumption for daemon processes).
cheers,
eugene
> Hi all,
>
> I'd just like to announce that we have a heap protection system for
glibc available for download. The system detects and prevents all heap
overflow exploits that modify inline control information from
> succeeding against a protected application, can be installed
> system-wide or on a per-process basis using LD_PRELOAD, and is
> transparent to existing applications.
>
> We would definitely appreciate any feedback and bug reports on the code.
The patch and some additional information is available at:
>
> http://www.cs.ucsb.edu/~wkr/projects/heap_protection/
>
> Enjoy!
>
> --
> William Robertson
> Reliable Software Group, UC Santa Barbara
> http://www.cs.ucsb.edu/~wkr/
William Robertson
02/12/03, 18:30
Hi Stefan,
On Dec 02, 2003, at 06:03, Stefan Esser wrote:
> Nice advertisement but you should underline the fact, that it only
> protects against glibc malloc()/free() problems. There are a number
> of software packages that implement their own heap wrappers or work
> with linked lists. They still are vulnerable to heap overflows.
> f.e. PHP.
This is correct, and we state as much in our LISA paper. Apologies for
not emphasizing it more in my post yesterday; I'll make sure the
project page makes this clearer.
> And on the other hand there is a much simpler way to protect any
> unlink from a linked list from ever beeing exploited.
This is true in the case of the fd and bk pointers, and in fact this is
one of the checks that dlmalloc's debugging code performs. However, as
we also demonstrated in the paper, you are still open to other
heap-related attacks, such as overwriting size fields and setting up
fake chunk headers. So, unfortunately I don't think that check alone
is sufficient.
> Stefan Esser
--
William Robertson
Reliable Software Group, UC Santa Barbara
http://www.cs.ucsb.edu/~wkr/
Stefan Esser
02/12/03, 19:30
Hello,
I looked onto your site for a few seconds and saw that you use magic
values.
> I'd just like to announce that we have a heap protection system for
> glibc available for download. The system detects and prevents all heap
> overflow exploits that modify inline control information from succeeding
> against a protected application, can be installed system-wide or on a
> per-process basis using LD_PRELOAD, and is transparent to existing
> applications.
Nice advertisement but you should underline the fact, that it only
protects against glibc malloc()/free() problems. There are a number
of software packages that implement their own heap wrappers or work
with linked lists. They still are vulnerable to heap overflows.
f.e. PHP.
And on the other hand there is a much simpler way to protect any
unlink from a linked list from ever beeing exploited.
1.5 years ago I added code to my glibc (and to the PHP malloc/free
wrappers (only on my system cause PHP group wanted this code
not in official Zend Engine)) that simply checks on unlink if my
backward pointed block really points with his forward pointer
to me and if my forward pointed block points with his backward
pointer to me. This makes the unlink process unexploitable, while
your approach is still attackable if someone guessed the magic
value. (Even if that sounds unrealistic it is still possible.)
The unlink macro would then look like
#define unlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
if (FD->bk != P || BK->fd != P) ATTACK_ON_UNLINK; \
FD->bk = BK; \
BK->fd = FD; \
}
(I am writing this down from my memory, I have the code
not here at the moment)
Stefan Esser
William Robertson
02/12/03, 23:45
On Dec 02, 2003, at 03:27, Eugene Tsyrklevich wrote:
> With such a poor random number generator you only raise a bar slightly
> higher whereby attackers have to predict your "random" canary in their
> exploits.
>
> Also, since you initialize "__heap_magic" once per process, an attacker
> might be able to use nmap to determine the uptime of the victim machine
> which will quite precisely determine when a process was started (a
> valid
> assumption for daemon processes).
Eugene,
Actually, I agree with you, that should be stronger. What I think is
even worse is the case of local heap exploits, where the attacker knows
with some precision when the process starts. It seems that this should
be patched to use some source of randomness such as /dev/random instead
of time().
Thanks!
--
William Robertson
Reliable Software Group, UC Santa Barbara
http://www.cs.ucsb.edu/~wkr/
Stefan Esser
03/12/03, 21:15
William Robertson wrote:
> This is true in the case of the fd and bk pointers, and in fact this
> is one of the checks that dlmalloc's debugging code performs.
> However, as we also demonstrated in the paper, you are still open to
> other heap-related attacks, such as overwriting size fields and
> setting up fake chunk headers. So, unfortunately I don't think that
> check alone is sufficient.
The last time I checked there was no such check in the unlink macro (no
matter if debug mode or not). Overwriting size fields and setting up
fake chunk headers are the standard way to exploit malloc()/free()
structures. And you should rethink about my unlink macro. It perfectly
stops ALL
heap attacks that try to make use of the unlink macro (and this are the
most out there). I know that modifying unlink does not protect against
frontlink attacks. But most heap exploiters do not even know that there
is anything else than unlink. I never said that the unlink macro is the
ultimate solution to all heap problems, but it is certainly securer to
check the pointers on unlink than protecting it only with magic numbers.
The best solution would be a combination of both.
Ohh btw... Feel free to demonstrate me an unlink exploit that works
while my unlink macro
is in place... In the last two years I nearly only concentrated on heap
exploits on a various
number of platforms. glibc/bsd/solaris/windows and I even exploited the
heap on XBOX
with my dashboard-font exploit. So I very much doubt that my statement
was incorrect.
Stefan Esser
Han Boetes
03/12/03, 21:45
William Robertson wrote:
> It seems that this should be patched to use some source of randomness
> such as /dev/random instead of time().
I ported arc4random from OpenBSD to linux some time ago. All I had to
do was to change the sysctl:
http://www.xs4all.nl/~hanb/software/arc4random.tar.bz2
I think it's a very usefull function.
# Han
William Robertson
04/12/03, 00:45
On Dec 03, 2003, at 05:01, Stefan Esser wrote:
> The last time I checked there was no such check in the unlink macro
> (no matter if debug mode or not).
Ah, ok, I see what you meant. The check I was referring to wasn't in
the unlink macro, but in one of dlmalloc's debugging routines. If you
move it into unlink itself, then it does indeed prevent all unlink
exploits, as you say. I agree that a combination of the two techniques
would theoretically be stronger than each on its own, but I also
believe that using properly randomized magic numbers in practice
guarantees that chunk headers cannot be tampered with. However, you do
get a lot for this simple check, so it makes sense to include it.
Thanks for pointing that out.
> Stefan Esser
--
William Robertson
Reliable Software Group, UC Santa Barbara
http://www.cs.ucsb.edu/~wkr/
In-Reply-To: <3FCDDEB3.8050006@nopiracy.de>
>heap attacks that try to make use of the unlink macro (and this are the
>most out there). I know that modifying unlink does not protect against
>frontlink attacks. But most heap exploiters do not even know that there
>is anything else than unlink. I never said that the unlink macro is the
>ultimate solution to all heap problems, but it is certainly securer to
>check the pointers on unlink than protecting it only with magic numbers.
>The best solution would be a combination of both.
>
Forgive my ignorance, I've been doing other things for the last two years, but isn't this precisely the advantage of magic numbers. If you only consider unlink exploits, then your macro is adequate protection. However if it's demonstratable that there a
re other ways to exploit heap corruption which do not require unlink() then your macro is equivalent to using a really poorly generated magic number for these other cases. There are demonstratable ways to exploit heap corruption that do not require unlink
() therefore your macro would seem to be inadequate.
It seems to me that if an attacker can overwrite p->fd and p->bk, then satisfying p->fd->bk == p->bk->fd == p is not very difficult, you could overwrite fd and bk with the value of p, or with an address you control.
The real question, then, is if an attacker who has passed the test in your macro is also left in a situation where exploiting frontlink() or some other possibly unknown technique is possible. Whether or not she can use an unlink() exploit at this point
seems only as relevant as whether or not she can use any other exploitation technique. Otherwise you would be basing the security of your system on how many attackers have figured out how to break it, and you might as well be designing a heap protection m
echanism for Redmond.
This question seems more complex than 'Feel free to demonstrate me an unlink exploit that works while my unlink macro is in place'. But I have to admit my own ignorance here, I can't say for certain whether an attacker who passes the test in your macro
is left in a situation where an exploit is possible.
You're right that the best bet would seem to be using both approaches. Doing sanity checks on data, and using canaries to make sure the data hasn't been modified seem quite complementary, one attempts to ensure the validity of the data, the other attemp
ts to ensure it's integrity.
And William's using srand( time( NULL ) ) was just goofy <tsk-tsk>.
Cheers,
~x
Stefan Esser
04/12/03, 18:30
xenophi1e wrote:
> This question seems more complex than 'Feel free to demonstrate me an
> unlink exploit that works while my unlink macro is in place'. But I
> have to admit my own ignorance here, I can't say for certain whether
> an attacker who passes the test in your macro is left in a situation
> where an exploit is possible.
Fact is my macro makes arbitrary pointer overwrites with unlink()
impossible. The magic value approach just makes it harder. You need to
guess a 32bit value. Even if this is totally random it is theoreticly
possible to exploit the unlink() macro in that case. And do not forget
the power of information leak exploits.
Just an example: The gamecube was hacked by an information leak exploit.
A crc feature the Phantasy Star Online game allows to request checksums
of arbitrary memory positions (and sizes).
So it was possible for the smart guy who did it, to create a complete
memory dump from
remote. In that case your magic values are worthless...
Stefan Esser
Marco Ivaldi
04/12/03, 19:30
> So, unfortunately I don't think that check alone is sufficient.
For in-depth information about dlmalloc's frontlink() macro exploitation,
check out the excellent paper by MaXX, at:
http://phrack.org/phrack/57/p57-0x08
You can also see an exploitation example of mine (heap/heap2-ex.c) in the
misc-exploits.tgz collection, available at:
http://www.0xdeadbeef.info/code/misc-exploits.tgz
Cheers,
:raptor
--
Marco Ivaldi
Antifork Research, Inc. http://0xdeadbeef.info/
3B05 C9C5 A2DE C3D7 4233 0394 EF85 2008 DBFD B707
William Robertson
04/12/03, 20:45
On Dec 03, 2003, at 01:52, Eugene Tsyrklevich wrote:
> indeed, it should
This has been patched to use /dev/urandom in v1.4, which also fixes a
couple of other issues.
> have you seen http://synflood.at/contrapolice/? your paper did not
> mention
> this.
We didn't find this when we did our related work search back during
late spring, but Andreas contacted me after our announcement. From
looking at the code, I don't think the goals are quite the same. We
only try to protect the chunk headers, but it seems that he wants
instead to protect data contained in the user-visible memory region.
This would be nice, but I think this has its own set of issues.
> any plans on porting this to OpenBSD (and saving me time :)?
I've started looking at it, but I don't think I'll have time to
seriously evaluate the situation there for a week or two, so feel free.
:-)
> eugene
--
William Robertson
Reliable Software Group, UC Santa Barbara
http://www.cs.ucsb.edu/~wkr/
Troed SÄngberg
04/12/03, 20:45
On Thu, 04 Dec 2003 12:10:05 +0100, Stefan Esser <se@nopiracy.de> wrote:
> Just an example: The gamecube was hacked by an information leak exploit.
> A crc feature the Phantasy Star Online game allows to request checksums
> of arbitrary memory positions (and sizes).
> So it was possible for the smart guy who did it, to create a complete
> memory dump from
> remote. In that case your magic values are worthless...
Which hack? The PSO-upload hack on the Gamecube is vastly different from
tmbinc's truly embarrassing (for Nintendo) hack on the so-called crypto.
In short: All communication between the serial chip holding the BIOS and
the Gamecube's flipper-chip is two-way. Naturally, if a chip is only
interested in receiving data it will shift out garbage. What tmbinc found
out was that when the encrypted data was shifted to the Flipper (for
decryption) the _decrypted data_ was shifted back.
Since the encryption was nothing more than a XOR-seed from a PNRG it was
trivial to XOR the encrypted BIOS image with the decrypted data and get
access to the whole XOR-key (starting seed always the same) and thus it's
trivial to produce BIOS replacements.
I agree that this is an information leak, but PSO has very little to do
with it. I do not consider the PSO-upload hack to be a hack of the
Gamecube, but tmbinc's retrieval of the BIOS encryption "key" certainly is.
We're straying off topic. Further off-topic discussions in mail.
regards,
Troed
Adam Shostack
04/12/03, 21:00
On Wed, Dec 03, 2003 at 08:54:11AM +0100, Han Boetes wrote:
| William Robertson wrote:
| > It seems that this should be patched to use some source of randomness
| > such as /dev/random instead of time().
|
| I ported arc4random from OpenBSD to linux some time ago. All I had to
| do was to change the sysctl:
|
| http://www.xs4all.nl/~hanb/software/arc4random.tar.bz2
|
|
| I think it's a very usefull function.
Can you explain why it's better than the kernel's randomness pool?
Adam
--
"It is seldom that liberty of any kind is lost all at once."
-Hume
Jim Knoble
05/12/03, 00:45
--xB0nW4MQa6jZONgY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Circa 2003-12-04 12:42:26 -0500 dixit Adam Shostack:
: On Wed, Dec 03, 2003 at 08:54:11AM +0100, Han Boetes wrote:
: | I ported arc4random from OpenBSD to linux some time ago. All I had to
: | do was to change the sysctl:
: |=20
: | http://www.xs4all.nl/~hanb/software/arc4random.tar.bz2
:=20
: Can you explain why it's better than the kernel's randomness pool?
The arc4random() function does not deplete the Linux kernel's entropy
pool, as reading from /dev/random does. As long as arc4random() is
properly seeded from /dev/random to begin with (and periodically stirred
with more entropy from /dev/random), it's perfectly good unpredictable
pseudorandom data, suitable for most anything except actually generating
cryptographic keys.
OpenBSD uses arc4random() as the basis for the mkstemp() function to
generate unpredictable temporary filenames, for example.
In sum, using a properly seeded arc4random() under Linux is similar to
reading from /dev/urandom, but it uses the ARC4 algorithm to generate
the pseudorandom data rather than the undocumented algorithm used by
Linux's /dev/urandom.
--=20
jim knoble | jmknoble@pobox.com | http://www.pobox.com/~jmknoble/
(GnuPG fingerprint: 31C4:8AAC:F24E:A70C:4000::BBF4:289F:EAA8:1381:1491 )
.................................................. ...................
:"The methods now being used to merchandise the political candidate :
: as though he were a deodorant positively guarantee the electorate :
: against ever hearing the truth about anything." --Aldous Huxley :
:................................................. ..................:
--xB0nW4MQa6jZONgY
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (OpenBSD)
Comment: See http://www.pobox.com/~jmknoble/keys/ for my public key.
iD8DBQE/z7RmKJ/qqBOBFJERAqgDAJ9Tf9GmYCwK8yjN9M1Lr9LCQSGkgwCggKc+
p9X2VZQbWgpcY4sIEHZYzCo=
=pX1p
-----END PGP SIGNATURE-----
--xB0nW4MQa6jZONgY--