2008-10-28 77 views
12

假設Perl腳本允許用戶在配置文件中指定幾個文本過濾器表達式,是否有安全的方法讓他們輸入正則表達式,而不會出現意外副作用或代碼執行的可能性?沒有真正解析正則表達式並檢查它們是否存在問題的構造,也就是說。不會有任何替代,只有匹配。從文件中讀取正則表達式安全嗎?

順便說一句,有沒有一種方法可以在實際使用之前測試指定的正則表達式是否有效?如果輸入了類似/foo (bar/的內容,我想發出警告。

感謝,Z.


編輯:
感謝非常有趣的答案。因爲我已經發現了以下危險的構造將只在正則表達式進行評估,如果使用 use re 'eval'編譯:

(?{code}) 
(??{code}) 
${code} 
@{code} 

默認爲no re 'eval';所以除非我錯過了某些東西,否則從文件中讀取正則表達式應該是安全的,唯一的檢查就是Axeman發佈的eval/catch。在我的測試中,至少我沒有能夠隱藏任何邪惡的東西。

再次感謝。 Z.

+0

我剛剛讀到,它被認爲是不錯的風格,不要編輯自己的問題來提供答案,而是發佈新的答案。我爲這個假人道歉,我在這裏還是很新的。但我正在學習:-) – Zilk 2008-10-28 23:31:00

回答

5

您可能需要做一定程度的衛生處理。例如,perlre手冊頁介紹下面的結構:

(?{ code }) 

,其允許一個模式匹配內的可執行代碼。

+1

你很近。當在正則表達式中進行變量插值時,該構造是不允許的,除非使用'reval';`,所以這將是安全的。 – 2008-10-28 10:15:29

11

eval { 
    qr/$re/; 
}; 
if ([email protected] ) { 
    # do something 
} 

編譯的表達,並讓您從錯誤中恢復。

您可以觀看惡意表達,因爲你只打算做配套,通過尋找這些模式,這將允許任意代碼運行:

(?: \(\?{1,2} \{ # '(' followed by '?' or '??', and then '{' 
| \@ \{ \s* \[ # a dereference of a literal array, which may be arbitrary code. 
) 

確保您與此編譯x標誌。

+0

這並不能保護您免受拒絕服務攻擊。根據具體情況,這可能不是問題。如果運行該程序的用戶也可以在(1){}'「時執行」perl -e「,那麼這並不重要。如果它是一個服務器,那麼... – tsee 2008-10-28 11:28:18

+1

我會在鬧鐘()中查看正則表達式來殺死超過一兩秒的任何東西。 – Schwern 2008-10-30 00:19:59

13

根據您的匹配情況以及您正在運行的Perl版本,可能會有一些正則表達式通過使用過量的lookahead,lookbehinds和其他斷言來充當有效的拒絕服務攻擊。

你最好只允許一小部分已知的正則表達式模式子集,並在你和你的用戶學習如何使用該系統時謹慎地擴展它。就像許多博客評論系統只允許一小部分HTML標籤一樣。

如果您需要對正則表達式進行復雜的分析,最終Parse :: RecDescent可能會變得有用。

5

我建議不要信任用戶的任何正則表達式。如果您確實這樣做了,請運行perl以污染(-T)模式。在這種情況下,您需要某種形式的驗證。您可以使用現有的正則表達式解析器,而不是使用Parse :: RecDescent編寫自己的正則表達式解析器,該解析器可能更快,由專家編寫並像魅力一樣工作。

最後,由於perl 5.10.0,你可以插入不同的正則表達式引擎到perl(詞法!)。您可以檢查是否有一個功能較弱的正則表達式引擎,其語法更容易驗證。如果您想沿着該路線行駛,請閱讀the API description,Avar's re::engine::Plugin,或者查看Avar's plugin engines中的任何一項。

0

Safe模塊對於編譯/執行不可信的正則表達式有什麼用處嗎?