CWE-352 in APIs
- CWE ID
- CWE-352
- Category
- Input Validation
- Severity
- HIGH
- Short Name
- CSRF
What is CWE-352
CWE-352, known as Cross-Site Request Forgery (CSRF), is a web application weakness where an attacker tricks a victim into executing unwanted actions on a web application in which they're authenticated. The attacker crafts a malicious request and forces the victim's browser to send it to the target application, exploiting the victim's existing session cookies or authentication tokens.
The weakness manifests when applications rely solely on client-side cookies or session identifiers for authentication without validating that the request originated from the legitimate user interface. Since browsers automatically include cookies with requests to a domain, an attacker can create a malicious page that makes requests to the target application using the victim's credentials.
CWE-352 in API Contexts
In modern API architectures, CSRF vulnerabilities take different forms than traditional web applications. While APIs don't use browser-based sessions in the same way, they remain vulnerable through several mechanisms:
- State-changing endpoints: APIs that perform actions (POST, PUT, DELETE) without proper anti-CSRF tokens
- Session-based authentication: APIs using cookie-based sessions instead of token-based authentication
- Missing SameSite cookie attributes: Cookies that can be sent in cross-site contexts
- Unsafe consumption patterns: APIs that process requests from untrusted origins without validation
RESTful APIs are particularly vulnerable when they accept cookie-based authentication for state-changing operations. An attacker can create a malicious website that makes POST requests to an API endpoint, and if the victim is authenticated (cookies included), the API will process the request as if it came from the legitimate user.
Detection
Detecting CSRF vulnerabilities in APIs requires both automated scanning and manual testing approaches. middleBrick's API security scanner includes comprehensive CSRF detection through multiple techniques:
Automated CSRF Testing
middlebrick scan https://api.example.com/v1/usersThe scanner tests for:
- State-changing endpoints without anti-CSRF tokens
- Cookie-based authentication on POST/PUT/DELETE endpoints
- Missing SameSite cookie attributes
- Unsafe consumption of cross-origin requests
Manual Testing Checklist
- Test POST/PUT/DELETE endpoints with cookie authentication
- Attempt state changes from external domains
- Check for anti-CSRF tokens in API responses
- Verify SameSite cookie attributes in response headers
- Test with browser-based tools (Postman, curl) from different origins
Code Review Indicators
// Vulnerable pattern - no CSRF protection
app.post('/api/v1/users', (req, res) => {
// Process user creation using session cookies
createUser(req.body, req.session.userId);
});Remediation
Effective CSRF protection in APIs requires a defense-in-depth approach. Here are proven remediation strategies with code examples:
1. Implement Anti-CSRF Tokens
The most robust defense is requiring a unique token for state-changing operations:
// Generate CSRF token middleware
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
// Protected endpoint
app.post('/api/v1/users', csrfProtection, (req, res) => {
// req.csrfToken() is automatically validated
createUser(req.body);
res.json({ success: true });
});2. Use SameSite Cookie Attributes
Prevent cookies from being sent in cross-site requests:
// Set SameSite cookies
res.cookie('session', sessionId, {
httpOnly: true,
secure: true,
sameSite: 'Strict' // or 'Lax' for GET requests
});3. Adopt Token-Based Authentication
Replace cookie-based sessions with JWT or API keys:
// JWT-based authentication (stateless)
const jwt = require('jsonwebtoken');
// Protected endpoint
app.post('/api/v1/users', authenticateJWT, (req, res) => {
if (!req.user) {
return res.status(401).json({ error: 'Unauthorized' });
}
createUser(req.body);
res.json({ success: true });
});4. Implement CORS Policies
Restrict which origins can access your API:
const cors = require('cors');
const corsOptions = {
origin: ['https://yourdomain.com'], // Allow only trusted origins
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization']
};
app.use(cors(corsOptions));5. Validate Request Origin
Check the Origin and Referer headers:
function validateOrigin(req, res, next) {
const allowedOrigins = ['https://yourdomain.com'];
const origin = req.get('origin') || req.get('referer');
if (allowedOrigins.includes(origin)) {
return next();
}
res.status(403).json({ error: 'Forbidden' });
}