WEB安全之: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 注入常用语句及函数

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 基于数据提交方式区分

  1. GET 注入
    • 提交数据的方式是 GET , GET请求的参数是放在URL里的,GET请求的URL传参有长度限制,中文需要URL编码。
    • 注入点的位置在 GET 参数部分。比如: http://host/?id=1, id 为注入点。
  2. POST 注入
    • 使用 POST 方式提交数据,POST 请求参数是放在请求 body 里的,长度没有限制。
    • 注入点位置在 POST 数据部分,常发生在表单中。
  3. COOKIE 注入
    • cookie参数放在请求头信息,提交的时候 服务器会从请求头获取参数。
    • 注入点存在 Cookie 当中的某个字段中。

1.6.2 基于数据类型的区分

  1. int 型注入
    • 如: http://host/?id=1 注入,一般被称为 int 型注入。其注入点 id 类型为数字,在大多数的网页中,像查看用户个人信息、文章等,大都会使用这种形式的结构传递 id 等信息,交给后端,查询出数据库中对应的信息,返回给前端。
    • SQL 语句原型:select * from 表名 where id=1
    • 查询语句: select * from user where id=1 and 1=1
  2. string 型注入
    • 如: http://host/?username=admin 注入,一般被称为 string 型注入。注意处理此类注入时,可能需要处理 SQL 语句闭合问题。
    • SQL 语句原型:select * from user where username='admin'
    • 查询语句:select * from user where username='admin' and 1=1'
  3. like 型注入
    • 指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 "keyword=关键字" 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。
    • SQL 语句原型:select * from user where username like '%关键字%'
    • 查询语句:select * from user where username like '%关键字%' and '%1%'='%1%'

1.6.3 基于注入方法区分

  1. 联合查询注入
    • union select 联合两个表注入
  2. 报错注入
    • 即页面会返回数据库报错信息,或者把注入的语句的结果直接返回在页面中。
  3. 盲注入
    1. 布尔型注入:即根据返回页面,判断条件真假的注入。
    2. 时间型注入:即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。

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秒返回页面。
posted @ 2021-06-01 08:23  f_carey  阅读(23)  评论(0编辑  收藏  举报  来源