Common pattern with `readBody` may lead to CSRF
Environment
N/A
Reproduction
The following pattern for creating endpoints is common, and may lead to a CSRF attack, provided it is a GET/POST handler, and only requires strings, or arrays of strings in the body.
The following is an example of what a vulnerable handler might look like:
export default defineEventHandler(async e => {
// Authenticated endpoint
await VerifyAuthenticationHere(e)
// Assumption here that content-type is validated.
const body = await readBody(e)
// Optional validation here ...
// Some sensitive action that relies upon body
if (body.action === "update") {
await UpdateUser(body.new_username)
}
})
Describe the bug
The readBody utility will accept multiple different content type's, including application/json application/x-www-form-urlencoded and text/plain.
There is an assumption that the readBody handler will only emit an object for the application/json content type, however, this also occurs for application/x-www-form-urlencoded.
This has implications for security as cross-site requests can be sent when using the application/x-www-form-urlencoded, but they cannot be sent when using application/json.
If readBody is called without appropriate CSRF protections, or without verifying the content-type header, the application may be at risk of a CSRF attack.
Additional context
The following handler is an example of how an attacker could exploit one of these issues:
await fetch('https://whatever.io/api/edit', {
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'username': 'hacked!',
}),
mode: 'no-cors'
}
Logs
No response