FirstBlood-#939 — Remote Code Execution via insecure deserialization on /api/checkproof.php
This issue was discovered on FirstBlood v2
On 2021-10-30, 0xblackbird Level 5 reported:
Hello! I was able to execute commands via an insecure deserialization on /api/checkproof.php
(and /vaccination-manager/pub/submit-vaccination-proof.php
).
Identification
When we try to be like a normal user and try uploading an (normal) image that contains nothing special, we can see that we first upload it via POST request on /vaccination-manager/pub/submit-vaccination-proof.php
and then that the file extension gets checked by /api/checkproof.php
via the proof GET parameter. The thing here is that a malicious user can use this to get remote code execution by uploading a malicious image and calling it via the phar stream wrapper (phar deserialization).
Steps to reproduce
- First of all, we need to identify the technology that's being used. In this case, we can see that there is a
/composer.json
file in the root directory. Opening this file gives us the following: Monolog v2.1.1
.
- Next, we can generate a malicious file containing our payload. We can use a tool like phpggc to generate and include it in our image. To do so, download the tool from Github and execute the following command:
sudo phpggc Monolog/RCE1 'system' 'whoami' -pj /home/user/picture.jpg -o /home/user/payload.jpg
. (In this command, we first specify the custom gadget (which we identified from the composer.json
) and also the PHP function including the parameters of the function, in this case we'll be executing system("id")
.) This will take the picture.jpg
file and generate another image in your home directory called payload.jpg
which contains the payload (the file we're going to upload).
- Now we have to upload it, start up firstblood v2 if you haven't already and navigate to
/vaccination-manager/pub/upload-vaccination-proof.php
. Enter any email-address in the email-address field, it has to be valid but not your personal one: [email protected]
will do fine. And finally, click on "Browse" to select the previously generated "image" (picture.jpg
). Once you've done so, click on "Upload".
- We'll have to intercept the request of the checkproof API endpoint. So forward the POST request to
/vaccination-manager/pub/submit-vaccination-proof.php
and send the GET request to /api/checkproof.php
to Repeater.
- In the Repeater tab, add the phar stream wrapper in the
proof
GET parameter (so that your value looks like the following phar:///app/firstblood/upload/{HASH}.jpg
) and resend the request. It'll take a bit before you get a response back, but as you can see, the function (system('id')
) was successfully executed! We got remote code execution! A malicious user can now for example upload a shell (backdoor) and make it easier for him to execute commands and/or escalate his/her privileges.
Thanks for the fun challenge!
Kind regards,
0xblackbird
P1 CRITICAL
Endpoint: /api/checkproof.php
This report contains multiple vulnerabilities:
FirstBlood ID: 34
Vulnerability Type: Deserialization
This endpoint calls filesize() on the path provided in the 'proof' param with no filtering or sanitisation. By adding the phar:// stream handler to the path, an attacker can force a previously uploaded file to be sent through deserialisation. Coupled with the fact that a gadget-chain vulnerable version of monolog is being used, this allows for RCE.
FirstBlood ID: 36
Vulnerability Type: Information leak/disclosure
It is possible to use the composer.json to aid with another vulnerability and gaining information/knowledge on versions used.