React Router 路径穿越漏洞分析 CVE-2025-61686

· 约 3 分钟 · 旧博客导入

最近看到了这个

【已复现】React Router 未授权路径遍历漏洞 (CVE-2025-61686):伪造 Cookie 即可实现任意文件写入

看完漏洞通报之后,大伙如果熟悉php应该能对这个漏洞一见如故,react router的文件session存储方案跟php如出一辙

下载react-router源码,找到@react-router/node的源码文件夹,发现文件很少,一眼就看到了packages/react-router-node/sessions/fileStorage.ts

image
image

这个文件也不是很长,里面也有明显路径穿越的痕迹

image
image

getFile方法就是拼接路径用的

image
image

感觉这里应该就是sink点,那么今天的漏洞分析就到这里

其实这个漏洞我本来想动手复现一下的,但是express+react服务端渲染配置起来比较麻烦,而react-router的cli默认又是安装最新版的react-router,手动修改版本又会出现依赖冲突;所以就不复现了,直接叫AI写代码片段给我

AI写的react-router session的使用方法大概如下

image
image
image
image

AI给我的代码应该是把session信息存储在cookie里面,类似jwt的方案,不过实际漏洞点不在这里,如果要复现漏洞的话,应该把createCookieSessionStorage改成createFileSessionStorage,也就是我们文章一开始就看到的那个文件:

image
image

言归正传,react-router服务端session的用法应该就是先createFileSessionStorage创建存储对象,要存东西的时候就通过getSession获取session,改完session之后再用commitSession写回去

但是createFileSessionStorage中并没有getSession和commitSession方法,这时注意到作为sink点的updateData是作为参数传入createSessionStorage的

直接看createSessionStorage方法,发现getSession和commitSession都在这里:

image
image

可以看到我们的sink点updateData在commitSession被调用了,作为污点的id则是由session参数传进来的

再看看AI的例子,可以发现session参数是从getSession获取的

image
image

接下来回到getSession,可以看到id是从await cookie.parse(cookieHeader, options)获取的

image
image

进入parse方法,可以看到这个id就是从cookie的值里拿到的

image
image

也就对应我们漏洞通报中poc的payload部分

image
image

因此只要攻击者在发起这个恶意请求时,服务端执行了commitSession,session存储文件就会目录穿越出来,造成任意位置的文件写入

最后看看官方怎么修的

Add some validation for session IDs (#14426) · remix-run/react-router@6ff0bb3

image
image

可以看到在getFile加了个正则,id只允许数字小写字母,而且长度必须为16。相当于做了严格的字符白名单

查找文章

↑↓ 选择 · Enter 打开 · Esc 关闭 查看全部结果