-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Add two checks for zend_mm_heap's integrity #13943
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Have you seen the related heap corruptions? |
Not in production no, but given how easy it is to control php's heap, even in remote exploits, adding those checks to guard against unlink is a low-hanging fruit. The performance impact should be in the noise level, since all the data used in the checks is accessed afterwards anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see big problems accepting this. This shouldn't affect performance.
On the other hand, I'm not sure if this significantly increases the heap protection.
Adaptation of exploit to bypassing this protection would take 5 additional minutes.
@iluuu1994 @nielsdos @arnaud-lb what do you think?
The idea here is to defend against linear heap overflows providing a partial write, I don't see how this safe-unlink could be trivially bypassed :/ |
Just write two addresses into the "poisoned chunk".
|
In addition to checking prev->next, PartitionAlloc stores a shadow pointer in the free block to detect corruptions. The original pointer is stored in big endian so that a partial corruption (like it is the case in the video) has more chance of resulting to an invalid address instead of an adjacent block. The XNU allocator used similar technics, and XORs the shadow with a secret. This would make it considerably more difficult to successfully override a pointer in the freelist, but not if the attacker can override the entire block and was able to disclose the secret. Ideally we should store the freelist externally in a bitmap so it can not be overriden with a linear overflow, but this is less ideal for performance. We could also isolate types in different heaps to make type confusion/use after free more difficult, as in kalloc_type. An additional benefit of type isolation + freelist bitmap is that we woundn't need the object_store anymore to enumerate objects. We could also allocate strings and array buckets in GigaCages so that a corrupt length doesn't allow to access anything else than other strings/array buckets. I think the proposed change is already useful and could be merged as-is. It would be interesting to measure the overhead of the endianness trick, shadow, and shadow XOR technics. |
Thank you @jvoisin! |
This is in the same spirit as php#13943: low-hanging, not in a hot-path, trivial, removing a limited-linear-write → arbitrary-write primitive, … moreover, given how many filters are available, having some low-hanging hardening there shouldn't hurt. cc @arnaud-lb
This is in the same spirit as php#13943: low-hanging, not in a hot-path, trivial, removing a limited-linear-write → arbitrary-write primitive, … moreover, given how many filters are available, having some low-hanging hardening there shouldn't hurt. cc @arnaud-lb
This is in the same spirit as php#13943: low-hanging, not in a hot-path, trivial, removing a limited-linear-write → arbitrary-write primitive, … moreover, given how many filters are available, having some low-hanging hardening there shouldn't hurt. cc @arnaud-lb
This is in the same spirit as php#13943: low-hanging, not in a hot-path, trivial, removing a limited-linear-write → arbitrary-write primitive, … moreover, given how many filters are available, having some low-hanging hardening there shouldn't hurt. cc @arnaud-lb
No description provided.