來源:https://www.leavesongs.com/PENETRATION/how-to-analyze-long-regex.html

作者:phithon@長亭科技

PHPMailer里面對于Email的正則表達式讓很多人看了頭疼,其實我看了也頭疼,但借助一些工具,加上一些經驗,還是能慢慢把有效信息剝離出來的。

首先推薦一個分析正則表達式的網站 https://regex101.com/ 。之前的很多網站,遇到今天這個正則表達式就都蔫兒了,實際上正則表達式的語法也不盡相同,比如PHP的正則和JavaScript就有區別,所以一定要找對正則表達式分析引擎。

regex101就可以選擇多個正則表達式引擎,我這里選擇pcre(php): https://regex101.com/r/aGGWWw/2

這個網站的諸多好處,自己使用去體會吧。

我們首先輸入我們需要分析的正則表達式,然后慢慢分析。

(?1)的分析

這個正則表達式看似很長很亂,其實主要用到的也就是下面三種語法:

(?!xxx)斷言,匹配后面不是xxx的位置

(?>xxx)一次性子組 ,見 http://php.net/manual/zh/regexp.reference.onlyonce.php

(?n)子匹配,等同于第n組正則

先來分析第一個子組,第一個子組在這里:

你說為什么不從頭開始分析?因為前面有多處用到(?1),如果不分析第一個組,前面的正則是看不懂的。

(?1)又分為兩部分:

  1. ((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)
  2. (\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\))

其實這兩部分也就是第2/3組,這也是為什么regex101右側邊欄中沒有2/3組的原因,因為2/3組是包含在第1組中的。

第2組主要匹配了換行(\x0D\x0A)和空白符(\t\x20),所以我們測試一下$str = "\x0D\x0A".' aaaa@gmail.com';,發現其實是可以匹配上的。

那為什么我們不能直接\t-X/home/www/success.php @gmail.com?因為,郵箱地址在檢測前進行了trim。這個方法gg。

第3組其實就是我發現的繞過validateAddress方法,分析可知:在中間可以填入包括(?2)、空白符、引號等在內的大量字符,并且還是遞歸的(也就是說3里還能有3)。

所以可知,通過使用括號,我們就可以構造空白符了。

(?4)的分析

第4組如下:

可見支持如下一些字符,其中是不包含空白符的:[!#-\'*+\/-9=?^-~-]。但如果兩邊有",那么支持的字符就多了:[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F],包括空白符。

這也就是漏洞發現者給出的POC使用的方法:將Payload用雙引號包裹。

@前的其余部分分析

如上圖,在(?1)前面的部分,是兩個消極斷言(?!),實際上是不允許的內容,但又不會捕捉,這就不會影響正則的走向,因為后面的1組還是會捕捉它。所以這兩句對我們繞過沒有任何幫助。

在(?4)后面的部分,其實比較有趣。(?>(?1).(?1)(?4))這里這句話導致了另一個繞過:

aaa. -X/tmp/test.php @gmail.com

原因是(?1)是可以包含空白符的,只要有一個空白符,(?4)就能逃出來了。

從(?>(?1).(?1)(?4))再往后看,這里再次調用一個(?1),所以又可以如下繞過:

(aaaa) -X/tmp/test.php (xxxx)@gmail.com

配合下圖,其實就很好理解了:

Group 1是可以包含空格的,因為兩處都調用的Group 1,所以夾在中間的部分Group 4也就是Payload了。

尾記

@后面的部分留給大家自己去分析。

那么本文叫“談一談復雜的正則表達式分析”,其實我也只分析了半個表達式而已。但訣竅已經在這里了:

  1. 找一個好的輔助工具
  2. 理解斷言、遞歸組、子匹配、一次性子組等概念
  3. 一段段分析,不要害怕

最后一條很重要,正則也是人寫出來的,所以沒有看不懂的道理。而且,在代碼審計的過程中,基本上你并不需要完全理解一個正則(比如本文中的正則我也有很多地方沒有分析,但這不妨礙我發現問題),你真正需要理解的是編寫者的意愿,他為什么會這么寫。

那么,PHPMailer中這個正則為什么會這么寫?

可能是作者為了完全實現RFC的一些規則,才會這樣編寫正則吧。

參考:

  • http://php.net/manual/zh/reference.pcre.pattern.syntax.php
  • https://regex101.com/r/aGGWWw/2

Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/163/