Laravel 审计安全问题前十名
发布于 作者: Stephen Rees-Carter
自 2022 年初以来,我一直从事为 Laravel 应用程序进行 安全审计和渗透测试 的工作。我审计过各种规模的应用程序,从只有几个控制器的微型应用程序,到拥有多个模块、多种编码风格和应用程序结构的庞大应用程序。
在所有这些审计中,我发现了一个非常明显的趋势,适用于我审计过的所有应用程序:**Laravel 非常安全,但很容易忽略一些细节,比如额外的防御层,而让漏洞潜藏在某个地方。**
事实上,可以公平地说,我在审计中发现的大多数问题要么是单个路由中被忽略的简单问题,要么是开发人员要么不知道,要么不愿意实现的额外安全层。
所以,让我们深入研究,看看我在安全审计中发现的十大最常见安全问题。
#10 → 输入验证不足
在控制器中经常发现输入验证不足。通常会使用验证器检查预期的输入键(尽管有时甚至没有),然后在之后立即使用 request()->all()
将数据提交到模型、事件等。如果没有适当的验证,很容易注入恶意值,从而导致错误、注入攻击等等。
例如,对此的常用 批量赋值防御 被认为是模型上的 $fillable
,但如果 $fillable
包含管理员门户的 admin
标志,那么任何人都可以在注册页面创建新的管理员用户……(是的,这是一个真实的例子。)
#9 → 缺少子资源完整性 (SRI)
子资源完整性 (SRI) 为防止受损的第三方脚本影响您的网站增加了一层保护,在我看来,它严重被低估了。风险在于第三方脚本和样式可以被修改,以包含恶意代码,例如 Magecart、键盘记录器、加密矿工等等。如果您在网站上包含了受损的脚本,那么即使您的应用程序没有被破坏,您的用户也面临风险。
SRI 通过在加载第三方资源的每个 <script>
和 <style>
标签上定义一个完整性哈希来工作,浏览器在加载资源之前会验证该哈希。如果哈希不匹配,资源将被阻止。
我审计的大多数网站都没有从第三方加载资源,因此无论如何都不需要 SRI,否则我预计它会在这份清单中排名更高!
#8 → 速率限制不足
速率限制对于限制机器人攻击和防止滥用至关重要,但通常会发现缺乏速率限制的端点。在处理诸如身份验证或查询敏感信息(如用户帐户是否存在)之类的路由时,这一点尤其令人担忧。例如,我发现一个基于短信的多因素身份验证 (MFA) 路由缺少速率限制 - 而且 6 位数代码在 5 分钟内过期。暴力破解一个有效的代码并强行进入非常容易。😈
也就是说,速率限制可能很难正确实现 - 您是根据 IP、用户名还是两者都进行限制?或者其他东西?这取决于路由,但有一些总比没有好。所以不要忽略它!
#7 → 跨站点脚本 (XSS)
前十名中最毫不奇怪的条目之一,但它可能比你预期的要低很多!XSS 通常通过单个输入在一个单独的路由中出现,由于一些类似于 Markdown (默认情况下不安全) 或有限的格式存在微妙的转义绕过问题。
这里最好的策略是注意那些讨厌的未转义的刀片标签({!! … !!}
)和原始 HTML 指令,如 v-html
,并确保所有使用都正确转义,Markdown 的安全功能已启用,并且用户提供的 HTML 已被净化。我建议尽可能避免使用这些标签,这样任何使用都会真正突出显示,并且可以轻松识别和审查。
#6 → 过时且存在漏洞的依赖项
另一个毫不奇怪的条目……您上次运行 composer/npm 更新是什么时候?
延迟依赖项更新以避免出现问题并保持系统稳定很常见,但依赖项中的漏洞可能会让您的应用程序暴露在风险之中,而您什么也做不了。包含大量依赖项也很常见,但每个依赖项都会增加您需要了解的潜在漏洞数量。
我建议每周或每月更新所有内容,并在您的构建系统中使用 composer audit --locked
和 npm audit
等工具,以便在发现漏洞时阻止部署。我还建议将您的依赖项缩减到最小值,任何可以轻松用简单的内部中间件或包装器替换的东西,都应该替换。
#5 → 不安全的函数使用
自从我开始使用 PHP 以来,我看到 md5(time())
(和 md5(microtime())
!)被使用的次数已经不计其数了 - 我可能在我的早期也写过一些!令人失望的是,这种趋势一直持续到今天。更糟糕的是,它通常用于生成随机令牌或唯一文件名。除了它既不随机也不唯一。它非常容易猜到和暴力破解,碰撞攻击也可能非常容易。
我敢打赌,如果您现在进入您的代码库并搜索 md5(
,您会发现它在某个地方被不安全地使用了……说真的,我对此有心理阴影!
不仅限于 md5(time())
,还包括 rand()
和 array_rand()
等其他函数,它们不是加密安全的,不能信任用于任何需要安全性的东西。
始终使用适当的安全随机数生成器,random_int()
和 Str::random()
,安全地生成随机值。
#4 → 缺少安全标头
现在我们正在讨论一些额外的保护层,这些保护层并不为人所熟知。Web 浏览器包含很多很棒的安全功能,您只需通过使用响应标头在您的网站上启用它们。虽然它们的缺失不会直接让您的网站被黑客入侵,但它们有助于防止点击劫持、推荐信息泄露、XSS 和其他注入攻击、HTTPS 降级攻击等等。启用许多这些安全标头非常简单,但大多数网站甚至没有启用简单的标头…… 😭
我能给您的最佳建议是访问 securityheaders.com 并扫描您的网站。它将列出您缺少的所有标头,并为您提供链接,让您了解更多关于添加这些标头的信息。
#3 → 缺少内容安全策略 (CSP)
内容安全策略 非常重要,以至于我在前十名中单独为它们留了位置。 CSP 是防御 XSS 和点击劫持的第二道防线,它让您了解哪些脚本、样式、字体、表单、框架等在您的应用程序上运行。 CSP 告诉浏览器哪些资源允许在网站上使用,它将阻止和/或报告任何违反策略的行为 - 阻止 XSS 攻击并让您了解网站上发生的事情。
它们经常被认为太难或“会破坏东西”,但是部署“仅报告”策略可以让您完全了解情况,而不会破坏任何东西。 因此,当您刚开始时,这绝对是最好的选择! 最简单的设置方法是使用 CSP 向导 在 Report URI 中。
我已经发布了我的 CSP 中间件,这是一个使用 CSP 的简单方法:https://gist.github.com/valorin/d4cb9daa190fdee90603efaa8cbc5886
#2 → 缺少授权
哦,天哪,这包含了关于授权(以及某种程度上的身份验证)的一堆东西。 我已经看到:不安全的直接对象引用 (IDOR)、缺少 `signed`、身份验证和策略中间件、忘记的 `authorize()` 调用、没有验证的 Webhook 等等... 最终,代码实际上并没有检查请求者是否被允许执行它想要做的事情。
我实际上很惊讶地发现它在列表中排名如此靠前,但事实证明,大多数项目中都隐藏着一个这样的漏洞,等待被利用。 通常这只是一个简单的开发人员忘记添加一行的问题,但它可能会留下一个巨大的漏洞。
我在这里最好的建议是在每个路由上为身份验证和授权添加测试,以及您其他测试。 这样,您就可以将有效和无效的权限作为标准测试流程的一部分进行检查,并且您会注意到授权是否缺失,因为测试将通过,而实际上它应该失败。
#1 → 公开的 API 密钥和密码
我还要再说多少次? 不要将秘密提交到 Git 中! 😡
这是列表中毫不意外的冠军:提交到版本控制中的 API 密钥和密码,以及散布在代码库中的密码。 这是如此普遍,以至于我在审计过程中没有遇到这种情况,我都感到惊讶。
想想你的代码会去哪里... 它在你的所有开发人员机器上,与承包商共享,在 GitHub、Bitbucket、GitLab 等等,以及第三方服务和构建工具中。 它散布在许多不同的位置。 您的 API 密钥解锁了计费、文件存储、个人识别信息、备份、基础设施等等。 如此多的敏感信息和访问权限,如果落入坏人之手,您的声誉就毁了。
我知道有一些教程建议提交这些东西,所以我可以理解为什么会出现这种情况。 但作为社区,我们需要努力阻止这种情况发生。
如果您不小心提交了凭据,请确保您在源头上将其撤销。 这将防止任何人发现它后使用它。 我还建议使用像 Gitleaks 和 TruffleHog 这样的工具来查找代码库中的秘密。
奖励 → 缺少 security.txt 文件!
它本身不是安全问题,所以我将其作为奖励包含进来,但将 `security.txt` 文件添加到您的应用程序是您为安全做的最简单和最好的事情之一。
security.txt
是一个文本文件,您将其放在 `/.well-known/security.txt` 中,它提供了您的(安全)联系方式,以防有人发现您的网站存在安全问题。 这使得安全人员能够非常容易地联系您,从而减少了报告问题的耗时和工作量,以便您可以更快地修复它们。
在这里生成一个:https://securitytxt.org
总结
好了,朋友们,这就是我的前十名! 有没有惊喜? 您需要在自己的应用程序中检查哪些东西? 也许有一些您不同意的地方? 前往 Twitter、Fediverse 或 Substack Notes 上的主题加入讨论!
对我来说,关键的收获是,虽然 Laravel 是安全的,但所有这些被忽略和遗漏的小事都很重要。 很容易认为您已经检查了每个路由上的授权,并且您的输出完全转义了,但可能存在您遗漏的一个实例。 这就是安全审计的好处 - 让一个不作假设的人来审查您的代码。 这也是我在 Practical Laravel Security 课程 中教的内容。
友好型黑客、演讲者和 PHP 和 Laravel 安全专家。🕵️ 我编写了 Securing Laravel,并在舞台上为了好玩而进行黑客攻击。 😈