基於ngx_lua模組的waf開發實踐

wyzsk發表於2020-08-19
作者: zhangsan · 2015/03/06 9:15

0x00 常見WAF簡單分析


WAF主要分為硬體WAF和軟體防火牆,硬體WAF如綠盟的NSFOCUS Web Application Firewall,軟體防火牆比較有名的是ModSecurity,再就是程式碼級別的ngx_lua_waf。下面談談個人對幾款防火牆的理解:

硬體WAF個人覺得只適合在那種訪問量較少的網站,比如政府網站,公司的介紹網站等等。硬體WAF的的優勢在於規則有專門的安全公司維護,管理方便,但也存在一個致命的弱點,使用傳統的方式來解包到應用層對效能的需求較高,而且當訪問量很大的時候延時比較大,這樣在高併發訪問的情況下要使用硬體WAF就只能使用很多臺WAF了,這樣成本就非常高了;還有一個在接觸過程中發現的問題,就是硬體WAF的規則雖然多而且有人維護,但是一般公司很難敢直接開啟阻難,很多都是隻記錄,並不能阻難,這樣WAF的意義就變得小多了。

ModSecurity在網上的評價都是很高的,效能高,規則全。最開始我研究的也是這款WAF,但是在實際使用過程中發現問題,就是在高併發的情況下,執行一段時間,會出現記憶體飆升,而且不下來的問題。這個問題再ModSecurity的討論論壇上面也發現了有人提出這樣的問題,但一直未解決(https://github.com/SpiderLabs/ModSecurity/issues/785)。針對於規則全的優勢,一般使用者也不敢直接開啟所有的規則攔截,畢竟每個公司的業務不同,規則也不可能直接套用。

基於高效能,低成本的想法,[email protected]_lua_waf,經過實際使用下來,確實效能極好,由於LUA語言的效能是接近於C的,而且ngx_lua_module本身就是基於為nginx開發的高效能的模組。安全寶的雲 WAF,以及cloudflare的新waf也是基於此模組使用LUA開發的。結合ModSecurity的思路,[email protected]_lua_waf來開發適合自己用的WAF,[email protected],再此也表示感謝。

0x01 WAF框架設計


WAF開發過程中的主要方向為:

  • 主引擎的開發,主要關注主引擎的效能和容錯能力
  • 規則的開發,主要關注規則的全面可靠,防勿攔截以及防繞過
  • 整體方案能夠適應多站點,高可用性的環境

WAF的主要功能為:

  • ip黑白名單
  • url黑白名單
  • useragent黑白名單
  • referer黑白名單
  • 常見web漏洞防護,如xss,sql注入等
  • cc攻擊防護
  • 掃描器簡單防護
  • 其他你想要的功能

WAF的總體檢測思路:

  • 當使用者訪問到nginx時,waf首先獲取使用者的ip,uri,referer,useragent,,cookie,args,post,method,header資訊。
  • 將獲取到的資訊依次傳給上述功能的函式,如ip規則,在ip規則中,迴圈到所有的ip規則,如果匹配到ip則根據規則的處理方式來進行處理,匹配到之後不繼續匹配後續規則。
  • 需要開啟的功能依次在主函式中呼叫即可,順序也可根據實際場景來確定最合適的順序。

圖示如下:

enter image description here

0x02 規則格式分析


規則說明:

比如規則:{"rule00001","rules","args|post|cookie",[[../]],"deny","logon"},

rule00001:規則編號,隨意寫

rules:規則名稱,如xssrules,隨意寫

args|post|cookie|header:檢測位置,|表示或,args,post,cookie,header可多選

../:匹配的正規表示式,標準PCRE正則

deny:處理方式,可選deny ,allow

logon:日誌記錄與否,可選logon,logoff

0x03 cc攻擊防護程式碼示例


#!bash
--在nginx.conf的HTTP中加入
--lua_shared_dict limit 50m; 根據主機記憶體調合適的值
--lua_shared_dict iplimit 20m;
--lua_shared_dict blockiplimit 5m;
-------------------------------------------------------------
CCDeny="on"   --cc攻擊開關
CCrate="60/60"--基於url的計數 次/秒
ipCCrate="600/60"--基於ip的計數 次/秒
-------------------------------------------------
ccdenyrules={"ccdeny1","ccdeny","","","","logon"}
function gethost()
    host = ngx.var.host
    if host == nil or type(host) ~= "string" then
        math.randomseed(os.time())
        host = "nohost"..math.random()
    end
    return host
end

function denycc(clientdata)
    if CCDeny=="on" then
        local uri=clientdata[2]
        local host = gethost()
        CCcount=tonumber(string.match(CCrate,'(.*)/'))
        CCseconds=tonumber(string.match(CCrate,'/(.*)'))
        ipCCcount=tonumber(string.match(ipCCrate,'(.*)/'))
        ipCCseconds=tonumber(string.match(ipCCrate,'/(.*)'))
        local token = clientdata[1]..host..uri
        local clientip = clientdata[1]..host
        local limit = ngx.shared.limit
        local iplimit = ngx.shared.iplimit
        local blockiplimit = ngx.shared.blockiplimit
        local req,_=limit:get(token)
        local ipreq,_=iplimit:get(clientip)
        local blockipreq,_=blockiplimit:get(clientip)
        if blockipreq or ipreq then
            if blockipreq or req then
                if blockipreq or req >= CCcount or ipreq >= ipCCcount  then
                    log(ccdenyrules,clientdata)
                    blockiplimit:set(clientip,1,300)
                    ngx.exit(403)
                    return true
                else
                    limit:incr(token,1)
                    iplimit:incr(clientip,1)
                end
            else
                limit:set(token,1,CCseconds)
            end
        else
            iplimit:set(clientip,1,ipCCseconds)
        end
    end
    return false
end

0x04 優勢舉例


可以很靈活的實現複雜的控制

比如我在我的個人網站上面就使用了這樣一個功能,後臺頁面需要特定useragent才能訪問。

程式碼如下:

#!bash
--特定頁面容許特定useragent可訪問
function houtai(clientdata)
    if stringmatch(clientdata[2],"wp-admin") then
        if stringmatch(clientdata[4],"hahahaha") then
            return
        else
            ngx.exit(403)
            return
        end
    else
        return
    end
end

可以測試http://www.zhangsan.me/wp-admin/

只有在特定的useragent才可以訪問此頁面,否則報403錯誤。

0x05 原始碼下載及使用


原始碼下載地址為:http://pan.baidu.com/s/18QQya

環境搭建就參考:http://wiki.nginx.org/HttpLuaModule#Installation

waf使用主要就是配置config.lua

SecRuleEngine = "on" attacklog = "on" logpath = "/home/waflog/"

分別為引擎是否開啟 是否記錄日誌 日誌的儲存路徑 日誌的儲存路徑需要給予nginx執行使用者的讀寫許可權

0x06 後續研究方向


  • 1.根據ModSecurity規則提取一份較適應自己用的規則
  • 2.根據最新出現的漏洞維護規則
  • 3.在多個站點的情況下,如果在站點變動,規則變動的時候,不影響其他站點,實現高可用性。

寫的很簡單,大牛勿噴,希望大家多提建議。

0x07 參考資料


1. https://github.com/loveshell/ngx_lua_waf
2. http://wiki.nginx.org/HttpLuaModule
3. http://www.freebuf.com/tools/54221.html
……
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章