10 个最常见的网络安全漏洞
已发表: 2022-03-11对于太多的公司来说,直到发生安全漏洞之后,Web 安全最佳实践才成为优先事项。 在我作为 IT 安全专业人士的这些年里,我一次又一次地看到 Web 开发安全问题对我的许多程序员同事来说是多么晦涩难懂。
根据定义,应对网络安全威胁的有效方法必须具有主动性和防御性。 为此,这篇文章旨在激发一种安全心态,希望给读者注入健康的偏执狂。
特别是,本指南重点介绍了需要注意的 10 个常见且重要的 Web 安全陷阱,包括有关如何缓解这些陷阱的建议。 重点关注由开放 Web 应用程序安全项目 (OWASP) 确定的十大 Web 漏洞,OWASP 是一个国际非营利组织,其目标是提高全球软件安全性。
开始之前的一点网络安全入门 - 身份验证和授权
在与其他程序员和 IT 专业人员交谈时,我经常会在授权和身份验证之间的区别上遇到困惑。 当然,缩写auth经常用于两者的事实有助于加剧这种常见的混淆。 这种混淆非常普遍,也许这个问题应该作为“常见的 Web 漏洞零”包含在这篇文章中。
因此,在我们继续之前,让我们澄清这两个术语之间的区别:
- 身份验证:验证一个人是(或至少看起来是)特定用户,因为他/她已正确提供了他们的安全凭证(密码、安全问题的答案、指纹扫描等)。
- 授权:确认特定用户有权访问特定资源或被授予执行特定操作的权限。
换句话说,身份验证是知道实体是谁,而授权是知道给定实体可以做什么。 考虑到这一点,让我们进入十大互联网安全问题。
常见的 Web 安全错误 #1:注入漏洞
注入缺陷是由于过滤不可信输入的经典失败造成的。 当您将未过滤的数据传递到 SQL 服务器(SQL 注入)、浏览器(XSS——我们稍后会讨论)、LDAP 服务器(LDAP 注入)或其他任何地方时,就会发生这种情况。 这里的问题是攻击者可以向这些实体注入命令,从而导致数据丢失并劫持客户端的浏览器。
您的应用程序从不受信任的来源收到的任何内容都必须进行过滤,最好根据白名单进行过滤。 您几乎不应该使用黑名单,因为要做到这一点非常困难,而且通常很容易绕过。 防病毒软件产品通常会提供失败的黑名单示例。 模式匹配不起作用。
预防:好消息是,防止注入“简单地”是正确过滤您的输入并考虑输入是否可以信任的问题。 但坏消息是所有输入都需要适当过滤,除非它可以毫无疑问地被信任(但这里确实想到了“永不言败”的说法)。
例如,在具有 1,000 个输入的系统中,成功过滤其中的 999 个是不够的,因为这仍然会留下一个字段,可以作为阿喀琉斯治疗来破坏您的系统。 您可能认为将 SQL 查询结果放入另一个查询是一个好主意,因为数据库是受信任的,但如果外围不是,则输入间接来自有恶意的人。 如果您有兴趣,这称为二阶 SQL 注入。
由于过滤很难做到正确(如加密),我通常建议依靠框架的过滤功能:它们被证明有效并且经过彻底审查。 如果你不使用框架,你真的需要认真思考在你的服务器安全环境中不使用它们是否真的有意义。 99% 的时间不会。
常见的 Web 安全错误 #2:身份验证损坏
这是身份验证失败期间可能出现的多个问题的集合,但它们并非都源于相同的根本原因。
假设有人仍然想在 2014 年推出自己的验证码(你在想什么??),我建议不要这样做。 很难做到正确,并且有无数可能的陷阱,仅举几例:
- URL 可能包含会话 ID,并将其在引用标头中泄漏给其他人。
- 密码可能在存储或传输过程中未加密。
- 会话 id 可能是可预测的,因此获得访问权限是微不足道的。
- 会话固定可能是可能的。
- 会话劫持可能是可能的,超时未正确实现或使用 HTTP(无 SSL 安全性)等......
预防:避免这种网络安全漏洞的最直接方法是使用框架。 您可能能够正确地实现这一点,但前者要容易得多。 如果您确实想编写自己的代码,请极度偏执并了解陷阱是什么。 有不少。
常见的 Web 安全错误 #3:跨站点脚本 (XSS)
这是一个相当普遍的输入清理失败(本质上是常见错误 #1 的特例)。 攻击者在输入时为您的 Web 应用程序提供 JavaScript 标记。 当这个输入未经过滤地返回给用户时,用户的浏览器将执行它。 它可以像制作一个链接并说服用户点击它一样简单,也可以是更险恶的东西。 在页面加载时,脚本运行,例如,可用于将您的 cookie 发布给攻击者。
预防:有一个简单的网络安全解决方案:不要将 HTML 标记返回给客户端。 这具有防御 HTML 注入的额外好处,这是一种类似的攻击,攻击者可以注入纯 HTML 内容(例如图像或响亮的不可见 Flash 播放器)——影响不大,但肯定很烦人(“请停止!”)。 通常,解决方法是简单地转换所有 HTML 实体,以便将<script>
作为<script>
返回。 . 另一种常用的清理方法是使用正则表达式去除 HTML 标签,使用<
和>
上的正则表达式,但这很危险,因为许多浏览器会很好地解释严重损坏的 HTML。 最好将所有字符转换为转义对应的字符。
常见的 Web 安全错误 #4:不安全的直接对象引用
这是信任用户输入并为由此产生的安全漏洞付出代价的经典案例。 直接对象引用意味着向用户公开诸如文件或数据库键之类的内部对象。 这样做的问题是攻击者可以提供此参考,并且如果未强制执行(或被破坏)授权,攻击者可以访问或执行他们应该被排除在外的事情。
例如,代码有一个download.php
模块,它读取并让用户下载文件,使用 CGI 参数指定文件名(例如, download.php?file=something.txt
)。 由于错误或由于懒惰,开发人员在代码中省略了授权。 攻击者现在可以使用它来下载运行 PHP 的用户可以访问的任何系统文件,例如应用程序代码本身或留在服务器上的其他数据,例如备份。 哦哦。
另一个常见的漏洞示例是密码重置功能,它依赖于用户输入来确定我们正在重置谁的密码。 点击有效的 URL 后,攻击者只需修改 URL 中的username
段,即可说出类似“admin”的内容。
顺便说一句,这两个例子都是我自己经常看到的“在野外”出现的东西。
预防:正确一致地执行用户授权,并将选择列入白名单。 不过,通常情况下,可以通过在内部存储数据而不依赖于通过 CGI 参数从客户端传递数据来避免整个问题。 大多数框架中的会话变量都非常适合此目的。
常见的 Web 安全错误 #5:安全配置错误
根据我的经验,配置错误的 Web 服务器和应用程序比配置正确的 Web 服务器和应用程序更常见。 也许这是因为不乏搞砸的方法。 一些例子:
- 在生产中启用调试运行应用程序。
- 在服务器上启用目录列表,这会泄露有价值的信息。
- 运行过时的软件(想想 WordPress 插件,旧的 PhpMyAdmin)。
- 在机器上运行不必要的服务。
- 不更改默认密钥和密码。 (发生的频率比你想象的要频繁!)
- 向攻击者揭示错误处理信息,例如堆栈跟踪。
预防:有一个好的(最好是自动化的)“构建和部署”过程,可以在部署时运行测试。 穷人的安全配置错误解决方案是提交后挂钩,以防止代码使用默认密码和/或内置的开发内容退出。
常见的网络安全错误 #6:敏感数据暴露
此网络安全漏洞与加密和资源保护有关。 敏感数据应始终加密,包括传输中和静止时。 没有例外。 信用卡信息和用户密码不应在未加密的情况下传播或存储,并且应始终对密码进行哈希处理。 显然,加密/散列算法不能太弱——当有疑问时,网络安全标准推荐使用 AES(256 位及以上)和 RSA(2048 位及以上)。

不用说,会话 ID 和敏感数据不应该在 URL 中传输,敏感 cookie 应该打开安全标志,这非常重要,不能过分强调。
预防:
传输中:使用带有适当证书和 PFS(完美前向保密)的 HTTPS。 不要通过非 HTTPS 连接接受任何内容。 在 cookie 上有安全标志。
在存储中:这更难。 首先,您需要降低曝光率。 如果您不需要敏感数据,请将其粉碎。 您没有的数据不会被窃取。 永远不要存储信用卡信息,因为您可能不想处理与 PCI 兼容的问题。 使用 Stripe 或 Braintree 等支付处理器注册。 其次,如果您有实际需要的敏感数据,请将其加密存储并确保所有密码都经过哈希处理。 对于散列,建议使用 bcrypt。 如果您不使用 bcrypt,请自学盐渍和彩虹表。
并且冒着明显的风险,不要将加密密钥存储在受保护的数据旁边。 这就像将您的自行车存放在带有钥匙的锁中。 通过加密保护您的备份,并使您的密钥非常私密。 当然,不要丢失钥匙!
常见的网络安全错误 #7:缺少功能级别的访问控制
这只是授权失败。 这意味着当在服务器上调用一个函数时,没有执行适当的授权。 很多时候,开发人员依赖于服务器端生成 UI 的事实,他们认为客户端无法访问服务器未提供的功能。 事情并非如此简单,因为攻击者总是可以伪造对“隐藏”功能的请求,并且不会因 UI 无法轻松访问此功能而被吓倒。 想象有一个/admin
面板,如果用户实际上是管理员,则该按钮仅出现在 UI 中。 如果缺少授权,没有什么可以阻止攻击者发现此功能并滥用它。
预防:在服务器端,必须始终进行授权。 是的,总是。 任何异常或漏洞都不会导致严重的问题。
常见的 Web 安全错误 #8:跨站请求伪造 (CSRF)
这是混淆代理攻击的一个很好的例子,浏览器被其他方欺骗以滥用其权限。 例如,第 3 方站点可以使用户的浏览器滥用其权限为攻击者做某事。
对于 CSRF,第 3 方站点使用您的浏览器和您的 cookie/会话向目标站点(例如,您的银行)发出请求。 例如,如果您在银行主页上的一个选项卡上登录,并且他们很容易受到这种攻击,那么另一个选项卡可以使您的浏览器代表攻击者滥用其凭据,从而导致混淆代理问题。 代理是浏览器滥用其权限(会话 cookie)来执行攻击者指示它执行的操作。
考虑这个例子:
攻击者爱丽丝想通过将他的一些钱转移给她来减轻目标托德的钱包。 Todd 的银行容易受到 CSRF 的攻击。 要汇款,Todd 必须访问以下 URL:
http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243
打开此 URL 后,将向 Todd 显示一个成功页面,并且传输完成。 Alice 还知道,Todd 经常访问她控制的网站 blog.aliceisawesome.com,她在其中放置了以下代码段:
<img src=http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243 width=0 height=0 />
访问 Alice 的网站时,Todd 的浏览器认为 Alice 链接到了一张图片,并自动发出 HTTP GET 请求来获取图片,但这实际上是指示 Todd 的银行向 Alice 转账 1500 美元。
顺便说一句,除了演示 CSRF 漏洞之外,这个示例还演示了使用幂等 HTTP GET 请求更改服务器状态,这本身就是一个严重的漏洞。 HTTP GET 请求必须是幂等的(安全的),这意味着它们不能更改访问的资源。 永远不要使用幂等方法来更改服务器状态。
有趣的事实:CSRF 也是人们过去用来填充 cookie 的方法,直到会员变得更聪明为止。
预防:将秘密令牌存储在第三方站点无法访问的隐藏表单字段中。 当然,您总是必须验证这个隐藏字段。 有些网站在修改敏感设置(例如您的密码提醒电子邮件)时也会询问您的密码,尽管我怀疑这是为了防止滥用您放弃的会话(例如在网吧中)。
常见的 Web 安全错误 #9:使用具有已知漏洞的组件
标题说明了一切。 我再次将其归类为更多的维护/部署问题。 在合并新代码之前,做一些研究,可能是一些审计。 使用从 GitHub 或某个论坛上随机获得的代码可能非常方便,但并非没有严重的网络安全漏洞风险。
我见过很多例子,例如,网站被拥有(即,外部人员获得对系统的管理访问权),不是因为程序员很愚蠢,而是因为第 3 方软件在生产中多年未打补丁。 例如,WordPress 插件一直在发生这种情况。 如果您认为他们不会找到您隐藏的phpmyadmin
安装,让我向您介绍 dirbuster。
这里的教训是,软件开发不会在应用程序部署后结束。 必须有关于如何维护和保持更新的文档、测试和计划,尤其是当它包含第 3 方或开源组件时。
预防:
谨慎行事。 除了在使用此类组件时显然要小心之外,不要成为复制粘贴编码器。 仔细检查您将要放入软件中的代码,因为它可能会被破坏而无法修复(或者在某些情况下,是故意恶意的——网络安全攻击有时会以这种方式在不知不觉中受到邀请)。
保持最新。 确保您使用的是您信任的所有内容的最新版本,并计划定期更新它们。 至少订阅有关产品的新安全漏洞的时事通讯。
常见的 Web 安全错误 #10:未经验证的重定向和转发
这又是一个输入过滤问题。 假设目标站点有一个将 URL 作为GET
参数的redirect.php
模块。 操作该参数可以在targetsite.com
上创建一个 URL,该 URL 将浏览器重定向到malwareinstall.com
。 当用户看到该链接时,他们将看到用户认为受信任且可以安全点击的targetsite.com/blahblahblah
。 他们几乎不知道这实际上会将它们转移到恶意软件放置(或任何其他恶意)页面上。 或者,攻击者可能会将浏览器重定向到targetsite.com/deleteprofile?confirm=1
。
值得一提的是,将未经过滤的用户定义输入填充到 HTTP 标头中可能会导致标头注入,这是非常糟糕的。
预防:选项包括:
- 根本不要进行重定向(它们很少需要)。
- 具有要重定向到的有效位置的静态列表。
- 将用户定义的参数列入白名单,但这可能很棘手。
结语
我希望我已经设法用这篇文章让你的大脑有点痒痒,并介绍一种健康的偏执狂和网站安全漏洞意识。
这里的核心要点是,古老的软件实践存在是有原因的,并且在当时适用于缓冲区溢出的做法,今天仍然适用于 Python 中的腌制字符串。 安全协议可帮助您编写(更多)正确的程序,这是所有程序员都应该追求的。
请负责任地使用这些知识,未经许可请勿测试页面!
有关更多信息和更具体的服务器端攻击,请查看:https://www.owasp.org/index.php/Category:Attack。
欢迎和赞赏对这篇文章及其缓解建议的反馈。 计划在未来发布相关帖子,特别是关于分布式拒绝服务 (DDoS) 和老式(非 Web)IT 安全漏洞的问题。 如果您对撰写哪种网络保护有具体要求,请随时通过 [email protected] 直接与我联系。
这是网站安全! 干杯。
- JSON Web Token 教程:Laravel 和 AngularJS 中的示例
- 性能和效率:使用 HTTP/3