today i’m going to write about an interesting vulnerability i’ve found in Square’s Acquisition website bookfresh.com that was escalated to remote code execution.
the story started when i saw that Bookfresh became a part of Square bug bounty program at Hackerone.
i decided to take a look at and start finding some vulnerabilities . i’ve found that the website is vulnerable to many XSS but i was looking for something bigger like Sql Injection or RCE.
so while i was checking for sql injection bugs i navigated to the profile page and found there is a file upload form to upload your profile photo . at the first moment i didn’t expect to find any vulnerability in that upload functionality but i decided to give it a try maybe i could be lucky.
i uploaded a jpg image file while intercepting the http request then i changed the filename extension from jpg to php and forwarded the request. i surprised that the image was uploaded with the php extension. i didn’t believe my eyes so i copied the image link and opened it in the browser. it displayed the image binary data as you were opening the image in a text editor which means it was successfully executed as php script and the response content-type was set to text/html
so this is a simple and direct file upload bypass, right ?
all i have to do is to inject my php code in the jpg file and get fast remote code execution . so i used a simple php code <? phpinfo(); ?> and injected it into the EXIF headers of jpg image then uploaded the image but when i viewed it again no php code was executed and nothing happened!
so i saved the image to my computer and executed strings command to see if it still have the phpinfo() code , however the results returned none !!
It turned out that all EXIF metadata was deleted from the image after uploading it to the server and the image was converted using the GD library in php using the imagecreatefromjpeg() function .
so this seems not exploitable using exif data, but what will happen if i injected my php code into the image data itself not the EXIF metadata ? i thought that would work ! so i tried to open the jpg file and inject the php code at the end of the file as the following
the image was still valid and working on my computer , after that i uploaded the image file “1.jpg”
but the results was like the following :
it displayed error message “File must be a valid image (.gif, .jpg, .jpeg, or .png)” , i was surprised how it detected that the image wasn’t valid image while the image is working on my computer so i tried with some other jpg files and it turned out that modifying a single character in any of those jpg images won’t be accepted by php-gd library as a valid image and will not be uploaded .
after that i tried the same thing with gif image and it worked like a charm and the image was uploaded successfully without throwing any errors , but when i tried to check the image after uploading it . i found that my php code was totally removed from it
i tried again to inject the php code into other gif images and in different places in the image but the php code was getting removed after uploading it .
that looks totally unexploitable , but i’m only one step away from getting RCE , so i should find a way to upload my image with the injected php code and bypass the imagecreatefromgif() function . i don’t know alot about image processing and how the php GD works but i tried to do that with simple old school way .
i came with an idea to compare the gif images before and after it get converted using php-gd and search for any similarity between them , so if i find a similar part in the original file that was kept also after converting using the php-gd then i can inject my php code in that part and get RCE
i decided to try this , so i coded a python script that will compare the images before and after converting and check for any similarity between them . then i searched in my computer for all the gif images and copied them all in one folder , afterwards i wrote a php script that will take all the gif images in that folder and regenerate them using the php-gd imagecreatefromgif() function and save them into another folder
then i used the python script to compare the files and check for any similar 13 bytes which will be the length of “<?phpinfo()?>” in the original and the converted gif image files , and the results was really awesome , i’ve found gif image with a big similarities after it was converted using php-gd .
the values were represented in hex , so i opened the original image file using a hex editor and searched for a one of those matched values “3b45d00ceade0c1a3f0e18aff1” and modified it to “<?phpinfo()?> , saved the file and converted it with php-gd then then checked the strings in the file.
i uploaded the gif image to bookfresh and that was the result
the trick successfully defeated the PHP-GD getimagesize() and imagecreatefromgif() functions that are used by many web developers nowdays to validate image uploads .
Finally here is video demonstration for the vulnerability
i’ve reported the vulnerability to square security team they released a fast fix for the vulnerability but i was able to bypass it again so i gave them my recommendations for a complete fix and they applied it and paid me a very nice bounty for this bug
some people were asking me for the gif file i’ve used in exploitation, so i’m sharing it
Image Link: http://www.secgeek.net/POC/POC.gif