一个朋友的入检公司去年被拖库了,整整六百万条用户数据挂在暗网上论斤卖。入检事后排查,入检攻击入口居然是入检登录框里那个看起来人畜无害的用户名输入框——程序员图省事,把参数直接拼进SQL语句,入检连个过滤都没做。入检这大概是入检sql注入最经典的死法,但真正让我后背发凉的入检,是入检这种漏洞到现在依然遍地都是。
sql注入的入检本质其实特别朴素:你写SQL查询时用了字符串拼接,用户输入的入检引号、注释符、入检联合查询关键字混进去,入检数据库就分不清哪些是入检你的代码,哪些是入检用户的数据。拿个最简单的例子,登录验证写的是SELECT * FROM users WHERE name='$user' AND pass='$pass',攻击者在用户名里填个' OR '1'='1,整条语句就变成了恒真条件,密码那栏随便敲几个字符就能登进去。这哪是黑客技术,分明是小学数学题。
但检测起来就没这么直白了。我见过不少团队拿正则表达式扫关键字,看见union、select就报警,结果漏掉了一堆用注释符/*断句、用编码绕过的变种。真正靠谱的检测得从两个维度下手:静态分析看代码里有没有危险拼接模式,动态检测则往输入点丢恶意payload,观察响应差异。前者像体检拍CT,后者像拿针扎穴位试反应,各有各的盲区。
说个具体案例。之前帮一家电商平台做渗透测试,他们的搜索接口用了参数化查询,理论上该是安全的。但我把请求里的keyword参数改成abc%' AND SLEEP(5)-- ,页面居然真卡了五秒才返回。后来查代码才发现,开发在ORM框架之外写了个原生SQL做模糊匹配,参数化只套了外层,内层拼接照样裸奔。这种藏在业务逻辑夹缝里的注入,靠扫描器根本扫不出来,得靠人脑模拟攻击者的思维路径。
动态检测有个讨巧的技巧叫布尔盲注判断。你往参数里塞AND 1=1和AND 1=2两个请求,如果前者返回正常页面、后者报错或者内容不同,基本就能断定存在注入点。更隐蔽的时间盲注则用IF(condition, SLEEP(5), 0)这种写法,通过响应延迟来盲猜数据库内容。这些手段听起来玄乎,其实就是跟数据库玩你问我答的猜谜游戏。
工具方面,sqlmap确实好用,但别迷信它。我见过有人拿sqlmap默认配置扫一个加了WAF的站点,直接被拦截封IP,转头就骂工具垃圾。实际上调整下--tamper参数,用空间注释替换、大小写混写这些绕过技巧,往往就能撕开防线。工具是死的,思路是活的,这行当永远在拼谁更懂数据库的脾气。
最后说句掏心窝的话,检测sql注入最有效的工具还是代码审查。自动化工具能帮你筛掉七八成低级错误,但剩下那两成藏得深的,全得靠人肉翻代码时突然冒出的那句“这地方不对劲”。毕竟数据库不撒谎,撒谎的永远是写代码的人。