為Nginx加入一個使用深度學習的軟WAF
一、前言
本文介紹如何向Nginx增加了一個使用Tensorflow C庫的軟WAF模組,模組主體基於Naxsi。
二、獲取資料及訓練資料
這裡,之前有Dalao發表過這樣一篇文章: 基於卷積神經網路的SQL注入檢測 。
這是一個開源的專案,但是由於速度的關係,我不打算使用這篇文章的模型,僅僅採用這篇文章使用的資料集。這樣可以節省很多特徵工程的時間。
資料訓練並不是這篇文章的重點,這裡僅僅說一下訓練結果,這裡為了防止CUDA週期對檢測時間的影響,使用CPU跑推理過程。
如果您對資料的訓練感興趣,可以看我之前寫的一篇文章: 使用CNN做SQL和XSS的識別 。
三、使用Tensorflow C庫做推理
我們的目標是向Nginx加入一個使用Tensorflow C庫的軟WAF模組。如果從頭開始寫一個軟WAF,想必會佔用相當多的時間,並且這個也和這篇文章的主旨偏離。
在Nginx的開源的軟WAF模組中,Naxsi是一個很受歡迎的模組。這個模組使用C作為主開發語言,因此,如果我們想基於這個模組加一個推理過程,很大可能性需要加入Tensorflow C庫。那麼,首先應該做的是,試著使用Tensorflow C庫做單次推理,並做好模組測試。
Main檔案如下:
編譯完成後,可以跑一下資料,這裡為了節省篇幅,僅測試一條
可見這部分程式碼已經可以正常工作了。
四、向Naxsi內加入程式碼
首先,回憶下Nginx的一些原理,Nginx在執行時使用fork,建立了一個master程序和若干worker程序,worker程序是實際處理資料的程序。每個模組的初始化函式,實際上是由初始化的程序來完成的,在這之後,如果配置了daemon,初始化的程序自動退出。
同時,為了便於理解,我們可以把推理流程拆分成這樣幾個部分:
1. 初始化模型 2. 將輸入轉化為Tensorflow識別的格式 3. 執行模型,獲取結果
其中,步驟1僅需執行一次,步驟2,3在每次執行這個模組時都需要進行。
我對於Nginx理解不深,DaLao輕拍。
由於worker程序是fork產生的,實際上是無法使用初始化程序產生的model,所以,每個worker程序需要自己初始化一次自己的model相關資源。因此,新加入的函式應該類似這樣:
這裡,我僅僅檢測uri內部的注入請求,其它部分的檢測程式碼應該是非常相似的,這裡就不再重複羅嗦了。
由於tf_model是在第一次呼叫模組時才會自動載入,因此,在這個伺服器的每個worker程序第一次接受到資料時,可能會稍卡頓一下。
五、編譯執行
將Naxsi和Nginx的程式碼同時複製到編譯伺服器內部,然後在編譯Nginx時,包含下Naxsi的程式碼部分。
由於Nginx在編譯時是不使用Tensorflow庫的,所以我們需要手動修改下Makefile,在連結時自動加入Tensorflow庫,最後編譯。
然後,需要將Naxsi的配置檔案複製到Nginx的conf資料夾內,配置Naxsi,並修改Nginx的配置檔案,加入Naxsi模組。自定義一個403的Page,作為注入發生時的替換介面。然後,執行Nginx。
六、手注測試
這裡使用簡單的手注,測試模組是否正常執行。這裡實際是不可能出現注入的情況的,如果有興趣的話,可以加入DVWA等靶機,使用sqlmap等工具實際攻擊。
七、總結
經過以上幾個步驟,我們就得到了一個使用DL的Nginx的軟WAF模組,並把它加入到了Nginx內。相比普通的規則匹配類的引擎,一般而言,這種方法的防禦效果更加優秀。考慮漏報和誤報率的話,使用測試集測試,可靠性提高了數倍。
當然,推理流程會對伺服器本身的效能造成一定的影響,因此在實際的環境中,可能需要使用Tensorflow C GPU庫來跑運算,或者將Nginx作為代理使用。
*本文作者:rochek,轉載請註明來自FreeBuf.COM