当前位置:首页 > 知识

sql漏洞

2011年,一个叫“小敖”的网友在乌云平台发了一条漏洞报告。某省移动公司的充值页面,输入手机号的地方加个单引号,页面直接报SQL语法错误。他把单引号换成 ' or '1'='1,登录框就开了。再往下,他用 union select 把数据库里的管理员账号密码全捞了出来。整个过程不到二十分钟。

这就是SQL注入。说穿了,它不是什么高深的技术,本质是程序员写代码时偷懒,把用户输入的内容直接拼进了SQL语句里,数据库分不清哪部分是代码、哪部分是数据,用户说什么它就执行什么。

一个真实的拼接现场

看一段典型的PHP代码:

$sql = "SELECT * FROM users WHERE username = '" . $_POST['username'] . "' AND password = '" . $_POST['password'] . "'";

正常用户输入 admin 和 123456,拼出来的语句没问题。但如果攻击者在用户名框里填 admin' --,SQL就变成了:

SELECT * FROM users WHERE username = 'admin' --' AND password = '...'

-- 在SQL里是注释符,后面的密码验证直接被注释掉了。数据库只检查用户名是否存在,密码根本不看。登录成功。

我第一次看到这个的时候觉得挺荒诞的——一个注释符号就能绕过整个认证体系。但事实就是这样,数据库它只认语法,不认意图。

危害远不止登录绕过

很多人以为SQL注入就是绕个登录,其实那只是最浅的一层。

2015年,英国电信运营商TalkTalk被一个15岁的少年用SQL注入攻破,窃取了15.7万用户的个人信息,公司股价暴跌,损失超过6000万英镑。少年用的工具?一个叫sqlmap的开源软件,敲一行命令的事。

SQL注入能做的事包括但不限于:拖库(把整个数据库下载下来)、提权(获取数据库管理员权限后执行系统命令)、篡改数据(改余额、改订单状态)。如果数据库配置不当,攻击者甚至能通过 xp_cmdshell 这类存储过程直接控制服务器操作系统。

我见过一个电商网站的后台,商品搜索框存在注入。输入 %' and 1=1 -- 返回所有商品,输入 %' and 1=2 -- 返回空。就这一个点,能一步步猜出数据库名、表名、字段名,最后把用户的手机号、地址、甚至支付记录全拿走。全程不需要任何高级工具,浏览器地址栏就够了。

为什么二十年了还没绝迹

SQL注入是最古老的Web漏洞之一,1998年就有公开文档。二十多年过去,它依然排在OWASP Top 10里。

原因不复杂。一方面,老旧系统太多。很多政府、医院、学校的内部系统是十几年前外包做的,代码质量堪忧,上线之后没人动过,也没人敢动。另一方面,新手开发者还在犯同样的错误。培训里讲预编译语句,实际写代码时图省事,字符串拼接顺手就来。

防御方法其实很明确:参数化查询(预编译语句)是根本解法,把所有用户输入当作参数传给数据库,而不是拼进SQL字符串。再加上最小权限原则——Web应用连接数据库的账号只给必要的权限,别用root。还有WAF做一层过滤,输入验证做一层兜底。

但说到底,技术方案从来不缺,缺的是写代码那个人愿不愿意多打几个字。

我自己的习惯是,每次看到拼接SQL的代码,不管三七二十一先标个红。因为你永远不知道下一个输入框里,用户会填什么进来。

分享到: