Cross Site Request Forgery (CSRF) — OWASP Juiceshop #2

DebianHat
3 min read3 days ago

--

Cross-site request forgery (also known as CSRF) allows an attacker to induce users to perform actions that they do not intend to perform (e.g., changing passwords, making purchases).
It allows an attacker to partly circumvent the same origin policy, which is designed to prevent different websites from interfering with each other.

Vulnerable Code:

  • The application relies only on cookies for authentication.
  • An attacker can trick the user into sending a malicious request while they are logged in.
app.post('/change-password', (req: Request, res: Response) => {
const { newPassword } = req.body;
const userId = req.session.userId; // Assuming session-based authentication

if (!userId) {
return res.status(401).json({ message: 'Unauthorized' });
}

// Update password in the database
updatePassword(userId, newPassword);
res.json({ message: 'Password changed successfully' });
});

Fixing CSRF (TypeScript):

  1. CSRF token using csurf middleware.
import express, { Request, Response, NextFunction } from 'express';
import csrf from 'csurf';
import cookieParser from 'cookie-parser';

const app = express();
app.use(cookieParser());
app.use(express.json());

// Initialize CSRF protection
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);

// Route to get CSRF token (Frontend should include it in requests)
app.get('/csrf-token', (req: Request, res: Response) => {
res.json({ csrfToken: req.csrfToken() });
});

// Secure Password Change Endpoint
app.post('/change-password', csrfProtection, (req: Request, res: Response) => {
const { newPassword } = req.body;
const userId = req.session?.userId; // Ensure session-based authentication

if (!userId) {
return res.status(401).json({ message: 'Unauthorized' });
}

updatePassword(userId, newPassword);
res.json({ message: 'Password changed successfully' });
});

2. Use satesite cookies.

app.use(require('express-session')({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
cookie: {
secure: true, // Only send cookies over HTTPS
httpOnly: true, // Prevent access from JavaScript
sameSite: 'strict' // Block CSRF attacks
}
}));

3. Restrict cors configuration.

import cors from 'cors';

app.use(cors({
origin: 'https://trusted-site.com', // Allow only trusted frontend
methods: ['GET', 'POST'],
credentials: true // Allow cookies only for trusted requests
}));

Code Fix for Juiceshop CSRF vulnerability

  1. Implement CSRF Protection Middleware:
  • Use the csurf middleware to enforce CSRF token validation for all state-changing requests (e.g., POST, PUT, DELETE).

2. Restrict CORS Policy:

  • Configure cors() to allow only trusted origins.

3. Use SameSite Cookies:

  • Set the SameSite attribute on cookies to Strict or Lax to prevent them from being sent with cross-origin requests.
Importing csuf
//csrf-fix
app.user(csurf({cookie: true}));
app.use(cors({origin: true, credentials: true
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
}));
app.use(cookieParser()
);
app.use((req: Request, res: Response, next: NextFunction) => {
res.cookie('XSRF-TOKEN', req.csrfToken())
next()
})
//csrf-fix

Once the changes are made and pushed to github, Snyk will automatically scan the code for changes.

Thanks for reading.
Happy Learning😊

Sign up to discover human stories that deepen your understanding of the world.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

DebianHat
DebianHat

Written by DebianHat

Penetration Tester, Ethical Hacker, Security Analyst

No responses yet

Write a response