楚慧杯?除晦杯!
👴大约的确很久没写过CTF相关的博客了。因为打CTF就是为了公费旅游,为了彳亍,为了口乞。当然,也可能是彳亍也没彳亍到,鸡毛没挣着,还还扣钱了。
但当👴看到它的名字的时候,👴就知道这是👴一定要打的比赛。因为快过年了,中国人传统上讲要除一除身上的晦气(每日吉祥话1/1)。所以“楚慧杯”这个名字确实有素质,本意是楚地的智慧,表示湖北省赛;谐音也可以表示除去晦气,迎接新的一年。决赛赛场上,果然有工作人员问我们的牌子是不是印错了,👴就是为了这碟醋才包的这盘饺子。
冲出西海岸
- Aidaip: 这比赛没什么人报,一个学校能报两队,你看这比赛分4个组,每个组都是前9有钱拿,这不是去捡钱?
- 👴们:去去去
于是👴们组织了一队本科生一队研究生报名。当即立下军令状,本科生打不过研究生,让人唠一辈子。
- 组委会:决赛再加8支队伍,一共9个奖谢谢。另外一个学校只能进一队哦~
- Aidaip: 他之前的公告绝对不是这样写的。
这下不得不打内战了。
初赛WP
初赛没啥好说的,传统CTF,都是老黄历了。
Web1
害搁这前端绕过呢,害搁这考www.zip
呢。里面是白给反序列化,白给命令执行。
|
|
Web2
里面是哈希长度拓展攻击,👴上一次遇见这玩意还是在第一次打带比赛的时候。
但是👴下了仨环境才下到好用的工具。然后后面能上传文件,还说文件名已写入数据库。但是题目名叫upload,你总不能考注入吧。然后👴就去看misc了。
然后还真是,sqlmap一把梭。傻逼题,血亏x1。
知识点总结: PHP:md5()
传统CTF考PHP哈希就这老三样:
- 弱类型0e绕过:
md5($a) == md5($b) && $a != $b
- 经典查表
|
|
- 强类型——数组绕过:
md5($a) === md5($b) && $a !== $b
?a[]=a&b[]=b
- 强类型——MD5碰撞:
md5($a) === md5($b) && (string)$a !== (string)$b
- fastcoll脚本仓库
- 同样适用于
md5('nmsl'.$a) === md5('nmsl'.$b)
- 长度拓展攻击: 已知
md5(a+b)
和len(a)
和b
,可以求md5(a+b+c)
和c
- 碰撞和拓展攻击的时候注意把不可见字符转urlencode
Misc1
对一个文件压缩4097次。写个递归zip解压的脚本,gpt秒了。但是要小心gpt的脚本跑完一看几千个压缩包好几十G,一个里纳米。解出来摩斯密码,没意思。
Misc2
提一内存镜像,volatility一把梭,提一个docx里面是空格和tab,是snow隐写,密码是镜像里面的管理员密码。👴没见过搁这看半天8进制,血亏x2。
Misc3
给一点阵字库文件,密文就是点阵序列。出题人想让我们去字库里查,但是有没有可能可以直接打印。点阵的格式是:
'0,0,960,1632,3120,3120,1632,960,1632,3120,3120,3120,1632,960,0,0'
每行16个数,每个数不大于4096,也就是16位2进制,加起来就是16*16的像素点阵,我直接让gpt打印:
|
|
打出来发现只有16种字符,也就是16进制咯。肉眼写个表匹配即可。
|
|
最后是个zip,压缩包密码给hint了,还是个二进制点阵,还是直接打印肉眼看。
初赛战报
“但是我们的球迷,他们不离不弃地陪伴着国足到最后一秒!”(递话筒)
初赛结果是本科生战队1445分撼负研究生战队1448分,👴队压线进决赛,这下让人唠一辈子了。
然后第二天:
- 本科👴:组委会打电话了,👴们递补进决赛了
- 👴:¿¿¿ 复活赛打赢了?
- 牢大:我没意见
坏了,这下真让他给冲出来了。这下凑够人演《武汉往事》了,你们师徒三人(本科生)对阵我们师徒三人(研究生),武汉等你嗷。
武汉往事
于是👴们来到了NCC国家网安基地,华科确实帅,宿舍/酒店确实好,食堂确实贵。
👴一看参赛手册,您猜怎么着,上午打一传统CTF,下午拿上午的web和pwn题打fix,还只有三轮,还是安恒平台。我只能说,不提供check down还是attack down的AWDp都是纯纯的厨生。
决赛WP
流量分析
还以为考misc,结果只多考了流量和逆向。👴配了一晚上环境,鸡毛没用上。👴队友也是,夜里的智慧全部木大。早知道好好睡一觉。
- 攻击者使用的管理员账户和密码是什么
http.request.method == "POST" && http.request.uri contains "login"
- 或者从后往前翻,找到执行恶意代码的地方,再往前就有了
- 攻击者通过什么文件泄露的密码
- 拿到密码往前搜呗。ctrl+F,分组字节流-字符串:
TPShop6.0
- 拿到密码往前搜呗。ctrl+F,分组字节流-字符串:
- 攻击者通过什么文件上传的后门
- 拿到密码往后翻,找到一个phtml的木马,再往前翻就有上传的接口
- 攻击者将shell反弹至公网IP,反弹shell的IP和端口是什么
统计→IPv4 Statistics→All Adresses
根据分组数量排名,前两个是服务器和黑客的客户端,第三多的IP显然就是反弹的了公网IP了。- 然后过滤tcp流,可以看到明文的bash流量,对应的端口就是了
- 攻击者使用什么文件提权
- 阅读tcp流,看他执行过什么命令就行了。大不了挨个试毕竟50次机会。
sudo /bin/systemctl status apache2.service
可以看到sudoer文件里提供了这条语句的免密执行,既然有sudo那就是systemctl
了
整套题难度不高,赛场上前面的带佬基本上1小时以内ak的。👴队还是在上面浪费了点时间。导致后面web2脚本没写完,血亏x3。
Web1
简单的文件上传CURD,过滤了php标签,但是👴直接传<? phpinfo();?>
就能执行。
fix阶段一看,拿include读文件内容,那没事了。
|
|
👴直接扬掉include,然后第一轮就宕了。👴是傻逼,光知道扬没把功能补全,血亏x4。
Web2
sql盲注,但是fuzz了很长时间才确定。然后盲注脚本就写不完了,属于是之前学的都忘光了。
|
|
这代码一眼GPT,过滤随便加点strtolower()
和黑名单就行。
知识点总结:SQLmap进阶
做一名合格的高级脚本小子要学会用sqlmap的时候自己写tamper脚本。实际上也很简单,对照现成的改改就是了。
本题的sqlmap命令:
python3 ./sqlmap.py -u "localhost/search.php" -data="search_query=*" --prefix "1' AND" --suffix "AND '1'='1" --technique=B --tamper=space2newline --dbs
--prefix
,--suffix
: 指定注入的前后缀。
默认情况下,sqlmap会使用前面闭合后面注释的手法,which is dumb。比如本题中注入点后方的的LIMIT子句就需要前面的SELECT环境。而本题中所有的注释方法都不好使。
因此,手注的时候首先闭合出一块完整的语法环境,然后交给sqlmap。在此题中闭合的语句是:
select * from images where id = '1' AND {sub_query} AND '1'='1' LIMIT 0,1
--technique=B
:{sub_query}
被夹在and中间,因此作为一个布尔表达式使用布尔盲注,指定参数使sqlmap不要浪费时间进行别的测试。所有注入技术类型如下:
|
|
--tamper
: 指定自定义过滤脚本。在本题中,空格被过滤且注释绕过/**/
,加号绕过+
都不好使。于是我们可以把tamper里自带的space2plus.py
中的+
都改成\n
,就变成了space2newline
比赛时远程环境有些空格能用%0a绕过有些不行,👴绞尽脑汁用括号绕过,最终耻辱下播。赛后复现的环境里urlencode都不好使了,最后想到直接全部用换行符\n
即可。
参考链接:
Web3
考一nodejs,没源码啥也看不出来。其实直接跟文件名就能读源码,但是上午👴忘了,血亏x5。
|
|
👴直接扬backdoor,然后就宕了,发一公告说不让删backdoor,只能加固。我只能说你这种Fix确实有点素质。
然后修也简单,加个waf防一下node题常见的payload关键字即可:
|
|
这道题不是很亏,就是有点亏。也不是特别亏,总之还是挺亏的。下午fix的时候离线资料里查到了相关题型,也不是很复杂,👴属于是残疾人复健。
赛后WP:首先用原型链污染拿到Object.door
,然后套vm2的沙箱逃逸payload即可:
|
|
参考链接:CVE-2021-23449。漏洞适用版本:vm2@3.9.3
Web4
给一jar包,虽然👴夜里的智慧装了java逆向的环境。但是看了看代码没啥业务逻辑,应该是框架的洞,👴不会,长大后再来学吧。
赛后看,👴猜有可能是这个洞:jeecg-boot/积木报表的Freemarker的SSTI任意代码执行
决赛战报
上午刚结束一分钟,👴队友出一个逆向,属于是典中典,血亏x6。上午排名20多,下午fix亏了300分左右。最后👴队第17名。本科生队更是寄中寄,建议立刻招开批斗大会,狠狠的唠一辈子。
下午结束后主办方问前20的要录屏,👴寻思应该能拿一奖状吧。于是提前开香槟,好歹没空手回去。于是高高兴兴到了颁奖典礼,还看一表演呢。
👴掐指一算,1 + 3 + 5 + 7 = 16 < 17
。嘶——这该死的宿命感。
贵🐋的诅咒:
- 比赛结束之后一分钟出flag
- 半场开香槟然后差一名拿奖
有捞无堂
释义:有奖金海底捞,没奖金滚回去吃食堂。
其实就算👴们把亏了的题都补上也够呛能进前9。所以也不是很亏,就是有点晦气。
总之,比完赛了还是要考虑办正事——旅游。这次来武汉可是除晦之行,绝对不能让比赛的晦气留给第二天。
除晦未半而中道崩殂
- 👴:揍!
- 队友A:鼻子堵着了很吉尔难受
- 队友B:👴要去见朋友
坏了,晦起来了。都怪去颁奖典礼的时候没穿外套给冻着了。👴去问隔壁队:
- 冰糖雪狸:👴队友也烧起来了
- 👴:?活着
什么嘛,这不是什么也没除掉吗(😎→🕶️🤏😭)
安顿好病人,最终只有👴和冰糖雪狸俩人去市里约会。到了地方一看,你找的这是什么地方??
但是武汉确实大城市。👴们终于吃了顿好的,俩人买4杯茶颜悦色还都tm喝完了。
- 👴:这糖水怎么没味啊?
- 冰糖雪狸:你就是山猪吃不了细糠
- 👴:确实
吃饱喝足,去江边看看黄鹤楼吧。于是👴们打车去了江滩。太美丽了长江,还是看看远处的黄鹤楼吧。我楼呢?
好容易来一趟看不着亏了。于是👴们打车去了黄鹤楼。你吗过个江20块钱,血亏。
最后到了黄鹤楼底下正好关门,寄。
👴突然意识到,这是不是象征着👴队比赛差一名没拿到奖。连起来了。
除晦辩证法
回来的🛫上,👴开始细数这一趟武汉之行的晦气。
我翻开参赛手册一查,这比赛食宿自理,整整齐齐的每页上都写着“楚慧杯”几个字。我横竖睡不着,仔细看了半夜,才从字缝里看出字来,满本都写着一个字是“晦”!
- 这比赛名字就沾点晦
- 以为去捡钱实际上鸡毛没赚着,此为第二晦
- 差一名拿奖状,此为第三晦
- 比完赛队友躺了俩,此为第四晦
- 晚上吃饭的地方也沾点晦
- 去黄鹤楼刚好关门,此为第六晦
贵🐋著名哲学家Aidaip在其著作《亏晦二象性》$^{[1]}$中阐释了晦气的基本原理:
亏了,却想着赚了,终于晦气。——Aidaip
这一原理后经学者整理成如下的形式化描述:
$$ 亏 \xrightarrow{\textit{想赚}} 晦 $$
本科👴真的为了打比赛去的,所以他们亏了,让人唠一辈子。为什么亏了,还是因为菜。菜就多练。
👴为了除晦而彳亍,此时还没有亏。也没有想赚,但还是晦气。 说明目前的主流理论不足以解释新的实验现象。
如果👴能把题都秒了,👴们就不会注意到其他的晦气。为什么👴不能秒了,因为👴太菜了。为什么👴太菜了,因为晦气。 但也正因为晦气,👴才会想除晦。
所以得出结论,越晦气,越晦气。
👴一抬头,大师我悟了,原来hui一直在我们身边。他真hui了吗,如hui。
给带🔥送上新年祝福:
- 2024希望带🔥都能远离晦气
参考文献
[1] AiDaip. 亏晦二象性[EB/OL]. 2022. https://aidaip.github.io/life/2022/06/01/%E4%BA%8F%E6%99%A6%E4%BA%8C%E8%B1%A1%E6%80%A7.html