浅析ReDoS
ReDoS(Regular expression Denial of Service) 正则表达式拒绝服务攻击。开发人员使用了正则表达式来对用户输入的数据进行有效性校验, 当编写校验的正则表达式存在缺陷或者不严谨时, 攻击者可以构造特殊的字符串来大量消耗服务器的系统资源,造成服务器的服务中断或停止。1 常见术语
先让我们来了解几个概念:
1.1 Regex
正则表达式(Regular Expression, Regex)是由字符(可为英文字母、数字、符号等)与元字符(特殊符号)组成的一种有特定规则的特殊字符串。在模式匹配中,正则表达式通常被用于验证邮箱、URL、手机号码等。
常用元字符:
| 元字符 | 说明 |
|---|---|
| \ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n” 匹配字符 “n”。“\n” 匹配一个换行符。序列 “\\” 匹配 “\” 而 “\(” 则匹配 “(”。 |
| ^ | 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^ 也匹配 “\n” 或 “\r” 之后的位置。 |
| $ | 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$ 也匹配 “\n” 或 “\r” 之前的位置。 |
| * | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z”、“zo” 以及 “zoo”。* 等价于 {0,}。 |
| + | 匹配前面的子表达式一次或多次。例如,“zo+” 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于{1,}。 |
| ? | 匹配前面的子表达式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 中的 “do”。? 等价于{0,1}。 |
| . | 匹配除 “\n” 之外的任何单个字符。要匹配包括 “\n” 在内的任何字符,请使用像 “ (.\$\lambda_1$\n)” 的模式。 |
| (pattern) | 匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用 “\(” 或 “\)”。 |
| \w | 匹配包括下划线的任何单词字符。等价于 “[A-Za-z0-9_]”。 |
| \W | 匹配任何非单词字符。等价于 “[^A-Za-z0-9_]”。 |
更多元字符请参考: 维基百科
1.2 DoS & DDoS
拒绝服务攻击(Denial-of-Service Attack)亦称洪水攻击,是一种网络攻击手法,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。
分布式拒绝服务攻击(Distributed Denial-of-Service Attack),是使用网络上两个或两个以上被攻陷的电脑作为 “僵尸” 向特定的目标发动 “拒绝服务” 式攻击。
DDoS攻击可以具体分成两种形式:
- 带宽消耗型攻击
- 洪水攻击
UDP、ICMP、ping of death
- 放大攻击
NTP、DNS
- 洪水攻击
- 资源消耗型攻击
SYN洪水、LAND attack、CC
1.3 FSM、DFA、 NFA
有限状态自动机:(FSM “finite state machine” 或者FSA “finite state automaton” )是为研究有限内存的计算过程和某些语言类而抽象出的一种计算模型。有限状态自动机拥有有限数量的状态,每个状态可以迁移到零个或多个状态,输入字串决定执行哪个状态的迁移。
有限状态自动机还可以分成确定与非确定两种, 非确定有限状态自动机可以转化为确定有限状态自动机。
正则表达式引擎分成两类:一类称为DFA(确定性有限状态自动机),另一类称为NFA(非确定性有限状态自动机)。两类引擎要顺利工作,都必须有一个正则式和一个文本串,一个捏在手里,一个吃下去。DFA捏着文本串去比较正则式,看到一个子正则式,就把可能的匹配串全标注出来,然后再看正则式的下一个部分,根据新的匹配结果更新标注。而NFA是捏着正则式去比文本,吃掉一个字符,就把它跟正则式比较,匹配就记下来:“某年某月某日在某处匹配上了!”,然后接着往下干。一旦不匹配,就把刚吃的这个字符吐出来,一个个的吐,直到回到上一次匹配的地方。
部分程序及其所使用的正则引擎:
| 引擎类型 | 程序 |
|---|---|
| DFA | awk(大多数版本)、egrep(大多数版本)、flex、lex、MySQL、Procmail |
| 传统型 NFA | GNU Emacs、Java、grep(大多数版本)、less、more、.NET语言、PCRE library、Perl、PHP(所有三套正则库)、Python、Ruby、set(大多数版本)、vi |
| POSIX NFA | mawk、Mortice Lern System’s utilities、GUN Emacs(明确指定时使用) |
| DFA/NFA混合 | GNU awk、 GNU grep/egrep、 Tcl |
2 ReDoS 原理
2.1 概述
DFA对于文本串里的每一个字符只需扫描一次,比较快,但特性较少;NFA要翻来覆去吃字符、吐字符,速度慢,但是特性(如:分组、替换、分割)丰富。NFA支持 惰性(lazy)、回溯(backtracking)、反向引用(backreference),NFA缺省应用greedy模式,NFA可能会陷入递归险境导致性能极差。
2.2 说明
我们定义一个正则表达式^(a+)+$来对字符串aaaaX匹配。使用NFA的正则引擎,必须经历2^4=16次尝试失败后才能否定这个匹配。同理字符串为aaaaaaaaaaX就要经历2^10=1024次尝试。如果我们继续增加a的个数为20个、30个或者更多,那么这里的匹配会变成指数增长。
下面我们以python语言为例子来进行代码的演示:
#!/usr/bin/env python# coding: utf-8import reimport timedef exp(target_str): """ """ s1 = time.time() flaw_regex = re.compile('^(a+)+$') flaw_regex.match(target_str) s2 = time.time() print("Consuming time: %.4f" % (s2-s1))if __name__ == '__main__': str_list = ( 'aaaaaaaaaaaaaaaaX', # 2^16 'aaaaaaaaaaaaaaaaaaX', # 2^18 'aaaaaaaaaaaaaaaaaaaaX', # 2^20 'aaaaaaaaaaaaaaaaaaaaaaX', # 2^22 'aaaaaaaaaaaaaaaaaaaaaaaaX', # 2^24 'aaaaaaaaaaaaaaaaaaaaaaaaaaX', # 2^26 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX', # 2^36 ) for evil_str in str_list: print('Current: %s' % evil_str) exp(evil_str) print('--'*40)
把上面的代码保存成redos.py文件并执行这个 py 脚本文件:
$ python redos.pyCurrent: aaaaaaaaaaaaaaaaXConsuming time: 0.0043--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaXConsuming time: 0.0175--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaXConsuming time: 0.0678--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaXConsuming time: 0.2370--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaaaXConsuming time: 0.9842--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaaaaaXConsuming time: 4.1069--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX
输出到最后一行貌似程序卡住了,我们来看下电脑的 CPU:
CPU利用率已经快接近100%了,我们在分别执行两次(电脑配置低的慎重操作):
2.3 总结
每个恶意的正则表达式模式应该包含:
- 使用重复分组构造
- 在重复组内会出现
- 重复
- 交替重叠
有缺陷的正则表达式会包含如下部分:
(a+)+([a-zA-Z]+)*(a|aa)+(a|a?)+(.*a){x} | for x > 10
注意: 这里的a是个泛指
2.4 实例
下面我们来展示一些实际业务场景中会用到的缺陷正则。
英文的个人名字:
- Regex:
^[a-zA-Z]+(([\'\,\.\-][a-zA-Z ])?[a-zA-Z]*)*$ - Payload:
aaaaaaaaaaaaaaaaaaaaaaaaaaaa!
- Regex:
Java Classname
- Regex:
^(([a-z])+.)+[A-Z]([a-z])+$ - Payload:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
- Regex:
Email格式验证
- Regex:
^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$ - Payload:
a@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
- Regex:
多个邮箱地址验证
- Regex:
^[a-zA-Z]+(([\'\,\.\-][a-zA-Z ])?[a-zA-Z]*)*\s+<(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})>$|^(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})$ - Payload:
aaaaaaaaaaaaaaaaaaaaaaaa!
- Regex:
复数验证
- Regex:
^\d*[0-9](|.\d*[0-9]|)*$ - Payload:
1111111111111111111111111!
- Regex:
模式匹配
- Regex:
^([a-z0-9]+([\-a-z0-9]*[a-z0-9]+)?\.){0,}([a-z0-9]+([\-a-z0-9]*[a-z0-9]+)?){1,63}(\.[a-z0-9]{2,7})+$ - Payload:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
- Regex:
使用python来进行测试有缺陷的正则示例:
$ python -c "import re;re.match('^[a-zA-Z]+(([\'\,\.\-][a-zA-Z ])?[a-zA-Z]*)*$', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa!')"
3 ReDoS 防范
哪里会用到Regex, 几乎在我们的网络程序与设备资源的任何位置都会用到。如: WAF、Web前端、Web后端、DB数据库等。
3.1 常见位置
客户端
- 浏览器
- 移动设备
服务器端
3.2 防范手段
防范手段只是为了降低风险而不能百分百消除 ReDoS 这种威胁。当然为了避免这种威胁的最好手段是尽量减少正则在业务中的使用场景或者多做测试, 增加服务器的性能监控等。
- 降低正则表达式的复杂度, 尽量少用分组
- 严格限制用户输入的字符串长度(特定情况下)
- 使用单元测试、fuzzing 测试保证安全
- 使用静态代码分析工具, 如: sonar
- 添加服务器性能监控系统, 如: zabbix
2.5 参考链接
- 《精通正则表达式》
- http://blog.csdn.net/c601097836/article/details/47040703
- http://hooopo.iteye.com/blog/548087
- http://www.guoziweb.com/archive/1160.html
- https://swtch.com/~rsc/regexp/regexp1.html
- https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
- https://en.wikipedia.org/wiki/ReDoS
- https://www.checkmarx.com/wp-content/uploads/2015/03/ReDoS-Attacks.pdf
- https://www.exploit-db.com/docs/38149.pdf
- https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
- https://www.owasp.org/images/3/38/20091210_VAC-REGEX_DOS-Adar_Weidman.pdf
- https://www.owasp.org/index.php/OWASP_Validation_Regex_Repository
浅析ReDoS的更多相关文章
- 浅析ReDoS的原理与实践
转载于http://www.freebuf.com/articles/network/124422.html ReDoS(Regular expression Denial of Service) 正 ...
- 浅谈 DDoS 攻击与防御
浅谈 DDoS 攻击与防御 原创: iMike 运维之美 什么是 DDoS DDoS 是英文 Distributed Denial of Service 的缩写,中文译作分布式拒绝服务.那什么又是拒 ...
- DDOS攻击与防御简单阐述,列出DDOS的攻击方法和防御方法
参考1:https://www.hi-linux.com/posts/50873.html#%E7%BD%91%E7%BB%9C%E5%B1%82-ddos-%E6%94%BB%E5%87%BB 什么 ...
- SQL Server on Linux 理由浅析
SQL Server on Linux 理由浅析 今天的爆炸性新闻<SQL Server on Linux>基本上在各大科技媒体上刷屏了 大家看到这个新闻都觉得非常震精,而美股,今天微软开 ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 高性能IO模型浅析
高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking ...
- netty5 HTTP协议栈浅析与实践
一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...
- Jvm 内存浅析 及 GC个人学习总结
从诞生至今,20多年过去,Java至今仍是使用最为广泛的语言.这仰赖于Java提供的各种技术和特性,让开发人员能优雅的编写高效的程序.今天我们就来说说Java的一项基本但非常重要的技术内存管理 了解C ...
- 从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler
熟悉WebForm开发的朋友一定都知道,Page类必须实现一个接口,就是IHttpHandler.HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...
随机推荐
- 笔记-Git基础
git配置 git config --global user.name "xxx" //配置用户名 git config --global user.email "xxx ...
- hydra-爆破工具的使用
0x01简介 hydra 是一个支持众多协议的爆破工具,在kali上集成,但也可以在windows上下载运行: github上的源码: https://github.com/vanhauser-thc ...
- idea中创建maven的Javaweb工程并进行配置
学完maven后,可以创建maven的javaweb工程,在创建完成后还需要一些配置,下面来说下具体步骤,在这里我创建的是一个模块,创建web项目的方式和创建模块一样 1.创建一个模块,点new-Mo ...
- P5016 龙虎斗
链接:P5016 ------------------------------------ 作为2019年的模拟,还是有必要写一些的 --------------------------------- ...
- 剑指offer-面试题36-二叉搜索树与双向链表-中序遍历
/* 题目: 将二叉搜索树转化为排序的双向链表,不能创建新的节点, 只能调整节点的指向,返回双向链表的头节点. */ /* 思路: 递归. 二叉搜索树的中序遍历得到的序列是递增序列. 左子树left& ...
- 聊聊SNMP协议
注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 本文源链接:https://www.cnblogs.com/chloneda/p/snmp-protoco ...
- Python机器学习及实践 课后小题
目录 第二章 2.3章末小结 @(Python机器学习及实践-----从零开始通往Kaggle竞赛之路) 第二章 2.3章末小结 1 机器学习模型按照使用的数据类型,可分为监督学习和无监督学习两大类. ...
- javascript 问题汇总(1)
1 jquery ajax提交有参数的请求,提示错误“Unsupported Media Type“ 解决:ajax 设置添加 contentType: "application/j ...
- gulp常用插件之wiredep使用
更多gulp常用插件使用请访问:gulp常用插件汇总 wiredep这是一款gulp插件,能够将js.css文件自动插入到html中. 更多使用文档请点击访问wiredep工具官网. Bower是一个 ...
- 【BZOJ 1022】 [SHOI2008]小约翰的游戏John(Anti_SG)
Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取 的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不 ...