HTMLy Version v2.9.6 - Stored XSS
# Exploit Title: HTMLy Version v2.9.6 - Stored XSS
# Exploit Author: tmrswrr
# Vendor Homepage: https://www.htmly.com/
# Version 3.10.8.21
# Date : 04/08/2024
1 ) Login admin https://127.0.0.1/HTMLy/admin/config
2 ) General Setting > Blog title > "><img src=x onerrora=confirm() onerror=confirm(1)>
3 ) After save it you will be see XSS alert HTMLy Stored XSS: Overview, Impact, and Remediation
Stored cross-site scripting (XSS) vulnerabilities remain one of the most common issues in content management systems and lightweight blogging platforms. A stored XSS arises when an application accepts untrusted input, persists it (e.g., in a database or configuration), and later renders that content into pages without proper encoding or filtering. This article explains the mechanics, impact, detection, and secure fixes for stored XSS in the context of HTMLy-like systems, with defensive code examples and practical mitigation guidance.
What is Stored XSS?
Stored XSS occurs when malicious input is saved on the server and returned to users as part of a web page. Because the payload is persistent, it can affect any user who views the compromised content, including administrators. Exploits often target places that accept rich text or configuration fields that are later rendered in HTML contexts.
Why CMS and Admin Configurations are High-Value Targets
- Configuration fields (site title, descriptions, widgets) are rendered on many pages, increasing the blast radius.
- Administrative interfaces often run with elevated privileges and can be used to pivot to other functionality or extract secrets.
- Public-facing content combined with persistent storage means attackers can reach many users without repeated action.
Typical Impact
| Impact | Examples |
|---|---|
| Session Hijacking | Stealing cookies (if not HttpOnly) or issuing unauthorized requests on behalf of other users. |
| Privilege Escalation | Executing actions in admin sessions or loading admin-only resources. |
| Malware Distribution | Injecting scripts that redirect users or load external malicious content. |
| Reputation & SEO Damage | Website defacement or search-engine penalties due to malicious content. |
Principles for Preventing Stored XSS
- Validate input to reduce unexpected content, but do not rely on validation alone to prevent XSS.
- Encode output according to context (HTML body, attribute, JavaScript, URL, CSS).
- Use a well-maintained HTML sanitizer if you allow limited HTML from users.
- Deploy defense-in-depth: HTTP-only cookies, Content Security Policy (CSP), and least privilege for administrative interfaces.
- Keep software dependencies and platforms updated with vendor patches.
Output Encoding by Context
| Context | Recommended Encoding/Function |
|---|---|
| HTML body | htmlspecialchars(..., ENT_QUOTES, 'UTF-8') |
| HTML attribute | htmlspecialchars(..., ENT_QUOTES, 'UTF-8') |
| URL parameter | rawurlencode() |
| JavaScript string | JSON encoding or specialized JS-escape routines |
| CSS | Avoid direct user data in CSS, use strict allowlists |
Secure PHP Examples
Example 1 — Safe rendering of a stored title in HTML body or attribute:
<?php
// Assume $siteTitle comes from a trusted retrieval from DB but is user-controlled input.
$siteTitle = $row['title']; // untrusted source
// When outputting into HTML content or attributes, escape properly:
echo '<title>' . htmlspecialchars($siteTitle, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '</title>';
// When using inside an attribute:
echo '<h1 title="' . htmlspecialchars($siteTitle, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '">' .
htmlspecialchars($siteTitle, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') .
'</h1>';
?>Explanation: htmlspecialchars with ENT_QUOTES ensures both single and double quotes are escaped. ENT_SUBSTITUTE avoids injection of invalid byte sequences. Always set the correct character set (UTF-8) to prevent encoding ambiguities.
Example 2 — Allowing limited HTML safely using a whitelist sanitizer (HTMLPurifier):
// Composer install: ezyang/htmlpurifier
require_once 'vendor/autoload.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'p,b,i,strong,em,a[href],ul,ol,li'); // strict whitelist
$purifier = new HTMLPurifier($config);
$dirtyHtml = $row['body']; // user-supplied
$cleanHtml = $purifier->purify($dirtyHtml);
echo $cleanHtml;Explanation: HTMLPurifier parses and rebuilds HTML using a configured whitelist. This approach is safer than regex-based stripping and prevents script insertion in allowed tags, attributes, or event handlers.
Content Security Policy (CSP) — Additional Layer
// Example PHP header for a restrictive CSP (adjust to your resources)
header(\"Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none';\");
Explanation: A conservative CSP reduces the risk of XSS payloads by restricting where scripts can be loaded from and disallowing inline scripts. Note that CSP is a mitigation not a replacement for output encoding; complex applications may need to permit specific external resources.
Other Practical Mitigations
- Set cookies with HttpOnly, Secure, and SameSite attributes to reduce theft risk.
- Enforce role-based access controls on configuration pages and require strong admin authentication (MFA).
- Limit where user-supplied configuration values are used — avoid rendering raw config fields into HTML without encoding.
- Log and monitor changes to high-impact configuration values and notify administrators of unexpected edits.
Detecting and Testing Stored XSS Safely
- Use automated scanners and static analysis tools to flag unencoded output paths.
- Perform manual application-level code reviews focusing on template rendering and escaping functions.
- When testing, use controlled, non-malicious markers and coordinate with owners — avoid automated payloads on production systems without authorization.
- Employ a staging environment that mirrors production for safe penetration testing.
Responsible Remediation and Disclosure
- Confirm the affected versions and apply vendor-released patches promptly. If a patch is not available, apply temporary mitigations: sanitize persisted fields and restrict access to admin pages.
- Report discovered vulnerabilities to the vendor through their official channels and allow reasonable time for a fix.
- After fixes, deploy and verify by testing the specific inputs and outputs in a safe environment.
Summary Checklist for Developers and Operators
- Audit all code paths where user input is stored and later rendered.
- Apply context-appropriate output encoding instead of attempting to filter all dangerous characters.
- Use a whitelist-based HTML sanitizer for rich text input.
- Harden cookies and transport (HTTPS, HSTS) and implement CSP where practical.
- Keep the platform and dependencies up to date and follow vendor advisories.