Axios SSRF漏洞(CVE-2026-40175)漏洞分析
学习一下漏洞原理和流程
漏洞描述:
Axios 是一个基于 Promise 的 HTTP 客户端,可在浏览器和 Node.js 环境中运行,用于向后端 API 发送异步请求,支持请求/响应拦截、数据转换、自动 JSON 处理等特性,是目前前端开发中最流行的 HTTP 请求库。
Axios 1.15.0 版本之前存在一个SSRF漏洞,未授权的攻击者可以构造畸形的HTTP结构发送至非预期目标,导致敏感信息泄露。
影响版本:Axios < 1.15.0
漏洞前言:
原型污染(Prototype Pollution):攻击者通过输入数据修改了 JavaScript 对象的原型(Object.prototype),导致所有对象都继承了恶意属性。
利用条件:
- 输入可控 攻击者能控制传给应用的参数(如 HTTP body、querystring、表单数据)。
- 解析库使用 应用使用
JSON.parse()、qs.parse()、lodash.merge()等库来处理用户输入。 - 未过滤特殊键 应用没有对
__proto__、constructor等特殊属性做过滤或清理。 - Axios配置合并 应用使用 Axios,并且在请求时会合并配置对象(
mergeConfig),从而继承污染后的属性。 - Header注入可利用 攻击者注入的 header 值中包含
\r\n,能让 HTTP 请求被拆分成多段。 - 代理或中间件存在 请求经过 Nginx、负载均衡或其他代理,允许请求走私生效。
漏洞效果:
请求走私导致ssrf,可造成由服务端发起的http请求
请求走私:攻击者可构造特殊请求,使前端转发一个请求,而后端将其拆分为多个请求,从而绕过安全控制。
例:
GET /test HTTP/1.1
Host: xxx
User-Agent: Mozilla/5.0
Accept: */*
X-Test: value\r\nGET /admin HTTP/1.1\r\nHost: localhost\r\n攻击链流程图
┌───────────────┐
│ 攻击者输入数据 │
│ (query/body) │
└───────┬───────┘
│ 带有 __proto__ 字段
▼
┌───────────────┐
│ 解析库处理输入 │
│ JSON.parse / │
│ qs.parse / │
│ lodash.merge │
└───────┬───────┘
│ 未过滤 __proto__
▼
┌───────────────┐
│ 原型污染成功 │
│ Object.prototype│
│ 被注入 headers │
└───────┬───────┘
│ 普通对象继承恶意属性
▼
┌───────────────┐
│ Axios 合并配置 │
│ mergeConfig │
└───────┬───────┘
│ header 中出现攻击者注入值代表污染成功
▼
┌───────────────┐
│ Header 注入 │
│ 值包含 \r\n │
└───────┬───────┘
│ 请求走私,请求被拆分成多段
▼
┌───────────────┐
│ 请求走私成功 │
│ 第一段正常 │
│ 第二段伪造 │
└───────────────┘漏洞复现:
参考https://github.com/pjt3591oo/CVE-2026-40175-poc。只解析test-prototype-pollution.js脚本即可
一、构造payload
58-66行定义payload。71行使用JSON.parse解析payload,JSON.parse默认是安全的,这里__proto__只是一个普通字符串 key

step1和step2输出结果。payload将会在headers中注入一个X-Smuggle,值为一个http请求数据包,Host填自身,这里填的imds,也可以写localhost。请求这个路径是 模拟窃取IAM凭证。

二、原型污染
关键点在于使用vulnerableMerge函数,通过递归调用,将攻击者传入的属性直接写入到全局的 Object.prototype。这里是写入 Object.prototype.headers。
为什么这里target[key]也就是target["__proto__"] 返回的是 Object.prototype?
- 在75行调用vulnerableMerge传入的target为{}
- 对于普通对象
{},它的原型就是Object.prototype。 - 所以
({})["__proto__"] == Object.prototype
为什么用这个函数?
为了演示污染原理,和axios合并配置一样,没有过滤 __proto__


Axios 合并配置缺陷
- Axios 在执行请求时会调用
mergeConfig合并默认配置和用户配置。 - 由于它没有过滤原型链上的属性,如 __proto__ ,攻击者污染的属性就会被“继承”进来。
- 例如:污染
headers,让所有请求都带上攻击者指定的头。
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请求中,无论这些请求是硬编码的还是动态生成的。
三、验证原型污染和请求走私
创建一个新的空对象 fresh, 如果原型污染成功,这个对象会继承被注入到 Object.prototype 的属性。
打印 fresh.headers。
- 如果污染失败,这里是
undefined。 - 如果污染成功,这里会显示攻击者注入的 headers 对象

step3输出结果,此时fresh.headers存在注入的X-Smuggle,原型污染成功。CRLF返回true代表 header 值里有 ,能够请求走私。

四、发起请求,CRLF注入导致HTTP请求走私
再次创建一个新的空对象 options,提取 options.headers(先前验证已经注入了X-Smuggle头) 赋值给taintedHeaders,这样它就变成了一个 普通对象的自有属性,不再依赖原型链 。接着 delete 清理掉全局污染,避免继续影响 Axios 内部逻辑, 关键点:如果不删除,全局污染会让 Axios 在合并配置时崩溃。
使用taintedHeaders作为header,adapter: rawSocketAdapter表示:HTTP 请求不走默认逻辑,而是自定义。

step4结果:可以看到taintedHeaders依旧存在X-Smuggle头,

五、请求响应
输出响应

服务端返回两个响应,第二个响应包存在:FAKE-IMDSv2-TOKEN-deadbeef1234, 说明伪造请求确实到达了模拟 IMDS 服务,并返回了假凭证。

进入容器内请求验证,响应内容一样,证明请求走私成功

参考链接:
https://github.com/pjt3591oo/CVE-2026-40175-poc
https://blog.csdn.net/weixin_42376192/article/details/160135877
