写这篇文章的目的一是由于目前网上关于java代码审计的资料实在是太少了,本人作为一个java代码审计的新手,深知学习java代码审计的难受之处,所以将自己学习过程中挖掘的一些漏洞写成博客发出来希望可以给后人一些帮助,同时也可以记录下自己的成长过程。目的二是由于这次挖掘的漏洞REDOS,个人觉得这个漏洞还是很有意思的,很早就知道这个漏洞了但是从来没有挖到过,终于在一个月前挖到了,很开心,记录一下。

先介绍下REDOS这个漏洞吧,可能很多人并不是很熟悉这个漏洞,一是由于这种漏洞造成的影响是拒绝服务,影响似乎不是很严重;二是这种漏洞一般需要通过白盒测试才能发现,通常的黑盒测试很难发现这种漏洞。

OWASP的对它的描述是:正则表达式拒绝服务(Regular expression Denial of Service-ReDoS)是一种拒绝服务攻击(Denial of Service),它利用了大多数正则表达式实现可能会导致极端情况的原因,这些极端情况导致它们工作得非常缓慢(与输入大小呈指数关系),然后攻击者可以使用正则表达式导致程序进入这些极端情况,然后挂起很长时间。

说白了就是,应用程序中经常会有使用正则表达式去匹配字符串的情况,(1)如果开发人员对正则表达式的原理并不是很熟悉写出了类似“^(a+)+$”这样的正则,(2)由于业务需求,正则是动态构造的,且受用户控制。这两种情况,程序都可能受到REDOS攻击。大家可能第一眼看到“^(a+)+$”不会觉得这个正则有什么问题,这里也就是为什么说要懂原理才行。因为这里其实涉及到了编译原理的知识,我尽量讲清楚:

正则表达式引擎分成两类,一类称为DFA(确定性有限状态自动机),另一类称为NFA(非确定性有限状态自动机)。两类引擎要顺利工作,都必须有一个正则式和一个文本串,一个捏在手里,一个吃下去。DFA捏着文本串去比较正则式,看到一个子正则式,就把可能的匹配串全标注出来,然后再看正则式的下一个部分,根据新的匹配结果更新标注。而NFA是捏着正则式去比文本,吃掉一个字符,就把它跟正则式比较,然后接着往下干。一旦不匹配,就把刚吃的这个字符吐出来,一个一个吐,直到回到上一次匹配的地方。也就是说对于同一个字符串中的每一个字符,DFA都只会去匹配一次,比较快,但特性较少,而NFA则会去匹配多次,速度相比会慢很多但是特性多啊,所以用NFA作为正则表达式引擎的会多些。现在我们再来看^(a+)+$,大家应该能看出些问题了,当我们用它去匹配“aaaax”这个字符串时,他需要尝试2^4=16次才会失败,当我们这个字符串再长一点时,需要尝试的次数会成指数增长,aaaaaaaaaaX就要经历2^10=1024次尝试。

如下图:

可以看到java、php、python都是用的NFA(JS中好像也是),也就是说这些语言中用了正则的api都是可能存在问题的哦。比如java中比较常见的split,replaceAll等,这些方法中既可以接受字符串也可以接受正则表达式的。

说了这么多,准备进入正题吧,为什么一个月前就发现漏洞了,现在才写博客呢,本来是想等作者修复漏洞后再写博客的,但是因为github上的作者到现在都没有回复我,似乎并不准备修复,而我也懒得等了,直接将漏洞披露出来吧,毕竟漏洞影响不大,并且漏洞和程序上下文的联系也不大,复现的时候只需要将缺陷代码单独拿出来在本地复现即可。

这整个java文件是将文件转化为pdf格式的一个工具类,在转化文件格式的同时还需要 将文件名的后缀也修改下。如上两个方法就是用来修改文件名后缀的。getOutputFilePath(String inputFilePath)用于将文件名的后缀修改为.pdf,而文件名后缀是通过getPostfix(String inputFilePath)这一方法截断文件名中最后一个.后面的内容来获取的。简单介绍下String.replaceAll(a,b)的意思就是将String中的字符串a全部替换成字符串b。比如说”aabbcc”.replaceAll(“a”,”b”),输出结果为“bbbbcc”,上面也说了a可以是正则表达式 当”aabbcc”.replaceAll(“(a)+”,”b”),输出结果为“fbbcc”。再回过头看代码,如果我们已知参数inputFilePath是可控的,怎样设置这个值才能触发REDOS攻击呢?

首先参数inputFilePath的后缀必须控制成一个真正表达式的样,我们可以先设置为.(a+)+,而.(a+)+作为正则表达式去匹配inputFilePath时,inputFilePath的前半部分必须符合这个正则才不至于匹配没开始就结束了,所以inputFilePath的前半部分也应该类似.aaaa这样,再和后缀拼凑起来就是.aaa.(a+)+

Ok,本地搭建环境测试一下:

发现程序运行的很快,关键是成功替换了字符串。回顾之前的说的,之所以能造成REDOS攻击是因为一直匹配失败,引擎才会反复尝试导致攻击的。怎样让他匹配失败呢又一直尝试呢?只需要将后缀.(a+)+改为.(a+)+$。这个正则的意思就是字符串必须以a结尾才行。修改之后重新运行:

发现虽然运行很快但是不会替换字符串了,也就是说匹配失败。

那我们再将inputFilePath改下,让程序匹配的时间长一些,如下图:

发现程序一直在运行,说明攻击成功了。

总结一下,挖掘REDOS漏洞,一是需要对程序中用到了正则的api有些了解(replaceAll只是最为常见的,其实还有很多),后面有时间的话我也会对这些api做些整理;二是要对正则有一定的了解才方便构造poc。

如何通过代码审计挖掘REDos漏洞的更多相关文章

  1. PHP代码审计6-实战漏洞挖掘-xdcms用户注册页面漏洞

    xdcms 源码:xdcms v2.0.8 1.配置 [一直下一步(仅为测试)] #数据库账号root,密码为空:管理员账号/密码:xdcms/xdcms #登录后台 2.查看后台登录页面的配置项[x ...

  2. PHP代码审计5-实战漏洞挖掘-cms后台登录绕过

    cms后台登录绕过 练习源码:[来源:源码下载](数据库配置信息有误,interesting) 注:需进行安装 1.创建数据库 2.设置账号密码,连接数据库 3.1 正常登录后台,抓包分析数据提交位置 ...

  3. 学习CSRF漏洞并挖掘CSRF漏洞

    什么是跨站请求伪造? 跨站请求伪造(英语:Cross-siterequest forgery),也被称为one-clickattack或者session riding,通常缩写为CSRF或者XSRF, ...

  4. Java Web代码审计流程与漏洞函数

    常见框架与组合 常见框架 Struts2 SpringMVC Spring Boot 框架执行流程 View层:视图层 Controller层:表现层 Service层:业务层 Dom层:持久层 常见 ...

  5. 2020/1/30 PHP代码审计之CSRF漏洞

    0x00 CSRF漏洞 CSRF(Cross-site request forgery)跨站请求伪造:也被称为"One Click Attack"或者Session Riding, ...

  6. 2020/1/29 PHP代码审计之XSS漏洞

    0x00 XSS漏洞简介 人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆.因此,有 ...

  7. 代码审计之DocCms漏洞分析

    0x01 前言 DocCms[音译:稻壳Cms] ,定位于为企业.站长.开发者.网络公司.VI策划设计公司.SEO推广营销公司.网站初学者等用户 量身打造的一款全新企业建站.内容管理系统,服务于企业品 ...

  8. PHP代码审计笔记--CSRF漏洞

    0x01 前言 CSRF(Cross-site request forgery)跨站请求伪造.攻击者盗用了你的身份,以你的名义向第三方网站发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻 ...

  9. [代码审计]php反序列化漏洞

    0x01 php面向对象简介 对象:可以对其做事情的一些东西.一个对象有状态.行为和标识三种属性. 类:一个共享相同结构和行为的对象的集合. 每个类的定义都以关键字class开头,后面跟着类的名字. ...

随机推荐

  1. nginx 的一些优化

    一般来说 nginx 配置文件中对优化比较有作用的为以下几项: worker_processes 8; nginx 进程数,建议按照 cpu 数目来指定,一般为它的倍数. worker_cpu_aff ...

  2. top-N 抽样

        1, 使用hive标记random:(如果是mr,就自己标记random值) use ps; set mapred.job.priority=VERY_HIGH; set mapred.job ...

  3. Android Bluetooth hci 命令分析

    Android在连接BLE设备的时候,遇到连接没多久就自动断开的情况.通过HCI来分析一下. BLE设备发送连接参数更新请求 3909 15:53:01.224737 TexasIns_f0:d3:4 ...

  4. python使用requests发送application/json报文数据

    def client_post_jsondata_requests(request_url,requestJSONdata): #功能说明:发送json请求报文到指定的地址并获取请求响应报文 #输入参 ...

  5. Kafka获取订阅某topic的所有consumer group【客户端版】

    之前写过如何用服务器端的API代码来获取订阅某topic的所有consumer group,参见这里.使用服务器端的API需要用到kafka.admin.AdminClient类,但是这个类在0.11 ...

  6. FZU 2150 fire game (bfs)

    Problem 2150 Fire Game Accept: 2133    Submit: 7494Time Limit: 1000 mSec    Memory Limit : 32768 KB ...

  7. JavaScript Promise:去而复返

    原文:http://www.html5rocks.com/en/tutorials/es6/promises/ 作者:Jake Archibald 翻译:Amio 女士们先生们,请准备好迎接 Web ...

  8. 10 windows server 2012R2 发布MVC框架网站注意事项

    1:网站编译完成之后,需要发布,网站中应包括的文件有:文件夹(bin,Views,Content等其他网站中涉及到的文件夹)文件(favicon.ico.Web.config.Global.asax) ...

  9. java核心技术笔记

    1.类和对象 第四章:面向对象 日历的作用是提供某个时间点的信息 查询设置信息:GregorianCalendar now = new GregorianCalendar() int month = ...

  10. spring-boot 集成 log4j 记录日志

    1.pom文件中移除和添加依赖 <!-- 移除boot—starter 的log4j --> <dependency> <groupId>org.springfra ...