客户在江西南昌市红谷滩区做二手车交易平台,有天早上发现网站首页被篡改,打开之后跳转到了一个博彩网站。登录服务器检查,发现数据库里多了一个不认识的表,里面存了几万条垃圾数据。
排查入侵途径
检查nginx访问日志,发现攻击者是通过一个搜索接口进来的。那个接口直接把用户输入的参数拼到了SQL语句里,没有做任何过滤。攻击者利用这个漏洞,构造了一个UNION查询,把数据库里的管理员账号密码导了出来,然后用管理员权限登录后台,篡改首页文件。
紧急处理
先把网站下线,防止用户访问被跳转。然后修改了所有管理员账号的密码,把被篡改的首页文件恢复成备份版本,删除了数据库里新增的垃圾表。
修复漏洞
找到那个存在注入漏洞的搜索接口,把SQL语句改成了参数化查询。原来的写法是直接拼接字符串:
$sql = "SELECT * FROM cars WHERE brand = '" . $_GET['brand'] . "'";
改成了预处理语句:
$stmt = $pdo->prepare("SELECT * FROM cars WHERE brand = ?"); $stmt->execute([$_GET['brand']]);
参数化查询会把用户输入当作数据而不是SQL代码来处理,从根本上杜绝了注入的可能。
同时检查了其他所有涉及数据库查询的接口,把类似的拼接写法全部改成了参数化查询。
加固措施
一是在nginx层加了WAF规则,拦截常见的SQL注入特征。宝塔面板的Nginx防火墙里有现成的规则集,开启之后能挡掉大部分自动化注入工具。
二是限制了数据库账号的权限。之前网站连接数据库用的是root账号,权限太大了。新建了一个只有增删改查权限的普通账号,网站连接数据库用这个新账号。即使被注入了,攻击者也无法执行删表、提权这些操作。
三是开启了数据库的操作日志,记录所有执行的SQL语句。万一再有异常,能快速定位到问题。
客户那边的情况
客户在南昌红谷滩区做二手车生意,平台上有几千辆车的信息。这次被攻击之后,他说之前完全不知道网站还有这种风险,以为只要服务器不宕机就没问题。
我跟他解释了一下,网站安全分好几个层面。服务器层面是防入侵,应用层面是防注入和XSS,数据层面是防泄露和篡改。每个层面都需要做对应的防护,不能只看服务器有没有宕机。
一点补充
SQL注入是最古老的Web漏洞之一,但到现在还是有人中招。根本原因就是开发的时候图省事,直接拼接SQL语句。参数化查询是解决注入最有效的方法,没有之一。如果网站用的是老代码,建议花点时间把所有SQL查询都过一遍,把拼接写法改掉。
