Background I found this vulnerability while I was assessing the security of the phar extension. When parsing a phar file, it is possible to trigger a buffer over-read condition and leak memory information. This vulnerability is interesting as it's not a typical exploitation just by controlling the read size. Affected version are PHP < 5.6.8RC1 Technical Details
Phar files metadata are stored in php serialized format. When processing a phar file, php attempts to unserialize the medatadata in phar.c:
php_var_unserialize() is the same function that is called when unserialize() is invoked in PHP "user-land".
Within Php_var_unserialize () there is a sanity check to ensure that p does not go beyond p + buf_len:
When we start unserializing a string in the format: s:<len>:"<Data>", lines 890-900 is essentially a loop to extract out <len>. As long as <len> is a digit, it would keep looping even if YYCURSOR goes beyond p+buf_len.
When YYCURSOR goes beyond max (aka p+ buf_len or YYLIMIT), it results in an integer underflow on line 907. Thus the sanity check on line 908 will always pass.
There's also some format checks:
Lines 900, 915 to 920 checks the data format for the tokens as highlighted : s:<len>:"<Data>" In essence, what this means is that once YYCURSOR goes beyond max when extracting <len>, <len> can be as large a number as you want and it will unserialize to a string successfully as long as it's in the format s:<len>:"<Data>" This is the state you want it look like during exploitation: At this point one might ask, how do we ensure that the ending byte is " since it's in a memory region beyond our control? Well you have 1 in 255 chance of strike gold. But one possible way to exploit it is just to keep "hammering" the various values of
xxxxxxxxxxxx . Sooner or later you will encounter a ". One might also ask, why can't I trigger this buffer over read through a typical unserialize call? For example why can't we trigger it via unserialize("s:0010") + some heap massaging? Why is it only vulnerable when we unserialize through phar?
Here's a screenshot of successful exploitation to leak memory a la Heartbleed style: After Thoughts I exploited this by using a serialized string type. It would be interesting to see if we can get code execution using other types. The full bug report could be found here. |
Blog >