Web應用防禦系統(也稱:網站應用級***防護系統 。英文:Web Application Firewall,簡稱: WAF)。利用國際上公認的一種說法:Web應用 防火牆 是經過執行一系列針對HTTP/HTTPS的 安全策略 來專門爲Web應用提供保護的一款產品。php
支持IP白名單和黑名單功能,直接將黑名單的IP訪問拒絕。html
支持URL白名單,將不須要過濾的URL進行定義。java
支持User-Agent的過濾,匹配自定義規則中的條目,而後進行處理(返回403)。node
支持CC***防禦,單個URL指定時間的訪問次數,超過設定值,直接返回403。linux
支持Cookie過濾,匹配自定義規則中的條目,而後進行處理(返回403)。nginx
支持URL過濾,匹配自定義規則中的條目,若是用戶請求的URL包含這些,返回403。git
支持URL參數過濾,原理同上。程序員
支持日誌記錄,將全部拒絕的操做,記錄到日誌中去github
異常檢測協議
Web應用防火牆會對HTTP的請求進行異常檢測,拒毫不符合HTTP標準的請求。而且,它也能夠只容許HTTP協議的部分選項經過,從而減小***的影響範圍。甚至,一些Web應用防火牆還能夠嚴格限定HTTP協議中那些過於鬆散或未被徹底制定的選項。
web
加強的輸入驗證
加強輸入驗證,能夠有效防止網頁篡改、信息泄露、***植入等惡意網絡***行爲。從而減少Web服務器被***的可能性。
及時補丁
修補Web安全漏洞,是Web應用開發者最頭痛的問題,沒人會知道下一秒有什麼樣的漏洞出現,會爲Web應用帶來什麼樣的危害。WAF能夠爲咱們作這項工做了——只要有全面的漏洞信息WAF能在不到一個小時的時間內屏蔽掉這個漏洞。固然,這種屏蔽掉漏洞的方式不是很是完美的,而且沒有安裝對應的補丁自己就是一種安全威脅,但咱們在沒有選擇的狀況下,任何保護措施都比沒有保護措施更好。
基於規則的保護和基於異常的保護
基於規則的保護能夠提供各類Web應用的安全規則,WAF生產商會維護這個規則庫,並時時爲其更新。用戶能夠按照這些規則對應用進行全方面檢測。還有的產品能夠基於合法應用數據創建模型,並以此爲依據判斷應用數據的異常。但這須要對用戶企業的應用具備十分透徹的瞭解纔可能作到,可現實中這是十分困難的一件事情。
狀態管理
WAF可以判斷用戶是不是第一次訪問而且將請求重定向到默認登陸頁面而且記錄事件。經過檢測用戶的整個操做行爲咱們能夠更容易識別***。狀態管理模式還能檢測出異常事件(好比登錄失敗),而且在達到極限值時進行處理。這對暴力***的識別和響應是十分有利的。
其餘防禦技術
WAF還有一些安全加強的功能,能夠用來解決WEB程序員過度信任輸入數據帶來的問題。好比:隱藏表單域保護、抗***規避技術、響應監視和信息泄露保護。
網絡防火牆做爲訪問控制設備,主要工做在OSI模型3、四層,基於IP報文進行檢測。只是對端口作限制,對TCP協議作封堵。其產品設計無需理解HTTP會話,也就決定了沒法理解Web應用程序語言如HTML、SQL語言。所以,它不可能對HTTP通信進行輸入驗證或***規則分析。針對Web網站的惡意***絕大部分都將封裝爲HTTP請求,從80或443端口順利經過防火牆檢測。
一些定位比較綜合、提供豐富功能的防火牆,也具有必定程度的應用層防護能力,如能根據TCP會話異常性及***特徵阻止網絡層的***,經過IP分拆和組合也能判斷是否有***隱藏在多個數據包中,但從根本上說他仍然沒法理解HTTP會話,難以應對如SQL注入、跨站腳本、cookie竊取、網頁篡改等應用層***。
web應用防火牆能在應用層理解分析HTTP會話,所以能有效的防止各種應用層***,同時他向下兼容,具有網絡防火牆的功能。
修改nginx配置文件在server中加入如下內容
set $block_user_agent 0; if ( $http_user_agent ~ "Wget|AgentBench"){ set $block_user_agent 1; } if ($block_user_agent = 1) { return 403 ; }
經過其餘機器去wget,結果以下
在nginx配置文件中加入以下內容,讓訪問sql|bak|zip|tgz|tar.gz的請求返回404
location ~* "\.(sql|bak|zip|tgz|tar.gz)$"{ return 404 }
在網站根目錄下放一個tar.gz
[root@iZ28t900vpcZ www]# tar zcvf abc.tar.gz wp-content/
經過瀏覽器訪問結果以下,404已生效
分析步驟以下:解析HTTP請求==》匹配規則==》防護動做==》記錄日誌
具體實現以下:
解析http請求:協議解析模塊
匹配規則:規則檢測模塊,匹配規則庫
防護動做:return 403 或者跳轉到自定義界面
日誌記錄:記錄到elk中,畫出餅圖,建議使用json格式
因爲nginx配置文件書寫不方便,而且實現白名單功能很複雜,nginx的白名單也不適用於CC***,因此在這裏使用nginx+lua來實現WAF,若是想使用lua,須在編譯nginx的時候配置上lua,或者結合OpenResty使用,此方法不須要編譯nginx時候指定lua
環境準備:Nginx安裝必備的Nginx和PCRE軟件包。
[root@nginx-lua ~]# cd /usr/local/src [root@nginx-lua src]# wget http://nginx.org/download/nginx-1.9.4.tar.gz[root@nginx-lua src]# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.37.tar.gz
其次,下載當前最新的luajit和ngx_devel_kit (NDK),以及春哥編寫的lua-nginx-module
[root@nginx-lua src]# wget http://luajit.org/download/LuaJIT-2.0..tar.gz[root@nginx-lua src]# wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz[root@nginx-lua src]# wget https://github.com/openresty/lua-nginx-module/archive/v0.9.16.tar.gz
最後,建立Nginx運行的普通用戶
[root@nginx-lua src]# useradd -s /sbin/nologin -M www
解壓NDK和lua-nginx-module
[root@openstack-compute-node5 src]# tar zxvf v0.2.19.tar.gz[root@openstack-compute-node5 src]# tar zxvf v0.9.16.tar.gz
安裝LuaJIT Luajit是Lua即時編譯器
[root@openstack-compute-node5 src]# tar zxvf LuaJIT-2.0.3.tar.gz [root@openstack-compute-node5 src]# cd LuaJIT-2.0.3[root@openstack-compute-node5 LuaJIT-2.0.3]# make && make install
安裝Nginx並加載模塊
[root@openstack-compute-node5 src]# tar zxvf nginx-1.9.4.tar.gz [root@openstack-compute-node5 src]# cd nginx-1.9.4[root@openstack-compute-node5 nginx-1.9.4]# export LUAJIT_LIB=/usr/local/lib[root@openstack-compute-node5 nginx-1.9.4]# export LUAJIT_INC=/usr/local/include/luajit-2.0[root@openstack-compute-node5 nginx-1.9.4]# ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-file-aio --with-http_dav_module --add-module=../ngx_devel_kit-0.2.19/ --add-module=../lua-nginx-module-0.9.16/ --with-pcre=/usr/local/src/pcre-8.37 [root@openstack-compute-node5 nginx-1.5.12]# make -j2 && make install[root@openstack-compute-node5 ~]# ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2 #必定建立此軟鏈接,不然報錯
安裝完畢後,下面能夠測試安裝了,修改nginx.conf 增長第一個配置
location /hello { default_type 'text/plain'; content_by_lua 'ngx.say("hello,lua")'; }[root@openstack-compute-node5 ~]# /usr/local/nginx-1.9.4/sbin/nginx –t[root@openstack-compute-node5 ~]# /usr/local/nginx-1.9.4/sbin/nginx
效果以下
安裝依賴包
[root@iZ28t900vpcZ ~]#yum install -y readline-devel pcre-devel openssl-devel
下載並編譯安裝openresty
[root@iZ28t900vpcZ ~]#cd /usr/local/src[root@iZ28t900vpcZ src]#wget https://openresty.org/download/ngx_openresty-1.9.3.2.tar.gz[root@iZ28t900vpcZ src]#tar zxf ngx_openresty-1.9.3.2.tar.gz[root@iZ28t900vpcZ src]#cd ngx_openresty-1.9.3.2[root@iZ28t900vpcZ ngx_openresty-1.9.3.2]# ./configure --prefix=/usr/local/openresty-1.9.3.2 --with-luajit --with-http_stub_status_module --with-pcre --with-pcre-jit[root@iZ28t900vpcZ ngx_openresty-1.9.3.2]#gmake && gmake installln -s /usr/local/openresty-1.9.3.2/ /usr/local/openresty
測試openresty安裝
[root@iZ28t900vpcZ ~]#vim /usr/local/openresty/nginx/conf/nginx.confserver { location /hello { default_type text/html; content_by_lua_block { ngx.say("HelloWorld") } }}
測試並啓動nginx
[root@iZ28t900vpcZ ~]#/usr/local/openresty/nginx/sbin/nginx -tnginx: the configuration file /usr/local/openresty-1.9.3.2/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/openresty-1.9.3.2/nginx/conf/nginx.conf test is successful[root@iZ28t900vpcZ ~]#/usr/local/openresty/nginx/sbin/nginx
在github上克隆下代碼
[root@iZ28t900vpcZ ~]#git clone https://github.com/unixhot/waf.git[root@iZ28t900vpcZ ~]#cp -a ./waf/waf /usr/local/openresty/nginx/conf/
修改Nginx的配置文件,加入(http字段)如下配置。注意路徑,同時WAF日誌默認存放在/tmp/日期_waf.log
#WAF lua_shared_dict limit 50m; #防cc使用字典,大小50M lua_package_path "/usr/local/openresty/nginx/conf/waf/?.lua"; init_by_lua_file "/usr/local/openresty/nginx/conf/waf/init.lua"; access_by_lua_file "/usr/local/openresty/nginx/conf/waf/access.lua";[root@openstack-compute-node5 ~]# /usr/local/openresty/nginx/sbin/nginx –t[root@openstack-compute-node5 ~]# /usr/local/openresty/nginx/sbin/nginx
根據日誌記錄位置,建立日誌目錄
[root@iZ28t900vpcZ ~]#mkdir /tmp/waf_logs[root@iZ28t900vpcZ ~]#chown nginx.nginx /tmp/waf_logs
WAF上生產以前,建議不要直接上生產,而是先記錄日誌,不作任何動做。肯定WAF不產生誤殺
config.lua即WAF功能詳解
[root@iZ28t900vpcZ waf]# pwd/usr/local/nginx/conf/waf[root@iZ28t900vpcZ waf]# cat config.lua --WAF config file,enable = "on",disable = "off" --waf status config_waf_enable = "on" #是否開啓配置 --log dir config_log_dir = "/tmp/waf_logs" #日誌記錄地址 --rule setting config_rule_dir = "/usr/local/nginx/conf/waf/rule-config" #匹配規則縮放地址 --enable/disable white url config_white_url_check = "on" #是否開啓url檢測 --enable/disable white ip config_white_ip_check = "on" #是否開啓IP白名單檢測 --enable/disable block ip config_black_ip_check = "on" #是否開啓ip黑名單檢測 --enable/disable url filtering config_url_check = "on" #是否開啓url過濾 --enalbe/disable url args filtering config_url_args_check = "on" #是否開啓參數檢測 --enable/disable user agent filtering config_user_agent_check = "on" #是否開啓ua檢測 --enable/disable cookie deny filtering config_cookie_check = "on" #是否開啓cookie檢測 --enable/disable cc filtering config_cc_check = "on" #是否開啓防cc*** --cc rate the xxx of xxx seconds config_cc_rate = "10/60" #容許一個ip60秒內只能訪問10此 --enable/disable post filtering config_post_check = "on" #是否開啓post檢測 --config waf output redirect/html config_waf_output = "html" #action一個html頁面,也能夠選擇跳轉 --if config_waf_output ,setting url config_waf_redirect_url = "http://www.baidu.com" config_output_html=[[ #下面是html的內容 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Language" content="zh-cn" /> <title>網站防火牆</title> </head> <body> <h1 align="center"> # 您的行爲已違反本網站相關規定,注意操做規範。詳情請聯微信公衆號:chuck-blog。 </body> </html> ]]
[root@iZ28t900vpcZ waf]# pwd/usr/local/openresty/nginx/conf/waf[root@iZ28t900vpcZ waf]# cat access.lua require 'init'function waf_main() if white_ip_check() then elseif black_ip_check() then elseif user_agent_attack_check() then elseif cc_attack_check() then elseif cookie_attack_check() then elseif white_url_check() then elseif url_attack_check() then elseif url_args_attack_check() then --elseif post_attack_check() then else return endendwaf_main()
書寫書序:先檢查白名單,經過即不檢測;再檢查黑名單,不經過即拒絕,檢查UA,UA不經過即拒絕;檢查cookie;URL檢查;URL參數檢查,post檢查;
顯示效果以下
日誌顯示以下,記錄了UA,匹配規則,URL,客戶端類型,***的類型,請求的數據
[root@linux-node3 ~]# ab -c 100 -n 100 http://www.chuck-blog.com/index.phpThis is ApacheBench, Version 2.3 <$Revision: 1430300 $>Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking www.chuck-blog.com (be patient).....doneServer Software: openrestyServer Hostname: www.chuck-blog.comServer Port: 80Document Path: /index.phpDocument Length: 0 bytesConcurrency Level: 100Time taken for tests: 0.754 secondsComplete requests: 10Failed requests: 90 #config.lua中設置的,60秒內只容許10個請求Write errors: 0Non-2xx responses: 90Total transferred: 22700 bytesHTML transferred: 0 bytesRequests per second: 132.65 [#/sec] (mean)Time per request: 753.874 [ms] (mean)Time per request: 7.539 [ms] (mean, across all concurrent requests)Transfer rate: 29.41 [Kbytes/sec] receivedConnection Times (ms) min mean[+/-sd] median maxConnect: 23 69 20.2 64 105Processing: 32 180 144.5 157 629Waiting: 22 179 144.5 156 629Total: 56 249 152.4 220 702Percentage of the requests served within a certain time (ms) 50% 220 66% 270 75% 275 80% 329 90% 334 95% 694 98% 701 99% 702 100% 702 (longest request) ```###3.5.3 模擬ip黑名單將請求ip放入ip黑名單中
[root@iZ28t900vpcZ rule-config]# echo 「1.202.193.133」 >>/usr/local/openresty/nginx/conf/waf/rule-config/blackip.rule
顯示結果以下![](ca1fa711-48e6-4041-a367-b15db7bf2d2f_128_files/c71edccb-507c-4340-a1fc-ad03e300a2fa.png)###3.5.4 模擬ip白名單將請求ip放入ip白名單中,此時將不對此ip進行任何防禦措施,因此sql注入時應該返回404
[root@iZ28t900vpcZ rule-config]# echo 「1.202.193.133」 >>/usr/local/openresty/nginx/conf/waf/rule-config/whiteip.rule
顯示結果以下![](ca1fa711-48e6-4041-a367-b15db7bf2d2f_128_files/3ded0e02-480f-48f4-8aab-41aff0fc5538.png)###3.5.5 模擬URL參數檢測瀏覽器輸入www.chuck-blog.com/?a=select * from table顯示結果以下![](ca1fa711-48e6-4041-a367-b15db7bf2d2f_128_files/744e4a20-5558-43fc-9f50-1546cbc765a3.png)詳細規定在arg.rule中有規定,對請求進行了規範```bash[root@iZ28t900vpcZ rule-config]# /usr/local/openresty/nginx/conf/waf/rule-config/cat args.rule \.\./\:\$\$\{select.+(from|limit)(?:(union(.*?)select))having|rongjitestsleep\((\s*)(\d*)(\s*)\)benchmark\((.*)\,(.*)\)base64_decode\((?:from\W+information_schema\W)(?:(?:current_)user|database|schema|connection_id)\s*\((?:etc\/\W*passwd)into(\s+)+(?:dump|out)file\s*group\s+by.+\(xwork.MethodAccessor(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(xwork\.MethodAccessor(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/java\.lang\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[\<(iframe|script|body|img|layer|div|meta|style|base|object|input)(|onerror|onload)\=[root@iZ28t900vpcZ rule-config]# pwd/usr/local/openresty/nginx/conf/waf/rule-config
HttpGuard是基於openresty,以lua腳本語言開發的防cc***軟件。而openresty是集成了高性能web服務器Nginx,以及一系列的Nginx模塊,這其中最重要的,也是咱們主要用到的nginx lua模塊。HttpGuard基於nginx lua開發,繼承了nginx高併發,高性能的特色,能夠以很是小的性能損耗來防範大規模的cc***。
限制訪客在必定時間內的請求次數
向訪客發送302轉向響應頭來識別惡意用戶,並阻止其再次訪問
向訪客發送帶有跳轉功能的js代碼來識別惡意用戶,並阻止其再次訪問
向訪客發送cookie來識別惡意用戶,並阻止其再次訪問
支持向訪客發送帶有驗證碼的頁面,來進一步識別,以避免誤傷
支持直接斷開惡意訪客的鏈接
支持結合iptables來阻止惡意訪客再次鏈接
支持白名單功能
支持根據統計特定端口的鏈接數來自動開啓或關閉防cc模式
詳見github地址,在後續的博文中會加入此功能
初期上線只記錄日誌,不開啓WAF,防止誤殺
WAF規則管理使用saltstack工具
要知道並非有了WAF就安全,存在人爲因素