Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 12 May 2021 14:46:31 +0000
From: "harris.johnson.x" <>
To: "" <>
Cc: "" <>
Subject: Re: [CVE-2020-28018] Use-After-Free on Exim Question

Greetings OSS-Security!

I took a look at that flaw too...but I wonder if there is a good technique to groom the heap to get that allocation right before the objective data. There are some limits on using a MAIL cmd, first u cannot use it if another MAIL cmd was successful. Second it calls smtp_reset() after finished. The only way 'd be using RSET so u can use MAIL again, but it will free all the subsequent heap buffers and return yield to the ptr specified on smtp_reset().

The only time in which u can send a MAIL cmd to alloc it would be between the second part of the cmd sent in the first TLS session, and the initialization of the new TLS session. After the initialization of the first TLS session lot of allocations happen, this will in fact extend the heap from the top chunk.

Once TLS connection is dropped out, and we start on plaintext again, after sending the EHLO cmd, smtp_reset() will be called, which will finally end up on freeing all subsequent heap buffers, except from the one pointed to by reset_point in the middle, which it's yield is just restored to point to it. At this point, top chunk size increased thanks to all the recently released chunks consequent to each other. And the objective struct is intact on the top chunk.

As u mentioned to "null p0int3r", there is an interesting parameter for MAIL cmd that lets you use encoding so it is an string, but then converted to binary data when copied to the allocated memory, so it bypasses any stuff related to parsing or NULL bytes. That specific parameter uses store_get(), so it hangs from the POOL_MAIN memory. This means the only way to perform an independent malloc() (so memory from top chunk is stolen, including the objective data) is first filling the current block, so in the store.c code, size will be > yield_length[store_pool], and will call malloc, so finally returning to us pointer to objective data to be overwrite with ours. Also, it will be better for that malloc() to have a really high request size, so the malloc() request does not reuse a freed chunk with specific requirements to be returned (if any).

R u guys using any specific technique to groom the heap / get the chunk returned by store_get() on that struct?

Good luck!

Harris Johnson

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.