为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