探索

如何防止sql注入攻击

时间:2010-12-5 17:23:32  作者:热点   来源:探索  查看:  评论:0
内容摘要:2017年,美国征信巨头Equifax因一个未打补丁的漏洞,泄露1.43亿用户数据。事后调查发现,攻击者并非用了什么惊天动地的黑客技术——他们只是把恶意SQL语句塞进了一个公开的查询接口。这个接口,本

2017年,何防美国征信巨头Equifax因一个未打补丁的止s注入漏洞,泄露1.43亿用户数据。攻击事后调查发现,何防攻击者并非用了什么惊天动地的止s注入黑客技术——他们只是把恶意SQL语句塞进了一个公开的查询接口。这个接口,攻击本应只接受“用户ID”,何防却稀里糊涂地把攻击者输入的止s注入字符串当作SQL代码执行了。这就是攻击SQL注入,一个存在了二十多年、何防至今仍高居OWASP Top 10榜单的止s注入“老古董”攻击。

SQL注入的攻击原理说白了就一句话:把用户输入当成了代码。你的何防程序本来想执行“SELECT * FROM users WHERE id = '用户输入'”,结果用户输入的止s注入是“' OR '1'='1”,整个查询就变成了“SELECT * FROM users WHERE id = '' OR '1'='1'”。攻击瞧,条件恒为真,攻击者直接拿到了全表数据。更狠的还能用“; DROP TABLE users; --”把整个表删了。

那怎么防?最核心的一条:永远不要用拼接字符串的方式构造SQL语句。有些程序员图省事,喜欢写“$sql = “SELECT * FROM users WHERE id = ” . $_GET['id']”,然后直接丢给数据库执行。这是最危险的写法,等于把数据库的钥匙挂在门口。

正确的做法是参数化查询(Prepared Statement)。拿Java的JDBC举例,你用“?”占位符写好SQL模板,再把用户输入作为参数传进去。数据库驱动会严格区分“SQL结构”和“数据”,用户输入再狡猾,也只会被当作单纯的字符串值,而不是代码。Python的sqlite3、PHP的PDO、Node.js的mysql2库,都支持参数化查询。这是第一道防线,也是最有效的一道。

光有参数化还不够。有些场景,比如动态表名、动态排序字段,没法用占位符。这时候就得上白名单校验。比如你要允许用户按“价格”或“销量”排序,那就把这两个字段名写死在代码里,用户传什么你都先比对一下,不在白名单里的直接拒绝。别想着黑名单过滤,黑名单永远不完整——攻击者可能用注释符、编码绕过、大小写混淆,总有一种方式能溜进去。

还有个细节容易被忽略:数据库账号权限。很多项目图省事,连接数据库用的都是root或管理员账号,权限大得能删库。一旦被注入,攻击者直接拿到最高权限。应该按需分配——查询业务用只读账号,写操作单独用一个账号,DDL操作(建表、删表)干脆禁用。这样就算被注入,攻击者能做的也极其有限。

再补充一个实战中常见的坑:ORM框架不等于安全。很多人觉得用了MyBatis、Hibernate就万事大吉,但MyBatis的“${ }”语法就是纯字符串拼接,跟手写SQL没区别。开发时务必坚持用“#{ }”参数占位。我见过不少团队,代码评审时没人注意到某个查询用了“${ }”,结果被扫描工具扫出漏洞才慌慌张张去改。

最后说个真实经历。去年帮一个朋友排查他的电商后台,发现登录接口居然能直接绕过密码——输入“admin' --”就能以管理员身份进去。原因就是登录SQL写成了字符串拼接,注释符把后面的密码校验逻辑全“注释”掉了。修复只花了十分钟,改成参数化查询,问题瞬间消失。但谁也不知道在这之前,这个漏洞已经暴露了多久。

SQL注入不是高深的黑客艺术,它就是一道“把输入当代码”的算术题。防住它的关键也不在花哨的安全产品,而在写每一行SQL时,心里绷着那根弦:用户输入永远只是数据,不是逻辑。

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap