Hello all
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.
and guess what ? the php code was still there
i uploaded the gif image to bookfresh and that was the result
php-code executed successfully and i’ve got RCE
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
Update :
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
Enjoy
That’s a very interesting and challenging vulnerability, Nice writeup
Keep that up bro (y)
Thanks alot my dear Friend
Bravo! Really great writeup!
Thanks alot Amine , glad that you liked it
I really enjoyed reading this great write-up and I am impressed by how you managed to escalate the bug to RCE no matter what and you didn’t give up until you’ve done it. Congratulations again!
Thank you so much , i’m happy that you liked it and yes bug hunters shouldn’t give up
Awesome catch bro… Keep it up .. U just define never give up
Thank you vivek , i apperciate your words
wow!
that’s an awesome finding.
but I think the bounty amount should be more for an issue like this. You could took over their whole server and DB information with it.
Adrianbelen received $2000 bounty from them for similier issue with less effort.
Thanks for detailed writeup!
Thanks Faisal , yes i agree with you but as you know this is a new bug bounty program and they already paid 2k$ for Adrian for a similair issue so they are paying alot of money coz of their incompelete fix for the vulnerability.
Great Work Bro
Congrats
Thanks mate
Really brilliant awesome bypass Bro !!!
!!!!!!!
Keep it up
Thanks my dear friend
Nothing new from our best security geek; always #1
hahahaha thanks alot Dr.Ali , if i’m #1 you should be #0
Excellent work bro. Kewwll!
Thanks Clifford
Nice find
Can you please share the PoC file with me?
Thanks!
Hello Deepankar,
i’ve updated the post with the POC file link
Enjoy
Very nice find indeed!
Thanks
Did you report to Square Team or Book Fresh team. Because when i reported a bug to Square team they told to report it to Bookfresh team but when i checked there it says the bounty program is closed.
Well i’ve reported it to square bug bounty when bookfresh was in the scope of their program , but after that they made bookfresh as standalone program and stopped paying monetary rewards.
I was wonder, if you interrupt the request and change the file name, how come it still upload the file?
i just intercepted the request sent from the browser and modified it then forwarded it to the web server , i just used this to bypass any client-side (javascript) validation in the browser on the file name .
Really nice work…you deserve to be #Never Give up (y)
Thanks
sweet!
good work and great writeup!
Thank you!
nice idea . well done
cool. Thanks
That’s very interested and great writeup acutely i am interested to know you mr ahmed
Thanks Adel , i’m happy to know you also
detailed explanation. awesome findings!
Thanks alot Yappare
, glad that you liked it 
It’s cool bro, thanks)
Wow, really nice finding and impressive write-up.
Would you mind sharing the python script that you used to compare the images? I am a bit new at Python and I would like to see which library’s did you use and how. Thanks you!
congratulations My genius friend
Hello
How can I change the code in the POC.gif file ??
Thank you
you can just replace the “< ?phpinfo();?>” inside the POC file with your own code using any hex editor , but keep in mind you can’t use long php code. it should be short or it might not work properly.
if you want any help you can email me or ping me on Twitter @aboul3la.
Really awesome find …
Thanks your idea,but I have some questions about the write up。
1. When I use the idea to bypass the other functions like imagecreatefromjpg() or imagecreatefrompng(),the size I choose is 30,but I cannot find a mathed sequence
2. I find your script use set(list1)&set(list2),It will create the numbers of the same sequunces,Why donn’t you divide the image into a couple of pieces。May be It’s a nice idea
Thanks Kevin, well regarding your questions:
1) To be honest i didn’t test the same vulnerability against other GD functions, but for imagecreatefrompng() you can see this article it will help you https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
2) My script is indeed divide the image into a couple of pieces and search for each piece in the other image, it don’t compare them in sequence.
That was quite impressive work !
Awesome catch bro & write up is too much interesting
Is there a specific PHP or GD version that this exploit works on? I tried the demo on kali linux with no success. I think my kali has the latest php and gd versions ………
can you provide bookfresh security email here
How u came to know that there are using php GD library for proper uploding..??
Is there any write up to know which engine ,library,function is being used for image uploding..