OWASP CoreRuleSet Multipart Charset WAF Bypass (CVE-2026-21876)
by John Doe (GitHub: daytriftnewgen) · 2026-07-05
- Severity
- Critical
- CVE
- CVE-2026-21876
- Category
- web
- Affected product
- Disclosed
- 2026-07-05
- Patch status
- unpatched
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-06 |
| Author / Researcher | John Doe (GitHub: daytriftnewgen) |
| CVE / Advisory | CVE-2026-21876 |
| Category | web |
| Severity | Critical |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | waf-bypass, owasp-crs, modsecurity, multipart-form-data, charset-smuggling, xss, docker-lab |
| Related | N/A |
Summary
CVE-2026-21876 is a bypass in the OWASP Core Rule Set (CRS) rule 922110, which is meant to block multipart/form-data parts that declare a forbidden (non-ASCII-safe) character set such as IBM037/EBCDIC. The rule only inspects the charset of the last part in a multipart body; by placing the forbidden-charset part earlier and appending a harmless UTF-8 part last, an attacker satisfies the rule’s check while the origin application still decodes the earlier part using its own declared charset. Several backend stacks (Flask with the Python email parser, ASP.NET Core [FromForm], and Spring Boot on Undertow) decode multipart fields per-part rather than at the request level, so they faithfully reconstruct the smuggled payload (e.g., a <script> XSS string) even though the WAF believed the request was safe. The repository ships a full Docker lab (CRS proxy + each vulnerable backend) and a demo script that sends both a baseline (blocked) and bypass (passed) request. Fixed upstream in CRS 4.22.0 / 3.3.8.
Vulnerability Details
Root Cause
OWASP CRS rule 922110 validates the multipart charset only on the final MIME part of the request body instead of every part, so a forbidden charset placed in a non-last part slips past the WAF while still being decoded by charset-aware backends (Undertow, ASP.NET Core, and the demo Flask app using Python’s email parser).
Attack Vector
- Attacker crafts a multipart/form-data body where the first part (e.g.,
username) uses a disallowed charset such asIBM037and contains the actual malicious payload (e.g.,<script>alert(1)</script>). - Attacker appends a second, throwaway part (e.g.,
dummy) using an allowed charset (utf-8). - The CRS-protected reverse proxy inspects only the last part’s charset, sees
utf-8, and forwards the request (HTTP 200) instead of blocking it (HTTP 403). - The backend application decodes each part with its own declared charset, reconstructing the original payload from the first part and reflecting/processing it as if it had passed sanitization.
Impact
Allows attackers to smuggle payloads (e.g., stored/reflected XSS or other injection strings) past a CRS-protected WAF into applications that perform per-part multipart charset decoding, defeating the intended protection entirely for this input path.
Environment / Lab Setup
Target: OWASP CRS reverse proxy (ModSecurity/nginx) in front of a Flask, ASP.NET Core, or Spring Boot (Undertow) backend
Attacker: Docker + Docker Compose, Python 3
Proof of Concept
PoC Script
See
modsec_stand1/(Flask),aspnet_stand/(ASP.NET Core),springboot_stand/andspringboot_undertow_stand/(Spring Boot) in this folder, each with its owndocker-compose.ymlanddemo/send.py.
| |
Each stand spins up the CRS-protected proxy and a vulnerable backend, then demo/send.py sends a baseline multipart request (charset violation in the last part, correctly blocked) followed by the bypass variant (charset violation in an earlier part, forwarded and decoded by the backend).
Detection & Indicators of Compromise
Signs of compromise:
- Multipart requests with mixed/unusual per-part charsets that were not blocked by the WAF
- Reflected content in application responses matching bytes that decode only under a rare charset (e.g., IBM037)
- CRS rule 922110 hit-count anomalies or absence of expected 403 responses for crafted multipart traffic
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade OWASP CoreRuleSet to 4.22.0 or 3.3.8 or later, which validates charset on every multipart part |
| Interim mitigation | Restrict allowed multipart charsets at the proxy/application layer, or reject multipart bodies containing more than one declared charset |
References
Notes
Mirrored from https://github.com/daytriftnewgen/CVE-2026-21876 on 2026-07-05.