碳基体

奋斗在产品安全第一线的安全妹子

ModSecurity 晋级-如何调用lua脚本进行防御快速入门(补充:开启IP-GEO封禁)

我是ModSecurity死忠,也是lua死忠,所以写这篇文章的时候超级高兴,瞬间变成了购物频道的促销员,脑袋里回响着“不是9999,也不是999,只要99,你就拥有”,ModSecurity的扩展脚本非常好写,我是个冒牌程序员都能搞定。


下面写个简单的实例

功能:判断HTTP请求GET参数中是否包含<script关键字,如果包含则进行跳转处理(当然啦,xss的拦截远远没有这么简单)


一、Lua脚本

先编写Lua脚本  /root/lua_script_modsecurity/xss_detect.lua

vim xss_detect.lua

local string_find = string.find
local m_getvars = m.getvars
local m_log = m.log
function main()
   --Retrieve all parameters
   local get_vars = m_getvars("ARGS_GET",{"lowercase","htmlEntityDecode"});

   --Examine all variables
   for _,v in pairs(get_vars) do
        if(string_find(v.value,"<script")) then
           --log something
           m_log(4,"Just a TEST, I'm hungry, but it is 4:33 p.m ")
           return("Suspected XSS in variable: " .. v.name .. ".")
        end
   end

   -- Nothing wrong found.
   return nil
end


关键函数解释:

m.getvars 获得ModSecurity变量,第一个参数是变量名,第二个参数是事件函数(transform function)

返回变量是lua table(类似perl的hash数据类型)的数据类型,索引name表示变量名(本例对应的是get参数的名字),索引value表示变量对应的值(本例对应的是get参数的取值)


m.log 该函数的作用是调试使用,需要开启如下ModSecurity配置


其他lua接口函数补充:

m.getvar 作用同m.getvars,但返回的变量类型不是table

e.g.  local RequestMethod = m.getvar("REQUEST_METHOD", {"none"})


m.setvar 作用等同ModSecurity setvar action

e.g. m.setvar("TX.MAX_NUM_ARGS_VIOLATION", "1")


vim /etc/modsecurity/modsecurity.conf

SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 4

m.log的输出会存放在/var/log/apache2/modsec_debug.log下,记得SecDebugLogLevel开启4及4以上就能看到调试内容

附:Log级别说明

0:无记录
1:错误
2:警告
3:注意事项
4:如何交易的细节处理

5:同上,但包括约每一条信息处理的信息
6:记录所有


上面xss_detect.lua脚本的意思就是,检测HTTP GET参数的值,如果包含了<script关键字则进行相应的处理,处理部分定义在规则文件中,如下所示


二、规则

vim /usr/share/modsecurity-crs/activated_rules/MY.conf

SecRuleScript /home/tanjiti/lua_script_modsecurity/xss_detect.lua " deny,msg:'suspected xss detect',id:1000001,phase:2,prepend:'suspected xss found. <script>window.location=\"/\";</script>'"

请自行替换脚本存放路径

该规则的意思是调用xss_detect脚本,如果命中,则以403拦截,并在拦截页面中提示“suspected xss found", 同时重定向到网站首页


注意: 要开启prepend动作,需要开启内容注入指令

vim /etc/modsecurity/modsecurity.conf

#enable prepend append action
SecContentInjection On

service apache2 reload


三、测试

添加规则后,重新加载配置文件

service apache2 reload


发送带攻击的HTTP请求

./HTTP.pl -url 'http://localhost:8080/xss.php?name=<script>alert(1);</script>'

发包工具有很多,curl,wget

HTTP.pl——通过HTTP发包工具了解HTTP协议

HTTP发包工具 -HTTPie

   

我们察看modsecurity审计日志

vim /var/log/apache2/modsec_audit.log

 黄线部分 就是lua脚本if逻辑中的return语句


我们察看modsecurity debug日志

vim /var/log/apache2/modsec_debug.log

 黄线部分 就是lua脚本if逻辑中的m.log输出语句

 

四、Lua脚本调试

在学习ModSecurity的Lua编程接口的时候,最好把相关的变量都打印出来另存到指定文件 

调试Lua脚本 /root/lua_script_modsecurity/log2File.lua  

添加的ModSecurity规则

SecRuleScript /root/lua_script_modsecurity/log2File.lua 


日志打印样例

more /tmp/modsec_wafLog.log (默认路径)


样例1: 普通的GET请求

 

样例2:文件上传请求

http localhost/a/b/xss.php file1@HTTP.pl file2@HTTPFromFile.pl submit=submit get_a="<sc" get_b="im>" -f -v

(附:HTTP的使用见  HTTP发包工具 -HTTPie

发送如下请求包

   日志记录如下: 

 


补充Modsecurity案例:按IP地址进行封禁

第一步:开启Geo查找功能

vim /usr/share/modsecurity-crs/modsecurity_crs_10_setup.conf 

增加(或者去掉原本注释)

SecGeoLookupDb /usr/share/GeoIP/GeoLiteCity.dat

GeoIP库的安装见使用免费的本地IP地理库来定位IP地理位置-GeoIP lookup


第二步:添加ModSecurity规则,按IP归属地国家的白名单进行封禁操作

vim /usr/share/modsecurity-crs/activated_rules/MY.conf 

SecRule REMOTE_ADDR "@geoLookup" "chain,id:0000006,phase:1,drop,msg:'Non-allowed IP address'"
SecRule &GEO "ge 0" "chain"
SecRule GEO:COUNTRY_CODE "!@pm US CN JP"



补充阅读

[科普文]ubuntu上安装Apache2+ModSecurity及自定义WAF规则

ModSecurity SecRule cheatsheets

ModSecurity CRS 笔记、WAF防御checklist,及WAF架构的一些想法

来源:碳基体

评论