服务端请求伪造 (SSRF)

网络安全Beginner
立即练习

简介

服务端请求伪造 (Server-Side Request Forgery, SSRF) 是一种 Web 安全漏洞,它允许攻击者诱导服务端应用程序向攻击者指定的任意域名发起 HTTP 请求。

关键点在于,请求是由服务器发起的,而不是由攻击者直接发起的。这意味着该请求继承了服务器的网络位置、信任关系以及对仅限内部访问的目标的访问权限。

在典型的 SSRF 攻击中,攻击者可能会诱导服务器连接到组织基础设施内仅限内部访问的服务。在其他情况下,他们可能能够强制服务器连接到任意外部系统,从而可能泄露授权凭据等敏感数据。

在本实验中,你将与一个模拟的易受攻击的 Web 应用程序进行交互。你将学习如何识别 SSRF 漏洞,观察基本的安全过滤器如何尝试阻止恶意请求,学习如何绕过这些过滤器,并最终提取敏感的内部数据和模拟的云元数据。为了使练习与共享实验环境兼容,模拟的元数据服务使用了一个非特权的高位端口,而不是端口 80。

识别 URL 参数

在这一步中,你将学习如何通过寻找从外部 URL 获取数据的应用程序功能来识别潜在的 SSRF 漏洞。

许多 Web 应用程序需要从其他服务器获取资源。例如,应用程序可能需要从社交媒体网站获取头像,或从第三方 API 检索数据。如果应用程序将 URL 作为用户输入并在没有适当验证的情况下获取它,那么它就可能容易受到 SSRF 攻击。

这就是为什么 SSRF 通常出现在看似合法的「URL 获取」功能中。这种危险行为隐藏在从产品角度看非常正常的工作流程中。

一个易受攻击的 Web 应用程序已为你启动,端口为 8080。该应用程序有一个 /check 端点,它接受一个 url 参数。它的设计初衷是检查外部网站的状态。

你可以通过要求应用程序获取一个良性的外部网站(例如 http://example.com)来测试此功能。在终端中使用 curl 命令向该易受攻击的应用程序发送 HTTP GET 请求。如果你对 curl 不熟悉,可以将其想象为一个简单的命令行 Web 浏览器,它发送请求并将服务器的响应打印在终端中。

curl "http://localhost:8080/check?url=http://example.com"

当你执行此命令时,运行在 8080 端口上的易受攻击应用程序会接收你的请求,提取 url 参数,并向 http://example.com 发起它自己的 HTTP 请求。然后,它会将 HTML 响应返回给你。

<!doctype html>
<html>
<head>
    <title>Example Domain</title>
...

通过观察到服务器成功获取并返回了所请求 URL 的内容,你已经确认 url 参数正在被主动处理并用于发起服务端请求。这是 SSRF 漏洞的第一个指标。

针对本地主机 (127.0.0.1) 测试 SSRF

在这一步中,你将尝试利用 SSRF 漏洞访问运行在服务器上的内部服务。

SSRF 的主要危险在于,发起请求的服务器在网络中通常处于特权地位。它可以访问未暴露给公共互联网的内部服务。在我们的场景中,有一个运行在 5000 端口的内部管理面板。此管理面板绑定到 127.0.0.1 (localhost),这意味着它只能从服务器本身访问,而不能从其他机器访问。你可以将 127.0.0.1 视为计算机在与自己对话。

作为攻击者,你可以利用 8080 端口上的 SSRF 漏洞,诱骗服务器代表你访问 5000 端口上的管理面板。

尝试通过将内部管理面板的本地 URL 传递给易受攻击的 /check 端点来访问它。

curl "http://localhost:8080/check?url=http://127.0.0.1:5000/admin"

当你运行此命令时,你会发现请求没有成功。相反,你收到了一条错误消息。

Error: Localhost access is blocked by WAF!

开发人员通常会实施 Web 应用防火墙 (WAF) 或输入过滤器来防止 SSRF 攻击。在本例中,应用程序会检查提供的 URL 是否包含字符串 127.0.0.1 或 localhost。由于你的输入匹配了此过滤器,应用程序阻止了该请求。

简单的字符串过滤器非常脆弱,因为网络目标有多种等效的表示形式。防御者需要的是能够理解规范网络含义的验证机制,而不仅仅是字面文本匹配。

了解应用程序如何过滤输入是利用 SSRF 的关键一步,因为它告诉你需要绕过哪些限制。

绕过输入过滤器

在这一步中,你将学习如何绕过你在上一步中遇到的基本输入过滤器。

绕过技术之所以有效,是因为 URL 解析、主机名解析和输入过滤并不总是使用相同的解释规则。

依赖简单字符串匹配(如阻止 127.0.0.1)的输入过滤器通常是有缺陷的,因为 IP 地址可以用多种方式表示。操作系统的网络栈仍然会将这些替代表示解析为相同的目标,但应用程序的文本过滤器可能无法识别它们。

以下是几种表示本地主机 IP 地址 (127.0.0.1) 的常见方式,它们可能会绕过实现不佳的过滤器。你可以使用缩短的 IP(如 127.1)、十进制 IP(如 2130706433)、八进制 IP(如 0177.000.000.001)或十六进制 IP(如 0x7f000001)。

由于应用程序仅阻止了字符串 127.0.0.1 和 localhost,你可以使用缩短的 IP 表示形式 127.1 来绕过过滤器并访问内部管理面板。

执行以下命令来测试绕过技术:

curl "http://localhost:8080/check?url=http://127.1:5000/admin"

由于 127.1 与被阻止的字符串不匹配,应用程序允许请求继续。服务器的网络栈将 127.1 解析为 127.0.0.1 并成功获取了内部管理页面。

Welcome to the Internal Admin Panel. Secret Key: SSRF_ADMIN_SUCCESS

你已经成功绕过了输入过滤器,并利用 SSRF 漏洞访问了受限的内部服务。

访问内部元数据

在这一步中,你将使用 SSRF 漏洞来访问敏感的云元数据。

当应用程序托管在云环境(如 AWS、Google Cloud 或 Azure)中时,它们通常可以访问一个特殊的、不可路由的 IP 地址:169.254.169.254。该地址托管着实例元数据服务 (IMDS),它提供有关正在运行的云实例的信息,包括高度敏感的临时 IAM(身份和访问管理)凭据。「不可路由」意味着该地址旨在用于本地云基础设施,而不是用于一般的公共互联网访问。

如果攻击者在云托管的应用程序中发现 SSRF 漏洞,查询此元数据端点通常是他们的首要目标,因为这可能导致整个云环境被攻破。

在本实验环境中,一个模拟的云元数据服务运行在 169.254.169.254:8000 上。真实的云元数据服务通常使用端口 80,但本实验特意使用了端口 8000,以便服务可以在无需特殊权限的情况下启动,且不会与其他软件冲突。首先,使用 SSRF 漏洞列出可用的元数据目录。

curl "http://localhost:8080/check?url=http://169.254.169.254:8000/latest/meta-data/"

服务器将获取元数据目录列表并将其返回给你。

iam/security-credentials/admin-role

输出显示了一个名为 admin-role 的 IAM 角色。你现在可以将此路径附加到你的 SSRF 有效载荷中,以提取与此角色关联的实际安全凭据。

执行以下命令来检索敏感凭据:

curl "http://localhost:8080/check?url=http://169.254.169.254:8000/latest/meta-data/iam/security-credentials/admin-role"

模拟的元数据服务将返回 JSON 格式的凭据。

{"AccessKeyId":"AKIAIOSFODNN7EXAMPLE","SecretAccessKey":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"}

如果此请求在你的环境中没有返回数据,请简要检查 /tmp/meta.log 并确认服务正在 169.254.169.254:8000 上监听。

通过成功提取这些凭据,你已经证明了 SSRF 漏洞在云环境中的严重影响。

总结

在本实验中,你成功探索并利用了服务端请求伪造 (SSRF) 漏洞。你学习了如何通过观察服务端获取数据的行为来识别易受攻击的 URL 参数。随后,你遇到了一个旨在阻止本地访问的基本输入过滤器,并成功使用替代的 IP 地址表示形式绕过了它。最后,你通过提取敏感的模拟云元数据凭据,展示了 SSRF 的严重影响。理解这些技术对于在安全评估中识别漏洞以及在 Web 应用程序中实施稳健的防御措施至关重要。