内容简介:Nginx Lua Web Application Security
前言
我们知道,Nginx Lua经常被用来编写WAF。但随着 lua 语言的广泛,在其他web应用中也会有大量的Lua。
安装配置
可以使用OpenResty或者nginx编译的时候添加 lua-nginx-module
模块。区别在于OpenResty自带了很多第三方Lua库。
所有测试均在以下环境:
Lua 5.1.4 nginx/1.9.15 lua-nginx-module-0.10.5
安装完成后,进行nginx配置。注意该配置只是拿来做漏洞测试。
server块添加一个location
location /sec_ngx_lua {
content_by_lua_file /opt/lua_module/content.lua;
}
http块添加lua模块
lua_package_path '/opt/lua_module/?.lua;;'; lua_code_cache on;
表示添加/opt/lua_module路径的所有模块。
接下来就只在/opt/lua_module路径中写代码测试了。
vuls.lua(漏洞代码)
local _M = {}
function _M.xss()
local name = ngx.req.get_uri_args().name or ""
ngx.header.content_type = "text/html"
ngx.say(name)
end
return _M
content.lua(调用vuls.lua中的代码)
local vul = require "vuls" vul.xss();
漏洞类型
XSS
漏洞代码
function _M.xss()
local name = ngx.req.get_uri_args().name or ""
ngx.header.content_type = "text/html"
ngx.say(name)
end
漏洞验证
http://joychou.me/sec_ngx_lua?name=<script>alert(9527)</script>
修复
没有提供方法进行编码,所以编码需要自己实现。
Sql Injection
由于要使用数据库,所以如果未使用OpenResty,需要添加OpenResty提供的 mysql.lua
库
下载地址:
https://raw.githubusercontent.com/openresty/lua-resty-mysql/master/lib/resty/mysql.lua
将下载的mysql.lua同样放在/opt/lua_module/路径。
漏洞代码
local _M = {}
function close_db(db)
if not db then
return
end
db:close()
end
function _M.sqli()
local mysql = require("mysql")
local db, err = mysql: new()
ngx.header.content_type = "text/html"
if not db then
ngx.say("new mysql error :", err)
return
end
db:set_timeout(1000)
local props = {
host = "127.0.0.1",
port = 3306,
database = "lua",
user = "root",
password = "joychouisgood"
}
local res, err, errno, sqlstate = db:connect(props)
if not res then
ngx.say("connect to mysql error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
return close_db(db)
end
local uid = ngx.req.get_uri_args().uid
local select_sql = "select id, name from info where id =" .. uid
res, err, errno, sqlstate = db:query(select_sql)
if not res then
ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)
return close_db(db)
end
for i, row in ipairs(res) do
for id, name in pairs(row) do
ngx.say("row ", i, " : ", id, " = ", name, "<br/>")
end
end
end
return _M
lua.info表数据
mysql> select * from info; +----+---------+ | id | name | +----+---------+ | 1 | joychou | | 2 | smilent | +----+---------+ 2 rows in set (0.00 sec)
漏洞证明
http://joychou.me/sec_ngx_lua?uid=2 UNION ALL SELECT CONCAT(0x7162766271,0x744a75536365647154756a6d51436a746b656b6e4f796c4e6461565153537254727851564f6a4c61,0x716a787871),NULL-- cils
返回
id = qbvbqtJuScedqTujmQCjtkeknOylNdaVQSSrTrxQVOjLaqjxxq
漏洞修复
使用 ngx.quote_sql_str
对参数进行编码
CRLF Injection
参数外部可控的情况下,可使用%0d%0a进行CRLR注入。
漏洞代码
function _M.crlf_injection()
local user = ngx.req.get_uri_args().user or ""
ngx.header.content_type = "text/html"
ngx.header['X-Test'] = user
ngx.say('crlf inject sec test')
end
漏洞验证
➜ ~ curl -v 'http://joychou.me/sec_ngx_lua?user=demo%0d%0aSet-cookie:JSPSESSID%3Djoychou' * Trying 35.185.163.135... * Connected to joychou.me (35.185.163.135) port 80 (#0) > GET /sec_ngx_lua?user=demo%0d%0aSet-cookie:JSPSESSID%3Djoychou HTTP/1.1 > Host: joychou.me > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.9.15 < Date: Tue, 13 Jun 2017 09:34:12 GMT < Content-Type: text/html < Transfer-Encoding: chunked < Connection: keep-alive < X-Test: demo < Set-cookie:JSPSESSID=joychou < crlf inject sec test
漏洞修复
过滤外部传参。
Command Injection
Lua可执行命令的方法
- io.popen
- os.execute (执行操作系统 shell 命令)
os.execute不能拿到回显,但io.popen可以。
漏洞代码
使用io.popen执行命令时,命令外部可控,导致任意命令执行。
function _M.cmd_injection()
ngx.header.content_type = "text/plain"
local user = ngx.req.get_uri_args().user or ""
local handle = io.popen("ls -l /home/"..user)
local result = handle:read("*a")
handle:close()
ngx.say(result)
end
漏洞验证
➜ ~ curl 'http://joychou.me/sec_ngx_lua?user=root;cat%20/etc/passwd' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync
漏洞修复
过滤外部传参。
任意文件读取
使用io.open进行文件读取时,文件名外部可控导致任意文件读取。
function _M.file_read()
local file = ngx.req.get_uri_args().file or ""
ngx.header.content_type = "text/html"
local f = io.open(file..".txt")
local ret = f:read("*a")
f.close()
ngx.say(ret)
end
漏洞验证
使用%00截断后面的 .txt
字符串
http://joychou.me/sec_ngx_lua?file=/etc/hosts%00
漏洞修复
过滤外部传参。
代码注入
先来看下loadstring造成的代码注入的实例
> x="os.execute('echo 111 > /tmp/xx')"
> assert(loadstring(x))()
[root@sectest]# cat /tmp/xx 111
如果loadstring的字符串里可外部控制,就可以导致代码注入,和 php 、 python 的 eval
一样。
lua中和loadstring类似的方法还有
require,dofile,loadfile,dostring,loadstring,loadlib,load
漏洞代码
function _M.code_injection()
local name = ngx.req.get_uri_args().name or ""
ngx.header.content_type = "text/html"
local html = string.format([[
ngx.say("Hello, %s")
ngx.say("Today is "..os.date())
]], name)
loadstring(html)()
end
漏洞证明
http://joychou.me/sec_ngx_lua?name=joychou") os.execute("echo 2333 > /tmp/xxx
[root@sectest]# cat /tmp/xxx 2333
漏洞修复
过滤外部传参。
参考链接
Lua Web Application Security Vulnerabilities
以上所述就是小编给大家介绍的《Nginx Lua Web Application Security》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
改变未来的九大算法
[美] 约翰.麦考密克 / 管策 / 中信出版社 / 2013-6 / 39.00元
Google得出的搜索结果是如何产生的? 百度为何会陷入“搜索门”,又是什么机制使然? 身处在大数据时代的我们,究竟该如何应对变化莫测的世界? …… 没有满篇的专业术语,第一次让我们通过简单明了的语言、生动的例证了解支撑计算机王国的灵魂支柱——9大算法,包括人工智能、数据压缩,以及Google著名的PageRank等。 本书精彩地介绍了搜索引擎、PageRank、公开......一起来看看 《改变未来的九大算法》 这本书的介绍吧!