MediumVerifiedOpenWebA03:2021 Injection

Reflected XSS on promo.php via unescaped mysqli_error echo (GET-link delivered)

GET
/promo.php
StorefrontEvaluation environmentDetected 1x

Attack Path

2 stepsfrom/to/promo.php

Business Impact

An attacker can send victims a malicious promo.php link that executes arbitrary JavaScript on the site's origin, enabling session token theft, credential phishing, or silent action forgery against visitors. The same unescaped error-echo sink also enables error-based extraction of database contents via extractvalue() concatenation, exposing promo code and potentially other database data. Because the page is promoted for checking promo codes, link-delivered exploitation could erode customer trust and trigger compliance issues around customer data protection.

Description

When a query against promo_codes fails, promo.php echoes the raw mysqli_error string into an alert alert-danger div WITHOUT htmlspecialchars - unlike the code param's value="" reflection, which is correctly escaped (" < >). Attacker-controlled text reaches the error message through extractvalue()'s XPATH error (payload must fit the ~32-char XPATH truncation window), producing a link-delivered reflected XSS: ?code=' AND extractvalue(1,concat(0x7e,'<img src=x onerror=alert(1)>'))-- - renders the img tag live in the victim's browser. Confirmed by headless Chromium render: alertCalled: true.

Proof of Concept

Setup

No authentication required. The value="" attribute reflection of ?code= IS escaped (double quotes become "), but the database-error path echoes mysqli_error unescaped. Payload text is embedded inside the SQL string and surfaces via the XPATH error message, truncated at 32 chars - so a short payload is required.

Exploit

GET /promo.php?code=' AND extractvalue(1,concat(0x7e,'<img src=x onerror=alert(1)>'))-- - HTTP/1.1
Host: storefront.example

(URL-encoded when sent as a link to a victim.)

Verification

Response body contains the payload UNESCAPED in the error div:

<div class="alert alert-danger mt-4">
<i class="fas fa-times-circle"></i> Database Error: XPATH syntax error: '~<img src="x" onerror="alert(1)">'
</div>

Headless Chromium render of the same URL: signals.alertCalled = true (script execution confirmed). Contrast: ?code="><img src=x onerror=alert(1)> reflects escaped as value="&quot;&gt;&lt;img src=x onerror=alert(1)&gt;" - no execution - proving the error echo is the unescaped sink.

Cleanup

None - reflected, no state persisted.

Observed Behavior

HTTP GET with the extractvalue payload returned 200 with Database Error: XPATH syntax error: '~<img src=x onerror=alert(1)>' rendered raw in the alert-danger div (the same payload in the value="" attribute came back HTML-escaped). browser_render of the identical URL reported alertCalled: true, evalCalled: true - real JavaScript execution in the browser. Longer marker payload <img src=x onerror=window.__xss_fired=true> was truncated at the 32-char XPATH window (onerror="window.__xss), confirming the payload-length constraint.

Attack Scenarios

  • 1

    Attacker sends a victim a crafted promo.php link (e.g. via email/chat - page advertises promo checking); JavaScript executes in the victim's browser on the site origin

  • 2

    Same error-echo sink also enables error-based data extraction (extractvalue concatenation), compounding the SQLi finding

Triage & Management

Validation Status

StatusValidated
Last Validated3 days ago
Confidence
82%
VerdictConfirmed
Verification runs automatically when marked remediated

Exploitability

Exploit Available No

Asset Information

Organization Evaluation environment
Application Storefront
Vulnerability ID promotion-reflected-xss

Anonymized staging evaluation. Explore the full detail view; management actions are available in your own workspace.

Find issues in your app