Skip to main content
FAQ Component
Question
What are some common security vulnerabilities in Drupal, and how would you mitigate them?
Answer

Drupal is a robust and secure CMS, but like any web application, it is susceptible to security vulnerabilities. Below are some common Drupal security vulnerabilities and best practices to mitigate them.


1. SQL Injection

Issue:

  • Attackers can manipulate database queries via unsanitized input fields, leading to data leaks or database corruption.

Mitigation:

Use Drupal’s Database API (db_query, db_select, etc.)
Drupal provides parameterized queries to prevent SQL injection.

❌ Bad (Vulnerable Code)

$query = "SELECT * FROM users WHERE uid = " . $_GET['uid'];
$result = db_query($query);

✅ Secure (Using Drupal Database API)

$query = \Drupal::database()->select('users', 'u')
    ->fields('u', ['uid', 'name', 'mail'])
    ->condition('uid', $_GET['uid'], '=');
$result = $query->execute();

2. Cross-Site Scripting (XSS)

Issue:

  • Attackers inject malicious JavaScript code into input fields, affecting users who view the page.
  • Can lead to cookie theft, session hijacking, and defacing of content.

Mitigation:

Use Twig auto-escaping in templates
Sanitize output using Drupal’s Xss::filter() and Html::escape() functions
Validate and restrict HTML inputs

❌ Bad (Vulnerable Code)

echo $_GET['name']; // Directly outputs user input (XSS risk) 

✅ Secure

use Drupal\Component\Utility\Html;
echo Html::escape($_GET['name']); // Escapes special characters 

In Twig templates, auto-escaping is enabled by default:

<p>{{ user_input }}</p> {# Auto-escaped in Twig #}

3. Cross-Site Request Forgery (CSRF)

Issue:

  • Attackers trick authenticated users into submitting malicious requests without their knowledge.

Mitigation:

Use Drupal’s built-in CSRF tokens (Form API and Url::fromRoute() with CSRF protection).
Verify tokens before executing critical actions.

❌ Bad (Vulnerable Code)

<form action="/delete-node" method="POST">
    <input type="hidden" name="node_id" value="123">
    <button type="submit">Delete</button>
</form>
  • If a user visits a malicious site while logged in, the site could trigger this action.

✅ Secure (Using Drupal CSRF Token)

use Drupal\Core\Url;

$url = Url::fromRoute('custom_module.delete_node', ['node' => 123], ['absolute' => TRUE])->toString();
echo '<a href="' . $url . '">Delete</a>';
  • This ensures only authenticated users with a valid session can perform the action.

4. Remote Code Execution (RCE)

Issue:

  • Attackers exploit poorly validated file uploads or unserialized data to execute malicious PHP code.

Mitigation:

Disable PHP execution in public file directories (sites/default/files).
Use file_validate_extensions() to restrict uploaded file types.
Avoid using eval(), system(), or exec().

✅ Secure File Upload in a Form

$form['file_upload'] = [
    '#type' => 'managed_file',
    '#title' => t('Upload File'),
    '#upload_validators' => [
        'file_validate_extensions' => ['jpg png pdf'], // Restrict file types
    ],
    '#upload_location' => 'public://uploads/',
];

✅ Secure File Access

use Drupal\Core\File\FileSystemInterface;

$file = file_save_data($data, 'public://uploads/secure-file.txt', FileSystemInterface::EXISTS_REPLACE);

5. Access Control Issues

Issue:

  • Improper role or permission management can allow unauthorized users to view, edit, or delete sensitive data.

Mitigation:

Define permissions in my_module.permissions.yml
Use user_access() to check permissions before executing actions.

✅ Secure Access Check

if (!\Drupal::currentUser()->hasPermission('administer site configuration')) {
    throw new AccessDeniedHttpException();
}

6. Security Misconfigurations

Issue:

  • Leaving development configurations enabled on a live site can expose debugging information, logs, and database errors.

Mitigation:

Disable error reporting in production (settings.php)
Use .htaccess to restrict access to sensitive directories (sites/default/files/private).
Always apply security updates (drush updb and composer update).

✅ Secure settings.php

$config['system.logging']['error_level'] = 'hide'; // Hide errors in production 

✅ Restrict Access to Sensitive Files

<FilesMatch "(\.env|settings.php|services.yml|.*\.log)">    Require all denied </FilesMatch>

7. Insecure Third-Party Modules

Issue:

  • Using unverified or outdated contributed modules can introduce security vulnerabilities.

Mitigation:

Only install trusted modules from Drupal.org
Enable security updates (drush pm:security)
Review module permissions and configurations

✅ Check for security updates

drush pm:security composer update --with-dependencies

8. Session Hijacking

Issue:

  • If session cookies are exposed, attackers can impersonate users.

Mitigation:

Use HTTPS ($settings['https'] = TRUE;)
Regenerate session IDs after login (session_regenerate_id(TRUE))
Set SameSite cookies to prevent CSRF attacks (cookie_samesite: 'Strict')

✅ Secure Session Configuration

$settings['cookie_samesite'] = 'Strict';
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_httponly', 1);

Final Takeaways

VulnerabilityMitigation
SQL InjectionUse Drupal’s Database API (->condition())
XSSEscape output (Html::escape()), use Twig auto-escaping
CSRFUse form tokens and Url::fromRoute()
RCERestrict file uploads (file_validate_extensions()) and disable PHP execution in /files/
Access ControlUse user_access() and properly configure permissions
Security MisconfigurationsDisable error reporting and secure settings.php
Third-Party ModulesInstall only trusted modules and run drush pm:security
Session HijackingUse HTTPS and secure cookies
Question
Can you explain how CSRF and XSS attacks work and the steps you take to prevent them in a PHP application?
Answer

Cross-Site Request Forgery (CSRF) & Cross-Site Scripting (XSS) in PHP Applications

Both CSRF and XSS are common web security vulnerabilities, but they work differently and require different mitigation strategies.


1. Cross-Site Request Forgery (CSRF)

How CSRF Works

A CSRF attack tricks an authenticated user into making unintended requests to a web application on which they are logged in. This can lead to unauthorized actions, such as changing account settings, transferring funds, or deleting content.

CSRF Attack Example

  1. A user logs into a banking website and stays logged in (session is active).
  2. The attacker sends a malicious email or embeds a hidden request in a page:

    <img src="https://bank.com/transfer.php?to=attacker&amount=1000" />
  3. When the user loads the email or visits the attacker’s page, their browser automatically sends the request with session cookies, transferring money to the attacker.

Mitigation Strategies

Use CSRF Tokens: Generate and verify tokens for critical actions.
Use SameSite Cookies: Prevent cookies from being sent with cross-site requests.
Verify Referrer Headers: Ensure requests originate from the same domain.
Require Re-authentication: For sensitive actions like changing passwords or transferring money.

CSRF Prevention in PHP

✅ Step 1: Generate a CSRF Token

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

✅ Step 2: Include CSRF Token in Forms

<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>

✅ Step 3: Validate CSRF Token in PHP

session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        die("CSRF token validation failed.");
    }
}

✅ Step 4: Use SameSite Cookies in php.ini

session.cookie_samesite = Strict session.cookie_secure = 1 session.cookie_httponly = 1 

2. Cross-Site Scripting (XSS)

How XSS Works

XSS allows attackers to inject malicious JavaScript into web pages, which can steal cookies, hijack sessions, or deface websites.

Types of XSS Attacks

TypeDescriptionExample
Stored XSSMalicious script is saved in the database and executed for all users.A comment section where users inject <script>alert("Hacked!");</script>.
Reflected XSSMalicious script is injected into URLs and executed when a user clicks the link.https://example.com/search?q=<script>alert('Hacked!')</script>
DOM-based XSSMalicious JavaScript is executed by modifying the page’s DOM without server interaction.document.write(location.search) used insecurely.

Mitigation Strategies

Escape User Input: Prevent scripts from executing by encoding special characters.
Use Html::escape() (Drupal) or htmlspecialchars() (PHP): Convert <script> to &lt;script&gt;.
Enable HTTP Content Security Policy (CSP): Restrict the execution of scripts to trusted sources.
Use X-XSS-Protection Header: Modern browsers block reflected XSS.
Validate and Sanitize Inputs: Remove unexpected input before saving to the database.

XSS Prevention in PHP

❌ Bad (Vulnerable Code)

echo $_GET['name']; // Unescaped output, allows script injection 

✅ Secure Code

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

✅ Secure Form Processing

$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8');

✅ Secure Output in JavaScript Context

echo json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);

✅ Use a Content Security Policy (CSP) In .htaccess or nginx.conf:

Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'"

Key Differences Between CSRF and XSS

FeatureCSRFXSS
Attack TypeForces user to perform unintended actionsInjects malicious scripts into a web page
GoalAbuse authenticated sessionSteal cookies, execute unauthorized JS
Common ExploitHidden form submissions, AJAX requestsInjecting <script> tags into inputs
MitigationCSRF tokens, SameSite cookies, referrer checksEscaping output, CSP, input validation

Final Thoughts

  1. CSRF attacks trick authenticated users into performing unintended actions.
    • Use CSRF tokens, SameSite cookies, and re-authentication for critical actions.
  2. XSS attacks inject malicious scripts to steal data or deface websites.
    • Escape all user input before outputting to the page (htmlspecialchars(), Html::escape()).
  3. Both vulnerabilities can be prevented with proper security measures such as CSP headers, input validation, and proper authentication mechanisms.
Tag
PHP