相关文章推荐
逼格高的路灯  ·  解决使用Java ...·  2 周前    · 
没读研的日记本  ·  java ...·  2 周前    · 
开朗的茄子  ·  Azure Database for ...·  2 周前    · 
玉树临风的水桶  ·  GUNSHIP ...·  3 周前    · 
知识大陆

官方公众号 企业安全 新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

打造基于Nginx的敏感信息泄露检测系统
2018-08-10 10:00:12

*本文原创作者:f4ckbaidu,本文属FreeBuf原创奖励计划,未经许可禁止转载

0、环境说明:

注意:本文所有的代码都放在/data/code下面

如路径变化则需要修改test.conf中标红的路径参数:

操作系统:CentOS 7 Minimal

OpenResty版本:1.13.6.2( https://openresty.org/cn/download.html

Splunk Free: https://download.splunk.com/products/splunk/releases/7.1.2/linux/splunk-7.1.2-a0c72a66db66-linux-2.6-x86_64.rpm

1、需求说明

在甲方的小伙伴一定会碰到这样的问题:

日了狗的开发总是不把应用/数据库的详细错误信息隐藏,妈蛋要是哪天出个error-based sqli岂不是倒霉了?如何主动检测敏感信息泄露然后拿去使劲怼开发呢?

答案当然是用春哥的神器OpenResty(继承了Nginx、Nginx lua等一堆模块的合体)

2、具体实现

Nginx Lua模块执行阶段如下图:

image.png

我们这次要实现的是服务器响应体敏感信息的记录,只需要用到body_filter(响应体处理)和log(日志记录)两个阶段处理,流程如下:

body_filter阶段匹配resp_body-->通过ngx.ctx跨阶段传日志到log阶段-->log阶段向Splunk发送日志-->Splunk统计、告警、分析

body_filter阶段代码如下:(body_filter.lua)

local resp_body = ngx.arg[1] --获取响应体
local eof = ngx.arg[2]
local ctx_log = {} --日志table
local regex = [[You have an error in your SQL syntax]] --匹配的敏感内容
local m = ngx.re.match(resp_body, regex, 'jio') --对响应体做正则匹配
if m then --如果匹配到敏感信息
	ctx_log.rule_match = m[0] --将匹配内容写入日志
	ctx_log.Request_line = ngx.var.request --记录请求URL,包括GET参数
	ctx_log.Request_headers = ngx.req.get_headers() --记录请求头部
	ngx.ctx.log = ctx_log --日志赋值给跨阶段的ngx.ctx.log
end

log阶段代码如下:(log.lua)

local logger = require "socket" --加载logger socket库
local cjson = require "cjson.safe" --加载cjson库
if not logger.initted() then --初始化logger
	local ok,err = logger.init{
			host = "127.0.0.1", --splunk IP
			port = 8888,		--splunk端口
			sock_type = "tcp",	--日志socket类型
			flush_limit = 1,
	if not ok then --初始化失败处理
		ngx.log(ngx.ERR,"failed to initialize the logger: ",err)
		return
local log = ngx.ctx.log --接收ngx.ctx.log跨阶段传过来的日志信息
if type(log) == "table" then --判断日志不为空则记录
	local bytes, err = logger.log(cjson.encode(log) .. "\r\n")
	if err then
		ngx.log(ngx.ERR, "failed to log message: ", err)	
end

然后在nginx的http级别include test.conf即可,test.conf内容如下:

lua_package_path '/data/code/?.lua;;';
body_filter_by_lua_file /data/code/body_filter.lua;
log_by_lua_file /data/code/log.lua;
lua_code_cache on;

image.png

我这里使用dvwa的sqli部分做实验,用来记录服务器返回的MySQL错误信息:

我这里的测试架构是:nginx(反向代理)-->httpd + php(dvwa)

输入单引号让服务器报MySQL错误

image.png

image.png

然后就能在splunk里看到日志了:

如下图所示,可以看到日志记录了客户端的请求头部(Request_headers、Request_line)以及服务器的相应体匹配数据(rule_match)

PS:如果要记录用户的POST请求体则会变得更复杂,需要在access阶段做处理,后面的文章里再说

image.png

Splunk需要注意的地方:

需要编辑props.conf以免在日志过多的时候Splunk自动把多行Json格式日志合并

vim /opt/splunk/etc/system/local/props.conf

加入以下内容:

[_json]  #这个是sourcetype
SHOULD_LINEMERGE = false  #告诉Splunk不自动合并行

3、参考:

春哥的nginx lua模块:

https://github.com/openresty/lua-nginx-module

OpenResty logger socket模块:

https://github.com/cloudflare/lua-resty-logger-socket

OpenResty最佳实践:

https://moonbingbing.gitbooks.io/openresty-best-practices/lua/main.html

*本文原创作者:f4ckbaidu,本文属FreeBuf原创奖励计划,未经许可禁止转载

本文作者:, 转载请注明来自 FreeBuf.COM

# nginx # 信息泄露 # 检测
被以下专辑收录,发现更多精彩内容 + 收入我的专辑 + 加入我的收藏 评论 按热度排序

登录 / 注册 后在FreeBuf发布内容哦

  • 0 文章数
  • 0 评论数
  • 0 关注者
登录 / 注册 后在FreeBuf发布内容哦