网鼎杯2018 Unfinish实战:从SQL注入到自动化脚本的完整解题路径

张开发
2026/6/11 20:08:14 15 分钟阅读
网鼎杯2018 Unfinish实战:从SQL注入到自动化脚本的完整解题路径
1. 漏洞发现与初步探测第一次接触这道题时我盯着那个简单的登录界面看了很久。典型的用户名密码表单看起来毫无破绽。但CTF比赛的题目往往就是这样表面风平浪静底下暗流涌动。我先尝试了最基础的SQL注入测试在用户名输入admin --结果系统直接返回用户名或密码错误连语法错误都没触发说明这里可能有严格的过滤机制。这时候就需要换个思路了。我掏出dirsearch开始扫描目录这是CTF选手的常规操作。扫描结果很有意思除了默认的login.php外还发现了register.php。这个注册页面立刻引起了我的注意因为注册功能往往涉及数据库写入操作而写入点经常存在二次注入的可能。注册时我特别注意了三个字段邮箱、用户名和密码。测试发现邮箱字段对特殊字符做了严格限制符号之后的内容会被校验格式。而密码字段在存储时可能做了加密处理不太适合作为注入点。唯独用户名字段虽然前端有长度限制但通过Burp Suite拦截修改后可以突破这个限制。2. 二次注入的利用技巧注册完测试账号后登录系统发现用户名直接显示在页面上。这个细节很关键说明用户名是从数据库读取后直接输出的。结合注册时的写入操作典型的二次注入场景就形成了恶意数据先被存入数据库之后在另一个上下文中被取出执行。我尝试构造了一个测试payloadtest(select 1)但页面显示为0。这说明注入确实存在但需要调整payload的构造方式。经过多次测试发现使用0(select ascii(substr(database(),1,1)))0这样的形式可以成功触发注入返回的数值119对应字母w正是数据库名的第一个字符。这里有个小技巧当直接拼接SQL语句不成功时可以尝试用算术运算的方式绕过。比如用连接查询结果让数据库先执行子查询再做加法运算。这种手法在不少CTF题目中都很常见。3. 过滤规则的识别与绕过随着注入的深入系统开始返回异常结果。通过对比不同payload的响应我发现几个关键字符被过滤了逗号,影响substr等函数的正常使用空格导致多词语句被阻断特定关键词如information阻止了对information_schema的查询绕过这些限制需要一些技巧对于逗号过滤可以用from...for...语法替代substr(database() from 1 for 1)空格可以用括号或注释替代select(1)或select/**/1information_schema被过滤时可以尝试使用sys库或其他替代方案我特别注意到当尝试查询sys.x$schema_table_statistics时注入失败了。这说明目标可能不是MySQL数据库或者权限设置不同。这时候就需要调整策略考虑盲猜表名或者使用其他技术手段。4. 自动化脚本的开发实战手工注入到这一步已经获取了不少信息但后续的爆破工作需要自动化。我决定用Python写个脚本主要解决两个问题自动枚举数据库名和表名自动提取flag字段内容脚本的核心逻辑是这样的def inject_char(position): payload f0(select ascii(substr((select * from flag) from {position} for 1)))0 # 注册请求 register_data { email: f{position}test.com, username: payload, password: 123 } # 登录请求 login_data {email: f{position}test.com, password: 123} # 解析返回页面获取结果 return result实际开发中遇到了几个坑需要处理会话保持确保注册和登录在同一个会话中网站可能有速率限制需要添加适当的延时字符编码转换要小心特别是处理非ASCII字符时最终脚本采用逐字符爆破的方式通过判断返回值的ASCII码来还原出完整flag。为了提高效率我还加入了多线程支持可以并行测试不同位置的字符。5. 解题过程中的经验总结这道题虽然最终解出来了但过程并不顺利。有几个关键点值得记录不要被表面现象迷惑。初始的登录页面看似安全但通过目录扫描发现的注册功能才是真正的突破口。过滤规则的识别需要耐心。通过对比不同payload的响应逐步摸清系统的过滤机制。自动化脚本要模块化开发。先验证核心功能可行再逐步完善异常处理和性能优化。遇到障碍时考虑替代方案。当sys库不可用时及时转向其他方法如猜测表名也很重要。在真实的CTF比赛中时间压力很大。建议先把整个流程手工走通确认技术路线可行后再投入时间开发自动化脚本。这样可以避免在错误的方向上浪费太多时间。

更多文章