请选择 进入手机版 | 继续访问电脑版
MSIPO技术圈 首页 IT技术 查看内容

了解安全漏洞:预防攻击的第一步

2023-06-28

当我十几岁的时候,我们当地的电话公司推出了一项新服务 - 付费电话(又名 1-900 号码)。有趣的是,我们发现了解决这些费用的方法,方法是拨打这些 1-900 号码将重定向到的连续本地号码。如果 1-900 的“支持号码”是 555-555,我们将拨打 555-455 和 555-655 之间的每个号码,直到中奖......

我们花了几个小时拨打这些号码,导致我们免费拨打了很多电话。这种攻击至今仍然很普遍,它被称为不安全直接对象引用(IDOR)。

干燥

在数字世界中,IDOR 与我们青少年的经历类似。这意味着依次尝试各种 ID 号,直到找到正确的 ID 号。几年前,一个名为 Parler 的社交网络通过连续的数字 ID 列出用户,当用户能够请求并下载该网络上的完整用户列表时,该网络就成为此类攻击的受害者。

例如,他们的 URL 如下所示:https://site.com/viewUser?id=999

一个人需要做的就是循环有效的序列号并发送请求以获取该站点上每个人的用户信息。这是微不足道的,任何技术技能相对较低的人都可以完成。

为了避免此类攻击,建议不要向最终用户公开可猜测的或连续的数字 ID。虽然 UUID 可能看起来很长,但它提供了更安全的替代方案。此外,还应该实施请求检查。如果用户请求有关他们未连接的用户的信息,则应阻止该请求。其他有效的缓解措施包括设置请求配额和请求之间的延迟,以防止大量数据抓取。

我不会讨论这些,因为它们通常在配置期间在 API 网关层中实现。您可以用代码编写此内容,但这是一项具有挑战性的任务,因为您可能有许多非常复杂的端点。经验法则是编写尽可能少的代码,更多的代码意味着更多的错误和恶意黑客更广泛的攻击面。

漏洞和漏洞利用

应用程序安全中的一个重要术语是漏洞。这是一个弱点或错误,可以比作你房子周围的栅栏上的一个洞。这些漏洞可能存在于您的代码、库、Java 本身、操作系统甚至物理硬件中。然而,并非所有漏洞都可以被利用。就像栅栏上的洞不一定可以进入您的房子一样,漏洞并不总是意味着您的代码可以被黑客攻击。我们的目标是堵塞尽可能多的漏洞,使利用我们系统的任务变得更加困难。

我知道洋葱的比喻现在已经很累了,但为了安全起见,它很有意义。我们需要在每一层加强安全性。在去年曝光的 Log4Shell 漏洞中,我们发现了一个重大的零日漏洞。零日漏洞是一种新发现的漏洞,以前没有人知道,就像栅栏上的一个新洞。

Log4Shell 漏洞依赖于人们在未先验证信息的情况下记录信息。在漏洞被发现之前,这是一种不好的做法。如果您使用的 Log4J 版本存在该漏洞,但清理了您的数据。尽管存在这种脆弱性,你还是安全的。

SQL注入

SQL 注入涉及通过手动连接查询字符串来构建您自己的查询。让我们看看这样的易受攻击的 SQL:

String sql = "SELECT * from Users WHERE id = " + id;
Enter fullscreen mode Exit fullscreen mode

考虑到我们之前使用的示例 URL,我们可以请求这样的 URL:https://site.com/viewUser?id=1 OR true=true

此 URL 将导致攻击者获取所有用户,因为条件将变为:

SELECT * from Users WHERE id = 1 OR true=true
Enter fullscreen mode Exit fullscreen mode

这始终是正确的。这是一个相对温和的结果。可以链接 SQL 语句来删除表,从而删除整个数据库。解决方案是使用准备好的语句语法,其中实现将所有内容视为字符串。这可以防止 SQL 关键字被利用,例如:

PreparedStatement sql = connection.prepareStatement("SELECT * from Users WHERE id = ?");
sql.setString(1, id);
Enter fullscreen mode Exit fullscreen mode

在这种情况下,当我们设置 id 的值时,即使存在 SQL 关键字或特殊字符,它也会将其视为字符串。使用 JPA(Spring Data、Hibernate 等)等 API 还可以在使用类似 API 时保护您免受 SQL 注入。

序列化

Java 序列化是另一个常见漏洞。这里的教训是避免使用序列化或要求序列化,而是使用阻止某些类型序列化的过滤器来运行应用程序。

这是我在上一篇文章中讨论过的内容,因此没有必要重复。

跨站脚本 (XSS)

跨站脚本攻击(XSS)是一种复杂的攻击。它涉及将恶意脚本注入网站,然后在访问该页面的每个人的浏览器上运行。这可能会导致用户 cookie 被盗,从而使攻击者能够冒充网站上的用户。防范 XSS 涉及验证用户提供的数据,将其视为显示内容,而不是可执行代码。

假设我有一个提交表单,它接受保存到数据库的用户输入。喜欢博客中的评论部分。我可以发布 JavaScript 代码,将用户的 cookie 提交到我控制的站点。然后我可以窃取这些信息并冒充用户。这是一种非常常见且令人惊讶的攻击,通常通过将脚本编码到通过电子邮件发送的链接中来执行。

XSS 攻击分为三种类型:

  • 存储型 XSS(持久)- 我在此描述的攻击是存储型 XSS 的一种形式,因为我要提交的评论保存在数据库中。此时,每个查看评论的用户都会受到攻击。

  • 反射型 XSS(非持久性)- 在这种形式中,攻击者向用户发送包含恶意脚本的链接(或诱使用户单击链接)。当用户单击链接时,脚本就会运行,将数据发送给攻击者。该脚本嵌入在 URL 中并反映在 Web 服务器上。这通常是网络钓鱼攻击的一部分。

  • 基于 DOM 的 XSS - 这种类型的攻击完全发生在受害者的浏览器中。 Web 应用程序的客户端脚本将用户提供的数据写入文档对象模型。随后,Web 应用程序从 DOM 读取数据并将其输出到浏览器。如果数据被解释为 JavaScript,则会执行它。

防止 XSS 需要对所有输入进行严格验证。我们可以通过检查用户提供的数据是否具有正确的形式并且不包含恶意内容来防止这些攻击。我们必须确保任何用户提供的内容都被视为显示内容,而不是可执行代码。

有多种方法可以验证用户提交的数据,Jsoup 库包含一种这样的 API。请注意,Spring Boot 包含 XSS 保护作为安全配置的一部分,稍后我将对此进行介绍。

personName = Jsoup.clean(personName, Whitelist.basic());
Enter fullscreen mode Exit fullscreen mode

请注意,在涉及安全漏洞时,验证输入是一个反复出现的主题。作为开发人员,我们经常努力提供最通用和灵活的工具,但这在涉及安全漏洞时对我们不利。即使我们没有发现问题,限制输入选项也很重要。

内容安全策略 (CSP)

实施 XSS 攻击的方法之一是将外部代码包含到我们自己的网站中。阻止这种情况的一种方法是使用特殊的 HTTP 标头来定义哪些网站可以包含我们的网站。这是一个相当复杂的过程,但令人高兴的是 Spring Security 也为我们很好地处理了这个问题。

仅 Http Cookie

可以使用 JavaScript 在浏览器中创建 Cookie。这是一个不好的做法。理想情况下,cookie 应始终来自服务器并标记为仅限 HTTP(且仅限 HTTPS)。这会阻止 JavaScript 代码访问 cookie。

这意味着即使以某种方式添加了脚本或单击了错误链接,它也无法访问 cookie 值。这可以减轻 XSS 攻击,因此即使您的网站容易受到攻击,攻击也无法窃取 cookie。当我们在服务器代码中设置cookie时,我们可以启用HttpOnly cookie。

未经验证的重定向和转发

另一个安全问题是未经验证的重定向和转发。在这里,攻击者创建一个看似来自您的域的 URL,但会重定向到另一个恶意站点。解决方案在于验证和限制包含或提交的 URL,切勿盲目地将用户发送到第三方网站。

假设我们有一个登录页面。登录后,我们会看到一个启动屏幕,然后我们被发送到实际目的地。这看起来很简单,但有些人需要转到页面 X,而其他人需要转到页面 Y。我们希望保持代码通用,因此我们接受目标 URL 作为参数。这样登录代码可以决定下一步去哪里,我们不需要知道所有用户类型,例如:https://bug.com/postLogin?dest=url

问题是,一个人可以创建一个看似来自我们域的 URL,但传入另一个 URL 作为最后一个参数。我们的用户最终可能会访问恶意网站,而没有意识到他们被重定向到新网站。

解决方案是验证和限制包含或提交的 URL,切勿盲目地将用户发送到第三方网站。

服务器端请求伪造 (SSRF)

SSRF 攻击在概念上类似,在这些攻击中,我们的服务器根据我们收到的请求执行请求。我们的服务器可以被操纵来向攻击者请求任意 URL。这可以作为信息盗窃、拒绝服务攻击等的基础。

跨站请求伪造 (CSRF)

CSRF 是另一个具有挑战性的问题,攻击者会诱骗用户入侵自己的帐户。通常,我们会登录一个网站。我们的凭据和 cookie 已设置。如果其他网站知道我们登录了某​​个网站,它可能会欺骗我们并让我们自我攻击......

假设您访问一个网站,它有一个大按钮,您可以按下该按钮就有机会赢得一百万美元。你要按一下吗?

到底有什么坏处呢?

如果该按钮是直接向您的银行提交请求的表单,则可以用来窃取货币等。

标准解决方案是将服务器生成的令牌添加到随每个请求而更改的 HTML 中,从而验证 HTML 来自合法站点。这是 Spring Security 支持的标准策略。

我们还可以将 cookie 设置为 SameSite 策略,这意味着如果用户位于单独的站点上,则他不会登录。为您的登录信息打开此功能可能是一个好主意。

最后一句话

总之,虽然我们没有在这篇文章中深入研究大量代码编写,但目的是阐明常见的安全漏洞和攻击以及如何预防它们。理解这些概念是构建安全应用程序的基础,我们了解得越多,就越有能力阻止潜在的威胁。

有很多用于安全验证的工具,如果您使用像 SonarQube 这样的像样的 linter,您将迈向更安全的应用程序。 Snyk 还拥有出色的工具,可以帮助捕获各种漏洞。

帖子中的这一段可能总结了最重要的方面:

请注意,在涉及安全漏洞时,验证输入是一个反复出现的主题。作为开发人员,我们经常努力提供最通用和灵活的工具,但这在涉及安全漏洞时对我们不利。即使我们没有发现问题,限制输入选项也很重要。

相关阅读

手机版|MSIPO技术圈 皖ICP备19022944号-2

Copyright © 2023, msipo.com

返回顶部