什麼是WAFphp
Web應用防禦系統(也稱:網站應用級入侵防護系統 。英文:Web Application Firewall,簡稱: WAF)。利用國際上公認的一種說法:Web應用 防火牆 是經過執行一系列針對HTTP/HTTPS的 安全策略 來專門爲Web應用提供保護的一款產品。html
WAF的功能java
支持IP白名單和黑名單功能,直接將黑名單的IP訪問拒絕。
支持URL白名單,將不須要過濾的URL進行定義。
支持User-Agent的過濾,匹配自定義規則中的條目,而後進行處理(返回403)。
支持CC攻擊防禦,單個URL指定時間的訪問次數,超過設定值,直接返回403。
支持Cookie過濾,匹配自定義規則中的條目,而後進行處理(返回403)。
支持URL過濾,匹配自定義規則中的條目,若是用戶請求的URL包含這些,返回403。
支持URL參數過濾,原理同上。
支持日誌記錄,將全部拒絕的操做,記錄到日誌中去node
WAF的特色python
一、異常檢測協議mysql
Web應用防火牆會對HTTP的請求進行異常檢測,拒毫不符合HTTP標準的請求。而且,它也能夠只容許HTTP協議的部分選項經過,從而減小攻擊的影響範圍。甚至,一些Web應用防火牆還能夠嚴格限定HTTP協議中那些過於鬆散或未被徹底制定的選項。linux
二、加強的輸入驗證 nginx
加強輸入驗證,能夠有效防止網頁篡改、信息泄露、木馬植入等惡意網絡入侵行爲。從而減少Web服務器被攻擊的可能性。git
三、及時補丁 程序員
修補Web安全漏洞,是Web應用開發者最頭痛的問題,沒人會知道下一秒有什麼樣的漏洞出現,會爲Web應用帶來什麼樣的危害。WAF能夠爲咱們作這項工做了——只要有全面的漏洞信息WAF能在不到一個小時的時間內屏蔽掉這個漏洞。固然,這種屏蔽掉漏洞的方式不是很是完美的,而且沒有安裝對應的補丁自己就是一種安全威脅,但咱們在沒有選擇的狀況下,任何保護措施都比沒有保護措施更好。
四、基於規則的保護和基於異常的保護
基於規則的保護能夠提供各類Web應用的安全規則,WAF生產商會維護這個規則庫,並時時爲其更新。用戶能夠按照這些規則對應用進行全方面檢測。還有的產品能夠基於合法應用數據創建模型,並以此爲依據判斷應用數據的異常。但這須要對用戶企業的應用具備十分透徹的瞭解纔可能作到,可現實中這是十分困難的一件事情。
五、狀態管理
WAF可以判斷用戶是不是第一次訪問而且將請求重定向到默認登陸頁面而且記錄事件。經過檢測用戶的整個操做行爲咱們能夠更容易識別攻擊。狀態管理模式還能檢測出異常事件(好比登錄失敗),而且在達到極限值時進行處理。這對暴力攻擊的識別和響應是十分有利的。
六、其餘防禦技術
WAF還有一些安全加強的功能,能夠用來解決WEB程序員過度信任輸入數據帶來的問題。好比:隱藏表單域保護、抗入侵規避技術、響應監視和信息泄露保護。
七、WAF相對於網絡防火牆的區別
網絡防火牆做爲訪問控制設備,主要工做在OSI模型3、四層,基於IP報文進行檢測。只是對端口作限制,對TCP協議作封堵。其產品設計無需理解HTTP會話,也就決定了沒法理解Web應用程序語言如HTML、SQL語言。所以,它不可能對HTTP通信進行輸入驗證或攻擊規則分析。針對Web網站的惡意攻擊絕大部分都將封裝爲HTTP請求,從80或443端口順利經過防火牆檢測。
一些定位比較綜合、提供豐富功能的防火牆,也具有必定程度的應用層防護能力,如能根據TCP會話異常性及攻擊特徵阻止網絡層的攻擊,經過IP分拆和組合也能判斷是否有攻擊隱藏在多個數據包中,但從根本上說他仍然沒法理解HTTP會話,難以應對如SQL注入、跨站腳本、cookie竊取、網頁篡改等應用層攻擊。
web應用防火牆能在應用層理解分析HTTP會話,所以能有效的防止各種應用層攻擊,同時他向下兼容,具有網絡防火牆的功能。
一、WAF實現規劃
分析步驟以下:解析HTTP請求==》匹配規則==》防護動做==》記錄日誌
具體實現以下:一、解析http請求:協議解析模塊 2.、匹配規則:規則檢測模塊,匹配規則庫 三、防護動做:return 403 或者跳轉到自定義界面 四、日誌記錄:記錄到elk中,畫出餅圖,建議使用json格式
二、基於lua模塊部署nginx
至於nginx的安裝部署請參考:https://www.cnblogs.com/goser/articles/7550582.html,本文只作nginx基於lua模塊的編譯安裝
下載當前最新的lua及時編譯器luajit和nginx開發工具NDK(ngx_devel_kit),以及lua模塊lua-nginx-module
[root@linux-node2 ~]# cd /tools/ [root@linux-node2 tools]# wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz [root@linux-node2 tools]# wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.0.tar.gz [root@linux-node2 tools]# wget https://github.com/openresty/lua-nginx-module/archive/v0.10.10.tar.gz [root@linux-node2 tools]# ll -rw-r--r-- 1 root root 849845 Aug 27 11:28 LuaJIT-2.0.5.tar.gz -rw-r--r-- 1 root root 611973 Aug 27 13:29 lua-nginx-module-0.10.10.tar.gz -rw-r--r-- 1 root root 66455 Aug 27 11:40 ngx_devel_kit-0.3.0.tar.gz
安裝LuaJIT
[root@linux-node2 tools]# tar xf LuaJIT-2.0.5.tar.gz [root@linux-node2 tools]# cd LuaJIT-2.0.5 [root@linux-node2 LuaJIT-2.0.5]# make && make install
解壓NDK和lua-nginx-module,並將解壓包放到nginx部署路徑下
[root@linux-node2 tools]# tar xf ngx_devel_kit-0.3.0.tar.gz [root@linux-node2 tools]# tar xf lua-nginx-module-0.10.10.tar.gz #建立存放NDK和lua模塊的路徑,將這些模塊放到這個路徑下 mkdir -p /application/nginx/extra/modules [root@linux-node2 tools]# cp -r ngx_devel_kit-0.3.0 /application/nginx/extra/modules/ngx_devel_kit [root@linux-node2 tools]# cp -r lua-nginx-module-0.10.10 /application/nginx/extra/modules/lua-nginx-module
建立luajit環境變量
[root@linux-node2 LuaJIT-2.0.5]# export LUAJIT_LIB=/usr/local/lib [root@linux-node2 LuaJIT-2.0.5]# export LUAJIT_INC=/usr/local/include/luajit-2.0
從新編譯nginx,將lua模塊添加進去
[root@linux-node2 tools]# cd nginx-1.12.2 [root@linux-node2 nginx-1.12.2]# ./configure --prefix=/application/nginx-1.12.2 --user=www --group=www --with-http_stub_status_module --with-http_ssl_module --add-module=/application/nginx/extra/modules/ngx_devel_kit/ --add-module=/application/nginx/extra/modules/lua-nginx-module/ --with-file-aio --with-http_dav_module #中止nginx服務,從新部署nginx [root@linux-node2 nginx-1.12.2]# /application/nginx/sbin/nginx -s stop [root@linux-node2 nginx-1.12.2]# make -j2 && make install # -j2表示同時使用兩個任務
檢查nginx語法報語法錯誤,解決以下:
[root@linux-node2 ~]# /application/nginx/sbin/nginx -t /application/nginx/sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory #上面報錯 ,說明nginx沒有加載到lua庫,調整lua庫文件地址 [root@linux-node2 ~]# ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2 #啓動nginx服務 [root@linux-node2 ~]# /application/nginx/sbin/nginx
安裝完畢後,下面能夠測試安裝了,修改nginx.conf 增長第一個配置
#部分代碼修改以下,在www.conf配置文件中添加以下location段 [root@linux-node2 conf]# vim extra/www.conf location /hello { default_type 'text/plain'; content_by_lua 'ngx.say("hello,lua,welcome!!!")'; } #重載nginx使配置生效 [root@linux-node2 conf]# /application/nginx/sbin/nginx -t [root@linux-node2 conf]# /application/nginx/sbin/nginx -s reload
使用瀏覽器打開http://192.168.80.172/hello檢查lua模塊是否加載
部署基於lua的waf應用:這裏使用開源的waf項目https://github.com/loveshell/ngx_lua_waf
[root@linux-node3 ~]# git clone https://github.com/loveshell/ngx_lua_waf.git #將waf規則庫放到ngixn的配置文件路徑下 [root@linux-node3 ~]# mv ngx_lua_waf /application/nginx/conf/waf [root@linux-node3 ~]# cd /application/nginx/conf/waf/ #修改waf的配置文件,修改規則庫規則的對應路徑並設置日誌記錄位置 [root@linux-node3 waf]# vim config.lua RulePath = "/application/nginx/conf/waf/wafconf/" attacklog = "on" logdir = "/tmp/" UrlDeny="on" Redirect="on" CookieMatch="on" postMatch="on" whiteModule="on" black_fileExt={"php","jsp"} ipWhitelist={"127.0.0.1"} ipBlocklist={"1.0.0.1"} CCDeny="on" CCrate="30/60" html=[[ <html xmlns="http://www.w3.org/1999/xhtml"><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>網站防火牆</title> <style> p { line-height:20px; } ul{ list-style-type:none;} li{ list-style-type:none;} </style> </head> <body style=" padding:0; margin:0; font:14px/1.5 Microsoft Yahei, 宋體,sans-serif; color:#555;"> <div style="margin: 0 auto; width:1000px; padding-top:70px; overflow:hidden;"> <div style="width:600px; float:left;"> <div style=" height:40px; line-height:40px; color:#fff; font-size:16px; overflow:hidden; background:#6bb3f6; padding-left:20px;">網站防火牆 </div> <div style="border:1px dashed #cdcece; border-top:none; font-size:14px; background:#fff; color:#555; line-height:24px; height:220px; padding:20px 20px 0 20px; overflow-y:auto;background:#f3f7f9;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; color:#fc4f03;">您的請求帶有不合法參數,已被網站管理員設置攔截!</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">可能緣由:您提交的內容包含危險的攻擊請求</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:0px;">如何解決:</p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1)檢查提交內容;</li> <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2)如網站託管,請聯繫空間提供商;</li> <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3)普通網站訪客,請聯繫網站管理員;</li></ul> </div> </div> </div> </body></html> ]] #修改ngxin.conf配置文件,在http段中添加以下內容 [root@linux-node3 conf]# vim nginx.conf .... lua_shared_dict limit 10m; lua_package_path "/application/nginx/conf/waf/?.lua"; init_by_lua_file /application/nginx/conf/waf/init.lua; access_by_lua_file /application/nginx/conf/waf/waf.lua; .... #重載nginx服務 [root@linux-node3 conf]# /application/nginx/sbin/nginx -t [root@linux-node3 conf]# /application/nginx/sbin/nginx -s reload
測試waf配置是否生效,使用http://192.168.80.173/mysql.sql模擬sql注入操做。顯示效果以下:
對應的日誌記錄以下:
[root@linux-node3 conf]# tail -f /tmp/www.goser.com_2018-08-31_sec.log 192.168.201.211 [2018-08-31 13:56:31] "GET www.goser.com/mysql.sql" "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" "\.(bak|inc|old|mdb|sql|backup|java|class)$"
測試客戶端使用壓力測試工具對網站攻擊
[root@linux-node2 tools]# yum install httpd-tools -y [root@linux-node2 tools]# ab -c 50 -n 1000 http://192.168.80.173/ 。。。。 Concurrency Level: 50 Time taken for tests: 0.707 seconds Complete requests: 1000 Failed requests: 941 。。。。 #經過上面的ab測壓工具能夠看到失敗了941次客戶端請求,這是由config.lua配置文件決定的 。。。。 CCDeny="on" CCrate="30/60" 。。。。
咱們都知道Nginx有不少的特性和好處,可是在Nginx上開發成了一個難題,Nginx模塊須要用C開發,並且必須符合一系列複雜的規則,最重要的用C開發模塊必需要熟悉Nginx的源代碼,使得開發者對其望而生畏。爲了開發人員方便,因此接下來咱們要介紹一種整合了Nginx和lua的框架,那就是OpenResty,它幫咱們實現了能夠用lua的規範開發,實現各類業務,而且幫咱們弄清楚各個模塊的編譯順序。關於OpenResty,我想你們應該再也不陌生,隨着系統架構的不斷升級、優化,OpenResty在被普遍的應用。
Nginx 採用的是 master-worker 模型,一個 master 進程管理多個 worker 進程,基本的事件處理都是放在 woker 中,master 負責一些全局初始化,以及對 worker 的管理。在OpenResty中,每一個 woker 使用一個 LuaVM,當請求被分配到 woker 時,將在這個 LuaVM 裏建立一個 coroutine(協程)。協程之間數據隔離,每一個協程具備獨立的全局變量_G。
ps. 協程和多線程下的線程相似:有本身的堆棧,本身的局部變量,有本身的指令指針,可是和其餘協程程序共享全局變量等信息。線程和協程的主要不一樣在於:多處理器的狀況下,概念上來講多線程是同時運行多個線程,而協程是經過代碼來完成協程的切換,任什麼時候刻只有一個協程程序在運行。而且這個在運行的協程只有明確被要求掛起時纔會被掛起。
首先咱們選擇使用OpenResty,其是由Nginx核心加不少第三方模塊組成,其最大的亮點是默認集成了Lua開發環境,使得Nginx能夠做爲一個Web Server使用。
藉助於Nginx的事件驅動模型和非阻塞IO,能夠實現高性能的Web應用程序。
並且OpenResty提供了大量組件如Mysql、Redis、Memcached等等,使在Nginx上開發Web應用更方便更簡單。目前在京東如實時價格、秒殺、動態服務、單品頁、列表頁等都在使用Nginx+Lua架構,其餘公司如淘寶、去哪兒網等。
下載openresty並編譯安裝openresty
[root@linux-node2 tools]# wget https://openresty.org/download/openresty-1.13.6.1.tar.gz [root@linux-node2 tools]# tar xf openresty-1.13.6.1.tar.gz [root@linux-node2 tools]# cd openresty-1.13.6.1 [root@linux-node2 openresty-1.13.6.1]# ./configure --prefix=/application/openresty-1.13.6.1 --with-luajit --with-pcre --with-pcre-jit --user=www --group=www --with-http_stub_status_module --with-http_ssl_module [root@linux-node2 openresty-1.13.6.1]# gmake && gmake install [root@linux-node2 openresty-1.13.6.1]# ln -s /application/openresty-1.13.6.1 /application/openresty #中止原生的nginx服務,啓動openresty中的nginx服務 [root@linux-node2 openresty-1.13.6.1]# /application/nginx/sbin/nginx -s stop [root@linux-node2 openresty-1.13.6.1]# /application/openresty/nginx/sbin/nginx -t [root@linux-node2 openresty-1.13.6.1]# /application/openresty/nginx/sbin/nginx
測試openresty安裝
#修改nginx.conf文件,添加以下location段 [root@linux-node2 tools]# cd /application/openresty/nginx/conf/ [root@linux-node2 conf]# vim nginx.conf location /hi { default_type text/html; content_by_lua_block{ ngx.say("hello openrastry!!!"); } } #重載openresty中的nginx服務 [root@linux-node2 conf]# /application/openresty/nginx/sbin/nginx -s reload
打開http://192.168.80.172/hi
基於openresty來部署WAF
#在github上克隆下代碼 [root@linux-node2 ~]# git clone https://github.com/unixhot/waf.git #將waf文件拷貝到openresty的nginx路徑下 [root@linux-node2 ~]# cp -r waf/waf/ /application/openresty/nginx/conf/ #修改waf中的config.lua文件,修改lua防火前規則路徑 [root@linux-node2 ~]# cd /application/openresty/nginx/conf/ [root@linux-node2 conf]# vim waf/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 = "/application/openresty/nginx/conf/waf/rule-config" --enable/disable white url config_white_url_check = "on" --enable/disable white ip config_white_ip_check = "on" --enable/disable block ip config_black_ip_check = "on" --enable/disable url filtering config_url_check = "on" --enalbe/disable url args filtering config_url_args_check = "on" --enable/disable user agent filtering config_user_agent_check = "on" --enable/disable cookie deny filtering config_cookie_check = "on" --enable/disable cc filtering config_cc_check = "on" --cc rate the xxx of xxx seconds config_cc_rate = "30/60" --enable/disable post filtering config_post_check = "on" --config waf output redirect/html config_waf_output = "html" --if config_waf_output ,setting url config_waf_redirect_url = "https://www.cnblogs.com/goser" config_output_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"> 您的行爲已違反本網站相關規定,注意操做規範。</h1> </body> </html> ]] #修改openresty中nginx的配置文件,在http段添加以下內容: [root@linux-node2 conf]# vim nginx.conf lua_shared_dict limit 50m; #防cc使用字典,大小50M lua_package_path "/application/openresty/nginx/conf/waf/?.lua"; init_by_lua_file "/application/openresty/nginx/conf/waf/init.lua"; access_by_lua_file "/application/openresty/nginx/conf/waf/access.lua"; #根據日誌記錄位置,建立日誌目錄並授予www用戶的權限 [root@linux-node2 conf]# mkdir /tmp/waf_logs [root@linux-node2 conf]# chown www.www /tmp/waf_logs/ #檢查nginx語法並重載nginx服務 [root@linux-node2 conf]# /application/openresty/nginx/sbin/nginx -t [root@linux-node2 conf]# /application/openresty/nginx/sbin/nginx -s reload
至於lua語言的編寫能夠參考Nginx API for Lua :https://github.com/openresty/lua-nginx-module#nginx-api-for-lua
模擬sql注入即url攻擊
這時候日誌顯示以下,記錄了UA,匹配規則,URL,客戶端類型,攻擊的類型,請求的數據
[root@linux-node2 conf]# tail -f /tmp/waf_logs/2018-08-30_waf.log {"local_time":"2018-08-30 11:52:23","client_ip":"192.168.80.253","rule_tag":"\\.(bak|inc|old|mdb|sql|backup|java|class|tgz|gz|tar|zip)$","attack_method":"Deny_URL","server_name":"192.168.80.172","req_url":"\/mysql.sql","req_data":"-","user_agent":"Mozilla\/5.0 (Windows NT 5.1) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/49.0.2623.112 Safari\/537.36"}
使用一臺客戶端,使用ab壓測工具模擬防cc攻擊
#安裝ab測壓工具 [root@linux-node3 ~]# yum install httpd-tools -y [root@linux-node3 ~]# ab -c 50 -n 1000 http://192.168.80.172/ .... Concurrency Level: 50 Time taken for tests: 0.220 seconds Complete requests: 1000 Failed requests: 979 ...... #從上面能夠看出失敗了979此請求,這是由config.lua配置文件配置決定的 [root@linux-node2 waf]# vim config.lua --cc rate the xxx of xxx seconds config_cc_rate = "30/60"
固然還能夠模擬ip黑名單和模擬ip白名單,配置相似,只要在/application/openresty/nginx/conf/waf/rule-config/whiteip.rule或blackip.rule 規則文件添加白名單的ip或黑名單的ip
模擬URL參數檢測: 瀏覽器輸入http://192.168.3.140/?id=select * from name where name="goser",顯示以下:
初期上線只記錄日誌,不開啓WAF,防止誤殺
WAF規則管理使用saltstack工具
要知道並非有了WAF就安全,安全在很大一部分是人爲因素