以下内容翻译自laravel的官方blog,该文是laravel的作者Taylor在2019年3月发布的

关于安全方面的漏洞或潜在威胁警告,除非它已经大范围被破解和利用,否则建议的做法是直接给软件或框架的作者发邮件说明,而不要直接在网络上公开公布相关的分析和实践,那样更容易让好事之徒有机可乘,本来不知道的,一分析随便个黑客就知道了;本来不会的新手,一分析新手也可以去捣乱了,这一点希望我们的正派程序员有一个基本的认识和规范,不要为了刷什么存在感,就给自己喜欢的框架或组件“添乱”。

昨天,我收到了一封来自某个安全研究员的邮件,说使用laravel的unique验证规则的时候,当终端用户控制的输入内容(比如request里的input),被作为要排除或忽略的id参数时,就有可能导致SQL注入的危险,例如这样:

Rule::unique('users')->ignore($request->input('id'))

这个unique验证规则的“忽略特定id”的功能,也即ignore(), 原本是只接收系统产生的id的,比如自增的id,或者uuid,所以我们在官方文档上,也只列出了这一种用法:

Rule::unique('users')->ignore($user->id)

但是,如果开发者没有严格按照这种方式来,传入了终端用户控制的输入数据,来作为要排除的id或字段,那么一个精心设计的邪恶请求,就可能导致SQL注入的危险。(注意这里的“精心设计”和“可能”两个字眼,因为笔者用一些常见的SQL注入方法,并不能奏效。有些国内的安全网站故意让mysql端报错,比如故意去查找个不存在的table或字段,来展示可能的执行语句,但是既然mysql都报错了,语句再危险,也执行不了了。但是这期间的意义是,很多的SQL注入都是Error-based,也即基于你的mysql报错来进一步找机会和漏洞的,如果他看不到数据库的报错,那么攻击就会难非常多,这一点按说不是大问题,因为个人不觉得会有人在生产环境还开着laravel的报错输出,这就太不应该了。当然了,潜在的威胁也是威胁,不要因此掉以轻心。)

所以呢,我们在文档上添加了一块红色的警告,当允许用户输入的信息传入unique规则的时候,要格外小心:

file

当然了,最好是当开发者即使不小心传入了用户输入的内容,我们的框架也能自动地阻止和过滤潜在的SQL注入,这个呢是在laravel v5.8.8里做了修复,国内有些安全论坛说是5.8.5就修复了,其实是不精确的,在5.8.5里先是用了str_replace做了修复,到了5.8.6里又改成了stripslashes方法,但这些修改导致只是调用unique方法,但是不调用ignore方法时反而出错了,所以最终在5.8.8里做了修复。

所以呢,大家可以考虑升级一下laravel版本,或者在用到这里的时候,做一下手动的输入过滤,像官方修复的那样。

最后呢,交代两点:

  1. 不要随意传播这些安全相关的分析,避免影响到那些还不知道或没来得及修复的小伙伴,也避免因为这些小的细节,影响我们喜爱的框架的声誉,让一些喷子有可乘之机;
  2. 不管是什么框架与语言,在对待用户传入的数据时,都要小心谨慎,看看是否需要自己手动过滤,以避免可能的危险。