但是回到現實面,我們知道很多時候該做的事情就是沒辦法進行,所以文章中提到的防護手法不一定能夠順利實施。原因有很多,不過歸到底通常都出在人身上。正所謂樹多有枯枝,人多有白痴。那怕只是一個程式設計師的一時鬼遮眼,都有可能讓系統產生莫大的安全漏洞。針對這種狀況,通常建議的作法就是採用 Virtual Patching,白話一點來說就是導入 WAF (Web Application Firewall)。不過再次回到現實面的現實面,導入 WAF 的金錢成本相當高,通常沒有準備七位數是沒有廠商會理你的。
好消息是沒錢也有沒錢的作法,其中 Apache 的 mod_security 模組正是一個免費的好用工具。在這次的文章中,我將示範如何利用 mod_security 來阻擋造訪路徑攻擊,環境為 CentOS 6。在進行前必須提醒讀者,因為示範過程將會改變網站的存取行為,因此請不要直接在正式的環境模擬。
為了完成這次的範例,我先在網站上放置了一個 PHP 程式 – get_file_content.php,其內容為
<?php $content = file_get_contents($_GET['path']); echo nl2br($content); ?>這個程式的功能很簡單,就是讓使用者透過 path 變數指定某個檔案名稱,然後程式就會將檔案內容完整顯示出來。所以當我們呼叫 get_file_content.php?path=../../../../../../etc/passwd 時,應該會看到這個熟悉的畫面
接下來,就讓我們一步步完成今天的範例吧。
- 安裝 EPEL Repository
EPEL 提供了 mod_security 的 RPM 套件,可以大幅簡化安裝與日後更新的動作,所以我選擇透過 EPEL 來安裝 mod_security。請先在 https://fedoraproject.org/wiki/EPEL 下載並安裝適合的版本。 - 安裝 mod_security
指令是yum -y install mod_security
- 新增造訪路徑攻擊字串的規則
mod_security 的規則設定檔放在目錄 /etc/httpd/modsecurity.d/activated_rules 內,檔案名稱必須以 .conf 結尾。請在這個目錄產生一個稱為 testing.conf 的檔案,並在檔案內加入下列內容SecRule REQUEST_URI "../" "phase:1,t:urlDecode,log,deny,status:503,id:1000"
- 重新讀取 apache 設定檔
指令是service httpd reload
- 重新載入網址
此時畫面應該會出現錯誤訊息 (Code=503) - 查看阻擋記錄
我們可以在日誌檔 /var/log/httpd/modsec_audit.log 看到類似下列的訊息--48927b7c-A-- [10/Jan/2014:01:24:19 +0800] Us7bQ8CoAHcAAEwAH-AAAAAB 192.168.10.11 51517 192.168.10.10 80 --48927b7c-B-- GET /get_file_content.php?path=../../../../../../etc/passwd HTTP/1.1 Host: 192.168.10.10 Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68 Accept-Encoding: gzip,deflate,sdch Accept-Language: zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4 --48927b7c-F-- HTTP/1.1 503 Service Temporarily Unavailable Content-Length: 402 Connection: close Content-Type: text/html; charset=iso-8859-1 --48927b7c-E-- --48927b7c-H-- Message: Access denied with code 503 (phase 1). Pattern match "../" at REQUEST_URI. [file "/etc/httpd/modsecurity.d/activated_rules/testing.conf"] [line "1"] [id "1000"] Action: Intercepted (phase 1) Stopwatch: 1389288259978368 472 (- - -) Stopwatch2: 1389288259978368 472; combined=48, p1=43, p2=0, p3=0, p4=0, p5=5, sr=0, sw=0, l=0, gc=0 Response-Body-Transformed: Dechunked Producer: ModSecurity for Apache/2.7.3 (http://www.modsecurity.org/). Server: Apache/2.2.15 (CentOS) Engine-Mode: "ENABLED" --48927b7c-Z--
- 下載 OWASP 規則
透過一個簡單的規則,我們就可以避免造訪路徑攻擊。儘管如此,這個規則其實功能有限,因為它只檢查了 Request 字串,萬一是透過 POST (也就是 Content Body) 傳遞攻擊字串,那可就一點也派不上用場了。
撰寫規則這種事,最好還是讓給專業的來。目前 mod_security 提供兩組規則,其中一組要錢,另外一組由 OWASP 所維護的規則則免費使用。在此我們選用 OWASP 的免費規則,指令如下cd /etc/httpd/modsecurity.d rm –f activated_rules/testing.conf wget https://github.com/SpiderLabs/owasp-modsecurity-crs/tarball/master -O owasp-modsecurity-crs.master.tgz tar xvfz owasp-modsecurity-crs.master.tgz
- 安裝所需規則
我們下載的檔案內包含許多規則,一般而言,我們不會啟用全部的規則。在此範例中,我們僅會啟用示範所需的規則。指令如下cd activated_rules/ cp ../SpiderLabs-owasp-modsecurity-crs-f4d33c4/modsecurity_crs_10_setup.conf.example modsecurity_crs_10_setup.conf ln –s ../SpiderLabs-owasp-modsecurity-crs-f4d33c4/base_rules/modsecurity_crs_42_tight_security.conf modsecurity_crs_42_tight_security.conf
- 重新讀取 apache 設定檔
指令是service httpd reload
- 重新載入網址
此時畫面應該會出現錯誤訊息 (Code=403)
雖然錯誤訊息有所不同,但是一樣達到阻擋造訪路徑攻擊的目的。 - 新增其他規則
等等,萬一駭客輸入的攻擊字串不包含 ../,而是直接輸入 /etc/passwd 呢?令人驚訝的是,呼叫 get_file_content.php?path=/etc/passwd 依舊會直接顯示出檔案內容。因為 /etc/passwd 實在太過重要,所以 OWASP 提供了其他的規則以避免這類攻擊字串,指令如下ln –s ../SpiderLabs-owasp-modsecurity-crs-f4d33c4/base_rules/modsecurity_40_generic_attacks.data modsecurity_40_generic_attacks.data ln –s ../SpiderLabs-owasp-modsecurity-crs-f4d33c4/base_rules/modsecurity_crs_40_generic_attacks.conf modsecurity_crs_40_generic_attacks.conf
- 再次重新讀取 apache 設定檔
指令是service httpd reload
- 再次測試
此時呼叫 get_file_content.php?path=/etc/passwd 應該也會看到錯誤訊息了
沒有留言:
張貼留言