如何防止跟踪 URL 中的敏感数据?

How to prevent tracking sensitive data in URLs?

我的单页应用 (SPA) 中的某些 URL 包含敏感信息,例如访问令牌、用户信息等。

示例:

/callback#access_token=HBVYTU2Rugv3gUbvgIUY
/?email=username@example.com

我看到 hotjar 允许从跟踪数据中抑制 DOM 元素和图像。是否可以在 URL 中隐藏参数或至少禁用某些页面的跟踪?

因为你说它是你的 SPA,你可以通过从 GET 请求(在 URL 中有参数)切换到 POST requests。我不知道 hotjar,但如果您告诉跟踪服务仅分析 URLs,那将是一个值得考虑的选项。

另一个经常使用的选项是 obfuscate your parameters in the URL, see e.g. Best way to obfuscate an e-mail address on a website? 但是,对于敏感数据,这从来都不是真正安全的解决方案,因为解密步骤太简单了,特别是如果您的中间人是否所有请求都发送到您的 SPA。

编辑。我刚在Hotjar allows RegEx中找到。假设您可以输入要排除的 URL 部分的正则表达式。 一般语法 /foo/bar/ 意味着 foo 应该替换为 bar,在我们的例子中,我们想要删除给定的片段,这就是为什么它是 /foo//.

对于访问令牌的给定情况,正则表达式为

/callback#access_token=[a-zA-Z0-9]{15}//

和 URL

的电子邮件部分
/\?email=(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])//

第二个 RegEx 部分取自 How to validate an email address using a regular expression?

在我看来,可以合理地假设跟踪脚本将尝试访问 window.location.href 或类似内容以获取它们将存储的当前 url。

因此,一个可能的解决方案是创建一个动态范围,它对 window.location.href 具有不同的值(过滤掉所有敏感信息)

它可能是这样工作的:

// get the tracker script as a string, so you can eval it in a dynamic scope

let trackerScript = 'console.log("Tracked url:", window.location.href)';

// now lets lock it up
function trackerJail(){
  let window = {
    location: {
      // put your filtered url here
      href: "not so fast mr.bond"
    }
  }
  
  eval(String(trackerScript))
}

trackerJail()

如果跟踪代码段包含在一个函数中,则可以通过重写它的原型来为其创建一个动态范围而无需 运行 eval。但我不确定您是否可以指望跟踪器脚本被包装在一个您可以修改的简洁函数中。

此外,脚本可能会通过多种方式尝试访问 URL,因此请确保覆盖所有出口

如果您控制脚本的页面和顺序,您可以从 url 中读取数据,然后在其他任何内容访问它之前将其删除。

proofOfConcept.html

<script id="firstThingToLoad.js">
    console.log(window.location.href);
    const keyRegex = /key=[^&]*/;
    const key = window.location.href.match(keyRegex);
    console.log("I have key", key);

    const href = window.location.href.replace(keyRegex, "");
    history.replaceState({}, "", href);
</script>

<script id="someSnoopyCode.js">
    console.log("I'm snooping: ", window.location.href);
</script>

<body>
    <a href="/?key=secret">Link to private</a>
</body>

当然 Link to private 不应该存在。此外,这确实会破坏刷新和大多数导航,尽管有一些方法可以捕捉并保存它。