CSRF and XSS Protection in PHP


Introduction

When developing secure web applications in PHP, two of the most critical vulnerabilities you must defend against are CSRF (Cross-Site Request Forgery) and XSS (Cross-Site Scripting). These attack vectors are widely used by hackers to steal user data, perform unauthorized actions, or inject malicious scripts.

In this guide, we'll explore:

  • What is CSRF and XSS in PHP?
  • Real-world examples of CSRF and XSS attacks
  • How to prevent CSRF attacks using tokens
  • How to protect against XSS using output encoding
  • Secure coding practices to reduce risks
  • Tools and libraries to enhance PHP security

What is CSRF in PHP?

CSRF (Cross-Site Request Forgery) Definition

CSRF is a type of session-riding attack where an attacker tricks an authenticated user into submitting a malicious request to your application.

Example CSRF Attack

Suppose a user is logged into their online banking account and clicks on a malicious link:

<img src="https://bank.com/transfer.php?to=attacker&amount=1000">

If the application doesn't verify the request's authenticity, the money will be transferred without user consent.

How CSRF Works in PHP

  • The attacker sends a request on behalf of a logged-in user.
  • The user's session cookie is automatically included.
  • The server accepts the forged request.

How to Prevent CSRF in PHP

The most effective way to prevent CSRF attacks in PHP is to use CSRF tokens.

What is a CSRF Token?

A CSRF token is a unique, random string generated for each session/form and verified on form submission.

Step-by-Step CSRF Token Implementation in PHP

1. Generate CSRF Token

session_start();

if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

2. Add Token to HTML Form

<form action="process.php" method="post">
  <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
  <input type="text" name="username">
  <input type="submit" value="Submit">
</form>

3. Validate Token in PHP Script

session_start();

if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    die("CSRF token validation failed");
}

This ensures that only genuine form submissions are processed.

XSS (Cross-Site Scripting) in PHP

What is XSS?

XSS occurs when an attacker injects malicious scripts into content that is viewed by other users.

Types of XSS Attacks

  • Stored XSS: Malicious code stored in a database
  • Reflected XSS: Code is included in URL and reflected back to the user
  • DOM-Based XSS: Injected into the page through the DOM (JavaScript)

Example Reflected XSS

echo "Welcome " . $_GET['name'];

If the URL is: ?name=<script>alert(1)</script>, the script will execute.

How to Prevent XSS in PHP

The key to preventing XSS is output encoding. Always escape special characters in user input before rendering.

1. Use htmlspecialchars()

$name = htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
echo "Welcome " . $name;

This converts:

  • < to &lt;
  • > to &gt;
  • " to &quot;
  • ' to &#039;

2. Encode All Output from User Input

Whenever you display data from users—via forms, database, or URLs—use htmlspecialchars().

3. Avoid echo $_POST or $_GET Directly

Instead, always sanitize like this:

echo htmlspecialchars($_POST['message']);

PHP XSS and CSRF Vulnerabilities in Forms

Insecure Example

<form method="post">
  <input type="text" name="comment">
  <input type="submit">
</form>

<?php echo $_POST['comment']; ?>

Secure Example

<form method="post">
  <input type="text" name="comment">
  <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
  <input type="submit">
</form>

<?php echo htmlspecialchars($_POST['comment']); ?>

Combines CSRF and XSS protection.

Secure Coding Practices for PHP

1. Sanitize User Input

Use filter_input() or filter_var() for validation:

$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

2. Set Content-Type Headers

header("Content-Type: text/html; charset=UTF-8");

This reduces risk of character-set-based XSS attacks.

3. Disable register_globals

Ensure your php.ini has:

register_globals = Off

This prevents automatic variable creation from $_GET and $_POST.

4. Use Content-Security-Policy (CSP)

In HTML headers:

header("Content-Security-Policy: default-src 'self'; script-src 'self';");

Helps mitigate XSS by controlling where scripts can be loaded from.

Tools and Libraries for CSRF/XSS Protection in PHP

1. Symfony Security CSRF Component

composer require symfony/security-csrf

Automatically handles token generation and validation.

2. Laravel Built-in CSRF Protection

Laravel includes CSRF tokens in all forms by default using Blade:

@csrf

3. OWASP PHP Security Cheat Sheet

Regularly updated guidelines: OWASP PHP Security

Comparison Table: CSRF vs XSS

Feature CSRF XSS
Attack Vector Forged requests Injected scripts
Targets Authenticated users End users
Type of Threat Unauthorized actions Data theft, session hijack
Prevention Method Tokens, SameSite cookies Output encoding, content validation
Typical Entry Point Forms, links URL, comment, input field