CSRF in JavaScript
Vulnerability: Cross-Site Request Forgery (CSRF)
Vulnerable Code:
javascriptCopy code// No CSRF token validation
fetch('/update-profile', {
method: 'POST',
body: JSON.stringify({ email: 'newemail@example.com' })
});
Reason for vulnerability: The code performs a sensitive action without validating a CSRF token, making it susceptible to CSRF attacks.
Fixed Code:
javascriptCopy code// Fetch CSRF token from meta tag
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
fetch('/update-profile', {
method: 'POST',
headers: {
'CSRF-Token': token,
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: 'newemail@example.com' })
});
Reason for fix: Including a CSRF token in the request header ensures that the request is legitimate and not forged by an attacker.
Vulnerable Code
@Controller
public class TransferController {
@PostMapping("/transfer")
public String transferMoney(@RequestParam String to, @RequestParam BigDecimal amount) {
// Perform money transfer
return "redirect:/success";
}
}
Reason for Vulnerability:
This endpoint doesn't implement any CSRF protection, allowing attackers to trick users into making unintended transfers.
Fixed Code:
javaCopy@Controller
public class TransferController {
@PostMapping("/transfer")
public String transferMoney(@RequestParam String to, @RequestParam BigDecimal amount,
@RequestParam String _csrf, HttpSession session) {
if (!_csrf.equals(session.getAttribute("csrfToken"))) {
return "redirect:/error";
}
// Perform money transfer
return "redirect:/success";
}
@ModelAttribute
public void addCsrfToken(HttpSession session, Model model) {
String csrfToken = UUID.randomUUID().toString();
session.setAttribute("csrfToken", csrfToken);
model.addAttribute("csrfToken", csrfToken);
}
}
Reason for Fix:
The fixed code implements a custom CSRF token validation. A more robust solution would be to use Spring Security's built-in CSRF protection.
Vulnerable Code:
from flask import Flask, request, session
app = Flask(__name__)
@app.route('/change_email', methods=['POST'])
def change_email():
new_email = request.form['email']
user_id = session['user_id']
update_email(user_id, new_email)
return "Email updated successfully"
Reason for Vulnerability:
This Flask route doesn't implement any CSRF protection, allowing attackers to trick users into changing their email without their knowledge.
Fixed Code:
pythonCopyfrom flask import Flask, request, session
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
csrf = CSRFProtect(app)
@app.route('/change_email', methods=['POST'])
@csrf.exempt
def change_email():
if request.form['csrf_token'] != session['csrf_token']:
return "CSRF token mismatch", 403
new_email = request.form['email']
user_id = session['user_id']
update_email(user_id, new_email)
return "Email updated successfully"
@app.before_request
def csrf_protect():
if request.method == "POST":
token = session.pop('csrf_token', None)
if not token or token != request.form.get('csrf_token'):
abort(403)
Reason for Fix:
The fixed code implements CSRF protection using Flask-WTF's CSRFProtect and custom token validation.
JavaScript Example
Vulnerable Code:
javascriptCopy// Client-side code
fetch('/api/update-profile', {
method: 'POST',
body: JSON.stringify({ name: 'New Name' }),
headers: {
'Content-Type': 'application/json'
}
});
// Server-side code (Express.js)
app.post('/api/update-profile', (req, res) => {
// Update user profile
res.send('Profile updated');
});
Reason for Vulnerability:
The API endpoint doesn't implement any CSRF protection, making it vulnerable to cross-site requests.
Fixed Code:
javascriptCopy// Client-side code
fetch('/api/update-profile', {
method: 'POST',
body: JSON.stringify({ name: 'New Name' }),
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
credentials: 'include'
});
// Server-side code (Express.js)
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/api/update-profile', csrfProtection, (req, res) => {
// Update user profile
res.send('Profile updated');
});
Reason for Fix:
The fixed code implements CSRF protection using the csurf middleware for Express.js and includes the CSRF token in API requests.
Last updated