2011年冬天,数据我在一台测试服务器上敲了一行单引号,库注整个登录框直接吐出了数据库里三千多个用户的数据明文密码。那是库注我第一次亲眼见到SQL注入的威力——没有漏洞扫描器,没有花哨工具,数据就是库注输入框里一个
' OR '1'='1,后端拼接的数据SQL语句当场叛变。原理其实不复杂。库注很多早期Web应用把用户输入直接塞进SQL查询字符串里。数据比如登录验证写的库注是
SELECT * FROM users WHERE username='$user' AND password='$pass'。你在用户名框里填admin'--,数据密码随便写,库注拼接后变成SELECT * FROM users WHERE username='admin'--' AND password='xxx'。数据两个连字符把后面的库注密码校验注释掉了,数据库只认前半句,数据直接放行。这跟锁没关系。门是好的,锁也是好的,但你把钥匙插进去的时候,顺手把整扇门卸了。
注入的类型比想象中多。数字型、字符型、报错注入、盲注、时间盲注、堆叠查询。盲注最磨人,页面不回显任何数据,你只能靠
AND SLEEP(5)让数据库睡五秒,通过响应时间一个字符一个字符地猜库名。2014年有个渗透项目,我写了个Python脚本跑了整整一夜,才从MySQL里拖出一张管理员表的哈希。脚本日志刷了四万行,每行只确认一个字母。有人觉得预编译语句(Prepared Statement)能一劳永逸。确实,参数化查询把SQL结构和数据彻底分离,数据库先编译模板再填值,注入串会被当成纯文本处理。但现实里绕过的方式不少。比如ORDER BY后面没法用占位符,很多框架偷懒直接拼接;比如某些ORM的
whereRaw方法,开发者图方便把用户输入原样丢进去。我见过一个项目,登录接口用了预编译,但排序参数?sort=直接拼在SQL末尾,照样被注入。WAF也不是保险箱。注释符混淆、大小写混写、URL编码、Unicode编码、内联注释
/*!50000SELECT*/,绕过规则库的手段层出不穷。2019年某次众测,目标站有云WAF,我试了十几种payload全被拦。最后用%bf%27这种畸形编码绕过了字符集判断,WAF解码失败直接放行,后端MySQL却把它当单引号处理。一个编码差异,防线就穿了。防守端最有效的手段其实很朴素。参数化查询覆盖所有数据库交互点,这是根上的事。数据库账号权限最小化,Web应用连库的账号不该有
FILE权限或xp_cmdshell执行权。错误信息别回显到前端,把SQLException堆栈直接打印在页面上,等于给攻击者递地图。定期用sqlmap跑一遍自己的接口,别等别人来跑。我至今保留着一个习惯:看到任何带参数的URL,手会痒。
顶: 9踩: 9?id=1后面加个单引号,看页面报不报错。这不是破坏欲,是职业病。数据库注入活了二十多年,原理没变过,变的只是包装。只要还有人把用户输入当代码执行,这门手艺就不会失传。






评论专区