sql注入能打进去,入漏前提往往不是洞存的前开发者的代码写得有多烂,而是入漏他压根没想过“用户输入”和“程序指令”会被混在一起。
我见过最典型的洞存的前案例,是入漏一家小公司的后台登录框。密码框里输入' or 洞存的前'1'='1,直接就进了管理页面。入漏开发者委屈地说,洞存的前他明明用了参数化查询。入漏可问题出在另一个地方——他为了做“模糊搜索”,洞存的前把用户输入直接拼进了一个动态排序的入漏字段里。那个字段本意是洞存的前接收列名,结果被塞进了一段字符串拼接的入漏SQL里,参数化查询救不了它。洞存的前
所以,入漏sql注入存在的第一个前提,是程序里存在“字符串拼接SQL”的路径。不管是WHERE子句、ORDER BY、还是表名,只要用户输入能碰到拼接点,就有戏。但这还不够。
第二个前提,是数据库的错误信息或者响应差异能被利用。有些系统把拼接点藏得很深,你输入单引号,它报错,你输入逻辑判断,它返回不同内容——这叫“可观测性”。如果所有错误都被吞掉,返回永远是一张白纸,那就算有注入点,你也很难确认它在哪。但别高兴太早,盲注技术就是为这种场景准备的,时间延迟、布尔判断,总能挤牙膏一样挤点信息出来。
第三个前提,往往被技术文章忽略——权限。很多sql注入漏洞看起来能打,但实际影响有限。比如你注入成功了,可连接数据库的账号只有SELECT权限,那你顶多拖几张表。真正致命的注入,是数据库账号有FILE权限,能写webshell,或者有调用存储过程的权限,能执行系统命令。我见过一个案例,注入点能读全库数据,但DBA把账号权限收得很紧,最后攻击者只能拿数据勒索,没法直接控制服务器。这算不幸中的万幸。
再说个反直觉的事。有些开发者觉得,只要用了ORM框架就安全了。可ORM也有原生查询接口,一旦用了rawQuery或者createNativeQuery,又没做过滤,拼接照样发生。工具只是工具,关键看人怎么使。
最后,sql注入能成立,还跟“输入校验的粒度”有关。你以为你过滤了单引号、过滤了关键字,可如果过滤逻辑放在解码之后、拼接之前,而程序内部又对输入做了二次URL解码或Unicode归一化,那你的过滤就是张破网。有个老案例,攻击者把SELECT写成SeLeCt,或者用%73%65%6c%65%63%74编码,就绕过了简单的黑名单。这提醒我们,过滤永远不如“参数化”来得干净。
说穿了,sql注入的前提,就是开发者把“数据”和“代码”混为一谈。你让用户输入一个值,却允许这个值去改变SQL语句的结构——这才是最根本的病灶。跟编程语言无关,跟框架无关,跟防火墙也无关。只要有人写出拼接语句,且错误信息或响应可被探测,且数据库账号权限没锁死,那漏洞就摆在那儿,等着某个好奇的家伙往输入框里敲上一个单引号。