重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
ELK分析ngx_lua_waf软件防火墙日志
创新互联公司2013年成立,先为龙华等服务建站,龙华等地企业,进行企业商务咨询服务。为龙华企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
ngx_lua_waf介绍及部署可以参考
https://github.com/loveshell/ngx_lua_waf
这个一个基于lua-nginx-module的web应用防火墙,作者是张会源(ID : kindle),微博:@神奇的魔法师。
用途:
防止sql注入,本地包含,部分溢出,fuzzing测试,xss,×××F等web***
防止svn/备份之类文件泄漏
防止ApacheBench之类压力测试工具的***
屏蔽常见的扫描***工具,扫描器
屏蔽异常的网络请求
屏蔽图片附件类目录php执行权限
防止webshell上传
总结:
1,Nginx_lua_waf总体来说功能强大,相比其他软件防火墙Modsecurity还稍微简单点。
2,Ngx_lua_waf的bug主要就是防火墙策略写的不严谨导致的,会造成两种结果:一是部分***通过伪装绕过防火墙;二是防火墙策略配置不当会造成误杀。
3,另外根据站点的类型需要配置不同的策略,默认配置后全局生效。比如论坛等比较特殊允许很多html插入,这样的策略需要更宽松。
4,最后生成的hack记录日志可以通过ELK分析,ELK这边需要根据日志格式制作特殊模版,此模版能兼容大部分日志类型,还有少部分完全没有规律的日志分析不了。
5,最后ELK能展示日志分析结果分类,但是还不能区分各种ruletag类型***属于哪一种直白的表示出来。
6,最后建议ngx_lua_waf如果真的要用可以考虑在部分源站站点少量试用,前端站点不建议使用,等对该软件理解深入后才可线上使用。
7,补充:目前对ngx_lua_waf拒绝特定的user agent、拒绝特定后缀文件访问、防止sql注入三大类比较熟悉。
后续计划:
有人(此人人称赵班长项目地址 https://github.com/unixhot/waf) 对ngx_lua_waf进行了二次重构,主要功能有:黑白名单、只记录***日志不限制访问(日志格式可能更友好点待观察)、另外使用openresty部署的,后期计划使用二次重构的waf再次测试下。
计划大概实施步骤:
1,不要一次性部署上线,先部署后,只记录日志,然后观察和调整规则,保证正常的请求不会被误防。
2,使用SaltStack管理规则库的更新。
3,使用ELKStack进行日志收集和分析,非常方便的可以在Kibana上做出一个漂亮的***统计的饼图。(目前也能实现)
以下是具体操作过程中需要注意的问题点
一,ELK新增针对nginx_lua_waf日志切分策略
1,日志格式
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n"
2,日志内容
192.168.200.106 [2016-07-26 16:56:17] "UA i.maicar.com/AuthenService/Frame/login.aspx?ra=0.5440098259132355" "-" "Baidu-YunGuanCe-ScanBot(ce.baidu.com)" "(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/)"
3,logstash 切分策略
最关键的还是grok正则表达式的书写,这里给两个建议:
1)一是参考系统自带的 /opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.5/patterns/
该目录下有系统自带的很多日志格式的grok正则切分语法,如:
aws bro firewalls haproxy junos mcollective MongoDB postgresql redis bacula exim grok-patterns java linux-syslog mcollective-patterns nagios rails ruby
默认没有规律的参考grok-patterns
2)二是网上有两个grok语法验证网站(都得×××)
http://grokdebug.herokuapp.com/
http://grokconstructor.appspot.com/do/match#result
也可以手动验证,举例如下
[root@elk logstash]# /opt/logstash/bin/logstash -f /etc/logstash/test1.conf Settings: Default pipeline workers: 4 Pipeline main started 192.168.200.106 [2016-07-26 16:56:17] "UA i.maicar.com/AuthenService/Frame/login.aspx?ra=0.5440098259132355" "-" "Baidu-YunGuanCe-ScanBot(ce.baidu.com)" "(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/)" { "message" => "192.168.200.106 [2016-07-26 16:56:17] \"UA i.maicar.com/AuthenService/Frame/login.aspx?ra=0.5440098259132355\" \"-\" \"Baidu-YunGuanCe-ScanBot(ce.baidu.com)\" \"(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/)\"", "@version" => "1", "@timestamp" => "2016-07-28T10:05:43.763Z", "host" => "0.0.0.0", "realip" => "192.168.200.106", "time" => "2016-07-26 16:56:17", "method" => "UA", "servername" => "i.maicar.com", "url" => "/AuthenService/Frame/login.aspx?ra=0.5440098259132355", "data" => "-", "useragent" => "Baidu-YunGuanCe-ScanBot(ce.baidu.com)", "ruletag" => "(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/)" }
其中test1.conf内容如下:
input{stdin{}} filter { grok { match => { "message" =>"%{IPV4:realip}\s+\[%{TIMESTAMP_ISO8601:time}\]\s+\"%{WORD:method}\s+%{HOSTNAME:servername}(?[^\"]+)\"\s+\"(?[^\"]+)\"\s+\"(? [^\"]+)\"\s+\"(? [^\"]+)\"" } } } output{stdout{codec=>rubydebug}}
最后线上切分策略如下:
filter { if [type] == "waf194" { grok { match => [ "message" , "%{IPV4:realip}\s+\[%{TIMESTAMP_ISO8601:time}\]\s+\"%{WORD:method}\s+%{HOSTNAME:servername}(?[^\"]+)\"\s+\"(?[^\"]+)\"\s+\"(? [^\"]+)\"\s+\"(? [^\"]+)\"" ] remove_field => [ "message" ] } } }
二,ELK新增针对nginx_lua_waf日志的索引模版
其中最关键问题是多个索引模版共存的问题,以前总是后加索引模版会覆盖原来的,参考http://mojijs.com/2015/08/204352/index.html 设置tempalte_name来区分不同的索引模版。
输出模版配置如下:
output { elasticsearch { hosts => ["192.168.88.187:9200","192.168.88.188:9200","192.168.88.189:9200"] sniffing => false manage_template => true template => "/opt/logstash/templates/logstashwaf.json" template_overwrite => true template_name => "logstashwaf.json" index => "logstash-%{type}-%{+YYYY.MM.dd}" document_type => "%{[@metadata][type]}" flush_size => 10000 } }
具体logstashwaf.json配置如下,这个是直接参考官方的elasticsearch-logstash.json,就修改了template名字,配置里面只要是string类型的都做了不分词,因为做视图时不分词一来可以节省内存,二来向url,agent,ruletag等等长stings只有不分词才能精确匹配,那种分词的模糊匹配用不上。另外如果只要某些string字段添加不分词,也可以修改"match" : "*",为具体的字段,如:
"match_pattern": "regex", #此行为新增加 "match" : "(realip)|(mothod)(servername)|(url)|(data)|(useragent)|(ruletag)",
线上总体配置如下:
{ "template" : "logstash-waf194*", "settings" : { "index.refresh_interval" : "5s" }, "mappings" : { "_default_" : { "_all" : {"enabled" : true, "omit_norms" : true}, "dynamic_templates" : [ { "message_field" : { "match" : "message", "match_mapping_type" : "string", "mapping" : { "type" : "string", "index" : "analyzed", "omit_norms" : true } } }, { "string_fields" : { "match" : "*", "match_mapping_type" : "string", "mapping" : { "type" : "string", "index" : "analyzed", "omit_norms" : true, "fields" : { "raw" : {"type": "string", "index" : "not_analyzed", "ignore_above" : 256} } } } } ], "properties" : { "@version": { "type": "string", "index": "not_analyzed" }, "geoip" : { "type" : "object", "dynamic": true, "properties" : { "location" : { "type" : "geo_point" } } } } } } }
三,Ngx_lua_waf生成的hack日志ELK上展示如下
其中制作视图制作模版等都省略
分析小部分日志结果如下: