在您的URL获取器到达私有网络之前阻止SSRF重定向链

在您的URL获取器到达私有网络之前阻止SSRF重定向链

_

在您的 URL 获取器到达私有网络之前拦截 SSRF 重定向链

服务器端请求伪造(SSRF)是一种众所周知的漏洞,允许攻击者滥用服务器端功能来发起非预期请求。虽然大多数开发人员了解 SSRF 的基础知识——例如阻止本地地址(如 localhost 或 127.0.0.1)——但一种更隐蔽且更危险的变体往往被忽视:重定向链。这些链可以利用 DNS 解析和 HTTP 重定向来访问私有网络,从而绕过初始允许列表。让我们深入探讨其工作原理以及如何缓解这一问题。

SSRF 重定向链漏洞利用

考虑以下场景:

  1. 用户提交 URL:用户提交 https://example.invalid/report。应用程序的初始允许列表可能会批准此请求,因为 DNS 查询返回的是一个公共 IP 地址。

  2. 服务器响应重定向:服务器处理请求并响应重定向到 http://169.254.169.254/latest/meta-data/。此 IP 地址属于 Google Compute Engine 元数据服务,通常仅限于内部网络。

  3. 获取客户端跟随重定向:应用程序的获取客户端自动跟随重定向,而不会重新评估允许列表。对 example.invalid 的原始批准在无声中赋予了访问完全不同主机的权限。

这是许多 URL 预览和导入服务忽视的 SSRF 边界:一个 URL 并非一个网络目的地。DNS 解析可以将公共主机名解析为私有 IP 地址,而 HTTP 重定向可以链式通过多个主机,最终到达受限网络。

这为何重要

1. 绕过允许列表

传统的 SSRF 防御通常依赖于允许列表(受信任主机的白名单)。如果攻击者可以构造一个解析到受信任域但重定向到私有 IP 的 URL,则允许列表会被绕过。

2. 访问敏感数据

私有网络通常包含敏感数据或服务。如果攻击者可以将获取请求重定向到 http://10.0.0.1/admin,他们可能会获得管理访问权限或窃取数据。

3. 通过多重重定向链式传递

攻击者可以创建一系列重定向,每个重定向都逐步接近目标网络。例如: - 初始 URL 解析到一个受信任的公共主机。 - 第一个重定向到一个半受信任的主机。 - 第二个重定向到目标网络内的私有 IP。

每个重定向看起来都是合法的,使得检测和缓解更加困难。

缓解策略

1. 深度检查重定向

不要盲目跟随重定向。在执行获取之前检查最终目的地。例如,在 Node.js 应用程序中使用 fetch 时,您可以拦截重定向:

const fetch = require('node-fetch');

async function fetchWithRedirects(url) {
  const response = await fetch(url, {
    redirect: 'manual' // 这允许手动处理重定向
  });

  if (response.type === 'opaqueredirect') {
    // 手动处理重定向
    console.log('重定向被拦截:', response.url);
    // 不要自动跟随重定向
    return null;
  }

  return response;
}

// 示例用法
fetchWithRedirects('https://example.invalid/report')
  .then(response => {
    if (!response) {
      console.log('由于重定向而取消获取');
    } else {
      response.text().then(console.log);
    }
  });

2. 阻止私有 IP 范围

阻止解析到私有 IP 范围(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 等)的请求。这可以在网络级别或应用程序内完成:

const isPrivateIP = (ip) => {
  const privateRanges = [
    '10.0.0.0/8',
    '172.16.0.0/12',
    '192.168.0.0/16'
  ];

  return privateRanges.some(range => {
    const [base, prefix] = range.split('/');
    const baseIp = parseInt(base.split('.').join(''), 16);
    const ipNum = parseInt(ip.split('.').join(''), 16);
    return ipNum >= baseIp && ipNum < (baseIp + (1 << (32 - parseInt(prefix))));
  });
};

// 示例用法
const ip = '10.0.0.1';
if (isPrivateIP(ip)) {
  console.log(`阻止私有 IP: ${ip}`);
} else {
  console.log(`允许 IP: ${ip}`);
}

3. 禁用获取的 DNS 解析

某些获取库允许禁用特定请求的 DNS 解析。例如,在 Go 中,您可以使用 net/http 并配合自定义的 Dialer:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net"
    "net/http"
    "time"
)

func main() {
    client := &http.Client{
        Transport: &http.Transport{
            Dial: func(network, address string) (net.Conn, error) {
                if net.ParseIP(address).IsLoopback() || net.ParseIP(address).IsPrivate() {
                    return nil, fmt.Errorf("blocked")
                }
                return net.Dial(network, address)
            },
        },
    }

    // 示例请求
    resp, err := client.Get("https://example.invalid/report")
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    // 处理响应
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

4. 使用 Web 应用防火墙(WAF)

WAF 可以帮助检测和阻止恶意重定向链。寻找能够识别链式重定向模式或请求私有 IP 范围的规则。

结论

SSRF 重定向链是一种复杂的规避技术,可以绕过传统的 SSRF 防御。通过理解这些链的工作原理并实施深度检查、阻止私有 IP 范围、禁用获取的 DNS 解析以及利用 WAF,您可以显著降低 SSRF 攻击的风险。始终假设任何外部输入都可能导向意外的网络目的地,并验证请求生命周期的每个步骤。

要点

永远不要信任 URL 的初始目的地。始终检查重定向并阻止对私有网络的访问,以防止 SSRF 重定向链破坏您的应用程序。

使用Nylas API自动发送预约提醒 2026-07-23
人工智能涉及的全灭未来分类学 2026-07-24

评论区