梦回2017-遇到.dwr
原创 swordlover 2026-08-06 17:31 山东

DWR是一个Java AJAX远程调用框架,让浏览器JS像调用本地函数一样调用后端Java方法。在国内的政企、运营商、传统金融行业,仍有大量基于 Struts2+DWR+jQuery老栈的存量系统在线运行。

声明:Tide安全团队原创文章,转载请声明出处!文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途给予盈利等目的,否则后果自行承担!

“I have no special talents. I am only passionately curious.” ---Albert Einstein(阿尔伯特·爱因斯坦)
一、因何而起
在某次已授权的渗透测试中,发现抓到的数据包长得不太一样,所有的荷载请求都左对齐,感觉它长得非常...板正...深得朕的喜爱,于是我翻了它的牌子,就想看看到底是啥。

二、为何梦回2017
因为这个技术是DWR(Direct Web Remoting)。它在2005年发布,在2017年进了Apache Attic后基本停止维护了,到现在已经停止维护超过8年。(也就是说,他停止维护的时候我才刚上大学,刚拥有电脑,刚进入互联网,刚开始涌动荷尔蒙)

2.1 那为什么还值得写 DWR
DWR是一个Java AJAX远程调用框架,让浏览器JS像调用本地函数一样调用后端Java方法。在国内的政企、运营商、传统金融行业,仍有大量基于 Struts2+DWR+jQuery老栈的存量系统在线运行。(比如这次我就遇到啦)

2.2 和常见 Web 请求的对比
2.2.1 请求格式的差异化对比:

2.2.2 Content-Type 与请求体对比

2.2.3 响应包格式对比

2.2.4 来张图一目了然

三、DWR安全风险
那看到这么一个DWR数据包能干些啥呢,大概捋了个思路
3.1 调试接口未授权访问
可以构造/dwr/test/(或老版本/dwr/index.html)的请求,会列出所有可调用的JSstub,就可以直接尝试调用,类似于swagger的swagger-ui.html。
GET /<context>/dwr/test/ GET /<context>/dwr/index.html GET /<context>/dwr/interface/<ScriptName>.js 
3.2 越权
如果通过3.1可以获取全部或者高权限的方法列表,可以替换methodName的值尝试越权访问。比如目前权限只有getUserById,我们获取到了一个管理员才有的deleteUserById方法,那么可以尝试替换进去看看有没有越权。(此处仅举例,非常不建议针对增删改功能进行测试!容易爆炸!)

3.3 XSS
第一种,插入xss触发输入异常报错,DWR异常处理时就会把Java异常信息直接拼到响应中回传。m如果包含未转义的用户输入就会形成反射型XSS,像这样。

第二种,早期版本的page参数报错会回显到响应里且没做转义,可以在 page字段插入XSS。

3.4 SQL注入
这个也很常见,前几年有一些厂商的应用爆出许多了sql注入漏洞。主要原因是DWR配置老旧、暴露的方法越来越多,比如每加一个业务就配一个。以我这次测试时发现的举例,拼接一下';waitfor delay '0:0:9'--+qs就触发了延时。

3.5 CSRF
DWR 早期版本完全依赖 JSESSIONID,没有 CSRF 防护。后续版本引入 scriptSessionId作为一次性令牌。但依旧可能会存在一些问题,比如:scriptSessionId没强制校验,置空即可绕过。测试时可以尝试 scriptSessionId=anyvalue、scriptSessionId=(空)发包仍能正常返回 ,那么CSRF 防护大概率可以绕过(可以摸鱼水个低危)。

3.6 其他已知的公开漏洞
1、圣乔ERP系统多处SQL注入漏洞
https://mp.weixin.qq.com/s/1iQAnHBLt8G6mFHxEtPmiQ
2、九思OA workflowSync.getUserStatusByRole.dwr SQL注入漏洞
https://mp.weixin.qq.com/s/PAFrcKJcMHUso463jQR0mw
3、泛微Ecology Dwr SQL注入漏洞
https://mp.weixin.qq.com/s/932wxtVWnIJlLP-HcXd4dA
4、Enesys客户服务管理平台dwr未授权访问
https://mp.weixin.qq.com/s/xZYIqI68oTfQ25EJ6xwF7w
5、CVE-2014-2609:DWR 2.x/3.x 反序列化漏洞
6、CVE-2013-5938:DWR 2.x/3.x 调用与ClassLoader相关问题
7、CVE-2014-0685:DWR 之前版本对scriptSessionId的处理缺陷
当然还有一些SSRF、任意文件读取等,但是实在找不到样例了,所以后面遇到要珍惜哦

四、总结
4.1 一些晦涩的术语

4.2 一些修复建议
1、内部必须用 PreparedStatement,禁止字符串拼接
2、DWR 关闭调试模式:debugfalse
3、加反代层白名单,仅允许特定 IP/UA 调用 *.dwr 路径
4、引入 RBAC 中间件,DWR 方法调用前后做角色校验
5、升级 DWR 至最后版本(3.0 RC 系列修复了若干反序列化问题);更优解是迁移到 Spring Boot + REST + Spring Security
往期推荐
E
N
D
