Buu学习笔记1

WEB

[HCTF 2018]WarmUp

打开后发现source.php那么应该是一道代码审计的题目;那我们就看看源码吧;这里我将源码分为两部分;

此时它对我们传入的$page进行一个判断;判断是否为空或者是否为字符串;若是为空或者不是字符串;则返回false;然后若是非空或者为字符串则进行判断$page是否在定义的白名单之内;若是在里面则返回true;然后接者对我们传入的$page进行一个截取并返回一部分;(获取 $page 中 从 0 开始 到 mb_strpos($page . ‘?’,
‘?’)结束的字符串);而mb_strpos($page . ‘?’, ‘?’)则是查找$page第一次出现?的位置(关于mb_strpos函数在测试时发现如果没有匹配到指定符号,将返回字符串长度);所以该段总结来说就是对我们传入$page进行一个截取;从第0位到第一次出现?的内容并进行一个白名单匹配;如果该内容在白名单内便返回true;所以我们应该构造/suorce.php?或者/hint.php?进行白名单匹配。

需要注意REQUEST函数、GET函数与POST函数的区别,REQUEST函数可以同时接受get与post方法提交的变量。
这里是主要判断的逻辑,首先判断 file 参数是不是空值,再判断 file 是不是字符串,最后将 file 传入 checkFile 类中再进行判断(传入后 $page=$_REQUEST[‘file’])

又因为hint.php提示我们flag下ffffllllaaaagggg中;然后include()函数又会帮我们把内容读出来;所以我们想到构建payload为:?file=source.php?ffffllllaaaagggg此时发现没有内容;我们便又想到了目录穿越的方法进行度读取?file=source.php?/../../../../ffffllllaaaagggg进行读取
或者?file=hint.php?/../../../../ffffllllaaaagggg

[强网杯 2019]随便注

老规矩先提交一个参数试试看;出现了数字1和一个字符串;此时猜测1就类似于sqli-labs里面的id值;

接着探测闭合形式;然后猜字段数;接着使用联合注入试一下;发现有匹配大小写的过滤

接下来试着绕过对select的过滤,发现是进行多次匹配,双写绕过无效,注释绕过无效,url编码绕过无效;应该是绕不过了吧。此时想到了叠堆注入的方法,发现页面有回显,接着继续爆表和列。
words表:

1919810931114514表:

此时发现flag在1919810931114514表中,但是因为select无法使用导致我们无法读取
法一:我们这时候突然注意到我们提交1时爆出的字段;因为第一个字段也比较像是id值,猜想输出的是words表中的。所以此时我们可以将words表改成别的名字,将1919810931114514表名改成words表名;这样就可以通过查询1爆出words表的值了。
1.先将words表改名:
rename table words to a;
2.改1919810931114514表名:
rename table 1919810931114514 to words;
3.将flag字段改成data字段:
alter table words change flag data varchar(100)
4:添加id字段(确保前面的1可以被查询到)
alter table words id add int unsigned not Null auto_increment primary key;
又因为时叠堆注入可以直接将这几句话连接在一起

1
1';rename table words to word1;rename table `1919810931114514` to words;alter table words change flag data varchar(100);alter table words add id int unsigned not Null auto_increment primary key;#

#注意,如果tableName是纯数字,需要用反引号包裹
法二:
因为select被过滤了,所以先将select * from 1919810931114514进行16进制编码;
prepare…from…是预处理语句,会进行编码转换。
execute用来执行由SQLPrepare创建的SQL语句。
所以构造payload为

1
0;SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#

法三:预编译绕过
因为select关键字被过滤了,所以我们可以通过预编译的方式拼接select 关键字;

1
1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE  hacker;#

格式:PREPARE 名称 FROM Sql语句 ? ;
SET @x=xx;
EXECUTE 名称 USING @x;

[SUCTF 2019]EasySQL

这题还是很有必要记录一下的毕竟涉及到了猜测后台的查询语句(好离谱!)
在猜测前我们先来了解一下逻辑运算符;&&:都真为真,一假就假 ||:一真就真,都假为假
短路语法:
a&&b:当a为false时直接输出false(等于说直接输出a);当a为true时直接输出b
a||b:当a为false时直接输出b;当a为true时输出输出true(等于说输出a)
接下来开始猜测它后端可以做到数字1回显其他都不回显,那么我们应该想到一定会有一个或结构也就是我们上面说的||;此时便可以猜测后台查询语句为select $a||xx from xx
因为你输入1的时候为真;那么便一定是select 1 from tables;而select 1 from tables的作用就是增加新的
一列(select任何一个常数都会在表中新建一列,然后查询出那一列的内容;这个也是Array ( [0] => 1 ) );

然后此时我们又想到了* 的作用和在查询表中的字段内容时,逗号,用于查询多个字段名。
此时便可以开始构造我们的payload:* ,1
此时的后台查询语句就变成了select * ,1||xx from tables;即为select * ,1 from tables
附一下后台的查询语句吧感觉这题出题角度有点刁钻了:sql=“select”.post[‘query’].”||flag from Flag”;

[GXYCTF2019]Ping Ping Ping

这里想记录一下几种绕过方法(当flag被过滤时,$IFS$1是针对空格和{}被过滤时):
1.变量拼接绕过:?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php;
2.Base64绕过:echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh;主要是后面的|base64 -d|sh
3.内敛绕过:?ip=127.0.0.1;cat$IFS$1ls
反引号将反引号内命令的输出作为输入执行ls将ls出来的文件作为输入 cat ls

[极客大挑战 2019]Secret File


根据提示此时猜测可能是网页跳转太快咱们没有看清(因为咱们访问的是action.php但是跳转到end.php)此时我们
可以借助bp进行查看

此时便出现了刚才没有的东西;然后登入后提示是flag放在flag.php里,咱们马上想到文件包含;然后利用伪协议进行读取

[极客大挑战 2019]Upload

这边主要想记录一下当<?被过滤时应该咋办此时可通过这样来绕过和文件头欺骗(我们通常在一句话木马前加入GIF89a?进行绕过文件头检查)

[极客大挑战 2019]BuyFlag


根据提示我们必须是要为该学院的学生,抓个包看看;发现在Cookie: user=0;0一般是假的意思;我们把0改成
1;然后防包,此时已经提醒我们是该学校的学生了;接下来翻阅源码

接下来介绍两个函数:
1.is_numberic():就是判断括号里面的变量是不是数值
is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。
2.int strcmp ( string $str1 , string $str2 )
参数 str1第一个字符串。str2第二个字符串。如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。
可知,传入的期望类型是字符串类型的数据,但是如果我们传入非字符串类型的数据的时候,这个函数将会有怎么样的行为呢?实际上,当这个函数接受到了不符合的类型,这个函数将发生错误,但是在5.3之前的php中,显示了报错的警告信息后,将return 0 ,
也就是虽然报了错,但却判定其相等
strcmp函数漏洞:strcmp比较的是字符串类型,如果强行传入其他类型参数,会出错,出错后返回值0,正是利用这点进行绕过。
比如这段代码

1
2
3
4
define('FLAG','pwnhub{this_is_flag}');
if(strcmp($_GET['flag'],FLAG) == 0){
echo "success,flag:".FLAG;
}

脚本意思是get到的flag和FLAG的值相等,就可以得到FLAG,但我们都不知道flag值是什么,利用strcmp函数特点尝试使用数组绕过。令flag[]=xxx flag[]=xxx 》》 strcmp比较出错 》》返回null 》》null==0 》》条件成立得到flag
可知,传入的期望类型是字符串类型的数据,但是如果我们传入非字符串类型的数据的时候,
这个函数将会有怎么样的行为呢?实际上,当这个函数接受到了不符合的类型,这个函数将发生错误,
但是在5.3之前的php中,显示了报错的警告信息后,将return 0 ,也就是虽然报了错,但却判定其相等

[BJDCTF 2020]easy_md5

这里想记录一下NSSCTF里面的一题;

当我看到这个显示框的时候第一个想的马上就是SQL注入;结果尝试了一番发现好像没有什么回显;十分的困惑
翻看wp后才知道这个就是SQL注入不过是添加了MD5的SQL注入:以下是给出的hint
select * from ‘admin’ where password=md5($pass,true)

这个时候出现了一个很新的东西md5($pass,true):
md5(string,raw):
语法:

1
2
string:必需。要计算的字符串。
raw:可选。默认不写为FALSE。32位16进制的字符串;TRUE。16位原始二进制格式的字符串

这里如果raw参数为true的话,这个函数的返回值是string的md5加密值进行十六进制解码的字符串。
这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 ‘or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。所以此题的关键就在于后面的那个true
然后我们在SQL注入时知道password=xx or 1;后面这个1是恒为真的意思(当然其他数字也可以除了0外)
所以我们就要构造一个or number 的类型进行绕过(所以为什么ffifdyop就是答案,因为ffifdyop的md5的原始二进制字符串里面有‘or’6这一部分的字符.)

1
2
3
4
content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c
string: 'or'6]!r,b

在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。要注意的是这种情况是必须要有单引号括起来的:
比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1,也就相当于password=‘xxx’ or true,所以返回值就是true。当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。
这边在提一嘴MD5的强弱绕过:数组绕过。原理是md5等函数不能处理数组,导致函数返回Null。而Null是等于Null的,导致了绕过。看下面的示例,是返回了yes的。(题目中便可以传入?a[]=1&b[]=2进行绕过)

[RoarCTF 2019]Easy Calc

这题还是很有记录的意义的,先学习几个函数。
1.var_dump($expression):
作用:函数用于输出变量的相关信息;显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
语法:

1
2
void var_dump ( mixed $expression [, mixed $... ] )
$expression: 你要输出的变量。

例子:

1
2
3
4
5
6
7
8
9
10
<?php
$b = 3.1;
$c = true;
var_dump($b, $c);
?>

输出结果为:

float(3.1)
bool(true)

2.scandir(directory,sorting_order,context):
作用:返回指定目录中的文件和目录的数组。
语法:
directory 必需。规定要扫描的目录。
sorting_order 可选。规定排列顺序。默认是 0,表示按字母升序排列。如果设置为 SCANDIR_SORT_DESCENDING 或者 1,则表示按字母降序排列。如果设置为 SCANDIR_SORT_NONE,则返回未排列的结果。
context 可选。规定目录句柄的环境。context 是可修改目录流的行为的一套选项。

var_dump(scandir(chr(47))),相当于system(ls /),chr(47)=”/“
3.file_get_contents(path,include_path,context,start,max_length) :
作用:把整个文件读入一个字符串中。该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持,还会使用内存映射技术来增强性能。
语法:
path 必需。规定要读取的文件。
include_path 可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 ‘1’。
context 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 NULL,则忽略。
start 可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 中新增的。
max_length 可选。规定读取的字节数。该参数是 PHP 5.1 中新增的。
file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)),相当于file_get_contents(/f1agg)即system(cat /f1agg)