DNS Rebinding 攻击在 JavaScript 环境中的原理和利用方式。

各位观众,各位朋友,大家好!我是今天的主讲人,接下来,咱们就聊聊这个听起来有点玄乎,但其实挺有趣的“DNS Rebinding”攻击。

开场白:什么是 DNS Rebinding?

想象一下,你去餐厅点了个宫保鸡丁,服务员告诉你:“好的,宫保鸡丁在192.168.1.100号窗口取餐。” 你屁颠屁颠跑过去,取到了。过了会儿,你想再来一份,服务员又告诉你:“好的,宫保鸡丁现在在10.0.0.5号窗口取餐。” 你是不是觉得有点奇怪?怎么餐厅的宫保鸡丁一会儿在这,一会儿在那?

DNS Rebinding 就有点像这个。你的浏览器(相当于你)去问 DNS 服务器(相当于服务员):“example.com 在哪儿?” DNS 服务器第一次说:“在 192.168.1.100”。你的浏览器记住了,然后去 192.168.1.100 拿东西(比如网页数据)。

但是,过了一段时间,你再次访问 example.com,DNS 服务器突然说:“啊,example.com 现在在 10.0.0.5 了!” 你的浏览器又屁颠屁颠跑去 10.0.0.5 拿东西。

如果 10.0.0.5 是你家里的路由器,而 192.168.1.100 是一个公网服务器,那么,原本只能在公网访问的网页,现在就可以通过 DNS Rebinding 访问你家里的路由器了!是不是有点刺激?

第一部分:DNS Rebinding 的原理

DNS Rebinding 的核心在于 DNS 协议的一个特性:短 TTL (Time To Live)

  • TTL 是啥?

    TTL 就像是 DNS 记录的“保质期”。 DNS 服务器告诉你的浏览器:“example.com 在 192.168.1.100”,同时会告诉你:“这个信息有效期是 60 秒(TTL=60)。” 60 秒内,你的浏览器会记住这个信息,不用再去问 DNS 服务器。 60 秒后,浏览器会重新询问 DNS 服务器,确保信息是最新的。

  • 短 TTL 的作用

    如果 TTL 很短(比如 0 秒),那么浏览器每次访问 example.com 都会重新询问 DNS 服务器。 这就给了我们“换 IP”的机会。第一次 DNS 查询返回公网 IP,第二次返回内网 IP。

  • 流程图示

    步骤 描述
    1 用户访问 evil.comevil.com 的页面包含一段 JavaScript 代码。
    2 JavaScript 代码发起一个请求到 api.evil.com
    3 浏览器向 DNS 服务器查询 api.evil.com 的 IP 地址。 DNS 服务器返回一个公网 IP 地址,TTL 很短 (比如 0 秒)。
    4 浏览器向公网 IP 地址发送请求,获取一些初始数据(比如 Cookie)。
    5 JavaScript 代码再次发起请求到 api.evil.com
    6 浏览器再次向 DNS 服务器查询 api.evil.com 的 IP 地址。 这次 DNS 服务器返回一个内网 IP 地址(比如 192.168.1.1)。 因为 TTL 很短,所以浏览器会重新查询。
    7 浏览器向内网 IP 地址 (192.168.1.1) 发送请求。 如果内网 IP 地址对应一个 Web 服务器(比如路由器管理界面),那么 evil.com 的 JavaScript 代码就可以访问这个 Web 服务器,从而窃取信息或者执行操作。

第二部分:JavaScript 环境下的利用方式

OK,原理搞清楚了,现在让我们看看如何在 JavaScript 环境下利用 DNS Rebinding。

  • 攻击场景

    最常见的场景是攻击用户家里的路由器。路由器通常运行着一个 Web 服务器,提供管理界面。如果攻击者能通过 DNS Rebinding 访问这个管理界面,就可以修改路由器的 DNS 设置,劫持用户的流量。

  • 必要条件

    1. 受害者访问攻击者的网站: 这才能执行攻击者的 JavaScript 代码。
    2. 攻击者控制的域名: 攻击者需要一个域名,并且能够设置该域名的 DNS 记录。
    3. 短 TTL: 攻击者需要将 DNS 记录的 TTL 设置得很短,最好是 0。
    4. 受害者处于内网环境: 攻击目标是内网设备,所以受害者必须处于内网环境中。
    5. CORS 策略的绕过或缺失: 浏览器有跨域策略,需要绕过或者目标内网服务本身就没有严格的 CORS 策略。
  • 攻击代码示例

    <!DOCTYPE html>
    <html>
    <head>
        <title>DNS Rebinding Attack</title>
    </head>
    <body>
        <h1>DNS Rebinding Attack</h1>
        <script>
            // 攻击目标:路由器管理界面,假设地址是 192.168.1.1
            const targetIp = '192.168.1.1';
            const targetUrl = 'http://api.evil.com/admin/login.html'; // 假设路由器的管理界面地址是 /admin/login.html
    
            // 用于发起请求的函数
            async function fetchData(url) {
                try {
                    const response = await fetch(url, {
                        mode: 'cors', // 尝试使用 CORS
                        credentials: 'omit' // 不发送 cookie
                    });
    
                    if (response.ok) {
                        const data = await response.text();
                        console.log('成功获取数据:', data);
                        // 这里可以处理获取到的数据,比如提取关键信息
                    } else {
                        console.error('请求失败:', response.status, response.statusText);
                    }
                } catch (error) {
                    console.error('请求出错:', error);
                }
            }
    
            // 发起攻击
            function attack() {
                console.log('开始攻击...');
                fetchData(targetUrl);
            }
    
            // 页面加载完成后开始攻击
            window.onload = attack;
        </script>
    </body>
    </html>

    代码解释:

    1. targetIp: 目标内网 IP 地址,这里假设是 192.168.1.1
    2. targetUrl: 目标 URL,这里假设是路由器的管理界面地址。需要替换成实际的地址。
    3. fetchData(url): 用于发起 HTTP 请求的函数。这里使用了 fetch API。

      • mode: 'cors':尝试使用 CORS 跨域请求。如果目标服务器没有设置正确的 CORS 头部,请求可能会失败。
      • credentials: 'omit':不发送 Cookie。 这可以避免一些 CORS 问题。
      • response.ok:检查 HTTP 状态码是否成功(200-299)。
      • response.text():将响应体解析为文本。
    4. attack(): 发起攻击的函数。
    5. window.onload = attack: 在页面加载完成后自动执行 attack() 函数。

    攻击步骤:

    1. 攻击者搭建一个 Web 服务器,并将上述 HTML 代码部署到服务器上。
    2. 攻击者设置 api.evil.com 的 DNS 记录,使其先指向一个公网 IP 地址(攻击者的服务器),TTL 设置为 0。
    3. 过一段时间后,攻击者修改 api.evil.com 的 DNS 记录,使其指向内网 IP 地址 192.168.1.1
    4. 攻击者诱骗受害者访问攻击者的网站。
    5. 受害者的浏览器首先向 api.evil.com 发起请求,DNS 服务器返回公网 IP 地址。浏览器从公网 IP 地址获取一些初始数据。
    6. JavaScript 代码再次发起请求到 api.evil.com,浏览器再次查询 DNS,这次 DNS 服务器返回内网 IP 地址 192.168.1.1
    7. 浏览器向 192.168.1.1 发送请求。如果 192.168.1.1 对应一个 Web 服务器(比如路由器管理界面),那么攻击者的 JavaScript 代码就可以访问这个 Web 服务器,从而窃取信息或者执行操作。

    注意事项:

    • CORS 问题: 浏览器有跨域策略,如果目标服务器没有设置正确的 CORS 头部,请求可能会失败。 可以尝试设置 mode: 'no-cors',但这会限制你能访问的响应数据。
    • 同源策略: JavaScript 的同源策略会阻止跨域访问,但 DNS Rebinding 正是利用了 DNS 记录的变更来绕过这个策略。
    • 实际攻击中,需要更复杂的逻辑来处理各种情况,比如错误处理、重试、数据提取等。
  • 绕过 CORS (Cross-Origin Resource Sharing) 策略

    CORS 是浏览器的一种安全机制,用于限制跨域请求。 但是,在 DNS Rebinding 攻击中,我们可以尝试绕过 CORS 策略。

    • OPTIONS 请求: 在发起实际请求之前,浏览器会先发送一个 OPTIONS 请求,询问服务器是否允许跨域请求。 如果服务器没有正确处理 OPTIONS 请求,或者根本没有处理,那么攻击就有可能成功。

    • 简单请求: 有些请求被认为是“简单请求”,不会触发 OPTIONS 预检。 简单请求的条件是:

      • 请求方法是 GET、HEAD 或 POST。
      • HTTP 头字段只能是以下几种:
        • Accept
        • Accept-Language
        • Content-Language
        • Content-Type (只能是 application/x-www-form-urlencodedmultipart/form-datatext/plain)
        • DPR
        • Downlink
        • Save-Data
        • Viewport-Width
        • Width
      • POST 请求的 Content-Type 必须是 application/x-www-form-urlencodedmultipart/form-datatext/plain

      如果你的请求满足这些条件,那么浏览器就不会发送 OPTIONS 预检请求。

    • JSONP: JSONP 是一种古老的跨域技术,它利用 <script> 标签可以跨域加载资源的特性来实现跨域请求。 但是,JSONP 只能用于 GET 请求。

    • CORS 策略缺失: 很多内网设备(比如路由器)并没有严格的 CORS 策略,甚至根本没有 CORS 策略。 这就使得 DNS Rebinding 攻击更容易成功。

  • 更复杂的利用方式

    除了访问路由器管理界面,DNS Rebinding 还可以用于:

    • 读取内网 Web 应用的数据: 比如,如果内网有一个 Web 应用存储了敏感信息,攻击者可以通过 DNS Rebinding 读取这些信息。
    • 攻击内网的 IoT 设备: 很多 IoT 设备也运行着 Web 服务器,攻击者可以通过 DNS Rebinding 控制这些设备。

第三部分:防御 DNS Rebinding 攻击

既然 DNS Rebinding 这么危险,我们该如何防御呢?

  • 对于用户:

    1. 使用安全的 DNS 服务器: 一些 DNS 服务器会检测 DNS Rebinding 攻击,并阻止恶意域名解析到内网 IP 地址。
    2. 保持浏览器更新: 浏览器会不断修复安全漏洞,保持浏览器更新可以提高安全性。
    3. 谨慎访问不明网站: 不要轻易访问来源不明的网站,特别是那些看起来很可疑的网站。
  • 对于开发者:

    1. 验证 Host 头部: 在 Web 服务器端,验证 HTTP 请求的 Host 头部,确保请求来自合法的域名。
    2. 禁用内网 IP 地址: 禁止 DNS 服务器将域名解析到内网 IP 地址。
    3. 使用随机子域名: 为每个用户生成一个随机子域名,并将这个子域名与用户的会话绑定。 这可以防止攻击者通过 DNS Rebinding 访问其他用户的会话。
    4. 实施严格的 CORS 策略: 确保你的 Web 服务器设置了正确的 CORS 头部,只允许来自受信任域名的跨域请求。
    5. 禁用不必要的服务: 如果你的设备不需要提供 Web 服务,那么就禁用 Web 服务器。
    6. 使用 TLS (HTTPS): 使用 HTTPS 可以防止中间人攻击,并提高安全性。
  • 对于路由器厂商:

    1. 使用 CSRF token: 在路由器管理界面中使用 CSRF token,防止跨站请求伪造攻击。
    2. 实施访问控制: 限制对路由器管理界面的访问,只允许来自授权 IP 地址的访问。
    3. 更新固件: 及时发布固件更新,修复安全漏洞。

防御措施总结

防御手段 描述 适用对象
使用安全 DNS 服务器 选择能够检测并阻止 DNS Rebinding 攻击的 DNS 服务器。 用户
保持浏览器更新 及时更新浏览器,修复安全漏洞。 用户
谨慎访问不明网站 避免访问可疑网站。 用户
验证 Host 头部 在服务器端验证 Host 头部,确保请求来自合法的域名。 开发者
禁用内网 IP 地址 配置 DNS 服务器,禁止将域名解析到内网 IP 地址。 开发者
使用随机子域名 为每个用户生成随机子域名,并与会话绑定。 开发者
实施严格 CORS 策略 设置正确的 CORS 头部,限制跨域请求。 开发者
禁用不必要的服务 禁用不需要的 Web 服务。 开发者
使用 TLS (HTTPS) 使用 HTTPS 加密通信。 开发者
使用 CSRF token 在 Web 表单中使用 CSRF token,防止跨站请求伪造攻击。 路由器厂商
实施访问控制 限制对管理界面的访问,只允许来自授权 IP 地址的访问。 路由器厂商
更新固件 及时发布固件更新,修复安全漏洞。 路由器厂商

第四部分:DNS Rebinding 的演进

DNS Rebinding 并不是一个新鲜的概念,它已经存在很多年了。 但是,随着 Web 技术的不断发展,DNS Rebinding 也在不断演进。

  • 早期 DNS Rebinding:

    早期 DNS Rebinding 主要依赖于短 TTL 和缺乏安全措施的内网设备。 攻击者通过控制 DNS 记录,将域名解析到内网 IP 地址,从而访问内网设备。

  • 现代 DNS Rebinding:

    现代 DNS Rebinding 更加复杂,攻击者会利用各种技术来绕过安全措施,比如:

    • WebSockets: WebSockets 是一种持久化的连接,可以绕过一些 CORS 限制。
    • Service Workers: Service Workers 是一种运行在浏览器后台的脚本,可以拦截网络请求,并修改请求和响应。
    • HTTP/2: HTTP/2 引入了头部压缩等特性,使得攻击者可以更有效地利用 DNS Rebinding。
  • 未来趋势:

    随着 Web 技术的不断发展,DNS Rebinding 可能会变得更加隐蔽和复杂。 攻击者可能会利用新的 Web API 和协议来绕过安全措施。 因此,我们需要不断学习和研究新的防御技术,才能有效地应对 DNS Rebinding 攻击。

总结:

DNS Rebinding 是一种利用 DNS 协议缺陷的攻击方式,它可以绕过浏览器的同源策略,访问内网设备。 虽然 DNS Rebinding 已经存在很多年了,但是它仍然是一种有效的攻击手段。 为了防御 DNS Rebinding 攻击,我们需要采取多种安全措施,包括使用安全的 DNS 服务器、保持浏览器更新、验证 Host 头部、实施严格的 CORS 策略等等。

希望今天的讲座能让你对 DNS Rebinding 有更深入的了解。 记住,安全无小事,时刻保持警惕!

谢谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注