郭卫东 发表于 2024-8-31 18:15:16

Web应用防火墙(WAF)的架构与实现

1. 目标

   为了保护Web服务安全稳定,部署Web应用防火墙(Web Application Firewall, WAF),通过对HTTP(S)请求举行检测,识别并阻断SQL注入、跨站脚本攻击(Cross Site Scripting, XSS)、网页木马上传、命令/代码注入、文件包罗、敏感文件访问、第三方应用毛病攻击、CC(寻衅黑洞)攻击、恶意爬虫扫描、跨站请求伪造等攻击。
   2. 架构

   (架构图)
   3. 实现功能

   

[*]支持IP白名单和黑名单功能,直接将黑名单的IP访问拒绝。
[*]支持URL白名单,将不需要过滤的URL举行界说。
[*]支持User-Agent的过滤,匹配自界说规则中的条目,然后举行处置处罚(返回403)。
[*]支持CC攻击防护,单个URL指定时间的访问次数,超过设定值,直接返回403。
[*]支持Cookie过滤,匹配自界说规则中的条目,然后举行处置处罚(返回403)。
[*]支持URL过滤,匹配自界说规则中的条目,如果用户请求的URL包罗这些,返回403。
[*]支持URL参数过滤,原理同上。
[*]支持日志记录,将所有拒绝的操纵,记录到日志中去。
[*]日志记录为JSON格式,便于日志分析,例如使用ELKStack举行攻击日志网络、存储、搜刮和展示。
   4. 构建WAF的方案

   
[*]开源框架openresty+nginx 实现web应用防火墙(WAF)
   

[*]官网: https://openresty.org/cn/download.html
   
[*]nginx lua lua-nginx-module构建web应用防火墙(WAF)
   

[*] https://github.com/unixhot/waf
   
[*]ModSecurity
   

[*]项目地址: https://github.com/SpiderLabs/ModSecurity
   
[*]HiHTTPS
   

[*]项目地址: https://github.com/qq4108863/hihttps
   
[*]OpenWAF
   

[*]项目地址: https://github.com/titansec/OpenWAF
   
[*]FreeWAF
[*]ESAPI WAF
[*]Java WAF
   

[*]项目地址: https://github.com/chengdedeng/waf
   
[*]Naxsi
   

[*]项目地址: https://github.com/nbs-system/naxsi
   
[*]X-WAF
   

[*]项目地址: https://github.com/xsec-lab/x-waf
   
[*]VeryNginx
   

[*]项目地址: https://github.com/alexazhou/VeryNginx/
   5. 安装openresty

   5.1. 安装依赖

                                 登录后复制                         yum install pcre-devel openssl-devel readline-devel gcc gcc-c++ curl wget -y      

[*]1.
                     5.2. 下载openresty

   下载地址:
   

[*] https://github.com/openresty/openresty/releases
[*] https://openresty.org/download/
                                 登录后复制                         wget https://github.com/openresty/openresty/releases/download/v1.15.8.2/openresty-1.15.8.2.tar.gz      

[*]1.
                     5.3. 解压openresty

                                 登录后复制                         tar -zxvf openresty-1.15.8.2.tar.gz
cd openresty-1.15.8.2      

[*]1.
[*]2.
                     5.4. 编译安装openresty

                                 登录后复制                         ./configure --with-http_stub_status_module --with-http_ssl_module --with-pcre --with-pcre-jit --with-luajit
gmake
gmake install      

[*]1.
[*]2.
[*]3.
                     参数阐明:
   

[*]--with-http_stub_status_module nginx监控模块
[*]--with-http_ssl_module nginx ssl模块
   6. 安装WAF

   6.1. 下载WAF

                                 登录后复制                         git clone https://github.com/unixhot/waf.git
cp -a ./waf/waf/ /usr/local/nginx/conf/      

[*]1.
[*]2.
                     6.2. 设置WAF

                                 登录后复制                         vi /usr/local/nginx/conf/nginx.conf      

[*]1.
                     在nginx.conf的http字段内添加以下内容:
                                 登录后复制                         #WAF
lua_shared_dict limit 50m; #防cc使用字典,大小50M
lua_package_path "/usr/local/nginx/conf/waf/?.lua";
init_by_lua_file "/usr/local/nginx/conf/waf/init.lua";
access_by_lua_file "/usr/local/nginx/conf/waf/access.lua";      

[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
                     根据日志记录位置,创建日志目录:
                                 登录后复制                         mkdir /tmp/waf_logs
chown -R nginx.nginx /tmp/waf_logs      

[*]1.
[*]2.
                     注意:日志目录权限与nginx启动权限相同
   WAF上生产之前,发起不要直接上生产,而是先记录日志,不做任何动作。确定WAF不产生误杀。
                                 登录后复制                         vi /usr/local/nginx/conf/waf/config.lua      

[*]1.
                                                   登录后复制                         config_log_dir = "/tmp/waf_logs" #日志记录地址
--rule setting
config_rule_dir = "/usr/local/nginx/conf/waf/rule-config"      

[*]1.
[*]2.
[*]3.
                     学习access.lua的设置
序次:先检查白名单,通过即不检测;再检查黑名单,不通过即拒绝,检查UA,UA不通过即拒绝;检查cookie;URL检查;URL参数检查,post检查;
   6.3. 启动WAF

                                 登录后复制                         /usr/local/openresty/nginx/sbin/nginx -t
/usr/local/openresty/nginx/sbin/nginx -s reload      

[*]1.
[*]2.
                     6.4. 设置阐明

                                 登录后复制                         --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秒内只能--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"> 您的行为已违背本网站相干规定,注意操纵规范。</h1></body> </html>      

[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
[*]15.
[*]16.
[*]17.
[*]18.
[*]19.
[*]20.
[*]21.
[*]22.
[*]23.
[*]24.
[*]25.
[*]26.
[*]27.
[*]28.
[*]29.
[*]30.
[*]31.
[*]32.
[*]33.
[*]34.
[*]35.
[*]36.
[*]37.
[*]38.
[*]39.
[*]40.
[*]41.
[*]42.
[*]43.
                     7. 安装包

   

[*]Luajit: http://luajit.org/
[*]Nginx: http://nginx.org/download/
[*]ngx_devel_kit: https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
[*]lua-nginx-module: https://github.com/openresty/lua-nginx-module/releases
   8. 安装依赖

                                 登录后复制                         yum install -y readline-devel pcre-devel openssl-devel gcc gcc-c++ lua-devel wget      

[*]1.
                     9. 解压NDK和lua-nginx-module

                                 登录后复制                         tar zxvf lua-nginx-module-0.10.10.tar.gz
tar zxvf ngx_devel_kit-0.3.0.tar.gz      

[*]1.
[*]2.
                     10. 安装LuaJIT

   10.1. 下载LuaJIT

                                 登录后复制                         git clone https://github.com/openresty/luajit2      

[*]1.
                     10.2. 编译并安装LuaJIT

                                 登录后复制                         make
make install      

[*]1.
[*]2.
                     10.3. 设置环境变量

                                 登录后复制                         cat >/etc/profile.d/luajit.sh<<EOF
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.1
EOF      

[*]1.
[*]2.
[*]3.
[*]4.
                     10.4. 加载环境变量

                                 登录后复制                         source /etc/profile      

[*]1.
                     11. 安装lua-cjson

   11.1. 下载lua-cjson

    https://www.kyne.com.au/~mark/software/download/lua-cjson-2.1.0.tar.gz
   11.2. 解压

                                 登录后复制                         tar zxvf lua-cjson-2.1.0.tar.gz
cd lua-cjson-2.1.0      

[*]1.
[*]2.
                     11.3. 设置lua-cjson

                                 登录后复制                         find / -name lua.h      

[*]1.
                     选择其中一个修改Makefile文件
                                 登录后复制                         ##### Build defaults #####
LUA_VERSION =       5.1
TARGET =            cjson.so
PREFIX =            /usr/local
#CFLAGS =            -g -Wall -pedantic -fno-inline
CFLAGS =            -O3 -Wall -pedantic -DNDEBUG
CJSON_CFLAGS =      -fpic
CJSON_LDFLAGS =   -shared
LUA_INCLUDE_DIR =   /root/luajit2/src
LUA_CMODULE_DIR =   $(PREFIX)/lib/lua/$(LUA_VERSION)
LUA_MODULE_DIR =    $(PREFIX)/share/lua/$(LUA_VERSION)
LUA_BIN_DIR =       $(PREFIX)/bin      

[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
                     11.4. 安装lua-cjson

                                 登录后复制                         make && make install      

[*]1.
                     报luaL_setfuncs错解决:
                                 登录后复制                         vi lua_cjson.c      

[*]1.
                     将static去掉static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)
                                 登录后复制                         make && make install      

[*]1.
                     12. 重新编译nginx

   12.1. 升级或新安装

   使用新版本升级
                                 登录后复制                         wget http://nginx.org/download/nginx-1.16.1.tar.gz
tar zxvf nginx-1.16.1.tar.gz
cd nginx-1.16.1      

[*]1.
[*]2.
[*]3.
                     12.2. 编译nginx

                                 登录后复制                         ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx--with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_gzip_static_module --add-module=../ngx_devel_kit-0.3.0/ --add-module=../lua-nginx-module-0.10.15/      

[*]1.
                     编译完成了,执行make,记住,这里不要执行make install,不然会把以前安装的会覆盖的
                                 登录后复制                         make      

[*]1.
                     参数阐明:
   

[*]--with-http_stub_status_module nginx监控模块
[*]--with-http_ssl_module nginx ssl模块
[*]--ngx_http_sub_module模块是一个过滤器,通过将一个指定的字符串更换为另一个字符串来修改相应
[*]--with-http_gzip_static_module 启动预压缩功能
   12.3. 创建毗连

                                 登录后复制                         ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2      

[*]1.
                     12.4. 验证nginx

   编译完成后,会新生成一个nginx执行文件,在nginx-1.16.1/objs目录下,测试一下对应的依赖有没有装上
                                 登录后复制                         cd nginx-1.16.1/objs
./nginx -V      

[*]1.
[*]2.
                     12.5. 备份nginx

   复制nginx命令覆盖以前的nginx
复制前,最好把之前的nginx备份一下,以防不测
                                 登录后复制                         cd /usr/local/nginx/sbin/
cp nginx nginx.old      

[*]1.
[*]2.
                     12.6. 覆盖nginx

   新的覆盖,覆盖之前,最好停掉nginx
                                 登录后复制                         cd nginx-1.16.1/
cp objs/nginx /usr/local/nginx/sbin/      

[*]1.
[*]2.
                     修改nginx设置在http块下设置
                                 登录后复制                         lua_load_resty_core off;      

[*]1.
                     12.7. 测试nginx

   先测试nginx有没有被玩坏,先检查一下
                                 登录后复制                         cd /usr/local/nginx
./sbin/nginx -t
./sbin/nginx      

[*]1.
[*]2.
[*]3.
                     接下来部署WAF方法和上面一样
   13. 测试WAF功能

   13.1. 模拟sql注入即url攻击

                                 登录后复制                         http://10.8.17.32/abc.sql      

[*]1.
                                                   登录后复制                         # cat /tmp/waf_logs/2019-12-20_waf.log      

[*]1.
                     日志表现如下,记录了
                                 登录后复制                         {"user_agent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/71.0.3573.0 Safari\/537.36","rule_tag":"\\.(bak|inc|old|mdb|sql|backup|java|class|tgz|gz|tar|zip)$","req_url":"\/abc.sql","client_ip":"10.8.80.104","local_time":"2019-12-20 14:37:29","attack_method":"Deny_URL","req_data":"-","server_name":"localhost"}      

[*]1.
                     日志记录了UA、匹配规则、请求URL、客户端IP、当地时间、攻击方法、请求数据和服务器名称。
   13.2. 使用ab压测工具模拟防cc攻击

                                 登录后复制                         yum -y install httpd-tools
ab -n 1000 -c 500 http://10.8.17.32/      

[*]1.
[*]2.
                     13.3. 模拟ip黑名单

   将请求ip放入ip黑名单中
                                 登录后复制                         echo "10.8.17.32" >>/usr/local/nginx/conf/waf/rule-config/blackip.rule      

[*]1.
                     13.4. 模拟ip白名单

   将请求ip放入ip白名单中,此时将不对此ip举行任何防护措施,所以sql注入时应该返回404
                                 登录后复制                         echo "10.8.17.32" >> /usr/local/nginx/conf/waf/rule-config/whiteip.rule      

[*]1.
                     13.5. 模拟URL参数检测

   浏览器输入http://10.8.17.32/?id=select * from name where name="jack"
   具体规定在arg.rule中有规定,对请求举行了规范
   14. 防cc攻击利器之httpgrard

   14.1. httpgrard介绍

   HttpGuard是基于openresty,以lua脚本语言开发的防cc攻击软件。而openresty是集成了高性能web服务器Nginx,以及一系列的Nginx模块,这其中最紧张的,也是我们主要用到的nginx lua模块。HttpGuard基于nginx lua开发,继续了nginx高并发,高性能的特点,可以以非常小的性能消耗来防范大规模的cc攻击。
   14.2. httpgrard防cc殊效

   

[*]限制访客在肯定时间内的请求次数
[*]向访客发送302转向相应头来识别恶意用户,并克制其再次访问
[*]向访客发送带有跳转功能的js代码来识别恶意用户,并克制其再次访问
[*]向访客发送cookie来识别恶意用户,并克制其再次访问
[*]支持向访客发送带有验证码的页面,来进一步识别,以免误伤
[*]支持直接断开恶意访客的毗连
[*]支持结合iptables来克制恶意访客再次毗连
[*]支持白名单功能
[*]支持根据统计特定端口的毗连数来自动开启或关闭防cc模式
   详见github地址 https://github.com/centos-bz/HttpGuard
   15. WAF上线

   初期上线只记录日志,不开启WAF,防止误杀。
WAF规则管理使用saltstack工具。
要知道并不是有了WAF就安全,安全在很大一部分是人为因素。
   16. FAQ

   16.1. FAQ1

   运行报错:
                                 登录后复制                         nginx: lua_load_resty_core failed to load the resty.core module from https://github.com/openresty/lua-resty-core; ensure you are using an OpenResty release from https://openresty.org/en/download.html (rc: 2, reason: module 'resty.core' not found:
no field package.preload['resty.core']
no file '../lua-resty-core/lib/resty/core.lua'
no file '../lua-resty-lrucache/lib/resty/core.lua'
no file './resty/core.lua'
no file '/usr/local/share/luajit-2.1.0-beta3/resty/core.lua'
no file '/usr/local/share/lua/5.1/resty/core.lua'
no file '/usr/local/share/lua/5.1/resty/core/init.lua'
no file './resty/core.so'
no file '/usr/local/lib/lua/5.1/resty/core.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
no file './resty.so'
no file '/usr/local/lib/lua/5.1/resty.so'
no file '/usr/local/lib/lua/5.1/loadall.so')      

[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
                     一旦使用了lua-nginx-module就表现使用了openresty,这个resty.core是openresty的核心模块,对其下的许多函数举行了优化等。之前的一些版本默认是不编译进去的,所以需要你手动安装
   下面是解决该问题的完整步骤:
   
[*]下载lua-resty-core
                                 登录后复制                         git clone https://github.com/openresty/lua-resty-core.git      

[*]1.
                     
[*]进入lua-resty-core目录
                                 登录后复制                         cd lua-resty-core      

[*]1.
                     
[*]使用luajit编译
                                 登录后复制                         export LUAJIT_LIB=/path/to/luajit/lib
export LUAJIT_INC=/path/to/luajit/include/luajit-2.1
make install      

[*]1.
[*]2.
[*]3.
                     注意将/path/to/luajit/lib和/path/to/luajit/include/luajit-2.1更换为现实的luajit库和头文件路径。
   
[*]编辑nginx.conf,在http块中添加
                                 登录后复制                         lua_package_path "/path/to/lua-resty-core/lib/?.lua;;";
lua_package_cpath "/path/to/lua-resty-core/lib/?.lua;;";      

[*]1.
[*]2.
                     将/path/to/lua-resty-core/lib/更换为现实的lua-resty-core安装路径。
   
[*]重新加载nginx设置
                                 登录后复制                         nginx -s reload      

[*]1.
                     这样应该就可以解决lua_load_resty_core失败的问题了。如果还是不行,可以检查一下luajit的路径是否正确,lua-resty-core是否安装成功等。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Web应用防火墙(WAF)的架构与实现