Статьи

Фінгерпрінтінг браузера. Як відстежують користувачів в Мережі

  1. Зміст статті Мене завжди напружувало те, як нав'язливо Google AdSense підсовував контекстну рекламу...
  2. явні ідентифікатори
  3. Cookies
  4. Local Shared Objects
  5. Ізольоване сховище Silverlight
  6. HTML5 і зберігання даних на клієнті
  7. кешовані об'єкти
  8. ETag і Last-Modified
  9. HTML5 AppCache
  10. SDCH-словники
  11. Інші механізми зберігання
  12. протоколи
  13. характеристики машини
  14. «Відбитки» браузера
  15. Мережеві «відбитки»
  16. Поведінковий аналіз і звички
  17. Підсумуємо

Зміст статті

Мене завжди напружувало те, як нав'язливо Google AdSense підсовував контекстну рекламу в залежності від моїх старих запитів у пошуковій системі. Начебто і часу з моменту пошуку пройшло досить багато, та й куки і кеш браузера чистилися не раз, а реклама залишалася. Як же вони продовжували відстежувати мене? Виявляється, способів для цього більш ніж достатньо.

невелике передмову

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

З тих пір багато чого змінилося, технології пішли далеко вперед, і в даний час відстеження користувачів одними тільки печеньки не обмежується. Насправді ідентифікувати користувачів можна різними способами. Найбільш очевидний варіант - встановити будь-які ідентифікатори, на зразок куків. Наступний варіант - скористатися даними про використовуваним користувачем ПК, які можна почерпнути з 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 можна подивитися, як вручну їх відключити).

З іншого боку, взаємодія браузерів з плеєром ще не настільки тісне, тому настройка в браузері політики для сторонніх куків не завжди торкнеться флеш-куки (на   сайті Adobe   можна подивитися, як вручну їх відключити)

Видалення даних з localStorage в Firefox

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

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

Проте, з огляду на, що достукатися до цього механізму через настройки браузера поки не можна, він не отримав такого широкого поширення в якості сховища для унікальних ідентифікаторів

Де шукати ізольоване сховище Silverlight

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

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

Наприклад, можна писати в localStorage і читати з нього через крос-доменні фрейми навіть при відключених сторонніх куках

Налаштування локального сховища для Flash Player

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

Всі хочуть, щоб браузер працював спритно і без гальм. Тому йому доводиться складати в локальний кеш ресурси відвідуваних сайтів (щоб не запитувати їх при наступному візиті). І хоча даний механізм явно не призначався для використання в якості сховища з довільним доступом, його можна в такий перетворити. Наприклад, сервер може повернути користувачеві 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 ніяк не впливає видалення куків і даних сайту, позбутися від них можна тільки очищенням кеша.

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

Сервер повертає клієнту ETag

HTML5 AppCache

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

SDCH-словники

SDCH - це розроблений Google алгоритм компресії, який грунтується на використанні наданих сервером словників і дозволяє досягти більш високого рівня стиснення, ніж Gzip або deflate. Справа в тому, що в звичайному житті веб-сервер віддає занадто багато повторюваної інформації - Хідер / футери сторінок, вбудований JavaScript / CSS і так далі. В даному підході клієнт отримує з сервера файл словника, що містить рядки, які можуть з'явитися в наступних відповідях (ті ж Хідер / футери / JS / CSS). Після чого сервер може просто посилатися на ці елементи всередині словника, а клієнт буде самостійно на їх основі збирати сторінку. Як ти розумієш, ці словники можна з легкістю використовувати і для зберігання унікальних ідентифікаторів, які можна помістити як в 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, які дозволяють клієнтам відновлювати HTTPS-з'єднання без виконання повного рукостискання. Досягається це за рахунок використання закеширувалася даних. Два цих механізму протягом невеликого проміжку часу дозволяють серверам ідентифікувати запити, які виходять від одного клієнта.
  3. Практично всі сучасні браузери реалізують свій власний внутрішній DNS-кеш, щоб прискорити процес розпізнавання імен (і в деяких випадках знизити ризик DNS rebinding атак). Такий кеш запросто можна використовувати для зберігання невеликих обсягів інформації. Наприклад, якщо мати 16 доступними IP-адресами, близько 8-9 закеширувалася імен буде досить, щоб ідентифікувати кожен комп'ютер в Мережі. Однак такий підхід може перевищувати обсягу внутрішнього 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).
  • Дані в кеші клієнта і його історія перегляду. Елементи кеша можна виявити за допомогою атак за часом - відстежує може виявити довгоживучі елементи кеша, що відносяться до популярних ресурсів, просто вимірявши час з завантаження (і скасувавши перехід, якщо час перевищує очікуваний час завантаження з локального кеша). Також можна отримувати URL'и, що зберігаються в історії перегляду браузера, хоча така атака в сучасних браузерах потребують невеликого взаємодії з користувачем.
  • Жести мишею, частота і тривалість натискання клавіш, дані з акселерометра - всі ці параметри унікальні для кожного користувача.
  • Будь-які зміни стандартних шрифтів сайту і їх розмірів, рівень zoom'а, використання спеціальних можливостей, таких як колір тексту, розмір.
  • Стан певних фич браузера, що настроюються клієнтом: блокування сторонніх куків, DNS prefetching, блокування спливаючих вікон, налаштування безпеки Flash і так далі (за іронією, користувачі, що змінюють дефолтні настройки, в дійсності роблять свій браузер значно легшим для ідентифікації).

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

Підсумуємо

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

Як же вони продовжували відстежувати мене?
Чим ще цікавий кеш?

Новости