做注入时的的步骤
1 . 判断注入的类型
如果是字符型的就需要考虑闭合符的问题
http://172.16.56.1/sqli/Less-1/?id=1 and 1=2 --+
2. 判断闭合的方式
如果是字符型,就先进行这一步
常见的闭合方式 ' ' " " (" ") ('')
http://172.16.56.1/sqli/Less-1/?id=1' and 1=2 --+
#正常执行了,证明闭合符是'
解释:1. 目标页面的原始 SQL 语句
SELECT * FROM 表名 WHERE id = '参数值'
这里的 '参数值' 表示参数被单引号(')包裹(字符型参数的常见处理方式)。当传入正常参数 id=1 时,SQL 语句为:
SELECT * FROM 表名 WHERE id = '1' 正常执行,查询id=1的记录
当输入 id=1' and 1=2 --+ 时,参数被拼接到 SQL 语句中,结果变为: SELECT * FROM 表名 WHERE id = '1' and 1=2 --+'
单引号(')的作用:原始 SQL 中 id='1' 的右单引号是闭合符,而注入语句中的第一个 ' 会提前闭合这个右单引号,使 1' 变成 '1'(即 id='1' 被提前闭合)。
and 1=2 的作用:这是一个逻辑判断(1=2 恒为假),用于改变 SQL 语句的执行结果。
--+ 的作用:-- 是 SQL 注释符(后面需跟空格),+ 在 GET 请求中会被解析为空格,因此 --+ 会将后续的原始 SQL 语句(如多余的 ')注释掉,避免语法错误。
原始 SQL 中参数是用单引号(')包裹的(即闭合符为 '),注入语句中的 ' 会精准闭合原始的单引号,后续的 and 1=2 --+ 会被正常解析为 SQL 逻辑,导致查询条件变为 id='1' and 1=2(因 1=2 为假,查询无结果),页面会显示异常(如无数据),但 SQL 语句本身语法正确,即 "正常执行"(无语法错误)。
若闭合符不是 '(比如是双引号 " 或无引号),注入的 ' 会导致 SQL 语法错误(如多余的单引号未闭合),页面会直接报错(如 "SQL 语法错误"),而不是 "正常执行" 后显示异常
3. 判断列数
数字型的第2步,字符型的第3步,
探测目标数据库表中包含的列(字段)数量。
order by 或者使用 group by
?id=1'order by 4;--+
?id=1'group by 3;--+
列数正常则正常显示;列数不对会进行报错
4. 判断回显的位置 ( 使用联合查询 )
当我们判断列数时,让他们显示三列,但是他们显示了两列,就代表有一列是没有前端回显的,这是我们就要判断前端回显位是在那一列
SELECT 1, 2, 3 是一种特殊的查询方式,它的作用是直接返回指定的常量值,而不涉及任何数据表。
?id=-1'union select 1,2,3;--+
当显示的页面中出现了数字几,几就是回显位,出现了2,3;回显的位置是在2,3的位置
回显位指的是 数据库查询结果在页面上显示的位置。在联合查询(UNION SELECT)中,只有当注入的 SELECT 语句与原始查询的字段数一致,且部分字段的结果会被页面渲染展示时,这些展示位置才被称为 "回显位"。
?id=-1': -1 是一个无效的参数值,让原始 SQL 查询(如 SELECT * FROM 表名 WHERE id='-1')无法匹配任何数据,确保原始查询结果为空,避免干扰后续联合查询的输出。
单引号 ' 用于闭合原始 SQL 中包裹参数的引号
为什么要判断回显位?
回显位是后续注入的关键,确定哪些字段位置会在页面显示后,就可以在这些位置替换成查询敏感信息的函数(如 database() 查库名、user() 查用户名等),从而获取数据库信息。
5. 查看当前使用的数据库名称
?id=-1'union select 1,(database()),3;--+
注入点利用:?id=-1' 部分是为了闭合原查询中的 SQL 语句结构,-1通常是为了让原始查询返回空结果,避免干扰注入结果。
UNION 查询拼接:union select 1,(database()),3;--+ 是核心注入部分:
UNION 用于将两个查询的结果合并
select 1,(database()),3 构造了一个新查询,其中:
1和3是为了匹配原查询的列数(确保 UNION 查询格式正确)
database() 是 MySQL 的内置函数,用于返回当前数据库的名称,要放在回显位
;--+ 用于结束 SQL 语句并注释掉后续可能存在的代码,避免语法错误
执行结果:当这个注入语句被服务器执行时,数据库会执行拼接后的完整查询,由于原始查询(id=-1)可能返回空,最终会显示UNION后查询的结果,其中就包含了database()函数返回的数据库名称。
6.通过数据库名来获取信息
6.1: information_schema.schemata 系统表
核心前提:利用information_schema系统库
information_schema是 MySQL(5.1 及以上版本)内置的系统数据库,它存储了整个数据库服务器的元数据(即数据库、表、列等的结构信息)。黑客通过注入语句查询这个库,就能获取目标数据库的详细结构。
information schema Schemata
关键字段 : schema_name(数据库名称)。
default_character_set_name:数据库默认的字符集。
default_collation_name:数据库默认的排序规则。
用途:通过查询information_schema.schemata表,可以获取 MySQL 服务器中所有存在的数据库名称;默认的字符集;默认的排序规则
Selsct ++++schema_name++++ FROM ++++information_schema.schemata++++ ;
从系统数据库 information_schema 的 schemata 表中
读取所有数据库的名称(schema_name 字段)
http://127.0.0.1/sqli/Less-3/?id=-1') union select 1,(select group_concat(schema_name) from information_schema.schemata),3--+
查询数据库的默认字符集(default_character_set_name)默认排序规则(default_collation_name)
从 information_schema.schemata 表中获取这两个字段的值,命令
http://127.0.0.1/sqli/Less-5/?id=-1' union select extractvalue("doc",concat('~',(select group_concat(schema_name) from information_schema.schemata))),2,3;--+
http://127.0.0.1/sqli/Less-3/?id=-1') union select 1,(select group_concat(schema_name, default_character_set_name, default_collation_name) from information_schema.schemata),3--+
这条命令会返回所有数据库的名称、对应的默认字符集(如 utf8mb4)和默认排序规则(如 utf8mb4_general_ci);
如果只想查看某个特定数据库(例如 testdb)的信息,可加上 WHERE 条件:
SELECT ++++schema_name, default_character_set_name, default_collation_name++++ FROM ++++information_schema.schemata++++ WHERE schema_name = 'testdb'; 替换为目标数据库名
http://127.0.0.1/sqli/Less-3/?id=-1') union select 1,(SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata WHERE schema_name LIKE '%SysYour%'),3--+
是通过模糊匹配,从目标数据库中查询所有名称包含 SysYour 字符的数据库名称,并将结果合并显示
http://127.0.0.1/sqli/Less-3/?id=-1') union select 1,
(select concat(schema_name,':',default_character_set_name,':',default_collation_name)
FROM information_schema.schemata LIMIT 0,1),3--+
这条注入语句会返回第一个数据库的名称、字符集和排序规则,
CONCAT(a, ':', b, ':', c):SQL 的字符串拼接函数,将三个字段的值用:连接成一个字符串(例如test_db:utf8mb4:utf8mb4_general_ci);
LIMIT 0,1:限制只返回第 1 条记录(0表示起始索引,1表示数量),因此最终只返回 "第一个数据库" 的信息。
6.2: information_schema.tables
information_schema.tables:存储所有表的信息;无论这些表属于哪个数据库
关键字段: table_schema ; table_type ; table_name
table_type 是 information_schema.tables 系统表中的一个字段,用于表示 "表的类型",即区分当前记录描述的是哪种类型的数据库对象(是真实表、视图还是其他类型)。
table_name 是字段名;存在于 information_schema.tables 这一系统表中,专门用于存储 "表的名称"。
table_schema 是数据库系统表中的一个关键字段,用于表示 "表所属的数据库名称"。它的核心作用是建立 "表" 与 "数据库" 之间的关联,帮助定位表所在的数据库
例:若 webapp 数据库中有一个 users 表,那么在 information_schema.tables 中,这条记录的 table_schema 是 webapp,table_name 是 users。 最常用的场景是筛选指定数据库中的表或列,避免查询到其他数据库的信息。
SELECT ++++table_name++++ FROM ++++information_schema.tables++++ WHERE table_schema = 'webapp';
WHERE table_schema = 'webapp':筛选条件,table_schema 字表
示表所属的数据库名称,这里指定只查询 webapp 数据库中的表。
用途:通过筛选table_schema(所属数据库),可以获取指定数据库中的所有表名
table_type 的详细解释
BASE TABLE:表示 "基础表",即真实存储数据的普通表(我们日常创建的表默认都是这种类型)。
VIEW:表示 "视图",是基于一个或多个表的查询结果创建的虚拟表,不实际存储数据,只保存查询逻辑。
SYSTEM VIEW:表示 "系统视图",是数据库系统自带的视图(如 information_schema 中的部分视图)。
主要用于筛选特定类型的表,避免查询到不需要的对象(如视图)。
- 只查询 "真实表"(排除视图)
需求:查询 webapp 数据库中所有真实存储数据的表(排除视图)。
SELECT table_name FROM information_schema.tables WHERE table_schema = 'webapp' -- 限定数据库
AND table_type = 'BASE TABLE'; -- 只保留普通表
通过 table_type = 'BASE TABLE' 筛选,结果中只会包含真实存储数据的表,不会出现视图。
- 只查询 "视图"
需求:查询 webapp 数据库中所有的视图(不看普通表)。
SELECT table_name FROM information_schema.tables WHERE table_schema = 'webapp' AND table_type = 'VIEW'; -- 只保留视图
用于单独管理或查看数据库中的视图对象(比如检查视图的定义是否正确)。
- 查看所有类型的表(用于对比)
需求:查看 webapp 数据库中所有表和视图,并区分它们的类型。
SELECT table_name AS '名称', table_type AS '类型' -- 显示表的类型FROM information_schema.tables WHERE table_schema = 'webapp';
核心用途:在查询表信息时,通过筛选 table_type 可以精准获取需要的对象类型(比如只查真实表,或只查视图)。
在 SQL 注入场景中:通常会用 table_type = 'BASE TABLE' 筛选出真实存储数据的表,因为这类表更可能包含敏感信息(如用户表、订单表)。
6.3: information_schema.columns
information_schema.columns:记录了当前 MySQL 服务器中所有表的所有列(字段)的基本信息。
关键字段:table_schema table_name column_name data_type:
Data(数据(dA ta))
http://127.0.0.1/sqli/Less-5/?id=-1' union select extractvalue("jdf",concat("~",(select group_concat(column_name) from information_schema.columns where table_name='COLLATIONS'))),2,3;--+