當前位置:
首頁 > 新聞 > 淺析ReDoS的原理與實踐

淺析ReDoS的原理與實踐

*本文原創作者:MyKings,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載

ReDoS(Regular expression Denial of Service) 正則表達式拒絕服務攻擊。

開發人員使用了正則表達式來對用戶輸入的數據進行有效性校驗, 當編寫校驗的正則表達式存在缺陷或者不嚴謹時, 攻擊者可以構造特殊的字元串來大量消耗伺服器的系統資源,造成伺服器的服務中斷或停止。


1 常見術語

先讓我們來了解幾個概念:


1.1 Regex

正則表達式(Regular Expression, Regex)是由字元(可為英文字母、數字、符號等)與元字元(特殊符號)組成的一種有特定規則的特殊字元串。在模式匹配中,正則表達式通常被用於驗證郵箱、URL、手機號碼等。

常用元字元:

















元字元

說明

將下一個字元標記為一個特殊字元、或一個原義字元、或一個向後引用、或一個八進位轉義符。例如,「n」 匹配字元 「n」。「
」 匹配一個換行符。序列 「\」 匹配 「」 而 「(」 則匹配 「(」。

^

匹配輸入字元串的開始位置。如果設置了RegExp對象的Multiline屬性,^ 也匹配 「
」 或 「
」 之後的位置。

$

匹配輸入字元串的結束位置。如果設置了RegExp對象的Multiline屬性,$ 也匹配 「
」 或 「
」 之前的位置。

*

匹配前面的子表達式零次或多次。例如,zo* 能匹配 「z」、「zo」 以及 「zoo」。* 等價於 {0,}

+

匹配前面的子表達式一次或多次。例如,「zo+」 能匹配 「zo」 以及 「zoo」,但不能匹配 「z」。+ 等價於{1,}

?

匹配前面的子表達式零次或一次。例如,「do(es)?」 可以匹配 「do」 或 「does」 中的 「do」。? 等價於{0,1}

.

匹配除 「
」 之外的任何單個字元。要匹配包括 「
」 在內的任何字元,請使用像 「 (.$lambda_1$
)
」 的模式。

(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: aaaaaaaaaaaaaaaaX
Consuming time: 0.0043--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaX
Consuming time: 0.0175--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaX
Consuming time: 0.0678--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaX
Consuming time: 0.2370--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaaaX
Consuming time: 0.9842--------------------------------------------------------------------------------Current: aaaaaaaaaaaaaaaaaaaaaaaaaaX
Consuming 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 實例

下面我們來展示一些實際業務場景中會用到的缺陷正則。



  • 英文的個人名字:




    • Re

      gex: ^[a-zA-Z]+(([",.-][a-zA-Z ])?[a-zA-Z]*)*$



    • Payload: aaaaaaaaaaaaaaaaaaaaaaaaaaaa!


  • Java Classname




    • Regex: ^(([a-z])+.)+[A-Z]([a-z])+$



    • P

      ayload: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!


  • 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: ^[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: ^d*[0-9](|.d*[0-9]|)*$



    • Payload: 1111111111111111111111111!


  • 模式匹配




    • 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!

使用python來進行測試有缺陷的正則示例:


$ python -c "import re;re.match("^[a-zA-Z]+(([",.-][a-zA-Z ])?[a-zA-Z]*)*$", "aaaaaaaaaaaaaaaaaaaaaaaaaaaa!")"


3 ReDoS 防範

哪裡會用到Regex, 幾乎在我們的網路程序與設備資源的任何位置都會用到。如: WAFWeb前端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


*本文原創作者:MyKings,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載



您的贊是小編持續努力的最大動力,動動手指贊一下吧!


本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊下面的「搶先收到最新資訊」瀏覽吧!



請您繼續閱讀更多來自 FreeBuf 的精彩文章:

國際航空訂票系統存在漏洞,可輕易取消、修改航班預約
揭秘:Signal通訊加密APP究竟是如何避開審查的
安全專家:俄羅斯干預美國大選的JAR報告並沒有什麼軟用
你所不知道的FIT 2017台前幕後大揭秘(附大會議題PPT)

TAG:FreeBuf |

您可能感興趣

WebSocket 實現原理淺析
LinkedList 的實現原理淺析
Spring AOP 的實現原理
Tomcat中的可插拔以及 SCI 的實現原理
Redis集群實現原理探討
jsonp的原理和實現
WordPress解析系列之PHP編寫hook鉤子原理簡單實例
Face ID在iPhone X上的工作原理
Photoshop色階的正確用法和原理
MySQL优化原理
Java NIO原理分析
熱修復之 Method Hook 原理分析
《深度學習原理與TensorFlow實踐》學習筆記(三)
Redis事務原理分析
iPhoneX的FaceID臉部辨識技術解析:從感光元件到3D立體影像感測原理
一文詳解神經網路 BP 演算法原理及 Python 實現
每月好書:? 深入淺出深度學習:原理剖析與Python實踐
MySQL優化原理
BadVPN詳解之組網原理剖析