Browser Fingerprint – анонімна ідентифікація браузерів



Валентин Васильєв (Machinio.com

Що ж таке Browser Fingerprint? Або ідентифікація браузерів. Дуже проста формулювання — це присвоєння ідентифікатора браузеру. Формулювання проста, але ідея дуже складна та цікава. Для чого вона використовується? Для чого ми хочемо привласнити браузеру ідентифікатор?


  • Ми хочемо враховувати наших користувачів. Ми хочемо знати, чи прийшов користувач до нас перший раз прийшов він вдруге або втретє. Якщо користувач прийшов вдруге, ми хочемо знати, на які сторінки він заходив, що він до цього робив. З анонімними користувачами це неможливо. Якщо у вас є система обліку записів, користувач логинится, ми все про нього знаємо — ми знаємо його обліковий запис, його персональні дані, ми можемо прив'язати будь-які дії до цього користувачеві. Тут все просто. У випадку з анонімними користувачами все стає набагато складніше.
  • Другий сценарій — персональна реклама. Це зараз скрізь. Ми заходимо, і раптом нам показують рекламу яких-небудь пиріжків, які ми хотіли придбати ще вчора. Як це робиться? Це робиться через ідентифікацію користувачів.
  • Третій сценарій — внутрішня аналітика. Якщо ви використовуєте, крім Google Analytics, Яндекс, власну самописную систему аналітики, Fingerprint JS і Browser Fingerprint, в цілому, може допомогти вам у досягненні майже повної ідентифікації анонімних користувачів. Ви зможете побачити, що користувач робив на вашому сайті, на які сторінки заходив, які заслання він клацав і т. д. І побудувати на основі цього цілу картину, карту дій користувача. Все це досягається за допомогою цієї техніки — Browser Fingerprinting.


Чому б для цієї мети не просто використовувати http cookie? Адже це дуже просто, і все це вміють робити. Працює це, ви всі знаєте як.

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

Якщо там ідентифікатора немає, значить, користувач прийшов до нас вперше. Ми генеруємо унікальний ідентифікатор, GUI, бінарну рядок якусь, записуємо це cookie, і потім, коли користувач прийде в наступний раз, ми цей cookie прочитаємо і зрозуміємо, що цей користувач до нас прийшов у другій, третій і наступні рази.

У cookie є один великий недолік — його можна очистити. Будь-який, навіть технічно неподкованный користувач знає, як очищати cookie. Він натискає «Налаштування», заходить і очищає. Все, користувач стає знову для вас анонімним, ви не знаєте, хто він такий.

Всі сучасні браузери, навіть Internet Explorer, здається, пропонують режим інкогніто. Це такий режим, коли нічого не зберігається, і коли користувач відвідав ваш сайт в цьому режимі, він не залишає ніяких слідів. Наступний раз, коли він зайде в режимі інкогніто, ви знову ж таки не дізнаєтеся, хто він такий і був він у вас до цього. Тобто в режимі інкогніто http cookie працювати не будуть.

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

Як програмісти намагалися і намагаються вирішити цю проблему?

Найбільш успішним проектом у сфері збереження інформації в cookie так, щоб неможливо було її видалити, на мій погляд, є проект evercookie, або persistent cookie — неудаляемый cookie, важко видаляється cookie. Суть його полягає в тому, що evercookie не просто зберігає інформацію в одному сховищі, такому як http cookie, він використовує всі доступні сховища сучасних браузерів. І зберігає вашу інформацію, наприклад, ідентифікатор. Починає він використовувати http cookies, записує ідентифікатор туди, потім, якщо в браузері доступний Flash, він використовує local shared objects для запису інформації в т. н. Flash cookies.



Flash cookies до недавнього часу не очищалися, коли ви очищали cookie. Лише останні версії Google Chrome вміють очищати Flash cookie, коли ви чистите звичайні cookie. Тобто до недавнього часу Flash cookies були практично не видаляються. Існувала спеціальна сторінка на сайті macromedia, куди потрібно було зайти, натиснути кнопку: «Так, я хочу очистити Flash cookies», і тоді вони очищаються, тобто без цієї сторінки було очистити неможливо.



Далі, evercookie використовує Silverlight Cookies. По-іншому вони називаються Isolated Storage. Це спеціальне виділене місце на жорсткому диску користувача, куди пишеться cookie інформація. Знайти це місце неможливо, якщо ви не знаєте точний шлях. Воно ховається десь у документах, Setting'ах, якщо на Windows, глибоко в надрах комп'ютера. І ці дані видалити за допомогою очищення cookie неможливо.



Далі. Evercookie використовує таку інноваційну техніку як PNG Cookies. Суть полягає в тому, що браузер віддає картинку, в якій в байти цієї картинки закодована інформація, яку ви зберегли, наприклад, ідентифікатор. Ця картинка віддається з директивою кешування назавжди, припустимо, на наступні 50 років. Браузер кешує цю картинку, а потім при подальшому відвідуванні користувачем за допомогою Canvas API зчитуються байти з цієї картинки, і відновлюється та інформація, яку ви хотіли зберегти cookie. Т. о. навіть якщо користувач очистив cookie, ця картинка з закодованим cookie PNG, як і раніше буде перебувати в кеші браузера, і Canvas API зможе її вважати при подальшому відвідуванні.



Evercookie використовує всі доступні сховища браузера — сучасний стандарт HTML 5, Session Storage, Local Storage, Indexed DB та інші.



Також використовується ETag header — це http заголовок, дуже короткий, але в ньому можна закодувати будь-яку інформацію, і якщо встановлений Java, то використовується java presistence API.



Evercookie — дуже розумний плагін, який може зберігати ваші дані практично скрізь. Для звичайного користувача, який не знає всього цього, видалити cookies просто неможливо. Потрібно відвідати 6-8 місць на жорсткому диску, виконати ряд маніпуляцій для того, щоб їх очистити. Тому звичайний користувач, коли відвідує сайт, який використовує evercookie, напевно не буде анонімним.

Незважаючи на все це, evercookie не працює в режимі інкогніто. Як тільки ви зайшли в режим інкогніто, ніякі дані не зберігаються на диску, тому що це основна суть інкогніто режиму — ви повинні бути анонімними. А еvercookie використовує зберігання на жорсткому диску, яке в цьому режимі не працює.



FingerprintJS — це маленька бібліотека, яку я написав, і яка намагається вирішити ці проблеми. Я розповім, як вона це робить, і що з цього вийшло.

Написав я її в 2012 році. Я тоді працював у «КупиКупон» Ruby розробником. І в мене було завдання зробити таку систему аналітики, щоб враховувати не просто залогиненных користувачів, тобто тих користувачів, які є у нас в системі, а також анонімних користувачів. Конкретно на сайті «КупиКупон» було багато анонімних користувачів, тому що люди часто приходили ззовні подивитися на якісь купони, знижки, пропозиції, у них ні в кого не було облікового запису, і тому система трекінгу, система відстеження відвідуваних сторінок, натискання на кнопки — все це не працювало, тому що користувачі були анонімними.

FingerprintJS, взагалі, не використовує cookie. Ніяка інформація не зберігається на жорсткому диску комп'ютера, де встановлений браузер. Працює в режимі інкогніто, тому що в принципі не використовує зберігання на жорсткому диску. Не має залежностей, працює навіть без jQuery, і розмір   1,2 Кб gzipped.



На даний момент використовується в таких компаніях як Baidu, це Google в Китаї, MasterCard, сайт президента США, AddThis   сайт размещениz віджетів і т. д.

Ця бібліотека швидко стала дуже популярною. Вона використовується приблизно на 6-7% всіх найбільш відвідуваних сайтів в Інтернеті на даний момент.



Як вона працює, розповім детально. Суть її в тому, що код цієї бібліотеки опитує браузер користувача на предмет всіх специфічних та унікальних параметрів і даних для цього браузера і для цієї системи, для комп'ютера. Ці дані об'єднуються у величезну рядок, потім вони подаються на вхід функції хешування. Функція хешування бере ці дані і перетворює їх в компактні красиві ідентифікатори. Як детально це працює, я розповім.

Спочатку зчитується userAgent navigator. Припустимо, тут він обрізаний, це приєднується до підсумковій рядку відбитка.



Зчитується мова браузера — який у вас язик — англійська, російська, португальська і т. д. Теж приєднується до рядку відбитка.

Зчитується часовий пояс, це кількість хвилин від UTC:



-180.

Це -6, виходить Москва.



Далі виходить розмір екрана, масив, глибина кольору екрана.



Потім відбувається отримання всіх підтримуваних технологій HTML5, тобто у кожного браузера підтримка відрізняється. FingerprintJS намагається визначити, які підтримуються, які   ні, і для кожної технології результат опитування наявності цієї технології і ступінь її підтримки додається до підсумкової функції відбитка.



SessionStorage, LocalStorage, IndexedDB, OpenDatabase і всілякі інші.

Опитуються дані, специфічні для користувача і для платформи, такі як налаштування doNotTrack (дуже іронічно, що налаштування doNotTrack використовується якраз для трекінгу), cpuClass процесора, platform і інші дані.



Тут у вас може виникнути закономірне питання — адже у дуже багатьох користувачів ці дані вони однакові? Припустимо, користувач живе в Москві, у нього буде однаковий мову, останній Chrome, у нього буде все практично однаково, і всі ці рядки, які були отримані на даному етапі, будуть однакові. Як це допоможе ідентифікувати користувача?

Є ще 2 способи, які додають унікальності.



  • Перший — це інформація про плагіни. Код опитує наявність всіх встановлених плагінів в системі. Для кожного плагіна виходить його опис та назву.А також, що дуже важливо, список всіх типів мультимедіа або main типів, які підтримують цей плагін. Вся ця інформація об'єднується у величезний масив рядків, і цей масив теж конкатенируется і додається до рядку відбитка. Як ви розумієте, на кожному комп'ютері список плагінів свій, досить унікальний, і версії плагінів можуть бути свої, і список підтримуваних main типів теж буде свій.


  • Наступне — до рядка відбитка додається т. н. Сanvas Fingerprint. Це ще одна техніка, яка дозволяє підвищити точність. Суть її полягає в тому, що на прихованому Сanvas елементі малюється певний текст з певними накладеними на нього ефектами. І потім отримане зображення серіалізуются в байтовий масив і перетворюється в base64 за допомогою виклику canvas.toDataULR().
У вас тут виникає питання: як це теж допомагає ідентифікувати? Несподіване для мене було дослідження, яке я знайшов. Воно говорить про те, що промальовування шрифтів, зокрема, в Canvas API, дуже платформозависима. Зовні ідентичні однакові зображення, намальовані в різних браузерах, будуть перетворені в різний байтовий масив. Чому? Це залежить від процесора, відеокарти, драйверів відеокарти, системних бібліотек, таких як direct X, систем відтворення шрифтів, тіней — все це на кожному комп'ютері може бути своє, тому результуючий байтовий масив буде відрізнятися практично на кожному комп'ютері, де буде різна апаратна і програмна начинка. І ця довга рядок, отримана при серіалізації Сanvas буде приєднана до підсумкового відбитку, і ми отримаємо величезну рядок.



Тут показано, як це працює. Ми отримуємо всі ці дані. Потім ми передаємо їх функції хешування, в FingerprintJS використовується nomo hash2, і на виході ми отримуємо 32-х бітне число. Це і є ваш ідентифікатор. Т. о., коли користувач заходить на наш сайт, йому присвоюється номер. Цей номер ви прочитаєте і використовуєте, як хочете, — ви базируете на ньому свою аналітику і т. д.

Тут питання: наскільки унікально і точно визначення? Дослідження, за основу якого було взято, було зроблено компанією Electronic Frontier Foundation, у них був проект Panopticlick. Воно говорить, що унікальність складає близько 94%, але на реальних даних, які були у мене, унікальність становила близько 90%-91%.

Бібліотеку стало використовувати багато людей і компаній, і з плином часу виявився ряд недоліків. Тобто вона не ідеальна, у неї є недоліки. Самий головний недолік — те, що точність ідентифікації лише 90%, але є й інші недоліки.



  1. UserAgent. У сучасних браузерів UserAgent змінюється дуже часто, кожні два місяці виходить нова версія Google Chrome. UserAgent буде змінюватися, тому що та версія Google Chrome, яка захист в UserAgent буде відрізнятися. А це означає, що UserAgent буде впливати на підсумковий відбиток. Якщо виходить новий браузер, підсумковий відбиток зміниться, тому що з точки зору FingerprintJS це буде новий користувач.
  2. IPhone, IPad та інші продукти Apple. Справа в тому, що вони дуже униформенные, однакові з точки зору апаратної реалізації. У них у всіх однакові процесори. Якщо ми візьмемо, звичайно, окремо взяту модель, припустимо IPhone 5S, у всіх IPhone 5S буде однаковий процесор, однаковий графічний прискорювач і однакові системні бібліотеки, і плагіни там будуть однакові, але насправді їх там немає. Це означає, що той байтовий масив, отриманий з Сanvas Fingerprint, буде однаковий для всіх версій IPhone 5S, а це означає, що точність ідентифікації для продуктів Apple буде нижче.
  3. Internet Explorer і Китай. Не підозрював про існування цієї проблеми, але потім я дізнався, що використовується в Китаї дуже багато старих версій IE, і для того, щоб отримати список плагінів, потрібно мати назви всіх плагінів заздалегідь. Тому що для того, щоб перевірити, чи є плагін чи ні, в IE просто неможливо викликати, наприклад, navigator.plugins. Це не буде працювати. Потрібно взяти і кожен плагін спробувати инстанциировать як active ex об'єкт. Якщо він створився, то значить все добре. Якщо викинута помилка, означає, що плагіни в IE не встановлені. Список плагінів для IE у мене був, але він був коротким   близько десяти плагінів. У мене не було визначення тих плагінів, які популярні в Китаї, таких як QQ, baidu і ін. Там дуже багато плагінів, які використовуються тільки там. Ці плагіни я не перевіряв, і список плагінів для Китаю конкретно був менше.
  4. Інший недолік першої версії — це відсутність інтеграції з Flash і Silverlight, а інтеграція з цими плагінами дозволяє поліпшити якість Fingerprint.
  5. І остання, але досить серйозна річ, яка нещодавно обрушилася на FingerprintJS, — це те, що, починаючи з версії 42, Google Chrome просто перестав активувати всі ті плагіни, які працюють через NPAPI. NPAPI — це дуже старий API для инстанциирования плагінів, він був розроблений ще компанією «Nextkey». Він так і називется — «Nextkey plugin API». Всі плагіни, які працюють і спираються на цей протокол, на цей API, перестали завантажуватися, і тому ні Silverlight, ні Java, а ці два плагіна найбільш популярні, які працюють через NPAPI, не відображаються в FingerprintJS — вони жодним чином не визначаються, і список їх main типів теж не відображається. Це означає, що в Chrome 42 і старше точність FingerprintJS знижена за рахунок цієї проблеми.
Тому, проаналізувавши все це, а зараз я теж використовую FingerprintJS, я прийшов до висновку, що пора розробляти нову бібліотеку, яка буде практично позбавлена всіх існуючих недоліків.

Я її почав робити зовсім недавно, розробка ведеться на github.



Як вона вирішує існуючі проблеми? Найголовніше — використовується фазихэширование або localsensitivehash, або нечітке хешування. Таке хешування, яке не змінюється, навіть якщо в звичайному хэшировании, якщо ви зміните хоча б один байт вхідної інформації, що виходить рядок теж зміниться, причому кардинальним чином. У фазихэшировании цього не відбувається, тут є поріг чутливості, коли певний відсоток вхідних даних може змінитися, що не вплине на вихідний відбиток. Припустимо, якщо змінилася в UserAgent тільки версія браузера, це трапляється дуже часто, припустимо, в Chrome, то результуючий відбиток буде однаковим, тому що версія становить 3 або 5 % від загальної довжини від UserAgent.



Друге — в FingerprintJS 2 використовується визначення встановлених шрифтів, всіх шрифтів, які встановлені в системі. Чим це корисно? Якщо ви поставили програму, припустимо, adobe pdf, ви додаєте в систему шрифти.



Якщо ви поставили Microsoft Office, ви додаєте в систему шрифти; якщо ви поставили якийсь Quick office, який має власні шрифти, ви знову ж додаєте в систему шрифти. І тому у вас може бути два абсолютно однакових комп'ютера, але на одному встановлений Office, а на іншому — немає. Це означає, що на першому, де немає Office, буде 320 доступних шрифтів, а, де є Office — 1700 шрифтів. І означає, що ви зможете отримати всі шрифти, які є на цьому комп'ютері, знову ж таки, для підсумкового відбитка. Це буде два різних відбитка, тому що різні шрифти.

За замовчуванням використовується Flash, маленький swf файл розміром 916 байт. Він отримує список всіх встановлених шрифтів, причому в платформозависимом порядку, т. к. вони доступні в системі, так вони і будуть повернені. Якщо Флеш не встановлений, використовується така техніка, вона називається site chanel technic. Вона вперше була опублікована на сайті lalit.org. Це визначення наявності шрифту за допомогою javascript only. Як це робиться? Для кожного референтного шрифту, який заданий за замовчуванням у браузері або в системі, вимірюється його ширина і висота, і цей масив ширини та висоти зберігається. Потім до прихованого тексту (текст, до речі, величезний, припустимо, 72 пікселя) застосовується інший шрифт. Якщо цей шрифт є в системі, текст змінить свої габарити правильно, і код, який змінює висоту і ширину, отримає новий масив, з висотою і шириною. Якщо він відрізняється від референтного, від того, який був отриманий при запиті дефолтного шрифту, значить, цей шрифт встановлений. Якщо не відрізняється, значить, цього шрифту немає.

Дуже проста ідея, але вона працює. На даний момент цей код може достовірно визначити близько 500 шрифтів без використання Flash. І, відповідно, той комп'ютер, де є Microsoft Office, і той, де його немає, будуть по-різному визначені в FingerprintJS 2 за рахунок цієї техніки.



Третя відмінність — WebGL Fingerprint. Це розвиток ідеї Сanvas Fingerprint. Суть його полягає в тому, що малюються 3D трикутники (на слайді не дуже добре видно, але це 3D). На нього накладаються ефекти, градієнт, різна анізотропна фільтрація і т. д. І потім він перетворюється в байтовий масив. Результуючий байтовий масив, як і у випадку з Canvas Fingerprint, буде різний на багатьох комп'ютерах. Потім до цього байтовому масиві ще додається інформація про платформозавісімих константи, які визначені в WebGL. Тобто в WebGL є набір констант, які обов'язково повинні бути в реалізації. Це глибина кольору, максимальний розмір текстур… Цих констант дуже багато, їх десятки. Код опитує всі ці константи і, ясна річ, що на android-девайси ці константи будуть відрізнятися, там глибина кольору може бути іншою, ніж на Windows або ніж на linux'е. Він опитує всі ці константи, все це знову ж складається у величезний масив, і все це додається до сериализованному зображення 3D трикутника, який намальований за допомогою апаратних ефектів.

Тут теж таке питання: як це допомагає идентифцировать? 3D графіка дуже платформозависима, версія драйверів, версія відеокарти, стандарт OpenGL в системі, версія шейдерного мови, — все це буде впливати на те, як всередині буде намальовано зображення. І коли воно буде перетворено в байтовий масив, воно буде різне на багатьох комп'ютерах.

Чому WebGl Fingerprint важливий? Тому що IOS 8.1 підтримує WebGL, а це допомагає ідентифікувати IOS девайси, про проблему ідентифікації яких я згадував. Тому WebGL підвищує точність Fingerprint.



Що ще належить реалізувати?

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

Що треба ще реалізувати? WebRTC Fingerprinting.

WebRTC — це стандарт peer-to-peer комунікацій через аудіопотоки, або це стандарт аудиокоммуникаций в сучасних браузерах. Він дозволяє робити аудиозвонки і т. д., він підтримується в FireFox і скоро буде підтримуватися в інших браузерах.

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

Буде використовуватися більше плагінів для IE. Будуть використані ті плагіни, які популярні в різних країнах — Китаї, Індії і т. д., тобто зростаючі інформаційні ринки. У першій версії недостатньо уваги було приділено цій проблемі, а у другій версії це буде вирішено.

Більше інформації буде збиратися про ОС. Як ми це будемо робити? Буде використовуватися інтеграція з Flash і Silverlight. Flash дозволяє отримувати інформацію про систему, таку як версія ядра, патч левел ядра. Silverlight, якщо на Windows, дозволяє отримати версію Windows, bild, номер Windows, все це доступно через Silverlight.

Пару слів про Silverlight, чому інтеграція з sliverlight теж досить важлива? Може бути, в Росії Silverlight плагін не дуже популярний, але в США, наприклад, є сервіс стримингового відео Netflix, який транслює відео, і я знаю точно, що вони використовують Silverlight. Зважаючи на те, що він підтримує DRM (це система обмеження цифрових прав на контент), т. к. Netflix часто показують різні свіжі голлівудські фільми, вони використовують Silverlight для того, щоб це відео не розходилося по Інтернету. Тому в США у багатьох десктопних користувачів Інтернету встановлений Silverlight плагін, який, до речі, доступний і на повне mac ' е теж, крім Windows.

Буде реалізовано визначення наявності декількох моніторів. Якщо ми запитаємо розміри через javascript, то отримаємо просто два числа — це ширина і висота екрану. Якщо ми зробимо те ж саме через Flash API, Actionscript API, ми отримаємо масив масивів. Це означає, що якщо встановлено кілька моніторів, де кожен подмассив — це буде розмір екрану кожного монітора. Якщо розробник сидить за п'ятьма моніторами, він отримає масив масивів з п'яти елементів, т. о., ми дізнаємося, що людина сидить за п'ятьма моніторами, а не за основним монітором, який повернув би javascript.

Всі ці дані в сукупності дозволяють на даний момент отримати точність визначення порядку 94-95%. Але, як ви розумієте, це недостатня точність ідентифікації. Тут постає питання: яким чином це можна покращити, і можна покращити? Я вважаю, що можна. Мета цього проекту — досягти 100% ідентифікації так, щоб можна було спиратися на Fingerprint в 100% випадках і гарантовано сказати: «Так, цей користувач до нас приходив; так, я все про нього знаю, незважаючи на те, що він використовує інкогніто mode, tor мережі...». Не важливо, все це буде визначено.



Контакти
» github
» Machinio.com

Ця доповідь — розшифровка одного з кращих виступів на конференції фронтенд-розробників FrontendConf.

Ну і головна новина — ми почали підготовку весняного фестивалю "Російські інтернет-технології", в який входить вісім конференцій, включаючи FrontendConf.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.