Blood Donor Management System v1.0 - Stored XSS

Exploit Author: Ehlullah Albayrak Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2023-09-04
# Exploit Title: Blood Donor Management System v1.0 - Stored XSS
# Application: Blood Donor Management System
# Version: v1.0   
# Bugs:  Stored XSS
# Technology: PHP
# Vendor Homepage: https://phpgurukul.com/
# Software Link: https://phpgurukul.com/blood-donor-management-system-using-codeigniter/
# Date: 15.08.2023
# Author: Ehlullah Albayrak
# Tested on: Windows


#POC
========================================
1. Login to user account
2. Go to Profile 
3. Change "State" input and add "<script>alert("xss")</script>" payload.
4. Go to http://localhost/blood/welcome page and search "O", XSS will be triggered.

#Payload: <script>alert("xss")</script>


Blood Donor Management System v1.0: A Case Study in Stored XSS Vulnerability

Security flaws in web applications can have far-reaching consequences, especially when they involve sensitive data handling. The Blood Donor Management System v1.0, developed using CodeIgniter and PHP, exemplifies a critical vulnerability that remains undetected in production environments: Stored Cross-Site Scripting (XSS). This article explores the exploit in depth, outlines its implications, and provides actionable mitigation strategies.

Understanding Stored XSS

Unlike reflected XSS, where malicious scripts are triggered via URL parameters, stored XSS occurs when attacker-supplied code is permanently saved in the application’s database or server-side storage. When users access the affected page, the malicious script executes automatically, compromising all visitors.

Stored XSS is particularly dangerous because:

  • It persists across sessions.
  • It can bypass client-side protections like CSP (Content Security Policy).
  • It enables long-term attacks, such as credential theft, session hijacking, or redirecting users to phishing sites.

The Vulnerability in Blood Donor Management System v1.0

As reported by researcher Ehlullah Albayrak on August 15, 2023, the system’s profile management feature allows users to update their personal information, including the "State" field. This input is not sanitized before being stored in the database.

Attackers can exploit this by injecting malicious JavaScript code directly into the "State" field. The payload used in the proof-of-concept (PoC) is:

<script>alert("xss")</script>

This script is stored in the database and later rendered on the Welcome page, where the system displays user data based on search queries. When a user searches for a specific character (e.g., "O"), the system retrieves and displays the stored "State" value, triggering the script.

Step-by-Step Exploit Analysis

Step Description Security Risk
1 Login to a user account Authentication bypass is not required; the vulnerability is accessible to authenticated users.
2 Navigate to Profile section UI interface exposes editable fields without input validation.
3 Modify "State" field with <script>alert("xss")</script> Malicious payload is saved to the database.
4 Visit http://localhost/blood/welcome and search for "O" Stored script is rendered and executed in the browser.

This demonstrates a real-world exploitation path where an attacker can:

  • Steal session cookies via document.cookie.
  • Redirect users to malicious websites using window.location.href.
  • Collect user data through hidden form submissions.

Why This Vulnerability Exists

At the core of this flaw lies a failure in input sanitization and output encoding. The system likely uses PHP functions like $_POST['state'] without filtering or escaping, leading to direct database storage of raw user input.

Code snippet from the vulnerable profile update function (hypothetical):

// Vulnerable code example
$state = $_POST['state'];
$this->db->insert('users', array('state' => $state));

This code fails to:

  • Validate input against a whitelist of acceptable values.
  • Escape special characters (e.g., <, >, ") using htmlspecialchars().
  • Apply output encoding when rendering data on the frontend.

Security Best Practices and Fixes

Here is a corrected implementation using CodeIgniter best practices:

// Secure code example
$state = $this->input->post('state');
// Sanitize input using htmlspecialchars
$state = htmlspecialchars($state, ENT_QUOTES, 'UTF-8');

// Validate input (optional)
if (!preg_match('/^[A-Za-z\s]+$/', $state)) {
    show_error('Invalid state input');
}

// Insert into database safely
$this->db->insert('users', array('state' => $state));

Explanation:

  • htmlspecialchars() converts dangerous characters to their HTML-safe equivalents (e.g., < becomes &lt;).
  • ENT_QUOTES ensures both single and double quotes are escaped.
  • Input validation via regex ensures only letters and spaces are allowed.
  • Database insertion uses sanitized data, preventing script injection.

Additional Mitigation Measures

Beyond input sanitization, developers should implement:

  • Content Security Policy (CSP): A header like Content-Security-Policy: script-src 'self'; restricts execution to trusted sources.
  • Output encoding: Always encode data before rendering in HTML, especially when displaying user-generated content.
  • Role-based access control: Limit who can edit profile fields, especially sensitive ones.
  • Regular vulnerability scanning: Use tools like OWASP ZAP or Burp Suite to detect XSS during development.

Conclusion

The Blood Donor Management System v1.0 serves as a cautionary tale for developers and organizations handling sensitive data. A seemingly minor oversight—failing to sanitize user input—can lead to widespread exploitation. Stored XSS is not just a technical flaw; it’s a systemic failure in security hygiene.

By adopting proactive measures such as input validation, output encoding, and defensive coding practices, developers can eliminate such vulnerabilities before they reach production. Remember: every user input is a potential attack vector.