Understanding Cross-Site Request Forgery (CSRF) with PHP, MySQL, and Docker

Understanding Cross-Site Request Forgery (CSRF) with PHP, MySQL, and Docker

Introduction

Cross-Site Request Forgery (CSRF) is a web security vulnerability where an attacker tricks a user into making an unintended request to a web application where they are authenticated. This can lead to unauthorized actions being performed on behalf of the victim.

In this tutorial, we will explore how CSRF attacks work, demonstrate an insecure PHP application vulnerable to CSRF, and implement proper mitigation techniques. We will also deploy our application using Docker.


How CSRF Attacks Work

  1. Victim Authentication: The victim logs into a legitimate website.
  2. Malicious Link: The attacker crafts a request that performs an action on the victim’s behalf.
  3. Tricking the Victim: The victim unknowingly clicks the malicious link or visits a page that sends the request.
  4. Unauthorized Request Execution: The website processes the request as if it came from the authenticated user.


Analogy: The Fake Check Trick

Imagine you have a signed blank check at home. You trust your roommate to handle your mail but never expect them to misuse your check.

One day, an attacker sends a convincing-looking letter pretending to be from your bank. The letter asks your roommate to fill in an amount and send the check on your behalf. Since your roommate doesn’t know any better, they follow the instructions, thinking it’s legitimate.

What just happened?

  • The attacker never needed your signature—they just tricked your trusted system (your roommate) into doing something on your behalf.
  • The bank processes the request because it looks like it came from you, just like a CSRF attack forces a website to process an unintended action using an authenticated session.

How This Relates to CSRF:

  • You (the victim) → The logged-in user on a website.
  • Your roommate (the browser) → The user's authenticated session.
  • The fake letter (malicious link/form) → The attacker's trick to send an unauthorized request.
  • The bank (website server) → The web application processing the request as if it were legitimate.

Just like how your bank wouldn’t question a signed check, many websites don’t verify if a request was intentionally made by the user—making them vulnerable to CSRF attacks.

Mitigation: Websites should require additional verification (like CSRF tokens) to prevent unauthorized requests—just like a bank should require extra authentication before processing critical transactions.


Setting Up Our Example Application

Requirements

  • PHP (Apache)
  • MySQL
  • Docker

Folder Structure

csfr-demo/
│── docker/
│   ├── Dockerfile
│   ├── docker-compose.yml
│── src/
│   ├── index.php
│   ├── login.php
│   ├── transfer.php (Vulnerable Transfer Endpoint)
│   ├── csrf_protected_transfer.php (Secure Transfer Endpoint)
│   ├── config.php (Database Configuration)
│── attacker/
│   ├── malicious_form.html
│── database/
│   ├── init.sql        

Database Setup (MySQL)

Create a MySQL database and user with the following SQL script (init.sql):

CREATE DATABASE csrf_demo;
USE csrf_demo;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL
);

CREATE TABLE transactions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    sender VARCHAR(50),
    recipient VARCHAR(50),
    amount DECIMAL(10,2)
);        

Vulnerable PHP Code (Without CSRF Protection)

This is a vulnerable transfer.php file that lacks CSRF protection:

<?php
session_start();
include 'config.php';

if (!isset($_SESSION['user'])) {
    die("Unauthorized access");
}

$recipient = $_POST['recipient'];
$amount = $_POST['amount'];
$user = $_SESSION['user'];

$query = $conn->prepare("INSERT INTO transactions (sender, recipient, amount) VALUES (?, ?, ?)");
$query->bind_param("ssd", $user, $recipient, $amount);
$query->execute();

echo "Transfer successful";
?>        

Problem:

  • No verification of request origin.
  • Any request from a logged-in user gets executed.


How an Attacker Exploits CSRF

The attacker creates a fake page (malicious_form.html) that tricks the victim into unknowingly transferring money.

<!DOCTYPE html>
<html>
<head>
    <title>Claim Your Prize</title>
</head>
<body>
    <h1>Congratulations! You've Won!</h1>
    <form action="https://localhost:8080/transfer.php" method="POST">
        <input type="hidden" name="recipient" value="attacker">
        <input type="hidden" name="amount" value="1000">
        <input type="submit" value="Claim Now">
    </form>
</body>
</html>        

Delivery Method:

  • Phishing Email: The attacker sends an email with a link to malicious_form.html.
  • Compromised Websites: The attacker embeds the form on a hacked webpage.
  • Social Media Links: The attacker spreads links to lure victims.


How the Victim Gets Tricked

  1. The victim is already logged into the banking site.
  2. The victim clicks the malicious link.
  3. The fake form submits an unauthorized transfer request.
  4. The banking system processes the request as if the victim authorized it.


Secure PHP Code (With CSRF Protection)

Modify csrf_protected_transfer.php to use CSRF tokens:

<?php
session_start();
include 'config.php';

if (!isset($_SESSION['user']) || !isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    die("Invalid CSRF Token");
}

$recipient = $_POST['recipient'];
$amount = $_POST['amount'];
$user = $_SESSION['user'];

$query = $conn->prepare("INSERT INTO transactions (sender, recipient, amount) VALUES (?, ?, ?)");
$query->bind_param("ssd", $user, $recipient, $amount);
$query->execute();

echo "Transfer successful";
?>        

Secure index.php (Generating CSRF Token)

<?php
session_start();
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
?>
<form action="csrf_protected_transfer.php" method="POST">
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    <input type="text" name="recipient" placeholder="Recipient">
    <input type="number" name="amount" placeholder="Amount">
    <input type="submit" value="Transfer">
</form>        

Building & Deploying with Docker

Dockerfile:

FROM php:apache
COPY src/ /var/www/html/
RUN docker-php-ext-install mysqli
EXPOSE 80        

docker-compose.yml:

version: '3'
services:
  web:
    build: .
    ports:
      - "8080:80"
    depends_on:
      - db
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: csrf_demo
    volumes:
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql        

Running the Project:

  1. Build and Start Containers: docker-compose up --build
  2. Access Application: Open https://localhost:8080/


Final Thoughts & Prevention Techniques

Preventing CSRF Attacks:

? Use CSRF tokens for form submissions.

? Implement SameSite cookies in session management.

? Validate HTTP Referer & Origin headers.

? Educate users on phishing threats.

? Implement multi-factor authentication (MFA) for sensitive actions.

By following these steps, you can protect your web applications from CSRF attacks. Stay secure! ??





















要查看或添加评论,请登录

Kathiresan Natarajan的更多文章

社区洞察

其他会员也浏览了