一、简介

本篇只介绍思路,不做详细注入语句讲解。

二、SQL注入产生原因

用户输入处理不当,用户数据被当做SQL语句执行。

三、注入类型

分类标准 分类
根据请求方式分类 GET方式注入 POST方式注入
根据注入点参数分类 整数型注入 字符型注入 搜索型注入
根据反馈类型分类 union联合查询注入 报错注入 布尔盲注 时间盲注 其他类型 (如请求头注入、内联注入、二次编码注入、宽字节注入、堆叠注入、二阶注入等)
根据数据库类型分类 Mysql、MSSql、Oracle、Access、MongoDB等

四、SQL注入思路

1、发现注入点

注入点

所有存在可变参数代入数据库中执行的数据

如:url中的?id=、页面中的搜索框、POST数据包中的可变参数、数据头中的UA、X-Forward-For等

判断:

在参数后加单引号、双引号、斜杠'、"、\,全部加。

若页面异常,则可能存在注入;

若页面无变化,则使用延时函数,判断是否存在时间延时盲注(各大数据库通用);其中,在mysql数据库中,需要额外判断宽字节注入、二次编码注入。若页面存在延时刷新、报错,可能存在sql注入。

2、判断闭合符

使用不报错的闭合符('或"),加上注释符(不同数据库不同,但-- a几乎可以通用:mysql中为–空格,mssql和oracle为–,access无注释符号)

注意:

mysql为?id=1' -- a形式

mssql、oracle、access均为?id=1' and 1=1/1=2 --形式(1=1正常、1=2异常)

若页面返回正常,则单或双引号即为闭合符;若页面依然异常,则在单或双引号后添加),直至页面恢复正常。添加部分与单或双引号组成闭合符。

注意:需要结合语境,判断可能使用的sql语句,更加容易判断闭合符。如搜索型语句处(多存在搜索框处),可能会使用like关键词,需要使用%闭合,构造形如%'and '%'='的闭合语句进行闭合判断。

3、判断数据库类型

在进行注入前,需要判断数据库类型,从而选择合适的注入语句。使用每个数据库独有的一个或多个语法、函数进行判断。

简单列举,够用即可。

数据库类型 注释 函数
mysql – a version()、@@version、length()
mssql @@version、len()、?id=1’ and exists (select * from sysobjects)>0 – 返回正常
oracle banner from sys.v_$version、length()
access and exists (select * from msysobjects)>0 返回正常

注:注释处为两个英文输入法的短横杠,非单横杠(显示问题)

4、选择注入方式

根据页面回显情况,选择通用注入方式:

1>首选union联合查询。要求:有回显位。

2>次选报错注入。要求:页面异常为报错信息。

3>最后是盲注。若页面只有正常和单一异常两种回显,选择布尔盲注;若页面无回显,选择时间盲注。

5、结合WAF确定注入语句

结合4,同一处注入点可以有多重注入手法,若是没有waf,按照优先级进行选择即可。若是有waf,需要结合绕waf选择注入方式。同时,在判断时,也可以尝试绕waf。

1>首先,判断and、or、空格是否存在waf拦截。

2>然后,按照注入手法优先级,将用到的关键词(如:order by、union select等)单独放入注入语句进行判断。

优先绕过waf,其次换可替代的关键词、最后换注入方式

3>最后,根据waf拦截方式,确定注入语句,依次注出当前数据库名、表名、字段名、数据即可。文末附上常见绕waf方式。

注意:

若为mysql数据库,可进行以下判断

--os-shell可对网站进行getshell,但是存在以下前提条件
1、存在sql注入
2、知道网站绝对路径
3、拥有数据库权限(dba权限),也可以使用sqlmap的--is-dba判断
4、数据库配置文件secure_file_priv未设置或设置为可读写的已知路径

4>其他:

时间延时盲注可用DNS外带节省注入时间,放在其他文章中再做讲述。

五、SQL注入防御

方式 说明
去掉单引号 现实场景常用单引号,去掉不合实际
转义单引号 对数字型无效(数字型不需要引号) 斜杠转义 addslashes()函数转义 php.ini配置文件转义(5.6以下版本开启magic_quotes_gpc = On)
强制类型转换 针对数字型 intval()
更改数据库连接方式 POD连接数据库将变量转换成字符串,再写入数据库,无法拼接

六、WAF绕过

sql语法特性 + http特性 + waf缺陷 = waf绕过

1、大小写绕过(现今几乎无效)

2、替换关键字
1> 关键字双写(代码级别waf有效)
2> 同价词替换,针对特殊关键词拦截的情况

and --> &&
or --> ||
= --> <、>
空格 --> %20、%09、%0a、%0b、%0c、%0d、%a0、//

3> 特殊字符拼接(mssql支持拼接、mysql不支持拼接)
​ ‘test1’+’test2’

3、编码绕过
常见的sql编码有unicode、hex、url、ascii、base64等
​ 1>url编码(或者二次编码)
​ 2>unicode编码(改/为%)
​ 常见unicode编码
​ 单引号:%u0027
​ 空格:%u0020
​ 左括号:%u0028
​ 右括号:%u0029

4、注释绕过
利用语言函数特性来绕过waf规则
常见注释符:
//、--、//、#、--+、---、;、--a
​ 1>普通注释
/**/在构造查询中插入注释,规避对空格的依赖或关键字识别
​ 2>内联注释
/*!*/表示注释里面的语句会被执行(只有MYSQL能识别)
/*!50001 select * from test*/表示数据库5.00.01以上版本才会执行该语句

5、参数污染
当同一参数出现多次,不同中间件会解析为不同结果。如果WAF只检测了同名参数中的第一个或最后一个,并且中间件特征正好取与WAF相反的参数,则可成功绕过

服务器中间件 解析结果 举例
ASP.NET/IIS 所有出现的参数值用逗号连接 par1=var1,val2
ASP/IIS 所有出现的参数值用逗号连接 par1=var1,var2
PHP/Apache 仅最后一次出现的参数值 par1=var2
JSP/Tomcat 仅最后一次出现的参数值 par1=val1
Perl CGI/Apache 仅第一次出现参数值 par1=var1

如:

/index.aspx?id=select 1,2,3 from table
-->
/index.aspx?id=select 1&id=,2,3 from table

6、缓冲区溢出
许多WAF是C语言写的,而C语言本身没有缓冲区保护机制,如果WAF在处理测试向量时超出了其缓冲区长度,会引发bug从而实现绕过
如:

?id=1 and (select 1)=(select 0xAAAAAA*1000 more A)+union select 1,2version()-- a

7、整合绕过
绕过技术结合使用

8、分块传输绕过
burpsuite中更实用post传输数据,设置Transfer-encoding: chunked
使用换行分割数据