网站差点被关停,仅因为一条SQL bug

事情经过:

因为这几天家里小孩子病了,所以没有怎么关注网站。昨天一早收到了服务商的一封警告:主机因有害信息即将被关停通知。当时就吓了小酋一跳:哇塞,难道哪篇帖子触及了红线?根据服务商提供的信息进行排查,发现原来是有人恶意发帖,而搜索语句中 MySQL AND 和 OR 联合使用不当,导致没有通过审核的文章放出来了,从而被服务商扫描到里面包含的敏感、有害信息。

网站差点被关停,仅因为一条SQL bug

MySQL AND 和 OR 联合使用怎么引入的坑呢?

这里以网上的一个例子做说明(为什么不用小酋的?当然是为了安全,再收到警告我都要哭了,当然小酋已经把网站发帖、回复的权限和审核机制限制的死死的了,再也不开方便之门了。给他人方便,就是给自己添麻烦啊!)

查询数据表中的内容:

SELECT * FROM products;

网站差点被关停,仅因为一条SQL bug

组合 AND 和 OR 带来了一个有趣的问题。为了说明这个问题,来看一个例子。假如需要列出价格为10美元(含)以上且由 BRS01 或 DLL01 制造的所有产品。下面的 SELECT 语句使用 AND 和 OR 操作符的组合建立了一个WHERE 子句:

SELECT prod_name, prod_price
FROM products 
WHERE vend_id = 'BRS01' 
  OR vend_id = 'DLL01' 
  AND prod_price >= 10 ;

网站差点被关停,仅因为一条SQL bug

请看上面的结果。返回的行中有两行价格小于10美元,显然,返回的行未按预期的进行过滤。

为什么会这样呢?

原因在于计算的次序!AND的优先级高于OR,因此会对AND两边的条件先操作,然后再与OR的条件结合。

当 SQL 看到上述 WHERE 子句时,它理解为“由供应商 DLL01 制造的任何价格为10美元(含)以上的产品,或者由供应商 BRS01 制造的任何产品而不管其价格如何”。换句话说,由于 AND 在计算次序中优先级更高,操作符被错误地组合了。(小酋搜索语句中,文章状态就是这样被错误组合的)

此问题的解决方法是使用圆括号明确地分组相应的操作符。请看下面的 SELECT 语句及输出:

SELECT prod_name,prod_price 
FROM products 
WHERE (
    vend_id = 'BRS01' 
    OR vend_id = 'DLL01'
  ) 
  AND prod_price >= 10 ;

网站差点被关停,仅因为一条SQL bug

这条 SELECT 语句与前一条的唯一差别是,这条语句中,前两个条件用圆括号括了起来。因为圆括号具有较 AND 或 OR 操作符高的计算次序,DBMS 首先过滤圆括号内的 OR 条件。这时,SQL 语句变成了选择由供应商 BRS01 或 DLL01 制造的且价格都在10美元(含)以上的任何产品,这正是我们所希望的。

任何时候使用具有 AND 和 OR 操作符的 WHERE 子句,都应该使用圆括号明确地分组操作符。不要过分依赖默认计算次序,即使它确实是你想要的东西也是如此。使用圆括号没有什么坏处,它能消除歧义。

最后说一句:生活不易,莫要搞事!



留言