Як визначити Headless Chrome

4 хв. читання

Що таке headless браузер?

Headless браузер – переглядач, що може використовуватись без графічного інтерфейсу. Його можна запрограмувати для автоматизації різних завдань (наприклад, для проведення тестів чи для створення скріншотів).

Для чого потрібно виявляти headless браузер?

Крім безневинних способів застосування наведених вище, headless браузер також можна автоматизувати для виконання шкідливих завдань. Збільшення рекламних показів, пошук вразливостей на сайті, веб-скрапінг (web scraping) – ось неповний перелік.

Раніше найбільш популярним серед headless браузерів був PhantomJS. Побудований на фреймворку Qt, він мав багато відмінностей в порівнянні з популярними браузерами. В цій статті показано як можна виявляти його за допомогою певних технік, що використовують відбитки браузера.

З версії 59, Google почали випускати headless варіант свого браузера Chrome. На відміну від PhantomJS, він побудований на ванільному Chrome, і не використовує жодного зовнішнього фреймворку, що робить важким виявлення його присутності.

Виявлення Chrome Headless

Увага: Свої тести ми проводили на чотирьох пристроях (2 Linux, 2 Mac). Існують і інші методи виявлення Chrome Headless.

User agent

Ми почали з виявлення user agent атрибуту, що широко використовують для визначення операційної системи та браузера користувача. На Linux комп'ютері з Chrome версії 59 його значення було «Mozilla/5.0 (X11; Linux x8664) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/59.0.3071.115 Safari/537.36»

Таким чином, ми можемо перевіряти присутність Chrome Headless:

if (/HeadlessChrome/.test(window.navigator.userAgent)) {
    console.log("Chrome headless!");
}

User agent також можна отримувати із заголовків HTTP. Проте досить просто зробити підміну (spoof) в обох випадках.

Плагіни

navigator.plugins повертає перелік плагінів, що є в браузері. Chrome має деякі плагіни за замовченням: Chrome PDF viewer чи Google Native Client. В headless режимі в переліку плагінів, що повертає браузер, немає жодного.

if(navigator.plugins.length == 0) {
    console.log("Схоже, що це Chrome headless");
}

Мови

В Chrome є два Javascript атрибута, які потрібно залучити, щоб отримати мови, що використовує користувач: navigator.language та navigator.languages. Перший – мова користувацького інтерфейсу браузера, другий – перелік мов, яким користувач надає перевагу. В headlees режимі navigator.languages повертає пустий рядок.

if(navigator.languages == "") {
    console.log("Chrome headless!");
}

WebGL

WebGL – API для виконання 3D рендерингу в HTML сторінках. За допомогою цього API можна дізнатися виробника графічного драйвера, а також рендер, що використовує графічний драйвер.

З ванільним Chrome та Linux, я отримав наступні результати для рендеру та виробника: «Google SwiftShader» та «Google Inc.». В headless режимі, було отримано «Mesa OffScreen», що є технологією, яка використовується для рендерингу без жодної віконної системи та «Brian Paul», що є програмою, яка є частиною графічної бібліотеки Mesa.

var canvas = document.createElement('canvas');
var gl = canvas.getContext('webgl');

var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);

if(vendor == "Brian Paul" && renderer == "Mesa OffScreen") {
    console.log("Chrome headless detected");
}

Не всі headless версії Chrome, можуть мати такі ж значення виробника та рендеру. Інші версії можуть мати значення аналогічні для не headless версій. Проте «Mesa Offscreen» та «Brian Paul» будуть вказувати на наявність headless версій.

Особливості браузера

Modernizr дає можливість протестувати наявність широкого спектру особливостей HTML та CSS, які присутні в браузері. Ми виявили тільки одну різницю між Chrome та headless Chrome. Останній не має hairline функції, яка дозволяє визначити підтримку hidpi/retina hairline функцій.

if(!Modernizr["hairline"]) {
    console.log("Схоже, що це Chrome headless!");
}

Відсутність зображень

І нарешті, наша остання знахідка, яка виглядає достатньо надійною. Вона походить з розмірів зображення, які використовує Chrome у випадку коли зображення не може бути завантажено.

У випадку ванільного Chrome, зображення має ширину та висоту і залежить від збільшення в браузері, але завжди відмінне від нуля. В headless Chrome зображення має нульові значення ширини та висоти.

var body = document.getElementsByTagName("body")[0];
var image = document.createElement("img");
image.src = "http://iloveponeydotcom32188.jg";
image.setAttribute("id", "fakeimage");
body.appendChild(image);
image.onerror = function(){
    if(image.width == 0 && image.height == 0) {
        console.log("Chrome headless!");
    }
}
Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 6.2K
Приєднався: 7 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація