You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展Hook Navigator对象遭反机器人检测,如何解决?

Chrome扩展反指纹识别:篡改Navigator仍被机器人检测的问题分析与解决

问题概述

我编写Chrome扩展篡改Navigator对象属性用于反指纹识别实验,采用相关技术修改了User-Agent且伪造值与真实UA完全一致,但在bot检测页面仍被识别为机器人,求原因及解决办法。

提供的代码

manifest.json

{
"manifest_version": 3,
"name": "Helper",
"description": "Base Level Extension",
"version": "1.0",

"background": {"service_worker": "bg.js"},

"host_permissions": ["<all_urls>"],

"permissions": [
    "scripting",
    "contentSettings",
    "tabs",
    "storage",
    "declarativeNetRequest",
    "declarativeNetRequestWithHostAccess"
],

"declarative_net_request": {
    "rule_resources": [{
        "id": "ruleset",
        "enabled": true,
        "path": "rules.json"
    }]
},

"action": {
    "default_popup": "helper.html",
    "default_icon": "helper.png"
}
}

bg.js

chrome.runtime.onInstalled.addListener(async () => {

const old = await chrome.scripting.getRegisteredContentScripts();

if (old[0]) await chrome.scripting.unregisterContentScripts({ids: old.map(s => s.id)});

await chrome.scripting.registerContentScripts([{
  id: 'write',
  js: ['write.js'],
  matches: ['<all_urls>'],
  runAt: 'document_start',
  world: 'MAIN',
}]);

write.js

var navigator = window.navigator;
var modifiedNavigator;

if ('userAgent' in Navigator.prototype) {
    modifiedNavigator = Navigator.prototype;

} else {
    modifiedNavigator = Object.create(navigator);
    Object.defineProperty(window, 'navigator', {
        value: modifiedNavigator,
        configurable: false,
        enumerable: false,
        writable: false
    });
}

console.info(navigator.userAgent)
console.info(navigator.appName)
console.info(navigator.appVersion)
console.info(navigator.platform)

var ua = navigator.userAgent

// I tried this
modifiedNavigator.__defineGetter__('userAgent', function () { return ua; });

// As well as this
Object.defineProperties(modifiedNavigator, {
    userAgent: {
        value: navigator.userAgent.replace(/\([^)]+\)/, 'Windows NT 5.1'),
        configurable: false,
        enumerable: true,
        writable: false
    }
});

原因分析

  1. 仅修改User-Agent不全面:指纹检测依赖的不只是User-Agent,还会校验platform、appVersion、webdriver、vendor等多个Navigator属性,甚至属性的描述符(可配置性、枚举性),单一属性修改会出现特征不一致。
  2. 请求头与页面UA不匹配:你只修改了页面内的Navigator.userAgent,但HTTP请求头中的User-Agent还是原始值,检测系统会对比这两个值,不一致直接判定为异常。
  3. 属性修改方式存在漏洞:使用__defineGetter__或直接覆盖属性的方式,会改变属性的原始描述符(比如可配置性),现代指纹检测会通过Object.getOwnPropertyDescriptor检查属性特征,发现篡改痕迹。
  4. 未处理webdriver属性:多数bot检测会检查navigator.webdriver,即便在非自动化环境,扩展修改Navigator的操作可能导致该属性状态异常,或未强制设置为符合正常浏览器的false。

解决办法

1. 同步修改请求头与页面UA

通过declarativeNetRequest修改HTTP请求头的User-Agent,确保和页面内伪造值完全一致。创建rules.json文件:

[
  {
    "id": 1,
    "priority": 1,
    "action": {
      "type": "modifyHeaders",
      "requestHeaders": [
        {
          "header": "User-Agent",
          "operation": "set",
          "value": "Mozilla/5.0 (Windows NT 5.1; rv:109.0) Gecko/20100101 Firefox/115.0" // 替换为你伪造的UA
        }
      ]
    },
    "condition": {
      "urlFilter": "*",
      "resourceTypes": ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"]
    }
  }
]

2. 全面篡改Navigator关键属性并模拟原生描述符

修改write.js,覆盖所有指纹检测常用属性,同时保留原生属性的描述符特征,避免被检测到篡改:

const originalNav = window.navigator;
// 定义要伪造的属性值,确保UA与其他属性匹配
const fakeProps = {
  userAgent: originalNav.userAgent.replace(/\([^)]+\)/, 'Windows NT 5.1'),
  platform: 'Win32',
  appVersion: '5.0 (Windows)',
  webdriver: false,
  vendor: '', // 根据目标浏览器填写,比如Chrome是'Google Inc.'
  language: 'zh-CN'
};

// 获取原生属性的描述符,用来模拟原始特征
const getOriginalDescriptor = (prop) => {
  return Object.getOwnPropertyDescriptor(originalNav, prop) ||
         Object.getOwnPropertyDescriptor(Navigator.prototype, prop);
};

// 逐个修改属性,保留原生描述符的可配置、枚举等特征
Object.keys(fakeProps).forEach(prop => {
  const originalDesc = getOriginalDescriptor(prop);
  if (!originalDesc) return;
  
  Object.defineProperty(Navigator.prototype, prop, {
    ...originalDesc,
    get: () => fakeProps[prop],
    value: fakeProps[prop],
    configurable: originalDesc.configurable !== undefined ? originalDesc.configurable : false
  });
});

// 移除调试用的console输出,避免暴露痕迹

3. 确保修改时机足够早

保持runAt: 'document_start'和world: 'MAIN'的配置,确保脚本在页面任何检测代码运行前完成属性篡改。

4. 隐藏扩展相关痕迹

避免在MAIN world脚本中引入任何扩展专属API(如chrome对象),同时删除调试用的console输出,防止被检测到异常脚本行为。


内容的提问来源于stack exchange,提问作者Andreas Toresäter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:37:01