Full Report
Cross-Site Request Forgery (CSRF) attacks have been mitigated largely by browser protections like SameSite cookie flags and pre-flight requests. Some technically work because of browser behavior but shouldn't be considered security-safe because the functionality could change. One mechanism for detecting CSRF is the rejection of requests with a Content-Type not equal to application/json. Since JSON triggers a pre-flight, it's common to use other content types, such as text/plain, to avoid this. There are some notable bypasses for this though. For instance, 307 redirects with Adobe Flash player in Firefox and in Chrome the navigator.sendBeacon had a vulnerability to set the content type header to an arbitrary value. The fetch API in JavaScript is used to make web requests. This function accepts both a string and a Blob object. By passing in a Blob object without a type into the fetch function, it will send a request without CORS or a content type header! The actual data in the blob will become the body of the request. They give an example of a Ruby on Rails endpoint that first checks the existing content type and then checks for the application JSON. Since it doesn't exist, the check is effectively skipped. Although this is unlikely to work as a complete bypass, it's an interesting trick none-the-less.
Analysis Summary
# Vulnerability: CSRF Protection Bypass via Null Content-Type Fetch
## CVE Details
- **CVE ID:** N/A (Note: The article references historical CVEs like CVE-2011-0059 and CVE-2011-0447 as context for similar bypasses, but the `fetch` Blob technique is a contemporary browser behavior observation).
- **CVSS Score:** N/A (Estimated 4.3 - 6.5 depending on application impact)
- **CWE:** CWE-352: Cross-Site Request Forgery (CSRF)
## Affected Systems
- **Products:** Web applications relying solely on `Content-Type` validation for CSRF protection.
- **Versions:** Applications using logical checks that assume a `Content-Type` header will always be present in cross-origin POST requests.
- **Configurations:** Systems that use the pattern: `if (contentType exists AND contentType != "application/json") { reject }`.
## Vulnerability Description
Conventional CSRF protection often relies on the assumption that browsers require a pre-flight (CORS) request for sensitive `Content-Type` headers like `application/json`. Developers sometimes attempt to block CSRF by rejecting "simple" types (like `text/plain`) while allowing `application/json`.
However, the JavaScript `fetch` API allows a `Blob` object to be passed as the request body. If a `Blob` is initialized without an explicit type, the browser sends the POST request **without any Content-Type header at all**. If the server-side logic only checks if the header is "wrong" rather than ensuring it is "correct" (and present), the security check is effectively skipped, allowing a cross-site POST request with an arbitrary JSON/data payload to be processed.
## Exploitation
- **Status:** PoC Available
- **Complexity:** Low
- **Attack Vector:** Network (Web-based)
## Impact
- **Confidentiality:** Low (CSRF is typically a "write" primitive)
- **Integrity:** Medium to High (Depends on the action performed by the vulnerable endpoint, e.g., fund transfers, password changes)
- **Availability:** Low
## Remediation
### Patches
- This is a logic flaw in application implementation rather than a specific software bug. Applications should be updated to use robust CSRF defenses.
### Workarounds
- **Strict Header Validation:** Ensure the `Content-Type` header is not only "not wrong" but is explicitly "present" and "correct."
- **SameSite Cookie Attribute:** Set cookies to `SameSite=Lax` or `SameSite=Strict` to prevent them from being sent in cross-site POST requests.
- **Anti-CSRF Tokens:** Implement unique, per-session synchronizer tokens for all state-changing requests.
- **Custom Headers:** Require a custom header (e.g., `X-Requested-With`) which forces a CORS pre-flight regardless of the content type.
## Detection
- **Indicators of Compromise:** HTTP POST requests to sensitive endpoints that lack a `Content-Type` header but contain a valid data body.
- **Detection Methods:** Web Application Firewalls (WAFs) can be configured to block state-changing requests (POST/PUT/DELETE) that arrive without a `Content-Type` header or with an unexpected `Origin` header.
## References
- **Original Research:** hxxps[://]nastystereo[.]com/2024/11/26/cross-site-post-requests-without-a-content-type-header/
- **Fetch Documentation:** hxxps[://]fetch[.]spec[.]whatwg[.]org/#cors-protocol-exceptions
- **Historical Context:** hxxps[://]www[.]mozilla[.]org/en-US/security/advisories/mfsa2011-10/