反爬虫類中のchrome無頭ブラウザのいくつかの検出と迂回方式


chromeヘッドレスブラウザのいくつかの検出方法


本試験で使用したchromeバージョンはMozilla/5.0(Macintosh;Intel Mac OS X 10_12_6)AppleWebKit/53.36(KHTML,like Gecko)Chrome/70.0.3514.2 Safari/53.36

1.UserAgent検出


ヘッドレスモードのUAにはHeadlessChromeキーが付きます
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/70.0.3521.2 Safari/537.36

UAのキーワードをチェックすることができます
if (/HeadlessChrome/.test(navigator.userAgent)) {
  // headless...
}

2.Webdriver検出


ヘッドレスモードでnavigator.webdriverはtrueであるため、以下のような検出が可能である.
// Webdriver Test
if (navigator.webdriver) {
  // headless...
}

この検出を迂回するために、この属性を再設定すればよい.
Object.defineProperty(navigator, 'webdriver', {
    get: () => false,
  });

プロトタイプからこのプロパティを削除することを推奨します
delete navigator.__proto__.webdriver;

补充说明:大麦网または淘宝网のスライダ検証コードはまず環境を検出し、通常はsufei_を利用する.Dataファイルは現在のブラウザ情報を検出し、webdriverコードは以下のように検出される.
        function r() {
            return "$cdc_asdjflasutopfhvcZLmcfl_"in u || f.webdriver
        }
        
//  ,         
// https://g.alicdn.com/secdev/sufei_data/3.6.8/index.js

したがって、スライダをドラッグしようとするときは、まずこのアトリビュートを変更します.そうでなければ、パスを変更する方法でエラーが表示され、再試行が要求されます.

3.chrome属性検出


ヘッドレスモードでwindow.chromeプロパティはundefinedですが、通常のインタフェースモードでは、以下のように定義されます.
csi: ƒ ()
embeddedSearch: {searchBox: {…}, newTabPage: {…}}
loadTimes: ƒ ()
app: (...)
runtime: (...)
webstore: (...)
get app: ƒ nativeGetter()
set app: ƒ nativeSetter()
get runtime: ƒ nativeGetter()
set runtime: ƒ nativeSetter()
get webstore: ƒ nativeGetter()
set webstore: ƒ nativeSetter(

従って、以下のような検出が可能となる
if (!window.chrome || !window.chrome.runtime) {
  // headless...
}

検出を迂回して属性を変更すればよい
 window.navigator.chrome = {
    runtime: {},
    // etc.
  };

4.Permissions検査

(async () => {
  const permissionStatus = await navigator.permissions.query({ name: 'notifications' });
  if(Notification.permission === 'denied' && permissionStatus.state === 'prompt') {
    // headless
  }
})();

ヘッドレスモードでpermissionとnavigatorpermissions.queryは逆の値を返します.そのため、迂回する方法は以下の通りです.
// Pass the Permissions Test.
await page.evaluateOnNewDocument(() => {
  const originalQuery = window.navigator.permissions.query;
  return window.navigator.permissions.query = (parameters) => (
    parameters.name === 'notifications' ?
      Promise.resolve({ state: Notification.permission }) :
      originalQuery(parameters)
  );
});

5.Plugins長さ検出


ヘッドレスモードでnavigator.plugins.lengthは0を返します
if (navigator.plugins.length === 0) {
  // headless
}

迂回方式は次の通りです.
Object.defineProperty(navigator, 'plugins', {
    get: () => [1, 2, 3, 4, 5],
  });

注意:逆登りは長さのほかに、内容もチェックします.長さを設定したら、内容を設定するのを忘れないでください.逆登りを防ぐ.

6.The Languages検出


navigator.Languages検出方法
if (!navigator.languages || navigator.languages.length === 0) {
  // headless
}

迂回方法
  Object.defineProperty(navigator, 'languages', {
    get: () => ['en-US', 'en'],
  });

7.原文アドレス


https://intoli.com/blog/not-possible-to-block-chrome-headless/https://intoli.com/blog/making-chrome-headless-undetectable/https://github.com/infosimples/detect-headless https://stackoverflow.com/questions/19877924/what-is-the-list-of-possible-values-for-navigator-platform-as-of-today