游客发表

sql注入原理及防范

发帖时间:2026-10-17 04:39:02

2011年,入原一个叫“Lsass.exe”的理及SQL注入攻击把索尼在线娱乐的数据库翻了个底朝天,超过100万用户的防范账号密码、邮箱、入原地址全被拖走。理及攻击者没用什么高级漏洞,防范就是入原在登录框里敲了一段带单引号的SQL语句。这件事让我意识到,理及SQL注入离普通人并不远,防范它可能就藏在你每天填的入原搜索框里。

SQL注入的理及本质,是防范程序把用户输入的数据当成了代码来执行。比如一个登录验证的入原SQL语句原本长这样:

SELECT * FROM users WHERE username = 'admin' AND password = '123456';

如果用户在密码框里输入 ' OR '1'='1,语句就变成了:

SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1';

数据库一看,理及'1'='1' 永远成立,防范于是直接放行。攻击者根本不需要知道真实密码。更狠的是,如果输入 '; DROP TABLE users; --,整张用户表可能直接被删掉。我见过一个真实案例,某电商网站的商品搜索参数没做过滤,攻击者用 UNION SELECT 把管理员密码哈希直接显示在页面上,整个过程不到三分钟。

为什么这种漏洞反复出现?因为很多开发者习惯把SQL语句和用户输入拼在一起。早期PHP项目里,mysql_query("SELECT * FROM news WHERE id=" . $_GET['id']) 这种写法遍地都是。拼字符串写起来快,但等于把数据库的钥匙交给了任何一个会打字的人。参数化查询其实早就有了,PDO、PreparedStatement都能解决,但总有人觉得“先上线再说”。

防范SQL注入,最有效的手段是参数化查询。它把SQL语句的结构提前编译好,用户输入只作为数据传入,不会被解释成代码。比如PHP里用PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->execute([$username, $password]);

这样即使输入里带引号或分号,数据库也只当它是普通字符。另一个常见做法是输入过滤,但我不太推荐只靠这个。黑名单永远有漏网之鱼,比如 SELECT 被过滤了,攻击者可以用 SeLeCt 大小写混写,或者用注释符 /**/ 隔开关键字。过滤规则越复杂,越容易误伤正常用户,比如有人密码里真带了个单引号。

还有一层防线是数据库权限控制。给Web应用用的数据库账号,只给必要的增删改查权限,别用root。就算注入成功了,攻击者也读不到系统表,删不了库。我见过一个运维图省事,所有项目共用一个高权限账号,结果一个注入点被利用,整个服务器上五个数据库全被导出。

最后说个容易被忽略的点:错误信息别直接吐给用户。有些网站报错时会把完整的SQL语句和数据库版本打印在页面上,这等于给攻击者递了张地图。把错误日志写到文件里,前端只显示“系统繁忙”,能省掉很多麻烦。

SQL注入不是什么高深技术,它更像是一扇没关好的门。参数化查询、最小权限、错误隐藏,这三招用好了,基本能挡住99%的注入尝试。剩下的1%,靠的是开发者每次写SQL时多问自己一句:这个变量,真的安全吗?

    热门排行

    友情链接