# Discovering a zero day and getting code execution on Mozilla's AWS Network

Unauthenticated WebPageTest on Mozilla AWS allowed header-spoofed 127.0.0.1 to upload a malicious zip, racing SecureDir cleanup to execute PHP.

- Payout: $500
- Severity: critical
- Program: WebPageTest
- Write-up by: Assetnote
- Disclosed: 2024-01-31
- Write-up quality: 8/10
- Original: https://www.assetnote.io/resources/research/discovering-a-zero-day-and-getting-code-execution-on-mozillas-aws-network
- Library page: https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-discovering-a-zero-day-and-getting-code-execution-on-mozillas-aws-network
- Tags: area:cloud domain:cloud domain:web impact:rce kind:research platform:research sev:critical tech:aws tech:php technique:race-window vuln:auth-bypass vuln:file-upload vuln:race-condition vuln:rce

**Target:** WebPageTest instance (workdone.php, common.inc) on Mozilla AWS
**Root cause:** common.inc trusts the FASTLY-CLIENT-IP header to overwrite REMOTE_ADDR, bypassing the 127.0.0.1 check; workdone.php extracts uploaded zips before SecureDir deletes executable files, leaving a race window.
**Steps:**
1. Recon finds unauthenticated WebPageTest at wpt-vpn.stage.mozaws.net and wpt1.dev.mozaws.net.
2. Run a traceroute via the UI to obtain a valid test ID (e.g. /result/171124_GW_9/).
3. Send request to /www/work/workdone.php with header `FASTLY-CLIENT-IP: 127.0.0.1` to satisfy the REMOTE_ADDR check.
4. Upload a zip containing a PHP webshell via `$_FILES['file']['tmp_name']`; ExtractZipFile writes it to $testPath.
5. Concurrently request the extracted PHP file before SecureDir unlinks it (Burp Intruder ~200 threads, or Turbo Intruder).
6. Shell executes; confirm with phpinfo() output.
**How found:** Assetnote Continuous Security flagged unauthenticated WebPageTest instances on Mozilla's attack surface; source audit of workdone.php revealed zip extraction and the 127.0.0.1 check, then common.inc revealed the FASTLY-CLIENT-IP header override, and SecureDir's post-extraction cleanup implied a race.
**Exploitation:** Two parallel Burp Intruder attacks: one repeatedly uploading the malicious zip, another repeatedly requesting the extracted PHP path during the race window, yielding code execution on the Mozilla AWS host.
**Insight:** When a localhost-only check exists, grep the codebase for header-to-REMOTE_ADDR overrides (proxy/CDN headers like FASTLY-CLIENT-IP, X-Forwarded-For); and when a sanitizer runs after extraction, race the window rather than defeating the sanitizer.

## Proof of concept (copied exactly from the original report)

**FASTLY-CLIENT-IP header spoofs REMOTE_ADDR to 127.0.0.1**

```
if (isset($_SERVER["HTTP_FASTLY_CLIENT_IP"]))
  $_SERVER["REMOTE_ADDR"] = $_SERVER["HTTP_FASTLY_CLIENT_IP"];
```

**Arbitrary Zip upload and extraction in workdone.php**

```
if (isset($_FILES['file']['tmp_name'])) {
  ExtractZipFile($_FILES['file']['tmp_name'], $testPath);
  CompressTextFiles($testPath);
}
```

**SecureDir race condition deleting dangerous extensions**

```
function SecureDir($path) {
    $files = scandir($path);
    foreach ($files as $file) {
        $filepath = "$path/$file";
        if (is_file($filepath)) {
            $parts = pathinfo($file);
            $ext = strtolower($parts['extension']);
            if (strpos($ext, 'php') === false &&
                strpos($ext, 'pl') === false &&
                strpos($ext, 'py') === false &&
                strpos($ext, 'cgi') === false &&
                strpos($ext, 'asp') === false &&
                strpos($ext, 'js') === false &&
                strpos($ext, 'rb') === false &&
                strpos($ext, 'htaccess') === false &&
                strpos($ext, 'jar') === false) {
                @chmod($filepath, 0666);
            } else {
                @chmod($filepath, 0666);    // just in case the unlink fails for some reason
                unlink($filepath);
            }
        } elseif ($file != '.' && $file != '..' && is_dir($filepath)) {
            SecureDir($filepath);
        }
    }
}
```

