Відслідковування користувачів Інтернету

Ідентифікація, відстеження користувача або веб-трекінг – це розрахунок і встановлення унікального ідентифікатора для кожного браузера, який відвідує певний сайт. Взагалі, спочатку ідентифікація не замислювалося як якесь вселенське зло і, як і всі, має зворотний бік, тобто покликане приносити користь. Наприклад, дозволити власникам сайту відрізнити звичайних користувачів від ботів або ж надати можливість зберігати вподобання користувачів і застосовувати їх при наступному візиті. Але в той самий час дана можливість дуже припала до душі рекламній індустрії. Відомо, що куки – один із найпопулярніших способів ідентифікації користувачів. І активно застосовуватися в рекламній індустрії вони почали аж із середини дев'яностих років.

Відтоді багато чого змінилося, технології пішли далеко вперед, і зараз відслідковування користувачів одними лише куками не обмежується. Насправді ідентифікувати користувачів можна різними способами. Найбільш очевидний варіант – встановити якісь ідентифікатори, на зразок куків. Наступний варіант – скористатися даними про використовувані користувачем комп’ютери, які можна почерпнути з HTTP-заголовків відправлених запитів: адреса, тип операційної системи, час тощо. Ну і наостанок можна відрізнити користувача за його поведінкою і звичками (рухом курсора, улюбленими розділами сайту та інше).

Очевидні ідентифікатори

Даний підхід досить очевидний, все, що потрібно – зберегти на стороні користувача якийсь ідентифікатор, який можна запитувати при подальшому відвідуванні ресурсу. Сучасні браузери надають достатньо способів виконати це прозоро для користувача. Насамперед це старі добрі куки. Потім особливості деяких плагінів, близькі за функціоналом до куків, наприклад Local Shared Objects під флеш або Isolated Storage в сілверлайті. HTML5 також включає в себе кілька механізмів зберігання на стороні клієнта, в тому числі localStorage, File і IndexedDB API. Крім цих місць, унікальні маркери можна також зберігати в кеш ресурсах локальної машини або метаданих кеша (Last-Modified, ETag). Крім цього, можна ідентифікувати користувача за відбитками, отриманими з Origin Bound сертифікатів, згенерованих браузером для SSL-з'єднань, за даними, що містяться в SDCH-словниках, і метаданих цих словників. Одним словом – можливостей багато.

Cookies

Коли справа стосується зберігання якогось невеликого обсягу даних на стороні клієнта, куки – це перше, що зазвичай приходить на гадку. Веб-сервер встановлює унікальний ідентифікатор для нового користувача, зберігаючи його в куках, і при всіх наступних запитах клієнт буде відправляти його серверу. І хоча всі популярні браузери вже давно забезпечені зручним інтерфейсом з управління куками, а в мережі повно сторонніх утиліт для управління ними та їх блокування, куки все одно продовжують активно використовуватися для трекінгу користувачів. Справа в тому, що мало хто переглядає і чистить їх. Мабуть, основна причина цього – всі бояться випадково видалити потрібний файл, який, наприклад, може використовуватися для авторизації. І хоча деякі браузери дозволяють обмежувати установку сторонніх куків, проблема не зникає, тому що дуже часто браузери вважають «рідними» куки, отримані через HTTP-редиректи або інші способи під час завантаження контенту сторінки. На відміну від більшості механізмів, використання куків прозоре для кінцевого користувача. Для того щоб «помітити» юзера, необов'язково навіть зберігати унікальний ідентифікатор в окремому файлі – він може збиратися зі значень декількох куків або зберігатися в метаданих, таких як Expiration Time. Тому на даному етапі досить непросто розібратися, чи використовується конкретна кука для трекінгу чи ні.

Local Shared Objects

Для зберігання даних на стороні клієнта в Adobe Flash використовується механізм LSO. Він є аналогом cookies в HTTP, але на відміну від останніх може зберігати не тільки короткі фрагменти текстових даних, що, в свою чергу, ускладнює аналіз і перевірку таких об'єктів. До версії 10.3 поведінку флеш-куків регулювали окремо від налаштувань браузера: потрібно було відвідати менеджер налаштувань Flash, розташований на сайті macromedia.com (до речі, він доступний і зараз). Сьогодні це можна виконати безпосередньо з контрольної панелі. До того ж більшість сучасних браузерів забезпечують досить щільну інтеграцію з флеш-плеєром: так, при видаленні куків та інших даних сайтів будуть також видалені і LSO. З іншого боку, взаємодія браузерів з плеєром ще не настільки тісна, тому настроювання в браузері політики для сторонніх куків не завжди торкнеться флеш-куків (на сайті Adobe можна подивитися, як відключити їх вручну).

Ізольоване сховище Silverlight

Програмна платформа Silverlight має досить багато спільного з Adobe Flash. Так, аналогом флешевих Local Shared Objects служить механізм під назвою Isolated Storage. Правда, на відміну від флешу налаштування приватності тут не зав'язані з браузером, тому навіть у випадку повного очищення куків і кеша браузера дані, збережені в Isolated Storage, все одно залишаться. Але ще цікавіше, що сховище виявляється загальним для всіх вікон браузера (крім відкритих в режимі «інкогніто») і всіх профілів, встановлених на одній машині. Як і в LSO, з технічної точки зору тут немає якихось перешкод для зберігання ідентифікаторів сесії. Проте, враховуючи, що достукатися до цього механізму через настройки браузера поки не можна, він не отримав такого широкого поширення як сховище для унікальних ідентифікаторів.

HTML5 і зберігання даних на клієнті

HTML5 представляє набір механізмів для зберігання структурованих даних на клієнті. До них відносяться localStorage, File API і IndexedDB. Незважаючи на відмінності, всі вони призначені для забезпечення постійного зберігання довільних порцій бінарних даних, прив'язаних до конкретного ресурсу. Плюс, на відміну від HTTP- і Flash-куків, тут немає якихось значних обмежень на розмір збережених даних. У сучасних браузерах HTML5-сховище розташовується поряд з іншими даними сайту. Однак як управляти сховищем через настройки браузера – здогадатися дуже важко. Наприклад, щоб видалити дані з localStorage у Firefox, користувачеві доведеться вибрати offline website data або site preferences і задати часовий проміжок everything. Ще одна неординарна фішка, притаманна тільки IE – дані існують тільки на час життя табів, відкритих в момент їх збереження. Плюс до всього перелічені механізми не особливо намагаються враховувати обмеження, застосовні до HTTP-куків. Наприклад, можна писати в localStorage і читати з нього через крос-доменні фрейми навіть при відключених сторонніх куках.

Кешовані об'єкти

Всі хочуть, щоб браузер працював швидко і не гальмував. Тому йому доводиться складати в локальний кеш ресурси відвідуваних сайтів (щоб не запитувати їх при наступному візиті). І хоча даний механізм явно не призначався для використання як сховища з довільним доступом, його можна в таке перетворити. Наприклад, сервер може повернути користувачеві JavaScript-документ з унікальним ідентифікатором всередині його тіла і встановити в заголовках Expires/max-age = далеке майбутнє. Таким чином скрипт, а з ним і унікальний ідентифікатор пропишеться в кеші браузера. Після чого до нього можна буде звернутися з будь-якої сторінки в мережі, просто запитавши завантаження скрипта з відомого URL'а. Звичайно, браузер буде періодично запитувати за допомогою заголовка If-Modified-Since, чи не з'явилася нова версія скрипта. Але якщо сервер буде повертати код 304 (Not modified), то закешована копія буде використовуватися вічно.

Чим ще цікавий кеш? Тут немає концепції «сторонніх» об'єктів, як, наприклад, у випадку з HTTP-куками. У той же час відключення кешування може серйозно відбитися на продуктивності. А автоматичне визначення хитрих ресурсів, що зберігають в собі якісь ідентифікатори/мітки, важке у зв'язку з великим обсягом і складністю JavaScript-документів, що зустрічаються в мережі. Звичайно, всі браузери дозволяють користувачеві вручну чистити кеш. Але як показує практика, проводиться це не так часто, якщо проводиться взагалі.

ETag і Last-Modified

Для того щоб кешування працювало правильно, серверу необхідно якимось чином інформувати браузер про те, що доступна більш нова версія документа. Стандарт HTTP/1.1 пропонує два способи для вирішення цього завдання. Перший базується на даті останньої зміни документа, а другий – на абстрактному ідентифікаторі, відомому як ETag. У випадку з ETag сервер спочатку повертає так званий version tag в заголовку відповіді разом із самим документом. При наступних запитах до заданого URL клієнт повідомляє серверу через заголовок If-None-Match це значення, асоційоване з його локальною копією. Якщо версія, зазначена в цьому заголовку, актуальна, то сервер відповідає HTTP-кодом 304 (Not Modified), і клієнт може спокійно використовувати кешовану версію. В іншому випадку сервер надсилає нову версію документа з новим ETag. Такий підхід чимось нагадує HTTP-куки – сервер зберігає довільне значення на клієнті тільки для того, щоб потім його рахувати.

Інший спосіб, пов'язаний з використанням заголовка Last-Modified, дозволяє зберігати принаймні 32 біта даних в рядку дати, яка потім вирушає клієнтом серверу в заголовку If-Modified-Since. Що цікаво, більшість браузерів навіть не вимагають, щоб цей рядок представляв дату в правильному форматі. Як і у випадку ідентифікації користувача через кешовані об'єкти, на ETag і Last-Modified ніяк не впливає видалення куків і даних сайту, позбутися від них можна тільки очищенням кешу.

HTML5 AppCache

Application Cache дозволяє задавати, яка частина сайту повинна бути збережена на диску і бути доступною, навіть якщо користувач знаходиться офлайн. Реалізується все за допомогою маніфестів, які задають правила для зберігання та вилучення елементів кешу. Подібно до традиційного механізму кешування, AppCache теж дозволяє зберігати унікальні, залежні від користувача дані – як усередині самого маніфесту, так і всередині ресурсів, які зберігаються на невизначений термін (на відміну від звичайного кешу, ресурси з якого видаляються після закінчення якогось часу). AppCache займає проміжне значення між механізмами зберігання даних в HTML5 і звичайним кешем браузера. У деяких браузерах він очищається при видаленні куків і даних сайту, в інших тільки при видаленні історії перегляду та всіх кеш документів.

SDCH-словники

SDCH – це розроблений Google алгоритм компресії, який ґрунтується на використанні наданих сервером словників і дозволяє досягти більш високого рівня стиснення, ніж Gzip або deflate. Справа в тому, що в звичайному житті веб-сервер віддає занадто багато повторюваної інформації. У даному підході клієнт отримує з сервера файл словника, що містить рядки, які можуть з'явитися в наступних відповідях. Після чого сервер може просто посилатися на ці елементи всередині словника, а клієнт буде самостійно на їх основі збирати сторінку. Ці словники можна з легкістю використовувати і для зберігання унікальних ідентифікаторів, які можна помістити як в ID словників, які повертаються клієнтом серверу в заголовку Avail-Dictionary, так і безпосередньо в сам контент. І потім використовувати подібно як і у випадку зі звичайним кешем браузера.

Інші механізми зберігання

Але це ще не всі варіанти. За допомогою JavaScript і його товаришів по цеху можна зберігати і запитувати унікальний ідентифікатор таким чином, що він залишиться живим навіть після видалення всієї історії переглядів і даних сайтів. Як один з варіантів, можна використовувати для зберігання window.name або sessionStorage. Навіть якщо користувач підчистить всі куки і дані сайту, але не закриє вкладку, в якій був відкритий сайт, то при подальшому заходженні ідентифікатор буде отриманий сервером і користувач буде знову прив'язаний до вже зібраних про нього даних.

Така ж поведінка спостерігається і у JS, будь-який відкритий JavaScript-контекст зберігає стан, навіть якщо користувач видалить дані сайту. При цьому такий JavaScript може ховатися в iframe'ах і так далі. Наприклад, завантажена в iframe реклама зовсім не зверне уваги на видалення історії переглядів і даних сайту і продовжить використовувати ідентифікатор, збережений в локальній змінній в JS.

Протоколи

Крім механізмів, пов'язаних з кешуванням, використанням JS і різних плагінів, в сучасних браузерах є ще кілька засобів, що дозволяють зберігати та видавати унікальні ідентифікатори.

  1. Origin Bound Certificates (aka ChannelID) – персистентні самопідписні сертифікати, які ідентифікують клієнта HTTPS-серверу. Для кожного нового домену створюється окремий сертифікат, який використовується для з'єднань, ініційованих потім. Сайти можуть використовувати OBC для трекінгу користувачів, не роблячи при цьому будь-яких дій, які будуть помітні клієнту. Як унікальний ідентифікатор можна взяти криптографічний хеш сертифіката, що надається клієнтом як частина легітимного SSL.
  2. Подібним чином і в TLS теж є два механізми – session identifiers і session tickets. За рахунок використання закешованих даних ці механізми протягом невеликого проміжку часу дозволяють серверам ідентифікувати запити, які виходять від одного клієнта.
  3. Практично всі сучасні браузери реалізують свій власний внутрішній DNS-кеш, щоб прискорити процес розпізнавання імен (і в деяких випадках знизити ризик DNS rebinding атак). Такий кеш запросто можна використовувати для зберігання невеликих обсягів інформації. Однак такий підхід обмежений розміром внутрішнього DNS-кеша браузерів і може потенційно призвести до конфліктів в дозволі імен з DNS провайдера.

Характеристики машини

Всі розглянуті до цього способи ґрунтувалися на тому, що користувачеві встановлювався якийсь унікальний ідентифікатор. Є інший, менш очевидний підхід до відстеження користувачів, що покладається на запит або вимірювання характеристик клієнтської машини. Поодинці кожна отримана характеристика являє собою лише кілька біт інформації, але якщо об'єднати декілька, то вони зможуть унікально ідентифікувати будь-який комп'ютер в Інтернеті. Крім того, що таке стеження набагато складніше розпізнати і запобігти йому, ця техніка дозволить ідентифікувати користувача, що сидить під різними браузерами або використовує приватний режим.

«Відбитки» браузера

Найбільш простий підхід до трекінгу – це побудова ідентифікаторів шляхом об'єднання набору параметрів, доступних в середовищі браузера, кожен з яких окремо не представляє ніякого інтересу, але спільно вони утворюють унікальне для кожної машини значення:

  • User-Agent. Видає версію браузера, версію ОС і деякі із встановлених аддонів. У випадках, коли User-Agent відсутній або хочеться перевірити його «правдивість», можна визначити версію браузера перевіркою на наявність певних можливостей, реалізованих або змінених між релізами.
  • Час. Якщо система не синхронізує свій годинник зі стороннім сервером часу, то рано чи пізно годинник почне відставати або поспішати, що породить унікальну різницю між реальним і системним часом, яку можна виміряти з точністю до мікросекунди за допомогою JavaScript'у. Насправді навіть при синхронізації з NTP-сервером все одно будуть невеликі відхилення, які також можна буде виміряти.
  • Інформація Про CPU і GPU. Можна отримати як безпосередньо (через GL_RENDERER), так і через бенчмарки і тести, реалізовані за допомогою JavaScript.
  • Розширення монітора і розмір вікна браузера (включаючи параметри другого монітора у випадку мультимоніторних систем).
  • Список встановлених в системі шрифтів, отриманих, наприклад, за допомогою getComputedStyle API.
  • Список всіх встановлених плагінів, ActiveX-контролів, Browser Helper Object'ов, включаючи їх версії. Можна отримати перебором navigator.plugins [] (деякі плагіни видають свою присутність в HTTP-заголовках).
  • Інформація про встановлені розширення та інше програмне забезпечення. Такі розширення, як блокувальники реклами, вносять певні зміни в популярні сторінки, за якими можна визначити, що це за розширення, і його налаштування.

Мережеві «відбитки»

Ще ряд ознак криється в архітектурі локальної мережі та налаштування мережевих протоколів. Такі знаки будуть характерні для всіх браузерів, встановлених на клієнтській машині, і їх не можна просто приховати за допомогою налаштувань приватності або якихось security-утиліт. Вони включають в себе:

  • Зовнішню IP-адресу. Для IPv6-адрес даний вектор особливо цікавий, оскільки останні октети в деяких випадках можуть виходити з MAC-адреси пристрою і тому зберігатися навіть при підключенні до різних мереж.
  • Номери портів для вихідних TCP/IP-з'єднань (зазвичай вибираються послідовно для більшості ОС).
  • Локальні IP-адреси для користувачів, що знаходяться за NAT'ом або HTTP-проксі. Укупі із зовнішньою IP-адресою дозволяє унікально ідентифікувати більшість клієнтів.
  • Інформація про використовувані клієнтом проксі-сервери, отримана з HTTP-заголовку (X-Forwarded-For). У поєднанні з реальною адресою клієнта, отриманою через кілька можливих способів обходу проксі, також дозволяє ідентифікувати користувача.

Поведінковий аналіз і звички

Ще один варіант – подивитися у бік характеристик, які прив'язані не до ПК, а скоріше до кінцевого користувача, такі як регіональні налаштування і поведінка. Такий спосіб знову ж дозволить ідентифікувати клієнтів між різними сесіями браузера, профілями і у випадку приватного перегляду. Робити висновки можна на підставі наступних даних, які завжди доступні для вивчення:

  • Мову, кодування за замовчуванням і часовий пояс (все це живе в HTTP-заголовках і доступне з JavaScript).
  • Дані в кеші клієнта і його історія перегляду.
  • Жести мишею, частота і тривалість натиснення клавіш, дані з акселерометра – всі ці параметри унікальні для кожного користувача.
  • Зміни стандартних шрифтів сайту та їх розмірів, рівень zoom'у, використання спеціальних можливостей, таких як колір тексту, розмір.
  • Стан певних додаткових можливостей браузера: блокування сторонніх куків, DNS prefetching, блокування спливаючих вікон, налаштування безпеки Flash і так далі (за іронією, користувачі, що міняють стандартні налаштування, насправді роблять свій браузер значно легшим для ідентифікації).

І це лише очевидні варіанти, які лежать на поверхні. Якщо копнути глибше – можна придумати ще.

Підсумок

На практиці існує значна кількість різних способів для трекінгу користувача. Якісь із них є плодом помилок в реалізації або упущень і теоретично можуть бути виправлені. Інші практично неможливо викорінити без повної зміни принципів роботи комп'ютерних мереж, веб-додатків, браузерів. Деяким технікам можна протидіяти – чистити кеш, куки та інші місця, де можуть зберігатися унікальні ідентифікатори. Інші працюють абсолютно непомітно для користувача, і захиститися від них навряд чи вийде. Тому найголовніше – подорожуючи мережею навіть в приватному режимі перегляду, пам'ятати, що твоє переміщення все одно можуть відстежити.

За матеріалами: supreme2.ru.

 

Читайте також: