Web 安全手工识别 SQL 注入全实战(DVWA Low 完整复现 + 底层源码拆解 + 踩坑防护)

Web 安全手工识别 SQL 注入全实战(DVWA Low 完整复现 + 底层源码拆解 + 踩坑防护) 前言很多网络安全初学者刚接触渗透测试时一上来就直接使用 Sqlmap 自动化工具跑注入完全忽略手工判断注入点这一核心基础能力。在等保测评、企业渗透实战中大量 WAF 会直接拦截工具特征流量此时只能依靠手工 Payload 判断漏洞同时面试、课程实训中手工注入原理也是高频考点。本文基于 DVWA 1.10 靶场 Low 安全等级完整复现从探测、验证到利用的全套手工 SQL 注入流程附带每一步拼接后的完整 SQL 语句、后端危险源码、实验截图、漏洞成因、线上真实防护方案解决大部分新手只懂操作不懂原理的问题全文实操可 1:1 复现。 实验环境PHPStudyDVWA1.10MySQL5.7安全等级Low无任何输入过滤适合入门理解字符型注入一、SQL 注入漏洞底层原理1.1 漏洞产生核心原因Web 程序将用户可控输入URL GET 参数、表单 POST 数据、Cookie不做过滤、转义、预处理直接字符串拼接进后端 SQL 查询语句攻击者可通过特殊符号破坏原有 SQL 语法结构篡改查询逻辑。 DVWA Low 级别 SQL 注入页面后端 PHP 原始危险代码php运行?php // 获取前端传入的id参数无过滤无转义 $id $_GET[id]; // 直接拼接用户输入存在致命注入漏洞 $query SELECT * FROM users WHERE id . $id . ; // 直接执行拼接后的SQL语句 $result mysqli_query($db, $query); ?这段代码是线上最典型的高危写法$_GET[id]接收用户可控参数后未做任何校验直接拼接进 SQL 字符串给注入提供了完整利用空间。1.2 字符型注入判定关键单引号 的作用MySQL 数据库中字符串类型字段的值必须使用单引号包裹闭合。 原有查询模板固定格式WHERE id用户输入输入提前闭合原有引号造成 SQL 引号数量不匹配抛出语法报错输入输入的两个单引号一个闭合原有语句另一个和后端末尾单引号配对抵消语法恢复正常以此确认注入点存在。二、实验前置环境配置启动 PHPStudy 集成环境开启 Apache 与 MySQL 服务浏览器访问 DVWA 首页使用默认账号 admin/admin 登录左侧菜单栏找到Setup / Reset DB点击重置数据库恢复原始测试数据进入DVWA Security页面安全级别下拉选择Low点击提交保存左侧导航切换至SQL Injection靶点页面进入 User ID 输入测试界面。三、分步手工探测 SQL 注入步骤 1正常业务逻辑测试确认查询规则操作在 User ID 输入框输入数字1点击 Submit 提交 页面返回结果ID:1First name:adminSurname:admin 拼接后执行 SQLsqlSELECT * FROM users WHERE id1;作用确认页面接收 id 参数、正常查询 users 表数据摸清基础查询结构为后续异常测试做对照。步骤 2输入 1通过数据库报错初步判定注入风险Payload 输入1页面返回 MySQL 原生语法报错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 1拼接后错误 SQLsqlSELECT * FROM users WHERE id1;报错原理拆解 原始语句末尾自带单引号用户输入的1多增加了一层闭合引号整条 SQL 出现奇数单引号语法结构错乱数据库直接抛出错误并回显到页面。关键判定点网站直接输出数据库底层报错信息说明用户输入内容直接参与 SQL 拼接存在 SQL 注入高危风险。步骤 3输入 1抵消引号消除报错实锤注入漏洞存在Payload 输入1页面现象无报错正常返回 ID1 的 admin 用户数据 拼接后完整 SQLsqlSELECT * FROM users WHERE id1;逻辑说明第一个闭合id后的原有单引号第二个和后端语句末尾自带的单引号配对整条 SQL 引号数量匹配语法合法不再抛出错误。 这一步是区分 “页面报错” 和 “可利用注入点” 的关键能抵消报错即可确认漏洞可被攻击者利用。步骤 4万能注入 Payload or 11 批量读取全表数据Payload 输入 or 11页面现象一次性打印 users 表内全部 6 条测试用户数据admin、Gordon、Hack、Pablo、Bob、user 拼接后最终执行 SQLsqlSELECT * FROM users WHERE id or 11;逐段拆解注入逻辑开头提前闭合id后的原有单引号跳出原有查询条件orSQL 逻辑或运算符任意一侧条件成立整条 WHERE 判断结果为 True11永久恒真条件永远成立末尾和后端自带单引号配对保证 SQL 语法无错误。 等效查询逻辑WHERE true忽略原有 ID 限制查询 users 表内全部记录实现数据库批量信息泄露。四、手工注入标准化判断流程4.1 字符型注入三步探测法原创实操总结正常数字测试输入纯数字确认页面存在参数查询功能单引号报错探测输入页面输出 SQL 语法报错 → 存在注入风险双引号抵消验证输入报错消失、页面正常展示数据 → 确认漏洞可利用。4.2 字符型 / 数字型注入快速区分字符型注入本次实验场景参数被单引号包裹必须使用闭合原有语句才能注入数字型注入参数无引号包裹直接输入or 11即可脱库无需额外单引号。4.3 手工 Payload 拓展除基础 or 11外同场景可用等效 Payload 验证漏洞plaintext or 22 or 11-- - admin or 11#-- -与#为 MySQL 注释符可注释掉后端原有 SQL 剩余语句避免语法冲突。五、SQL 注入真实线上危害核心业务数据泄露用户账号、明文 / 哈希密码、手机号、身份证、订单数据全部脱库恶意篡改、删除数据通过 UPDATE、DELETE 语句清空业务数据表造成企业业务瘫痪服务器权限接管数据库账号拥有高权限时可通过into outfile写入 Webshell完全控制服务器合规处罚等保 2.0 明确将 SQL 注入列为高危漏洞存在该漏洞未修复会面临整改、罚款。六、生产环境完整防护方案6.1 代码层根治最优方案从根源杜绝注入使用参数化预编译查询PDO 预处理彻底分离用户输入与 SQL 语句示例安全 PHP 代码php运行?php $stmt $db-prepare(SELECT * FROM users WHERE id?); $stmt-bind_param(s, $_GET[id]); $stmt-execute(); ?预编译会将 SQL 模板与用户输入分开解析用户输入仅作为参数值不会被数据库解析为 SQL 指令。6.2 输入校验与过滤ID 类数字参数使用正则白名单仅允许 0-9 数字拦截单引号、or、union、#、-- 等特殊字符文本输入对单引号、双引号、反斜杠进行转义处理。6.3 服务器与运维层面防护关闭线上详细 SQL 报错页面统一返回自定义 404 / 错误提示禁止向前端输出数据库原生报错数据库账号最小权限Web 业务连接账号仅授予 SELECT 查询权限禁止 DROP、ALTER、FILE 等高危权限部署 WAF 应用防火墙拦截携带单引号、or、union 等注入特征的恶意请求定期渗透测试上线前手工 工具结合扫描提前修复注入漏洞。七、实验踩坑总结切换 DVWA 安全级别后未重置数据库旧数据干扰测试结果每次实验前务必 Reset DBPayload 空格缺失or11无空格会导致 SQL 语法错误or 前后必须保留空格靶场 MySQL 服务未启动页面无数据返回先检查 PHPStudy 数据库服务状态线上环境打印数据库报错攻击者可利用报错信息判断表名、字段名大幅提升注入成功率线上必须关闭。八、课后拓展练习将 DVWA 安全级别调整为 Medium分析后端数字过滤逻辑寻找绕过注入方法学习 Union 联合查询注入通过手工 Payload 爆库名、表名、字段名学习布尔盲注、时间盲注应对无回显、无报错的注入场景对比 Sqlmap 自动化注入与手工注入的优缺点总结实战中两者适用场景。