lua与nginx强强联合-openresty

openresty=nginx+lua_nginx_module+lualib的组合

lua_nginx_module学习性价比极高,非常值得花10分钟学习。

一、简单安装及第一个例子

yum install readline-devel pcre-devel openssl-devel gcc
https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz
tar -zxvf ngx_openresty-1.9.7.1.tar.gz
cd ngx_openresty-1.9.7.1
./configure && gmake && gmake install

未指定prefix将安装到/usr/local/openresty目录中,进入安装目录看到“bin, luajit, lualib, nginx”四个目录。

编辑nginx/conf/nginx.conf 插入location 

location /ip {
                default_type 'text/plain';
                content_by_lua 'ngx.say(ngx.var.remote_addr)';
 }

访问 http://hostname/ip   页面返回访问用户ip

二、编译安装及库引用

openresty是官方提供的集成包,有时候我们希望自己编译安装(附自动安装脚本,最好自己更新版本号)

#!/bin/bash 
yum -y install gcc wget unzip openssl openssl-devel pcre pcre-devel bc
tools_path=/usr/local/lua_nginx
mkdir -p $tools_path
install_path=/usr/local

# 软件包
wget -P $tools_path http://luajit.org/download/LuaJIT-2.0.4.tar.gz
wget -P $tools_path https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz
wget -P $tools_path https://github.com/openresty/lua-nginx-module/archive/v0.9.17.tar.gz
wget -P $tools_path http://nginx.org/download/nginx-1.4.7.tar.gz
wget -P $tools_path http://waf.sec.uuzu.com/setup/waf-nginx-conf.zip

# 安装
tar -zxf $tools_path/LuaJIT-2.0.4.tar.gz -C $tools_path
tar -zxf $tools_path/v0.2.19.tar.gz -C $tools_path
tar -zxf $tools_path/v0.9.17.tar.gz -C $tools_path
tar -zxf $tools_path/nginx-1.4.7.tar.gz -C $tools_path

cd $tools_path/LuaJIT-2.0.4/ && make && make install
cd $tools_path/nginx-1.4.7/ && ./configure –prefix=$install_path/nginx –user=nobody –group=nobody –add-module=$tools_path/ngx_devel_kit-0.2.19 –add-module=$tools_path/lua-nginx-module-0.9.17 –with-http_ssl_module –with-http_stub_status_module –with-http_gzip_static_module –with-ipv6 –with-ld-opt="-Wl,-rpath,$LUAJIT_LIB" && make && make install

# 配置
ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0
#end

同样将上一段配置添加到nginx.conf中,一样可以成功返回访问用户ip。

lualib库引用(以redis库举例)

下载ngx_redis (lua文件),放到任意目录,在nginx.conf配置文件http标签内增加 

lua_package_path "/usr/local/nginx/conf/lualib/?.lua;;";

    location /total {
        default_type text/plain;
        content_by_lua '
            ngx.header.content_type="application/json;charset=utf8"

            local redis = require "resty.redis"
            local red = redis:new()

            red:set_timeout(1000) — 1 sec
            local ok,err = red:connect("127.0.0.1", 2002)
            if not ok then
                ngx.say("failed to connect:", err)
            end

            local total, err = red:get("total")
            if not total then
                ngx.say("failed to found", err)
            end
            ngx.say("今日已投票:", total)';
    }

ps:可使用content_by_lua_block替换单引号的方式来避免lua代码中的特殊符号的转译问题,init(rewrite|access)_by_lua_block同理,xxx_block的方式0.9.17 版才添加进来,注意版本号。

三、一些参考

https://github.com/openresty/lua-nginx-module  官方权威,文档超级详细

https://openresty.org/  同样官方权威

http://groups.google.com/group/openresty   邮件列表,提问可召唤春哥

https://moonbingbing.gitbooks.io/openresty-best-practices/content/index.html   介绍详细的中文教程

 

post类型sql注入漏洞扫描

一、背景

SQL注入漏洞是常见web漏的中危害最大的,是危害大的漏洞中最常见的。

幸运的是主流扫描器对SQL注入漏洞扫描识别准确率非常理想

缺陷是对post请求、有用户验权(是否登录)的请求通常无能为力。

二、解决方案

一句话说明:nginx搭建代理服务器,记录代理日志,web通过代理访问,根据日志扫描。

详细说明:

1.nginx代理服务器搭建

新建server 监听9999

server {
listen 9999;
resolver 8.8.8.8 233.5.5.5;

location ~.*\.(jpg|png|jpeg|gif|js|css)$ {
proxy_pass http://$http_host$request_uri;
}

location / {
proxy_pass http://$http_host$request_uri;
}
}

本地浏览器使用代理,访问网站,保证代理可用。

2.记录请求日志

在 “location /”中记录日志 ,这里我用lua处理(nginx与lua集成见百度)

location / {
		access_by_lua '
			
			function conv2str (o)
				local rs = ""
				if type(o) == "string" then
					rs = o
				elseif type(o) == "nil" then
					rs = "nil"
				elseif type(o) == "number" then
					rs = tostring(o)
				elseif type(o) == "boolean" then
					rs = tostring(o)
				elseif type(o) == "table" then
					for k,v in pairs(o) do
						if type(v)=="string" then
							rs = rs..k.."="..v.."&"
						else
							rs = rs..k.."="..conv2str(v).."&"
						end
					end
					if string.find(rs, "&", string.len(rs)-1) ~= nil then
						rs = string.sub(rs, 0, string.len(rs)-1)
					end
				else
					error("cannot serialize a " .. type(o))
				end
				return rs
			end

			function write(logfile, msg)
				local fd = io.open(logfile,"ab")
				if fd == nil then return end
				fd:write(msg)
				fd:flush()
				fd:close()
			end
			
			function logall()
				local remote=ngx.var.remote_addr or "-"
				local host=ngx.var.host or "-"
				local nowtime=ngx.var.time_local or "-"
				local reqMethod=ngx.req.get_method() or "-"
				local reqUri=string.gsub(ngx.var.request_uri, "?.*", "") or "-"
				local args=""
				local post=""
				local headers=ngx.req.get_headers()
				local cookies=conv2str(headers["Cookie"])
				local header=conv2str(headers)
				local line=""
				args=conv2str(ngx.req.get_uri_args())
				if string.len(args) > 0 then
					line="sqlmap.py -u \\"http://"..host..reqUri.."?"..args.."\\""
				else
					line="sqlmap.py -u \\"http://"..host..reqUri.."\\""
				end
				if reqMethod=="POST" then
					local postlength=tonumber(ngx.var.content_length)
					if postlength then
						if postlength < 10485760 then
						   	post=conv2str(ngx.req.get_post_args())
							line=line.." --data \\""..post.."\\""
						end
					end
				end
				
				if cookies~="nil" then 
					line=line.." --cookie \\""..cookies.."\\""
				end
				--line=remote.." - - ".."["..nowtime.."]".." - - "..reqMethod.." - - "..reqUri.." - - host:"..host.." - - [args]:"..args.." [post]:"..post.." [header]:"..header.."\\n"
				
				local filename = "/tmp/proxy.log"
				write(filename,line.."\\n") 
			end
			
			logall()
		';
		proxy_pass http://$http_host$request_uri;
	}

reload nginx 测试,检查/tmp/proxy.log下输出是否正常

不出意外的话,proxy.log 中将打印处理好的sqlmap扫描命令(出了意外百度解决)

3.设置扫描

新建sqlant_job.sh

#!/bin/bash
# auth:zhanghang.org#gmail.com
today=`date +%Y%m%d`
proj_dir="/opt/sqlant"
mkdir -p $proj_dir
mv /tmp/proxy.log $proj_dir/$today
/bin/sh $proj_dir/$today

设置此脚本每日定时执行,剩下的检查sqlmap扫描报告就可以了