sql注入登录
一个登录框,入登背后可能藏着一扇门。入登门后不是入登数据库,而是入登整个服务器的控制权。
我在一次授权测试中遇到过这么个案例。入登某后台管理系统,入登登录框干干净净,入登没有验证码,入登也没有任何安全提示。入登我随手在用户名输入框敲了' or 入登1=1 --,密码随便填了一串数字。入登点击登录,入登页面直接跳转到了管理后台。入登整个过程不到三秒——没有报错,入登没有拦截,入登连个多余的白屏都没有。就像钥匙插进锁孔,门自己开了。
这不是什么高深技巧。SQL注入之所以存在,是因为开发者把用户输入直接拼进了SQL查询语句。后台代码大概是这样的:SELECT * FROM users WHERE username='$user' AND password='$pass'。当我把用户名传成' or 1=1 --,整条语句就变成了SELECT * FROM users WHERE username='' or 1=1 --' AND password='...'。两个单引号把条件闭合,1=1永远为真,--把后面的密码验证注释掉。查询结果返回了所有用户记录,系统一看有数据,直接放行。
这种漏洞的根源不在于程序员笨,而在于信任。开发者默认用户输入是“干净”的,默认密码不会包含单引号,默认没人会刻意破坏语句结构。现实恰恰相反——攻击者最擅长的就是往输入框里塞各种奇怪字符。你把输入当字符串处理,它偏要变成代码的一部分。
更麻烦的是,注入点不只存在于登录框。搜索框、排序参数、分页参数、HTTP头里的User-Agent,甚至Cookie里的某个值,都可能成为注入点。登录框只是最显眼的一个。我见过有人通过修改请求中的id参数,把1改成1 UNION SELECT username,password FROM users,直接拖走了整个用户表。那种感觉就像你本来只想看看门锁,结果发现整个房子都没有墙壁。
防御SQL注入没那么玄乎。最有效的办法是参数化查询——把用户输入当作数据,而不是SQL语句的一部分。用Java的PreparedStatement、PHP的PDO预编译,或者Python的数据库适配器自带参数绑定,都能从根上杜绝这个问题。另外,给数据库账号设置最小权限也很重要。哪怕注入成功,攻击者也只能操作他该操作的表,而不是整个数据库。
那次测试结束后,我在报告里写了一句:“该登录框可以直接获取管理员权限,建议立即修复。”后来客户回复说已经让开发改了。三个月后我复查,发现他们只是在前端加了个JavaScript校验,禁止输入单引号。我绕过前端,直接抓包改请求,又进去了。这事让我挺感慨——很多人觉得安全是加个过滤函数的事,实际上过滤黑名单永远有漏网之鱼,白名单也总有你想不到的编码绕过方式。
一个登录框的安全,本质上是对“用户输入不可信”这个原则的执行力问题。代码写得不严谨,攻击者就有机可乘。别觉得漏洞离你很远——你下一个项目里那个看起来不起眼的登录接口,可能就藏着这么一道没上锁的后门。
本文地址:http://www.79wt.cn/news/027b0399969.html
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。