如何在Suricata中编写检测下载文件变更的Lua脚本
Suricata Lua文件变更检测实现指导
原代码核心问题修正
你提供的初始代码存在几个不符合Suricata Lua开发规范和Lua语法的问题,需要先调整:
init函数的作用是向Suricata声明当前脚本需要捕获的流量字段,不能作为读取当前传输文件的入参,你原来的read_file(init())调用逻辑完全错误- Lua语法中不等判断符为
~=而非!=,if条件判断结束后必须加end闭合 - Suricata中运行的Lua脚本无法直接通过标准IO接口读取流量中的文件内容,需要调用Suricata内置的流量API获取响应体
- 全量文件内容比对性能极低,建议改为比对文件哈希值降低性能开销
- Suricata调用的Luajit脚本必须实现
match函数,该函数返回true时才会触发规则中定义的动作
可用的实现代码示例
-- 初始化函数:声明需要捕获HTTP响应体 function init(args) return { http.response_body = true } end -- 工具函数:读取本地文件内容 local function read_file(path) local file = io.open(path, "rb") if not file then return nil end local content = file:read("*a") file:close() return content end -- 工具函数:计算内容的MD5哈希 local function calc_md5(content) local md5 = require "md5" return md5.sumhexa(content) end -- 加载基准文件的哈希值(提前计算好基准文件的哈希存到该路径) local baseline_hash = read_file("/etc/suricata/baseline_file.hash") -- 去首尾空格避免换行符干扰 if baseline_hash then baseline_hash = baseline_hash:gsub("%s+", "") end -- 核心匹配函数:Suricata命中规则时会调用该函数 function match(args) -- 无基准哈希时不触发阻断 if not baseline_hash then return false end -- 获取当前HTTP响应的完整body local resp_body = HttpResponseBody.get() if not resp_body then return false end -- 计算当前传输文件的哈希 local current_hash = calc_md5(resp_body) -- 哈希一致说明文件未变更,返回true触发阻断 if current_hash == baseline_hash then return true end -- 哈希不一致说明文件已变更,不阻断 return false end
配套Suricata阻断规则
你提供的规则只需调整脚本名称和描述即可使用,规则中drop动作会在Lua脚本的match函数返回true时触发:
drop http any any -> any any (msg:"未变更文件下载阻断"; flow:established,to_client; luajit:file_check.lua; classtype:policy-violation; sid:1000000; rev:1;)
部署注意事项
- 提前计算基准文件的MD5哈希,写入
/etc/suricata/baseline_file.hash文件,仅保留哈希值不要加其他内容 - 需确认Suricata的配置中开启了HTTP响应体捕获和Luajit支持,大文件场景要开启流重组配置避免响应体不完整
- Lua脚本需放到Suricata配置中指定的Luajit脚本搜索路径下,默认一般为rules目录
- 测试阶段建议先把规则中的
drop改为alert,确认匹配逻辑无误后再改为drop避免误拦截
内容的提问来源于stack exchange,提问作者hamid
相关产品推荐
相关产品推荐

