本文轉自:https://mp.weixin.qq.com/s/CXTedk3BAVNt0elOsaFccA
做了略微的修改。
1 WAF功能
WAF全稱叫Web Application Firewall,和傳統防火牆的區別是,它是工作在應用層的防火牆,主要對web請求/響應進行防護。那么WAF有什么功能呢?
防火牆都是防御性的產品,有防就有攻,要了解WAF有什么功能,就要從攻擊者的角度去思考。
攻擊的目的要么是為了利益,要么是為了炫技。目前攻擊者大多都是悶聲發大財,很少會為了炫技而惹上麻煩。那么,攻擊目標越大,越有價值。
一個攻擊者的目標由大到小,往往是這樣 :
- 全網
- 網絡上某一主機
- 某一主機的數據庫
- 某一主機WEB系統的管理員
- 某一主機WEB系統其它用戶
假設一個WEB網絡大致如下,圖中為目前能得到僅有信息,下文會一步步完善。
WEB服務器與瀏覽器之間已經用傳統防火牆防護起來,也就是說,對http://www.a.com進行端口掃描之類的攻擊行為已經沒用了。攻擊者可以通過下面步驟來得到這個網絡的信息:
1)通過OPTIONS,TRACE方法來探測里面的拓撲。如果webserver支持並允許這兩個方法,通過檢查響應包的Via或Max-forwards字段,可以得到各個節點的域名。
2)通過檢查響應包的Server字段或X-Powered-By字段來確定各個節點的http服務器軟件版本和腳本語言解釋器版本。同時由第一步得到的域名,也可以到相應域名注冊網站(如站長之家)上查找IP。而且有時候,由於網絡管理員的疏忽,通向其它節點的路徑並沒有禁止端口掃描,那樣通過端口掃描,可以得到系統信息,如操作系統類型,版本,開啟了什么服務。然后在CVE上查詢相應版本漏洞和exploit-db上下載相應的payload來攻擊,獲取主機的控制權。
3)如果第二步不奏效,也可以通過HTTP的OPTIONS方法來獲取網站支持的方法,比如允許DELETE方法,或者PUT方法,那么攻擊者可以上傳一個腳本獲取整個站點的源代碼和數據庫數據甚至獲取整個站點所有主機的權限,或者把認證的腳本給刪除。
4)如果第三步也不奏效,攻擊者可能就會掃描所有網頁,看是否存在文件路徑遍歷,文件包含注入,API注入,命令注入之類的漏洞,來獲取整個站點的系統信息甚至獲取webshell。
5)如果第四步也不奏效,繼續掃描所有頁面,看是否有sql注入的漏洞,看能否獲取站點的數據庫數據或是否可通過數據庫執行系統命令,獲取主機權限。
6)如果第五步也不奏效,只能看有沒有XSS,url注入等漏洞,能否騙到其它合法用戶的權限。或者看能否上傳惡意文件。
再思考多一點,如果攻擊者並沒有打算攻陷a.com或從它偷取數據,而是頻繁向a.com發送消耗大量資源的請求,比如請求會使用大量數據庫查詢的接口,或上傳大量文件,導致正常服務無法響應。這種方式叫做CC攻擊(ChallengeCollapsar)。
那么,WAF必須具備防護CC攻擊能力,也就是說,WAF具備限制對某些URI請求次數的能力和限制文件上傳功能的能力。
從性能角度來看,由於HTTP是應用層的協議,每次WAF都要解析它,會造成很大性能損耗。而對於某些經常發惡意請求的IP或進行CC攻擊的IP,如果能夠在網絡層就把它們攔截了,對WAF性能是有很大的提升。所以WAF還必須具備IP黑名單的能力。
有黑名單就有白名單,對於某些資源,如圖像,影音,css,js文件,WAF對它們應用規則,只會浪費計算資源和降低服務的響應速度,所以,需要把一些資源URL放在白名單里。
關於IP黑名單,再從安全運維角度來看,如果是IP黑名單是通過手工輸入,那么,當攻擊者使用IP池攻擊,可能會導致IP黑名單的防護攻擊失效。那么,如果WAF是支持動態黑名單,就可以很好解決這個問題。如果是由WAF本身產生黑名單,會對WAF性能有很大影響,所以WAF需要能夠對接實時計算平台,由實時計算平台產生黑名單回饋給WAF。那么WAF就必須支持與實時計算平台對接的能力。
總體來說,WAF功能有如下:
- 禁止HTTP協議的非安全方法
- 偽裝Web服務的特征
- 防止API和命令注入
- 防止路徑遍歷和文件包含注入,對敏感的系統路徑進行保護
- 防止sql注入
- 防止XSS攻擊
- 防止網頁掛馬
- 防護CC攻擊
- 文件上傳的防護
- 動態IP黑名單
- 白名單
- 與實時計算平台對接
2 WAF部署模式
WAF也是防火牆,那么它應該是部署在哪里呢?在部署上,它和傳統防火牆有什么區別呢?
傳統防火牆處理的消息格式大多是格式化,基本上內容都是固定或者索引方式。而WAF處理的消息是文本,是非格式化消息,都是可變的。在處理這兩種不同的消息格式,在性能上的消耗相差非常大。我之前測試過,不使用正則,處理http內容匹配比格式化要慢上5-20倍,如果用上正則還可能再慢上20倍。
因此,如果WAF像傳統防火牆那樣,放置在網絡入口,那么,對於DDOS攻擊來說,它是很容易淪陷的。
所以WAF一般是部署在防火牆(特別是高防DDOS設備)后面,基本架構如下圖
由於性能差異這么大,所以WAF和防火牆之間還會部署負載均衡設備。
那么,WAF和web服務之間部署還會有什么方式?WAF畢竟也是防火牆,而且它又有web服務的處理能力。所以它有下面四種部署方式:
1)作為WEB服務器的模塊。
好處是,由於和WEB服務器結合緊密,對惡意請求的攔截准確率是最高,而且完全可以用ModSecurity或naxis。缺點是,過於分散,不好管理和部署。
2)作為一台反向代理服務器。好處是,部署方便簡單,集中管理。缺點是,對惡意請求的誤判率會上升。
3)作為一台路由器。好處是,部署方便簡單,集中管理。缺點是,也有單點問題,需要雙機,同時由於作為一個路由器,需要在用戶態上實現協議棧(TCP/IP),維護路由信息,不占用域名,對性能要求更高;且對https支持難度高。因此整體實現難度很高。
4)作為一台交換機。好處是,部署方便簡單,集中管理,不占域名,也不占用IP,也就是說,對攻擊者來說,它完全是透明的。缺點是,也有單點問題,需要雙機,作為一個交換機,也需要在用戶態實現協議棧(鏈路,TCP/IP),維護轉發表,也由於同時防護多個站點,對性能要求高;且對https支持難度高。
在實際應用中,第一種模式基本只是學習者使用,一般用開源的ModSecurity或Naxis較多。第三,第四種模式過於復雜,而且出問題會導致整個子網出問題,也基本沒見到使用。第二種模式,基本主流的WAF產品都是采用這種模式。
3 WAF工作模式
由於WAF一般和業務系統是串聯的,並且還是部署在業務系統前面。如果采用反向代理部署模式,假設WAF出現故障,那么會導致單個或者多個站點不可用。這意味着WAF的功能必須是隨時可以關閉的。一個WAF往往需要同時防護多個站點,如果把整個WAF關閉,是會導致整體業務群都失去保護。所以,WAF的工作模式必須有對站點隨時關閉的模式。
當WAF有新功能或者有新策略發布,是不可以立馬把新功能或新策略對現有站點進行防護,需要一段時間來進行觀察,看功能是否可用或策略的命中率,漏判率和誤判率。如果貿然上線的話,很容易背鍋走人的。所以,WAF的工作模式必須有監聽模式。
不用說,WAF工作模式當然要有防護模式。這是WAF存在的意義。
那么,這些工作模式如何設計呢?
先從關閉模式看起,對某個站點使用關閉模式,到這個站點的流量就感受不到WAF的存在。一般的做法,是解綁域名,再到web服務上綁定該域名。
這種做法優缺點如下:
- 優點
- 由於web服務和WAF完全分享,WAF的故障不會影響到web服務。
- 少了WAF這個中間節點,web服務的響應速度不受影響。
- 缺點
- 解綁和重綁,涉及到接入備案過程,流程較長,生效時間較長。
- 原先隱藏在內網的web服務集群對公網開放,除了web應用本身的攻擊面,還增加了主機層面的攻擊面,增大了整體網絡的攻擊面。
關閉模式也有一種快速生效的實現方式。這種實現方式和監聽,防護兩種模式的實現很統一。
這種方式的優缺點如下:
- 優點
- 不需要進行域名解綁和重綁,生效時間快
- 不會增加整體網絡的攻擊面
- 缺點
- 流量還是要經過WAF,對web服務響應速度還是影響
- 流量要經過WAF,所以WAF的故障也會影響到web服務
由於一個IP可以對應多個域名,一個域名也可以對應多個IP,對針對每個域名來配置工作模式,WAF必須要獲取到http請求的URL或頭部的host字段。WAF解析完http/https,拿到了請求的域名,再根據域名的配置,決定是否送去過規則還是直接傳遞給web服務。所以,WAF的http/https模塊解析要和規則引擎模塊分開。
所以,WAF的關閉模式如下圖:
同樣,WAF的監聽模式是既過規則,也會直接傳遞給web服務,大致如下圖:
最后,WAF的防護模式是直接過規則,不會直接傳遞給web服務,大致如下圖:
可見,這樣的設計,會使得這三種工作模式在實現和原理上都非常統一。
4 規則引擎原理
WAF無非就是攔截有害請求和偽裝響應,出於性能考慮,攔截有害請求又分為兩個層面,由網絡層攔截和由應用層攔截,且任何請求應該先在網絡層過濾再到應用層過濾。也就是說,規則引擎分為兩塊,對請求過濾和對響應過濾,而對請求過濾分為兩大步,網絡層過濾和應用層過濾。
原理圖大致如下:
1)請求部分
- 網絡層
- 白名單:很多時候部署在WAF后面的應用,需要測試接口對非法輸入的處理,但又不想關閉對該站點的監控,為了防止WAF對測試活動的影響,對來源IP和目標IP設置白名單,繞過WAF的攔截。從性能角度來考慮,白名單過濾功能是不可能放在其它過濾功能后面,那么它應該是規則引擎在網絡層過濾的第一步。
- 黑名單:同樣,對於已知有害的來源IP,是越早攔截越好,出於性能考慮,黑名單攔截功能應該在網絡層,那么它應該緊跟在白名單后面。
- 應用層
- https拆解:隨着https越來越普及,WAF需要對https請求和響應進行檢測和過濾,所以,WAF必須支持使用證書對https內容進行拆解。
- http方法防護:不少http方法是有安全風險的,如果webserver的配置有問題,如果不在這一步攔截掉,而url白名單的來源IP又可能被攻擊,那么就可以存在站點淪陷的風險。一般是攔截除了HEAD,GET,POST之外的方法
- url白名單:由於某些接口(如請求某些靜態資源)並不會存在漏洞,沒必要對這些url進行規則過濾,或者防護站點某些url接口有所更新,需要特定的來源IP進行測試。應當存在url和來源IP對應的白名單
- url黑名單:同樣由於某些接口的實現可能會涉及大量運算,可能需要對該url訪問進行次數限制,需要存在一個url和次數的黑名單。
- http請求解碼:http請求很多時候對頭部和內容的數據往往會進行編碼,如url編碼,html編碼,js編碼,十六制編碼,base64編碼,主要是為了傳輸一些二進制數據,或攻擊者用於繞過各種防護設備。只有對數據進行解碼,才能夠知道它真實的payload。所以需要對http請求進行解碼。
- http請求頭部過規則:GET,HEAD方法的參數都是緊跟URL,這個階段就可以進行過濾,而且先對請求頭部過濾,也是基於性能考慮。畢竟請求url參數和頭部都是key-value方式,解析相對比內容要快。
- http請求內容過規則:POST方法的參數基本都是放在請求內容里。
2)響應部分
- 響應頭部過規則:響應頭部有不少字段會泄露背后服務的關鍵信息,如server會泄露webserver軟件及版本,x-powered-by會泄露cgi語言和版本(PHP,Python,Perl,Ruby之類),Via和Max-Forward會泄露WebServer的拓撲。為了避免攻擊者利用這些信息攻擊,需要對響應頭部某些字段進行屏蔽或偽裝。
- 響應內容過規則:這一部分也叫做軟補丁功能。為什么呢?如果webserver的應用服務拋異常了,並把異常信息顯示在頁面,這是一種常見的信息泄露。如果需要研發團隊來修改和測試,運維團隊對該服務進行打補丁上線,整個過程可能持續幾周,存在很大的風險窗口。如果在WAF上,對這些信息進行偽裝或屏蔽,就可以極大降低安全風險。更加不用那些會泄露用戶信息,金融信息等服務。
5 WAF動作
WAF每條規則都會配置動作,對命中規則的請求進行對應的處理。
每個WAF產品對動作定義不大一樣。
1)ModSecurity定義了allow, block, deny, drop, pass, pause, proxy, redirect
- allow: 命中了某條規則后,不需要對請求/響應應用其它規則,直接讓請求通過。這個可以用於白名單。
- block: 並不是一個真正的動作,它的行為取決於配置的默認動作,如果默認動作更新,使用block的規則行為也隨即改變。在安全響應方面,它可用於批量進行規則作為更新。
- deny: 中斷規則處理,攔截請求/響應。在客戶端的角度來說,這個動作會返回4xx或5xx的狀態碼(取決於規則定義status),但並沒有中斷當前的連接
- drop: 對當前tcp連接進行關閉操作,它和deny的不同是:deny之后,客戶端仍然可以提交請求,但使用drop后,客戶端只有重新連接才可以訪問。這個動作可以節省后端服務的連接數
- pass: 命中某條規則繼續匹配下一條規則。可用於對請求進行精細地過濾,但會對響應速度有較大影響。
- pause: 命中某條規則,對當前事務暫停指定的毫秒。一般用於防止登錄爆破。如果遭受DDOS攻擊,會惡化整個web服務的響應速度
- proxy: 把命中規則的請求轉發到另外一個web服務去。這個功能類似反向代理。由於它對客戶端完全來說,完全是無感知,可以用它導向請求到蜜罐系統。這個動作是一個非常優秀的動作。
- redirect: 當規則被命中,它會返回一個重定向,指示瀏覽器訪問另外一個url。它和proxy的區別是,它對客戶端是感知。可用於配置新上線接口或屏蔽某些有問題的接口。
2)Naxsi定義了accept, block, drop
- accept: 對應ModSecurity的allow, 一旦命中立馬放行
- block: 對應ModSecurity的deny
- drop: 對應ModSecurity的drop
3)華為雲WAF定義了allow, deny, redirect
- accept: 對應ModSecurity的allow, 一旦命中立馬放行
- deny: 對應ModSecurity的deny, 默認返回418
- redirect: 對應Modsecurity的redirect
4)openrestyl lua WAF定義了allow, deny,drop, redirect
- accept: 對應ModSecurity的allow, 一旦命中立馬放行
- deny: 對應ModSecurity的deny, 默認返回403
- drop: 對應ModSecurity的drop
- redirect: 對應Modsecurity的redirect
其中華為雲WAF和openresty lua WAF,在實現pass動作,都是通過規則組來實現。
對於動作配置方面,有這樣的建議:
- 在功能開發方面,drop最好能夠先返回一個狀態碼再停止掉整個連接,drop, deny狀態碼盡量可以通過規則配置。
- 在配置規則時,對於drop, deny的狀態碼,每條規則或規則組都返回不同的狀態碼。
這樣做的好處是:
- 有效隱藏WAF的特征,讓攻擊者無法確認是否有WAF存在
- 當出現規則誤攔截時,可以根據返回碼快速定位是哪條規則誤攔截。這是從無數次背鍋感悟出來的血的教訓
6 WAF規則與報表
1)規則配置
首先,WAF規則的定義是什么?
從前面的內容可以看到,基本上,WAF處理http分為四個階段:請求頭部,請求內容,響應頭部,響應內容。那么WAF規則就是,定義在某個階段WAF對符合某種條件的http請求執行指定動作的條例。
根據這個,WAF規則必須要包含這些元素:過濾條件,階段,動作。由於http消息在傳輸過程中會對數據進行某種編碼,所以,WAF規則往往也需要定義解碼器。同時為了審計作用,WAF規則往往定義id,是否對結果記錄,以及字段抽取,命中規則的嚴重級別所以,一條WAF規則往往包含:id, 解碼器,過濾條件,階段,動作和日志格式,嚴重級別。
以一條ModSecurity規則為例:
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "\bsys\.user_catalog\b" \ "phase:2,rev:'2.1.3',capture,t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,t:replaceComments,t:compressWhiteSpace,ctl:auditLogParts=+E, \ block,msg:'Blind SQL Injection Attack',id:'959517',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1', \ tag:'PCI/6.5.2',logdata:'%{TX.0}',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score}, \ setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"
看起來非常恐怖。翻譯成XML就清晰多了
<rule> <id>959517</id> <version>2.1.3</version> <description></description> <severity>2</severity> <phase>2</phase> <decoder>none, urlDecodeUni,htmlEntityDecode,lowercase,replaceComments,compressWhiteSpace</decoder> <condition> <field>REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/*</field> <operator>regex</operator> <pattern>\bsys\.user_catalog\b</pattern> </condition> <action>block</action> <tags></tags> <log> <format></format> <varibles></varibles> </log> </rule>
2)規則陷阱
規則之間的關系非常復雜,特別過濾條件是使用正則表達式的,往往是會有包含關系,如[0-9]+包含了[1-2]+。那么,假設規則a先加入WAF,后面又新增了條規則b,在語法上,b的過濾條件包含了a,而且在配置上,不小心放在a前面,那么,就會出現誤判的情況。
誤判和漏判,是很常見的問題。但在嚴重程度上,卻是不一樣。
漏判,可能會造成惡意請求繞過WAF,跑到業務后台,但在業務后台加上其它安全措施,卻可以緩解威脅。誤判,則是直接在WAF把正常請求給攔截掉,影響正常的業務。曾經某大廠重要業務部門上WAF,由於誤判,導致正常交易只有50%成功,幾上幾下之后,WAF團隊的人基本干掉了。
所以,在測試環境,WAF規則要越嚴格越好。但在生產環境,對有把握的規則才維持原樣,其它規則盡量放寬松一些。
雖然WAF規則可以設置一個id用於追溯,這遠遠不夠,因為無法追溯是由哪個消息觸發,規則對消息處理的順序是怎樣。所以,一個穩妥的規則引擎,應當在http消息接收時,在頭部增加一個消息id,當消息離開WAF前,刪除掉這個消息id。通過這種方式,可以很好追溯到每條消息會觸發哪些規則,觸發結果是怎樣。當出現誤判情況下,也可以立馬知道是哪些規則有問題,順序是怎樣,規則定義是否合理。
3)報表
WAF報表除了是展示給用戶看,還可以用於優化規則。如下面場景:
- 某些規則一直沒有命中,配置起來只會浪費計算資源,影響用戶體現。
- 某些規則雖然有命中,但命中率較低,應該是放置在后面,而命中率高的則應該調整在前面。
- 某些URL訪問頻率較高,且並非標准瀏覽器訪問,需要進一步觀察和分析,看是否會有漏判風險
那么,報表應該從哪些維度來展示呢?
先從語義來描述一下http消息流經waf的過程:
- 客戶端A在物理地點B,使用IP地址C訪問站點D,向URL地址E發起方法為F的HTTP請求G,命中了解碼器為H,類型為I,風險級別為J,執行動作為K的規則L。
- 站點M向IP地址N返回響應O,命中了解碼器為P,類型為Q,風險級別為R,執行動作為S的規則T。
由語義來看,去重之后,報表的維度至少要包含:
- 客戶端(user_agent)分布
- IP地址,甚至是IP段分布
- 物理地點分布
- 站點分布分布
- URL分布
- HTTP方法分布
- 請求分布(這個會比較困難,基於長度來看會比較好)
- 解碼器分布
- 規則類型分布(一般是指針對的攻擊類型)
- 風險級別分布
- 動作分布
- 規則ID分布
- 響應分布(和請求分布一樣困難)
- 時間分布(任何事件只能在時間中進行)
- 總請求數
- 攔截數量
每個維度並不是孤立,還會相互影響,純組合可以達到216=65536種組合。
7 WAF特征
在滲透或安全測試過程中,總是會發現不少WAF的存在。有些是有意展示自己的存在,作為一種廣告,如華為雲WAF,CloudFlare之類,有些是開發者的意識懶惰或沒時間。
檢測WAF存在,一般是幾種方法:
- 查看響應頭部字段,是否有特征字段或不尋常字段或某些常見字段缺失
- 查看響應內容
- 嘗試各種web攻擊類型,和正常請求對比返回的狀態碼或返回內容。
- 嘗試DOS攻擊,超過一定次數后,看該IP的連接是否drop掉,再用另外一個IP查看,如果正常,說明觸發了黑名單或CC防護。可以確認WAF存在
下面是業務常見的WAF特征:
1)360 Firewall:
- 攔截狀態碼是493
- 響應頭部包含X-Powered-By-360WZB
- 攔截的返回內容
- 引用指向wangshan.360.cn
- 包含文本“Sorry! Your access has been intercepted because your links may threaten website security.”
2)阿里雲盾:
- 攔截的狀態碼為405
- 攔截的返回內容
- 引用指向errors.aliyun.com
- 包含文本“Sorry, your request has been blocked as it may cause potential threats to the server's security”
3)AWS (Amazon):
- 攔截狀態碼為403
- 響應內容頭部server包含”AWS“
4)百度雲加速:
server字段可能會為”Yunjiasu-nginx"或"Yunjiasu"
5)BitNinja:
攔截響應內容會包含“Security check by BitNinja”
6)思科ACE XML Gateway:
server字段有“ACE XML Gateway"
7)Cloudflare:
- 響應頭部:可能有cf-ray字段;server字段包含”cloudflare";Set-Cookie包含"__cfuid=".
- 響應內容:可能包含“Attention Required!”或“Cloudflare Ray ID:”;請求無效URL會有“CLOUDFLARE_ERROR_500S_BOX”返回
8)飛塔FortiWeb:
- 響應頭部:在惡意請求返回情況會有“FORTIWAFSID=”
- 攔截返回的響應內容:會引用“.fgd_icon"圖標;頁面內容會有”Server Unavailable!“
9)華為雲WAF:
- 攔截狀態碼為418
- 響應頭部server為HuaweiCloudWAF
- 第一次響應"Set-Cookie"包含”HWWAFSESID“和”HWWAFSESTIME“
10)IBM DataPower:
響應頭部可能存在字段”X-Backside-Transport“,取值是”OK"或“FAIL"。
11)ModSecurity (Trustwave):
- 響應頭部server可能會包含”Mod_Security“或”NYOB“
- 攔截的響應內容會包含”This error was generated by Mod_Security", "One or more things in your request were suspicious", "rules of the mod_security module", "Protected by Mod Security"
12)NAXSI (NBS Systems):
- 響應頭部:server包含"naxsi/waf";可能存在“X-Data-Origin”字段,值包含“naxsi/waf"
- 響應內容:包含”This Request Has Been Blocked By NAXSI“
13)綠盟WAF
server字段包含”NSFocus“
14)OpenResty Lua WAF:
- 攔截狀態碼為406
- 響應頭部:server包含”openresty/{version}"
- 攔截內容包含“openresty/{version}"
15)騰訊雲WAF:
- 攔截狀態碼為405
- 攔截內容會指向waf.tencent-cloud.com
更多的WAF特征可以看一下sqlmap和wafw00f的代碼。github上最新sqlmap代碼,已經不包含了waf目錄。