ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SQL注入双写绕过实战:从基础原理到CTF解题技巧

SQL注入双写绕过实战:从基础原理到CTF解题技巧 1. 项目概述与核心挑战最近在复盘一些经典的CTF题目BUUCTF平台上的“[极客大挑战 2019]BabySQL”这道题可以说是Web安全入门特别是SQL注入学习路上的一块绝佳的“磨刀石”。乍一看标题“BabySQL”似乎暗示着题目非常简单但实际接触下来你会发现它巧妙地融合了基础注入原理和常见的过滤绕过技巧非常适合用来检验和巩固对SQL注入核心流程的理解。这道题的核心场景是一个典型的登录框或者查询接口背后连接着一个数据库而我们的目标就是利用这个接口存在的SQL注入漏洞绕过前端或后端设置的一些简单过滤最终获取到数据库中的关键信息比如flag。对于刚接触安全测试的朋友来说它能让你清晰地看到一个看似简单的输入点如何通过精心构造的Payload一步步“撬开”数据库的大门理解从信息探测到数据获取的完整链条。2. 解题思路与注入点探测面对任何一个疑似存在注入的点第一步永远是信息收集和试探。对于BabySQL这道题我们通常会从一个最简单的单引号‘开始。在输入框可能是用户名或查询框中输入一个单引号并提交目的是触发数据库的语法错误。如果页面返回了与正常输入不同的错误信息比如包含“SQL syntax”、“MySQL”、“You have an error”等关键词那么这里存在SQL注入漏洞的可能性就非常大。这一步至关重要它直接确认了我们的攻击面。确认存在注入后下一步是判断注入类型和闭合方式。常见的闭合方式有单引号闭合‘...‘、双引号闭合“...”、单引号加括号‘(‘...‘)等等。通过尝试‘ and ‘1‘‘1和‘ and ‘1‘‘2观察页面返回结果的差异可以判断注入点是否在布尔盲注的上下文中可用。如果‘1‘‘1返回正常页面真而‘1‘‘2返回错误或空白页面假那么我们就可以利用这种真/假响应来逐位提取数据。另一种常见方式是联合查询注入Union Inject这通常需要先确定当前查询语句的字段数。使用‘ order by N--这样的Payload通过不断增加N的值直到页面报错就能确定字段数。例如‘ order by 3--正常而‘ order by 4--报错则说明原查询语句由3个字段组成。注意在实际测试中注释符的选择很重要。--后面有个空格是MySQL的单行注释#也是。但有时#会被URL编码或过滤--加号在URL中代表空格是另一种常见的替代写法。BabySQL这道题可能就对某些注释符或关键词进行了过滤这就需要我们灵活变通。3. 关键词过滤绕过策略解析“BabySQL”之所以不是一道“一眼到底”的题就在于它设置了一些过滤规则。根据常见的出题思路和网络上的解题分享这道题很可能过滤了某些关键的SQL关键词比如union,select,from,where,or,and等。当我们的Payload中包含这些词时可能会被替换为空字符串str_replace或者直接导致请求被拦截。这时双写绕过是一种非常经典且有效的技巧。其原理是如果过滤函数只是简单地将目标关键词如union替换成空字符串那么当我们输入ununionion时中间的union被删除剩下的部分un和ion又会重新组合成union。所以我们需要将可能被过滤的关键词进行双写处理union-ununionionselect-selselectectfrom-frfromomwhere-whwhereereor-oorrand-anandd除了双写大小写混合绕过如UnIoN、SeLeCt有时也有效这取决于过滤逻辑是否区分大小写。内联注释/*!*/在某些场景下也能绕过简单的关键词匹配例如/*!union*/。对于这道题双写绕过通常是解题的关键步骤。你需要敏锐地观察页面返回如果使用了union select却没有任何回显或报错就要立刻联想到可能是union或select被过滤了尝试将其双写。4. 完整注入流程与数据提取实战假设我们已经通过‘ order by 3--探测出字段数为3并且确认了union和select等关键词需要双写绕过。接下来就是构造完整的联合查询Payload来获取数据库信息。流程如下第一步探测回显点我们使用双写后的关键词构造Payload确定哪几个字段的内容会显示在页面上。‘ ununionion selselectect 1,2,3--如果页面正常显示并且出现了数字“2”和“3”假设123是测试数据说明第2和第3个字段是回显点。我们后续就可以将想要查询的信息放在这两个位置。第二步获取当前数据库名和用户将回显点替换为我们想查询的函数。‘ ununionion selselectect 1, database(), user()--database()函数返回当前数据库名user()函数返回当前数据库用户。从回显中我们就能知道我们在操作哪个数据库。第三步获取数据库中的所有表名在MySQL中information_schema.tables表存储了所有表的信息。我们查询该表并限定表所属的数据库table_schema为我们刚刚得到的数据库名。‘ ununionion selselectect 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schemadatabase()--这里用到了group_concat()函数它将多行结果合并成一个字符串方便查看。同样information_schema和where也进行了双写infoorrmation_schema,whwhereere。执行后我们就能得到该数据库下的所有表名比如可能看到users,flag等。第四步获取目标表的所有列名假设我们发现了名为flag的表接下来需要知道这个表里有哪些列。查询information_schema.columns表。‘ ununionion selselectect 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_schemadatabase() anandd table_name‘flag‘--这里注意table_name‘flag‘中的flag是字符串需要用单引号括起来。执行后可以得到该表的列名例如id,flag等。第五步最终提取Flag数据知道了表名flag和列名flag最后一步就是取出数据。‘ ununionion selselectect 1,2,flag frfromom flag--或者如果列名不是flag则替换为实际的列名。执行后真正的flag就应该在页面的回显位置显示出来了。5. 工具辅助与手动注入的权衡在解决这类题目时很多人会想到使用自动化工具如sqlmap。对于BabySQL理论上可以通过sqlmap的--tamper参数指定脚本来处理双写绕过。例如可以编写一个简单的tamper脚本将union替换为ununionion。命令可能类似于sqlmap -u “http://target.com/login.php“ --data“usernameadminpasswordpass“ --tamperdoublewrite.py --dbs然而在CTF比赛中尤其是对于这种知识点明确的入门题我更推荐手动注入。原因有三点第一手动注入能让你深刻理解每一步的原理和Payload的构造逻辑这是工具无法替代的学习过程第二题目环境可能对自动化工具的发包频率、特征有检测或限制第三像双写绕过这种过滤有时需要根据页面反馈即时调整手动操作更灵活。工具更适合在复杂、重复的实战渗透测试中节省时间而学习阶段亲手“拆解”每一个步骤至关重要。6. 常见错误与排查技巧实录在实际操作BabySQL或类似题目时很容易踩到一些坑。这里记录几个我遇到过的典型问题及解决方法问题1注释符失效。输入‘ union select 1,2,3--没反应。这可能是因为--没有被正确解析。尝试换成#注意在URL中或表单提交时#可能被当作锚点需要编码为%23或者使用‘ or ‘1‘‘1这种不用注释符的闭合方式。在BabySQL中使用--或%23都是值得尝试的选项。问题2双写后语法错误。当你将union select 1,2,3 from flag双写成ununionion selselectect 1,2,3 frfromom flag后页面报错。请仔细检查双写是否正确。一个常见的错误是双写的位置不对或者漏掉了某个关键词。例如information_schema双写为infoorrmation_schema确保被过滤的部分or被包裹在中间。另一个检查方法是在本地文本编辑器里模拟过滤把疑似被过滤的词删掉看剩下的部分是否能重新组合成正确的SQL语句。问题3无回显点。使用了union select 1,2,3但页面上看不到数字1、2、3。这可能有两个原因一是字段数判断错误需要用order by重新确认二是页面虽然执行了查询但回显位置不在我们看到的网页主体部分可能在页面标题、隐藏标签或源代码注释里。一定要养成查看网页源代码CtrlU的习惯。问题4过滤了information_schema。这是一个进阶的过滤。在MySQL 5.7及以上版本如果information_schema被过滤可以尝试使用sys.schema_auto_increment_columns等替代视图来获取表信息但这在CTF题中较少见。BabySQL通常只过滤基础关键词。如果遇到可以考虑时间盲注或布尔盲注来逐字猜解表名和列名。为了更清晰我将常见问题、可能原因和解决思路整理成下表问题现象可能原因排查与解决思路输入单引号后无错误1. 注入点不存在2. 错误被前端/后端屏蔽3. 闭合方式不是单引号。1. 尝试数字型注入id1 and 112. 尝试双引号“3. 尝试‘),“)等闭合。union select无回显1. 关键词被过滤2. 字段数不对3. 回显点不在页面可视区域。1. 尝试双写、大小写绕过2. 用order by重新确认字段数3. 查看网页源代码。双写Payload仍报错1. 双写格式错误2. 还有其他关键词被过滤如from,where3. 空格被过滤。1. 仔细检查双写位置2. 对所有关键词进行双写3. 尝试用/**/代替空格。知道表名后查不到数据1. 表名或列名猜错2. 数据不在当前表3. 查询语句构造有误。1. 重新确认information_schema中的列名2. 检查SQL语句闭合和语法。7. 从题目到实战的思考延伸解出BabySQL的flag只是开始更重要的是理解其背后的安全逻辑。这道题模拟了一个非常真实的场景开发者在处理用户输入时试图通过简单的字符串替换来过滤危险关键词但由于只进行了一次替换且规则简单导致了双写绕过漏洞。在真实的项目开发中防御SQL注入的正确做法应该是使用参数化查询预编译语句这是最根本、最有效的办法。让SQL引擎严格区分代码和数据用户输入永远被视为数据而非代码的一部分。使用安全的ORM框架成熟的ORM框架如SQLAlchemy, Hibernate通常内置了防注入机制。最小权限原则数据库连接账户不应具有DROP,FILE等高级权限仅授予其应用所需的最小权限。输入验证与过滤虽然不能作为主要防御手段但针对业务逻辑进行严格的输入格式、类型、长度验证可以阻挡大部分非法输入。过滤应使用白名单而非黑名单。对于安全测试者而言BabySQL训练了我们“见招拆招”的能力。面对过滤思路要开阔除了双写还有编码URL编码、十六进制、等价函数替换substring-mid-substr、注释符混淆、利用数据库特性如MySQL的/*!50001select*/等多种绕过方式。这道题是一个很好的起点它告诉你安全防护如果只做表面功夫是多么不堪一击。手动完成一次这样的注入比看十篇理论文章印象都深刻。最后在实战测试中务必在获得授权的范围内进行所有的技术学习都应以建设和提升安全性为目的。
返回列表