0x0 前言
本文是上个月学校 NEX 战队招新赛中部分题目的 WriteUP ,因为赛事从结果上来说还是很令人高兴的,所以一直都想单独写一篇博客来记录这些题目,但是因为学校的一堆事情+拖延症的问题,差不多过了1个月才着手做这件事…
0x1 相关环境
1 | Python v3.7.4 |
0x2 各WriteUP
0x20 Web 签到
1 |
|
代码如上,分析知 ttt 类的析构函数会输出 flag 内容,而代码中存在 unserialize 函数,故可知该代码存在反序列化漏洞。下面来构造 ttt 类的序列化内容,代码如下:
1 |
|
那么现在解决问题的关键就是构造满足三个 if 条件的请求,以使程序流程到达反序列化函数那里。get 和 post 都是常规的请求,这里可以了解一下 X-Forwarded-For ,然后可通过 Python3+Requests 构造如下请求来获取 flag:
1 | __import__('requests').post('http://<ip>:<port>/?get=1', data={'post':'1','class':'O:3:"ttt":0:{}'}, headers={'X-Forwarded-For':'127.0.0.1'}).content |
0x21 Baby Flask
源码 提取码: upiv
可以看到,路由 /admin 可以获取到 Flag ,该视图函数通过验证 session 中 admin 的值来返还不同的内容;而因为 Flask 是客户端session的模式,故这个值可以人为修改。
那么解题的目标就变成了通过寻找注入点来获取 secretkey ,查看代码知调用 render_template_string 函数时第一个参数传递了 template.replace,将 模版中的 $remembered_name 替换成了 session 中 name 的值,通过查看 index.html 可知该占位符出现在 Info 模块和 Author 输入框的 value 属性中,故可通过合理控制 Author 中的值来实现注入。
而在 app.py 中,通过定义 safe_input 函数针对 post 过来的输入进行了过滤,查看代码可知输入中不能出现 ()[]_ 这几种字符,所以可以通过全局变量 config 来获取secretkey。
拿到key以后,通过构造 session ,并使用浏览器自带的开发者工具将原来的值替换掉即可通过访问 /admin 拿到 Flag。
0x22 Baby xxe
1 |
|
提示信息:Flag 在 ./flag.php 中
尝试直接访问 flag.php 发现内容为 flag{f4ke_fl4g} ,也就是假 Flag ;那么根据提示来分析,很有可能真正的 Flag 被写在 php 代码的注释中或是有 if 条件来限制,所以首要的目标是拿到 flag.php 的代码。
通过分析上面的代码,可以发现 else 中 xmlfile 被双引号扩住,所以不能通过写入 SYSTEM 关键字来达到 xxe 的效果,而 else if 中只要出现 xml 字样就会替换 entity 关键字,但没有进一步的过滤措施,故可以通过载入 dtd 的方式实现注入。
题目本身是放在服务器上的,故想要访问自定义的 dtd 文件需要具备公网 ip 的设备,这里的复现因为在本地,就不做相关处理了。假设文件名为 tmp.dtd ,内容如下:
1 | <!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=./flag.php"> |
这里要注意的是,由于最后 php 解析的是 xml 内容,而 flag.php 代码中存在诸如 <> 的符号,会对解析造成干扰,故采用 php 伪协议将文件内容以 base64 进行编码。
然后通过 Python+Requests 发送如下 POST 请求
1 | __import__("requests").post("http://<ip>:<port>/<题目文件名>", data={"name":'<?xml version="1.0"?><!DOCTYPE root SYSTEM "tmp.dtd"><root>&test;</root>'}).content |
将得到的 base64 内容解码即可得到 php 代码,经过相关处理得到 Flag。
0x23 ScriptBoy
文件包 提取码: gxfa
题目描述:筛选出所有文件中前两个数字都是4位的一行,将选出的每一行的第20位组成一个字符串, flag就是这个字符串的32位小写MD5的值
分析文件结构后可以用如下脚本构造 Flag:
1 | from hashlib import md5 |
0x24 ljmisc
图片 提取码: mnck
⬆️打开链接前请做好心理准备
拿到图片后,执行 binwalk 1000.png
即可发现从 0x8B3F4 处开始隐藏了一个压缩包,故可执行 dd if=1000.png of=test.zip skip=0x8b3f4 bs=1
来将它提取出来。据说这个包经过了伪加密,但是当时因为环境是 MacOS ,所以也没有经历解密的操作,这里也就先不记录相关内容了。
打开后出现一个新的压缩包和两张图片,新的压缩包是真的被加密过的,所以要从另外两张图片寻找解压密码的线索。
两张图片并不能看出什么分别,但是大小却差了很多,故可以猜测是盲水印。
使用bwm处理后可以获得解压密码为 glgjssy_qyhfbqz,输入后即可打开压缩包到达第三层。
解压后的文件是一个充满0和1的文件,当时看了好久都没什么头绪。但是在我万能的舍友的帮助下,猜测这可能是描述了一张二维码,故通过以下脚本将1的位置填充为黑,0的位置填充为白:
1 | from PIL import Image |
扫描二维码即可获取 Flag。
0x3 总结
本文记录了本次招新赛中的部分题目,其他的题目因为难以复现而暂时无法记录。
技术上的话题就到此为止了,下面是一些题外话:
1 | 5Zug5Li65piv56ys5LiA5qyh5YGaIGN0Zu+8jOaJgOS7peinieW+l+aXoOiuuuWmguS9lemDveimgeWGmeS4gOS6m+S4nOilv++8jOWPr+iDveaYr+S9nOS4uuaWsOaWueWQkeeahOi1t+eCue+8jOS5n+WPr+iDveaYr+S4uuS6huaWueS+v+aXpeWQjueahOWbnuW/huOAggoK5pyA6L+R6YGH5Yiw5LqG5ZCE56eN5LqL5oOF77yM55Sx5q2k5Lmf5oOz5LqG5b6I5aSa44CC5bCx5Zyo5LiK5Liq5a2m5pyf77yM5oiR5Zug5Li65b2T5pe255y85YWJ5q+U6L6D55+t5rWF6ICM5ouS57ud5LqG5LiA5Liq5py65Lya77yM5rKh5oOz5Yiw6L+Z5a2m5pyf5Y205Zug5q2k6ZSZ6L+H5LqG5b6I5aSa5LqL5oOF44CC5a+55LqO6L+Z5Lu25LqL77yM6K+05LiN5ZCO5oKU5piv5LiN5Y+v6IO955qE77yM5L2G5oiR5Y+I5LiN5piv5LiA5Liq5Lya55So6L+H5Y675Y+N5aSN5oqY56Oo6Ieq5bex55qE5Lq677yM6YCJ6ZSZ5LqG5bCx5piv6YCJ6ZSZ5LqG77yM5Lmf5rKh5LuA5LmI5aW96K+055qE44CCCgrog73lpJ/ov5vlhaUgTkVYIOaYr+aIkeayoeacieaDs+WIsOeahO+8jOi/meS5n+iuuOaYr+WPpuS4gOS4quacuuS8muOAguS4jeeuoeaAjuS5iOivtO+8jOWug+S7juWPpuS4gOS4quWxgumdouiuqeaIkeeci+WIsOS6huW+iOWkmuS4nOilv++8jOi/meS+v+Wkn+S6huOAggoK6LCo5Lul5q2k5paH6K2m6YaS5pyq5p2l55qE6Ieq5bex44CC |