Cross Browser Detection – totální mazec!

Totální mazec. Technologie, která vás dokáže trackovat napříč webovými browsery a to včetně anonymních oken. Na rootu o tom vyšel článek, který stručně popisuje základní metody, které slouží k detekci uživatele napříč browsery. My se na to podíváme trochu podrobněji.

Jak detekce probíhá, když se na ni podíváme hlouběji?

Na stránkách http://www.uniquemachine.org/ je k dispozici live proof of concept, odkaz na zdrojové kódy na githubu a také popis fungování v pdf.

Celý základní koncept cross-browser trackování vychází z myšlenky, že hardware počítače je unikátní a stejná úloha by měla být na stejném počítači zpracována stejně, nezávisle na tom, kdo o zpracování úlohy požádal. Tedy v tomto případě se jedná především o vykreslování grafických prvků, o které se stará grafická karta skrze technologie WebGL. Zpracování této výpočetní úlohy tedy není v režii webového prohlížeče, nýbrž grafické karty. Z toho vyplývá, že pošleme-li do grafické karty z různých prohlížečů identické úlohy k renderování, měli bychom vždy dostat totožný výsledek. Ten je však unikátní k naší kombinaci hardware a driverů. Což je parametr zjevně dostatečně unikátní.

Které browser-agnostic vlastnosti tato metoda používá? (seznam převzat z Root.cz)

Rozlišení obrazovky – Používá se při běžném fingerprintingu, ale je možné jej využít i v CBF. Když se k němu ještě přidá míra zvětšení (zoom) stránky, jedná se o velmi spolehlivý prvek.

Počet procesorových jader – Parametr prohlížeče nazvaný hardwareConcurrency je ve většině prohlížečů stejný, u některých je nutné provést triviální přepočet. Například v Safari jej vynásobíte dvěma. (poznámka Tuňáka: používá se spíše celkem komplexní knihovny, která zajišťuje polymorfismus pro hardwareConcurrency a počet jader odhaduje na základě paralelního běhu úloh WebWorkers).

AudioContext – Nabízí sadu funkcí pro zpracování signálů a využívá při tom rozhraní operačního systému i funkcí zvukové karty. Měřením výstupních hodnot je tak možné získat unikátní data.

Seznam fontů – Nová technika, která staví na tradičním postupu, se spoléhá na různé metody používané při vykreslování vektorových písem.

Renderování vektorů a anti-aliasing – Vědci (poznámka Tuňáka: 1 profesor, 1 doktorand a 1 student, který je již mrtvý) jsou schopni měřit, jak prohlížeč vykresluje čáry, křivky a jak provádí anti-aliasing. Používají k tomu HTML5 Canvas a WebGL, čímž zapojí do činnosti grafickou kartu, která podá jedinečný výsledek.

Vertex Shader – Vykreslování grafiky pomocí karty a jejich ovladačů využije vertex shadery pro zobrazení stínů a světel na 3D objektech ve WebGL.

Fragment Shader – Je možné je využít podobně jako vertex shadery.

Průhlednost pomocí alfa kanálu – Prohlížeče dnes používají grafickou kartu k aplikaci průhlednosti v obrázcích. Výstup je pak shodný ve všech prohlížečích, protože se používají stejné algoritmy.

Nainstalované jazyky – Čínština, korejština či arabština vyžadují doinstalování speciálních knihoven, které kvůli své velikosti nejsou součástí ostatních lokalizací. Prohlížeč k nim nenabízí API, takže není možné získat jednoduše jejich seznam, ale je možné použít postranní kanál: lze sledovat, zda se text v daném jazyce na konkrétním počítači vyrenderoval správně nebo jsou místo znaků třeba jen čtverečky. Výsledek se pak může snadno stát součástí fingerprintu.

Modeling a Multiple Models – Další technika, která zapojuje do práce grafickou kartu. Testuje se, jak počítač vykreslí připravené 3D modely.

Lighting a Shadow Mapping – Podobně touto metodou je možné měřit, jak počítač zpracovává světla a stíny v 3D obraze.

Kamera – Není tím myšlena web kamera v počítači, ale další technika související s 3D modelováním. Používá se k porovnávání různých 2D reprezentací 3D modelů.

Ořez roviny – Měří se, jak se počítač vyrovná s umístěním 3D objektů na omezené roviny. Ořezová operace WebGL je opět předána grafické kartě a prohlížeč ji sám neprovádí.

Odeslání dat z browseru na server

Tento seznam parametrů a různých hashů o vás váš počítač práskne za ani ne 15 sekund. Což je sice řádově více, než si označkovat browser permanentní cookies, ale zase máte o jednu krutě cennou informaci navíc. Při využití nějaké optimalizace, kdy tuto detekci použít, ted řekněme jen při prvním setkání se s browserem a následného značkování jen přes evercookie, pak zde máme nenáročné a celkem ultimátní řešení.

{
	"fontlist": ["Agency FB", "Algerian", "Arial", "Arial Black", "Arial Narrow", "Arial Rounded MT Bold", "Baskerville Old Face", "Bauhaus 93", "Bell MT", "Berlin Sans FB", "Berlin Sans FB Demi", "Bernard MT Condensed", "Blackadder ITC", "Bodoni MT", "Bodoni MT Black", "Bodoni MT Condensed", "Bodoni MT Poster Compressed", "Book Antiqua", "Bookman Old Style", "Bookshelf Symbol 7", "Bradley Hand ITC", "Britannic Bold", "Broadway", "Brush Script MT", "Calibri", "Calibri Light", "Californian FB", "Calisto MT", "Cambria", "Cambria Math", "Candara", "Castellar", "Centaur", "Century", "Century Gothic", "Century Schoolbook", "Chiller", "Colonna MT", "Comic Sans MS", "Consolas", "Constantia", "Cooper Black", "Copperplate Gothic Bold", "Copperplate Gothic Light", "Corbel", "Courier", "Courier New", "Curlz MT", "Ebrima", "Edwardian Script ITC", "Elephant", "Engravers MT", "Eras Bold ITC", "Eras Demi ITC", "Eras Light ITC", "Eras Medium ITC", "Felix Titling", "Fixedsys", "Footlight MT Light", "Forte", "Franklin Gothic Book", "Franklin Gothic Demi", "Franklin Gothic Demi Cond", "Franklin Gothic Heavy", "Franklin Gothic Medium", "Franklin Gothic Medium Cond", "Freestyle Script", "French Script MT", "Gabriola", "Gadugi", "Garamond", "Georgia", "Gigi", "Gill Sans MT", "Gill Sans MT Condensed", "Gill Sans MT Ext Condensed Bold", "Gill Sans Ultra Bold", "Gill Sans Ultra Bold Condensed", "Gloucester MT Extra Condensed", "Goudy Old Style", "Goudy Stout", "Haettenschweiler", "Harlow Solid Italic", "Harrington", "High Tower Text", "Impact", "Imprint MT Shadow", "Informal Roman", "Javanese Text", "Jokerman", "Juice ITC", "Kristen ITC", "Kunstler Script", "Leelawadee UI", "Leelawadee UI Semilight", "Lucida Bright", "Lucida Calligraphy", "Lucida Console", "Lucida Fax", "Lucida Handwriting", "Lucida Sans", "Lucida Sans Typewriter", "Lucida Sans Unicode", "MS Gothic", "MS Outlook", "MS PGothic", "MS Reference Sans Serif", "MS Reference Specialty", "MS Sans Serif", "MS Serif", "MS UI Gothic", "MT Extra", "MV Boli", "Magneto", "Maiandra GD", "Malgun Gothic", "Malgun Gothic Semilight", "Marlett", "Matura MT Script Capitals", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft JhengHei Light", "Microsoft JhengHei UI", "Microsoft JhengHei UI Light", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Sans Serif", "Microsoft Tai Le", "Microsoft YaHei", "Microsoft YaHei Light", "Microsoft YaHei UI", "Microsoft YaHei UI Light", "Microsoft Yi Baiti", "MingLiU-ExtB", "MingLiU_HKSCS-ExtB", "Mistral", "Modern", "Modern No. 20", "Mongolian Baiti", "Monotype Corsiva", "Myanmar Text", "NSimSun", "Niagara Engraved", "Niagara Solid", "Nirmala UI", "Nirmala UI Semilight", "OCR A Extended", "Old English Text MT", "Onyx", "PMingLiU-ExtB", "Palace Script MT", "Palatino Linotype", "Papyrus", "Parchment", "Perpetua", "Perpetua Titling MT", "Playbill", "Poor Richard", "Pristina", "Rage Italic", "Ravie", "Rockwell", "Rockwell Condensed", "Rockwell Extra Bold", "Roman", "Script", "Script MT Bold", "Segoe MDL2 Assets", "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Black", "Segoe UI Emoji", "Segoe UI Historic", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Semilight", "Segoe UI Symbol", "Showcard Gothic", "SimSun", "SimSun-ExtB", "Sitka Banner", "Sitka Display", "Sitka Heading", "Sitka Small", "Sitka Subheading", "Sitka Text", "Small Fonts", "Snap ITC", "Stencil", "Sylfaen", "Symbol", "System", "Tahoma", "Tempus Sans ITC", "Terminal", "Times New Roman", "Trebuchet MS", "Tw Cen MT", "Tw Cen MT Condensed", "Tw Cen MT Condensed Extra Bold", "Verdana", "Viner Hand ITC", "Vivaldi", "Vladimir Script", "Webdings", "Wide Latin", "Wingdings", "Wingdings 2", "Wingdings 3", "Yu Gothic", "Yu Gothic Light", "Yu Gothic Medium", "Yu Gothic UI", "Yu Gothic UI Light", "Yu Gothic UI Semibold", "Yu Gothic UI Semilight", "Z@R5682.tmp", "Z@R5869.tmp"],
	"fonts": "000000000000000000000000110000000000000010000000000000000000010000000000100010000000000000000000000000000000010010000001000000000000000100000000000000100000000000000001000000101000000000010000000000000001000010100000000000000010000010000000000000000000000000000000000000000000000000000001100000000000010010100000100000000100000000010100000100010000000000000110000000000010100000000000010001000000000000010000010010001000100000000000000000000001000000000000000000000000000000100100000000000001000100100000000010000000100001000000000100100000000010000000000000000000000000010000000000010000000010000000011000000000110000000000000000000010000000000000001010100000000000000000001100010000100001001101100000010000100000000000000000000000000001000000000000000001111111010000001111000010101000000100000010000001100000000010010100000000000110000001000000010000000001000001001010101000001000100010000000000100000001000000000000000100000000000000100000010000000000001000000010000000000000010100100001000000000000001000001000010000000001000000000001001000001000000000000000000001010000000000000011010000000100000000000100000000000000100000000010000000000000000000000000000000000000101000000000000000100000000000010000000000000000000000000000000000000000000010000000000101000010000000000100000100000000000010000010000000000100010000000000000000100000010001011101001000000000010000000000100000000000001010000010000000100000000000010000001000000010100000000000000000000000000000000000010000010000000010000001000000000000000000000000000001000100001000000000000000000000000000001011000001000010000000110110000000010100000000000000100001000000000000000000000000000000000000100010000000000000000000100000000000000000100000001000000000000001000010001000000000000000000000000100001000000001000000001100000000000000000010101000000000000000000000000000000000000000000100000000000001010000000010000110000000001000000000000000010000000000000000000010000000000010010000000000000100001000000000000100100000100000000110000000000000000000000000000010100000000000000000010010000000000000001000000000000000000100010000000000000000001000000010000100000000010001000100001000000000001000000000100010010000100000000000001101000000000000000100000000010000000000000000000000000000111000110000000000000001000000000000000100000010000000011000001000000000000100100000000010010000000000010001000000000000000000000000000000010000011000000000010100000000000000000010000110000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000001000001001100000000010000010100010001001000100000000100100000101001000000000000000000111000000000000000000000110000010001000000000000101000000000010100000000101010110110000110000000000000000000000000000010000000000000000000000000000000000000000000010000000100000000000000100010100011010000000000001010000000000000000000100000000000000000000000100100000001000000000000000000100000000010000000000100000000000000000000000000000000000000001000000001010000000000000000000001000000100000010100010000000000000001000100000100000000000000000000000001000000000000010000000000000000010000000000000000000100000000000000000000000000100000111000010000000000100000000000000000001010000000001000000100111000100000000001001010100000000010100000000000000000000001000001000000000000000001000000000000000000000000000101000000000000000000000000000000000000000001000000000100100000000010000000000000000000001000010001000001100000000000010001001001000000001000000000000001000000000000000000000000001000000100000001000000000000000000000000000000000000000000000000000000000100000100000000000000000010100000000000001100000000000010000000000000010000000000000000001001000100000110001100000000001000000000000000000000100000000000000000000010000010100000000000110000000000000000000000100000000000001000010000000000000000000000000100000000100000000000000000000000101000000000000001001001000000001000000001000010000000000000000000000000000000100000000010100000000100001100000100000000100000000001000001000000000000100000000000000000000010000000000000000000000000000000001000000000000000000001000000000000100010010001000110000000101000010000000000000010000001000000000000000000000000000001000000010000000010000000110001000100000010000000000001000000000000001000000010000010100100000000001000000010000000000000100000000000000000000000000000000000000100000000000010000000000000000001000000100000000000100000000000000000100000",
	"WebGL": true,
	"inc": "Google Inc.",
	"gpu": "ANGLE (Intel(R) HD Graphics 520 Direct3D11 vs_5_0 ps_5_0)",
	"hash": 1667567911,
	"timezone": -60,
	"resolution": "1920_1080_1_1920_1080_24_1920_1040_undefined_undefined_1536_-216_700_1920_0",
	"plugins": "Widevine Content Decryption ModuleShockwave FlashChrome PDF ViewerNative ClientChrome PDF Viewer",
	"cookie": true,
	"localstorage": true,
	"manufacturer": "Undefined",
	"gpuImgs": {
		"0": -1914283016,
		"1": 1162298933,
		"2": 1699334155,
		"3": 1015470206,
		"4": -1892436752,
		"5": 959950211,
		"6": -1586769663,
		"7": -210705507,
		"8": 1845374004,
		"9": 1371681631,
		"10": 278281231,
		"11": -906422261,
		"12": 656514208,
		"13": 1582080968,
		"14": -1476774810,
		"15": 1499489935,
		"16": -457865815,
		"17": 1345892236,
		"18": -843376850,
		"19": -2023652240,
		"20": 301413135,
		"21": 1857436101,
		"22": -1754342325,
		"23": -732263890,
		"24": -666704790,
		"25": 182686738,
		"26": -1525876703,
		"27": 1667567911
	},
	"adBlock": "Yes",
	"cpu_cores": 4,
	"canvas_test": "4aeeb4c9aedc21314a3a722acbe277979efbbecd",
	"audio": "48000_2_1_0_2_explicit_speakers",
	"langsDetected": [],
	"video": []
}

Některé parametry jsou jasné, některé je třeba prozkoumat blíže.

Detekce přes anomálie při vykreslování specifických fontů

Tyto fonty si script natáhne ze serveru a pak nad nimi zkouší různé paznaky a podle toho, zda je váš komp zvládne vykreslit, nebo po nich zbyde jen prázdný čtvereček, tak pozná, že to renderovala stejná mašina.

 

O fontech se na server posílá:

  • odesílá seznam systémových fontů – fontlist
  • odesílá výsledky z renderování písem – fonts
"fontlist": ["Agency FB", "Algerian", "Arial", "Arial Black", "Arial Narrow", "Arial Rounded MT Bold", "Baskerville Old Face", "Bauhaus 93", "Bell MT", "Berlin Sans FB", "Berlin Sans FB Demi", "Bernard MT Condensed", "Blackadder ITC", "Bodoni MT", "Bodoni MT Black", "Bodoni MT Condensed", "Bodoni MT Poster Compressed", "Book Antiqua", "Bookman Old Style", "Bookshelf Symbol 7", "Bradley Hand ITC", "Britannic Bold", "Broadway", "Brush Script MT", "Calibri", "Calibri Light", "Californian FB", "Calisto MT", "Cambria", "Cambria Math", "Candara", "Castellar", "Centaur", "Century", "Century Gothic", "Century Schoolbook", "Chiller", "Colonna MT", "Comic Sans MS", "Consolas", "Constantia", "Cooper Black", "Copperplate Gothic Bold", "Copperplate Gothic Light", "Corbel", "Courier", "Courier New", "Curlz MT", "Ebrima", "Edwardian Script ITC", "Elephant", "Engravers MT", "Eras Bold ITC", "Eras Demi ITC", "Eras Light ITC", "Eras Medium ITC", "Felix Titling", "Fixedsys", "Footlight MT Light", "Forte", "Franklin Gothic Book", "Franklin Gothic Demi", "Franklin Gothic Demi Cond", "Franklin Gothic Heavy", "Franklin Gothic Medium", "Franklin Gothic Medium Cond", "Freestyle Script", "French Script MT", "Gabriola", "Gadugi", "Garamond", "Georgia", "Gigi", "Gill Sans MT", "Gill Sans MT Condensed", "Gill Sans MT Ext Condensed Bold", "Gill Sans Ultra Bold", "Gill Sans Ultra Bold Condensed", "Gloucester MT Extra Condensed", "Goudy Old Style", "Goudy Stout", "Haettenschweiler", "Harlow Solid Italic", "Harrington", "High Tower Text", "Impact", "Imprint MT Shadow", "Informal Roman", "Javanese Text", "Jokerman", "Juice ITC", "Kristen ITC", "Kunstler Script", "Leelawadee UI", "Leelawadee UI Semilight", "Lucida Bright", "Lucida Calligraphy", "Lucida Console", "Lucida Fax", "Lucida Handwriting", "Lucida Sans", "Lucida Sans Typewriter", "Lucida Sans Unicode", "MS Gothic", "MS Outlook", "MS PGothic", "MS Reference Sans Serif", "MS Reference Specialty", "MS Sans Serif", "MS Serif", "MS UI Gothic", "MT Extra", "MV Boli", "Magneto", "Maiandra GD", "Malgun Gothic", "Malgun Gothic Semilight", "Marlett", "Matura MT Script Capitals", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft JhengHei Light", "Microsoft JhengHei UI", "Microsoft JhengHei UI Light", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Sans Serif", "Microsoft Tai Le", "Microsoft YaHei", "Microsoft YaHei Light", "Microsoft YaHei UI", "Microsoft YaHei UI Light", "Microsoft Yi Baiti", "MingLiU-ExtB", "MingLiU_HKSCS-ExtB", "Mistral", "Modern", "Modern No. 20", "Mongolian Baiti", "Monotype Corsiva", "Myanmar Text", "NSimSun", "Niagara Engraved", "Niagara Solid", "Nirmala UI", "Nirmala UI Semilight", "OCR A Extended", "Old English Text MT", "Onyx", "PMingLiU-ExtB", "Palace Script MT", "Palatino Linotype", "Papyrus", "Parchment", "Perpetua", "Perpetua Titling MT", "Playbill", "Poor Richard", "Pristina", "Rage Italic", "Ravie", "Rockwell", "Rockwell Condensed", "Rockwell Extra Bold", "Roman", "Script", "Script MT Bold", "Segoe MDL2 Assets", "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Black", "Segoe UI Emoji", "Segoe UI Historic", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Semilight", "Segoe UI Symbol", "Showcard Gothic", "SimSun", "SimSun-ExtB", "Sitka Banner", "Sitka Display", "Sitka Heading", "Sitka Small", "Sitka Subheading", "Sitka Text", "Small Fonts", "Snap ITC", "Stencil", "Sylfaen", "Symbol", "System", "Tahoma", "Tempus Sans ITC", "Terminal", "Times New Roman", "Trebuchet MS", "Tw Cen MT", "Tw Cen MT Condensed", "Tw Cen MT Condensed Extra Bold", "Verdana", "Viner Hand ITC", "Vivaldi", "Vladimir Script", "Webdings", "Wide Latin", "Wingdings", "Wingdings 2", "Wingdings 3", "Yu Gothic", "Yu Gothic Light", "Yu Gothic Medium", "Yu Gothic UI", "Yu Gothic UI Light", "Yu Gothic UI Semibold", "Yu Gothic UI Semilight", "Z@R5682.tmp", "Z@R5869.tmp"],
"fonts": "000000000000000000000000110000000000000010000000000000000000010000000000100010000000000000000000000000000000010010000001000000000000000100000000000000100000000000000001000000101000000000010000000000000001000010100000000000000010000010000000000000000000000000000000000000000000000000000001100000000000010010100000100000000100000000010100000100010000000000000110000000000010100000000000010001000000000000010000010010001000100000000000000000000001000000000000000000000000000000100100000000000001000100100000000010000000100001000000000100100000000010000000000000000000000000010000000000010000000010000000011000000000110000000000000000000010000000000000001010100000000000000000001100010000100001001101100000010000100000000000000000000000000001000000000000000001111111010000001111000010101000000100000010000001100000000010010100000000000110000001000000010000000001000001001010101000001000100010000000000100000001000000000000000100000000000000100000010000000000001000000010000000000000010100100001000000000000001000001000010000000001000000000001001000001000000000000000000001010000000000000011010000000100000000000100000000000000100000000010000000000000000000000000000000000000101000000000000000100000000000010000000000000000000000000000000000000000000010000000000101000010000000000100000100000000000010000010000000000100010000000000000000100000010001011101001000000000010000000000100000000000001010000010000000100000000000010000001000000010100000000000000000000000000000000000010000010000000010000001000000000000000000000000000001000100001000000000000000000000000000001011000001000010000000110110000000010100000000000000100001000000000000000000000000000000000000100010000000000000000000100000000000000000100000001000000000000001000010001000000000000000000000000100001000000001000000001100000000000000000010101000000000000000000000000000000000000000000100000000000001010000000010000110000000001000000000000000010000000000000000000010000000000010010000000000000100001000000000000100100000100000000110000000000000000000000000000010100000000000000000010010000000000000001000000000000000000100010000000000000000001000000010000100000000010001000100001000000000001000000000100010010000100000000000001101000000000000000100000000010000000000000000000000000000111000110000000000000001000000000000000100000010000000011000001000000000000100100000000010010000000000010001000000000000000000000000000000010000011000000000010100000000000000000010000110000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000001000001001100000000010000010100010001001000100000000100100000101001000000000000000000111000000000000000000000110000010001000000000000101000000000010100000000101010110110000110000000000000000000000000000010000000000000000000000000000000000000000000010000000100000000000000100010100011010000000000001010000000000000000000100000000000000000000000100100000001000000000000000000100000000010000000000100000000000000000000000000000000000000001000000001010000000000000000000001000000100000010100010000000000000001000100000100000000000000000000000001000000000000010000000000000000010000000000000000000100000000000000000000000000100000111000010000000000100000000000000000001010000000001000000100111000100000000001001010100000000010100000000000000000000001000001000000000000000001000000000000000000000000000101000000000000000000000000000000000000000001000000000100100000000010000000000000000000001000010001000001100000000000010001001001000000001000000000000001000000000000000000000000001000000100000001000000000000000000000000000000000000000000000000000000000100000100000000000000000010100000000000001100000000000010000000000000010000000000000000001001000100000110001100000000001000000000000000000000100000000000000000000010000010100000000000110000000000000000000000100000000000001000010000000000000000000000000100000000100000000000000000000000101000000000000001001001000000001000000001000010000000000000000000000000000000100000000010100000000100001100000100000000100000000001000001000000000000100000000000000000000010000000000000000000000000000000001000000000000000000001000000000000100010010001000110000000101000010000000000000010000001000000000000000000000000000001000000010000000010000000110001000100000010000000000001000000000000001000000010000010100100000000001000000010000000000000100000000000000000000000000000000000000100000000000010000000000000000001000000100000000000100000000000000000100000",

Co práskne grafárna a WebGL?

Nejdříve si řekněme, co je WebGL. Wiki postačí.

WebGL (Web Graphics Library) is a JavaScript API for rendering 3D graphics within any compatible web browser without the use of plug-ins.[2] WebGL is integrated completely into all the web standards of the browser allowing GPU accelerated usage of physics and image processing and effects as part of the web page canvas.

"WebGL": true,
"inc": "Google Inc.",
"gpu": "ANGLE (Intel(R) HD Graphics 520 Direct3D11 vs_5_0 ps_5_0)",
"hash": 1667567911,

WebGL parametr

Takže to, jestli máme WebGl, záleží jen na tom, zda jej browser podporuje. Ale je to jen API, takže zde nehraje roli konkrétní implementace. To je důležité. Takže první parametr WebGL je true.

Co o ná je ochotné prásknout WebGL se můžete podívat třeba zde: https://browserleaks.com/webgl

inc parametr

Script se ptá na konstantu UNMASKED_VENDOR_WEBGL, která obsahuje hodnotu (Return the VENDOR string of the underlying graphics driver.):

Ten vrací hodnotu jako „Google Inc.„. Mozilla ji nevrací vůbec. Zjevně zde není ještě vše doimplementováno.

Není to tedy parametr, který by přímo něco sděloval o našem počítači, předpokládám tedy, že parametr může sloužit k nějakým korekcím na serveru, pokud jsou známy určité anomálie v implementacích.

gpu parametr

Script se ptá na hodnotu konstanty UNMASKED_RENDERER_WEBGL, která je mnohem zajímavější. Obsahuje poměrně hodně informací o našem železe.

ANGLE (Intel(R) HD Graphics 520 Direct3D11 vs_5_0 ps_5_0)

hash parametr

Ten si do canvasu vykreslí čtvereček 256 na 256, nechá si o něm vrátit objekt Uint8ClampedArray a z něj spočítá hash. Jeho obsahem jsou 0-255 rozsahy nad jednotlivými pixely obrázku s otisky prstů.  Finta je v tom, že obrázek na vstupu nemá 256 na 256, ale 610 na 458 pixelů a každý renderer jej tedy může vykreslit mírně odlišně. To následný hash rozezná. Tohle už je celkem cool detekce. A to se teprve rozjíždíme.

function hash(array) {
      var hash = 0, i, chr, len;
      if (array.length === 0)
        return hash;
      for (i = 0, len = array.length; i < len; i++) {
        chr = array[i] | 0;
        hash ^= (((hash << 5) - hash) + chr + 0x9e3779b9) | 0;
        hash |= 0; // Convert to 32bit integer
      }
      return hash;
    }
    var w = 256, h = 256;
    // Send pixels to server
    var pixels = ctx.getImageData(0, 0, w, h).data;
    var hashV = hash(pixels);

Husté parametry

"timezone": -60,
"resolution": "1920_1080_1_1920_1080_24_1920_1040_undefined_undefined_1536_-216_700_1920_0",
"cpu_cores": 4,
"canvas_test": "4aeeb4c9aedc21314a3a722acbe277979efbbecd",
"audio": "48000_2_1_0_2_explicit_speakers",

Timezone – je stejný napříč browsery, resolution (monitor) je stejný (některé browsery jinak počítají rozlišení při zoomování, je třeba provést nějaké korekce).

cpu_cores – to už je velmi zajímavý údaj. Používají k detekci polyfill Core Estimator do navigator.hardwareConcurrency.

audio – zatím vrací jen základní informace o zvukovém zařízení, tedy vzorkovací frekvenci, počet kanálů, typ repráků a tak. Ale v dodávaných scriptech je naznačeno něco mnohem hustějšího a to pokus o propočet nějakého generovaného šumu a z něho vypočtený hash. Tato věc je ve scriptu zakomentovaná, ale jasně naznačuje dost zajímavý způsob detekce.

var distortion = audioCtx.createWaveShaper();

function makeDistortionCurve(amount) {
    var k = typeof amount === 'number' ? amount : 50,
        n_samples = 44100,
        curve = new Float32Array(n_samples),
        deg = Math.PI / 180,
        i = 0,
        x;
    for (; i < n_samples; ++i) {
        x = i * 2 / n_samples - 1;
        curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
    }
    return curve;
};
distortion.curve = makeDistortionCurve(400);
distortion.oversample = '4x';

compressor = audioCtx.createDynamicsCompressor();
compressor.threshold && (compressor.threshold.value = -50);
compressor.knee && (compressor.knee.value = 40);
compressor.ratio && (compressor.ratio.value = 12);
compressor.reduction && (compressor.reduction.value = -20);
compressor.attack && (compressor.attack.value = 0);
compressor.release && (compressor.release.value = .25);

gainNode.gain.value = 0;
oscillator.type = waveType;
//oscillator.connect(distortion);
//distortion.connect(analyser);
//oscillator.frequency.value = 10000;
oscillator.connect(compressor);
compressor.connect(analyser);
//oscillator.connect(analyser);
analyser.connect(scriptProcessor);
scriptProcessor.connect(gainNode);
gainNode.connect(audioCtx.destination);

function ret(bins) {
    drawBasic(bins);
    //cb(bins);
}

scriptProcessor.onaudioprocess = function() {
    if (finished == true) return 0;
    console.log('here');
    var bins = new Float32Array(analyser.frequencyBinCount);
    analyser.getFloatFrequencyData(bins);

    analyser.disconnect();
    scriptProcessor.disconnect();
    gainNode.disconnect();
    finished = true;
    ret(bins);
};
oscillator.start(0);

Nejkrutější parametry

gpuImg jsou výsledky série různých testů snažících se vykreslit nějaký 3D objekt, případně nějakou jinou složitou situaci v canvasu a z toho počítají hash.

"gpuImgs": {
  "0": -1914283016,
  "1": 1162298933,
  "2": 1699334155,
  "3": 1015470206,
  "4": -1892436752,
  "5": 959950211,
  "6": -1586769663,
  "7": -210705507,
  "8": 1845374004,
  "9": 1371681631,
  "10": 278281231,
  "11": -906422261,
  "12": 656514208,
  "13": 1582080968,
  "14": -1476774810,
  "15": 1499489935,
  "16": -457865815,
  "17": 1345892236,
  "18": -843376850,
  "19": -2023652240,
  "20": 301413135,
  "21": 1857436101,
  "22": -1754342325,
  "23": -732263890,
  "24": -666704790,
  "25": 182686738,
  "26": -1525876703,
  "27": 1667567911
}

Je libo renderovat bublinky nad obrázkem s přírodou?

Co třeba kostička v jehlanu s ořezem na dvou hranách?

Co třeba renderování průběhu matematických funkcí založené na iracionálních číslech? Renderování šíleného patvaru a potažené prahnusnou multibarevnou tapetou ve forme jpeg obrázku?

Jak vypadají tyto sripty řídící tento tanec?

Jsou to scripty v jazyce GLSL a dávají tak instrukce Shaderu.

void main()
{
  fragTexCoord = vertTexCoord;
  gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
  gl_FragColor = texture2D(sampler, fragTexCoord);
}
void main()
{
  fragTexCoord = vertTexCoord;
  gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
  gl_FragColor = texture2D(sampler, fragTexCoord);
}
void main()
{
  fragTexCoord = vertTexCoord;
  fragNormal = (mWorld * vec4(vertNormal, 0.0)).xyz;

  gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
	vec3 surfaceNormal = normalize(fragNormal);
	vec3 normSunDir = normalize(sun.direction);
	vec4 texel = texture2D(sampler, fragTexCoord);

	vec3 lightIntensity = ambientLightIntensity +
		sun.color * max(dot(fragNormal, normSunDir), 0.0);

	gl_FragColor = vec4(texel.rgb * lightIntensity, texel.a);
}

 

void main()
{
  fragTexCoord = vertTexCoord;
  fragNormal = (mWorld * vec4(vertNormal, 0.0)).xyz;

  gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
	vec3 surfaceNormal = normalize(fragNormal);
	vec3 normSunDir = normalize(sun.direction);
	vec4 texel = texture2D(sampler, fragTexCoord);

	vec3 lightIntensity = ambientLightIntensity +
		sun.color * max(dot(fragNormal, normSunDir), 0.0);

	gl_FragColor = vec4(texel.rgb * lightIntensity, texel.a);
}
void main()
{
    vPosition = mView * vec4(vertPosition, 1.0);
    fragTexCoord = vertTexCoord;
    fragNormal = (mWorld * vec4(vertNormal, 0.0)).xyz;

    gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
    vec3 lightDirection = normalize(sun.direction - vPosition.xyz);
    vec3 normSunDir = normalize(sun.direction);
    vec3 surfaceNormal = normalize(fragNormal);
    vec4 texel = texture2D(sampler, fragTexCoord);

    float specularLightWeighting = 0.0;
    vec3 eyeDirection = normalize(-vPosition.xyz);
    vec3 reflectionDirection = reflect(-lightDirection, surfaceNormal);
    specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), 16.0);

    float diffuseLightWeighting = max(dot(surfaceNormal, sun.direction), 0.0);

    vec3 lightIntensity = ambientLightIntensity +
        sun.specular * specularLightWeighting + 
        sun.diffuse * diffuseLightWeighting;

	gl_FragColor = vec4(texel.rgb * lightIntensity, texel.a);
}
void main()
{
    vPosition = mView * vec4(vertPosition, 1.0);
    fragTexCoord = vertTexCoord;
    fragNormal = (mWorld * vec4(vertNormal, 0.0)).xyz;

    gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
    vec3 lightDirection = normalize(sun.direction - vPosition.xyz);
    vec3 normSunDir = normalize(sun.direction);
    vec3 surfaceNormal = normalize(fragNormal);
    vec4 texel0 = texture2D(image0, fragTexCoord);
    vec4 texel1 = texture2D(image1, fragTexCoord);

    float specularLightWeighting = 0.0;
    vec3 eyeDirection = normalize(-vPosition.xyz);
    vec3 reflectionDirection = reflect(-lightDirection, surfaceNormal);
    specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), 16.0);

    float diffuseLightWeighting = max(dot(surfaceNormal, sun.direction), 0.0);

    vec3 lightIntensity = ambientLightIntensity +
        sun.specular * specularLightWeighting + 
        sun.diffuse * diffuseLightWeighting;

	gl_FragColor = vec4(texel0.rgb * texel1.rgb * lightIntensity, texel0.a* texel1.a);
}
void main()
{
    vPosition = mView * vec4(vertPosition, 1.0);
    fragTexCoord = vertTexCoord;
    fragNormal = (mWorld * vec4(vertNormal, 0.0)).xyz;

    gl_Position = mProj * mView * mWorld * vec4(vertPosition, 1.0);
}
void main()
{
    vec3 lightDirection = normalize(sun.direction - vPosition.xyz);
    vec3 normSunDir = normalize(sun.direction);
    vec3 surfaceNormal = normalize(fragNormal);
    vec4 texel = texture2D(sampler, fragTexCoord);

    float specularLightWeighting = 0.0;
    vec3 eyeDirection = normalize(-vPosition.xyz);
    vec3 reflectionDirection = reflect(-lightDirection, surfaceNormal);
    specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), 16.0);

    float diffuseLightWeighting = max(dot(surfaceNormal, sun.direction), 0.0);

    vec3 lightIntensity = ambientLightIntensity +
        sun.specular * specularLightWeighting + 
        sun.diffuse * diffuseLightWeighting;

	gl_FragColor = vec4(texel.rgb * lightIntensity, texel.a * uAlpha);
}

Výstpu z takového programu se pak přepočítá jako HASH a ten se odešle na server.

Nepříliš zajímavé hodnoty

"plugins": "Widevine Content Decryption ModuleShockwave FlashChrome PDF ViewerNative ClientChrome PDF Viewer",
"cookie": true,
"localstorage": true,
"manufacturer": "Undefined",
"adBlock": "Yes",
"langsDetected": [],
"video": []

AdBlock – zde lze jen předpokládat, že uživatel použije AdBlock ve všech svých browserech. Jinak celkem bezvýznamný parametr. Možná taky slouží čistě pro autory tohoto PoC, ale alternativně servírovali reklamu přes self-hosted brány. Pro toto téma to není podstatné.

Plugins – tady upřímně nevím, k čemu to může být dobré pro tuto detekci. Napadá mě jen pokus o zneužití Flash cookie k přenosu ID do jiného browseru. Něco ve stylu Evercookie. Alternativně budou možná některé pluginy ve více prohlížečích. Ale nevím.

Cookie – to je také hodnota, která mi moc smysl nedává. Cookie is dead!

LocalStorage – to samé, nedává moc smysl.

Manufacturer, LangsDetected, video – není ve scriptu dosud implementovaný.

Možná to vše bude souviset s exludováním např. robotů, aby si šetřili místo v databázi na backendu a neplýtvali zdroji. Hloupý robot neumí cookies, nemá rozlišení a nemá pluginy. Takového můžeme z měření rovnou vyhodit a neplatit za výpočetní čas. Myslím si, že pokud by toto někdo chtěl nasadit masově, tak to bude výpočetně dost náročná služba v porovnání jakýchkoliv mně známých synchronizačních serverů.

Odpověď serveru

{
	"IP": "212.80.64.110",
	"WebGL": "True",
	"accept": "NULL",
	"adblock": "Yes",
	"agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
	"audio": "48000_2_1_0_2_explicit_speakers",
	"browser_fingerprint": "84c96d6398290f72071e58f72e5bcfaf",
	"canvas_test": "4aeeb4c9aedc21314a3a722acbe277979efbbecd",
	"computer_fingerprint_1": "0b3c61e058d911b7e76a44d655bf9791",
	"cookie": "True",
	"cpu_cores": -1,
	"encoding": "gzip, deflate",
	"fontlist": null,
	"fonts": "000000000000000000000000110000000000000010000000000000000000010000000000100010000000000000000000000000000000010010000001000000000000000100000000000000100000000000000001000000101000000000010000000000000001000010100000000000000010000010000000000000000000000000000000000000000000000000000001100000000000010010100000100000000100000000010100000100010000000000000110000000000010100000000000010001000000000000010000010010001000100000000000000000000001000000000000000000000000000000100100000000000001000100100000000010000000100001000000000100100000000010000000000000000000000000010000000000010000000010000000011000000000110000000000000000000010000000000000001010100000000000000000001100010000100001001101100000010000100000000000000000000000000001000000000000000001111111010000001111000010101000000100000010000001100000000010010100000000000110000001000000010000000001000001001010101000001000100010000000000100000001000000000000000100000000000000100000010000000000001000000010000000000000010100100001000000000000001000001000010000000001000000000001001000001000000000000000000001010000000000000011010000000100000000000100000000000000100000000010000000000000000000000000000000000000101000000000000000100000000000010000000000000000000000000000000000000000000010000000000101000010000000000100000100000000000010000010000000000100010000000000000000100000010001011101001000000000010000000000100000000000001010000010000000100000000000010000001000000010100000000000000000000000000000000000010000010000000010000001000000000000000000000000000001000100001000000000000000000000000000001011000001000010000000110110000000010100000000000000100001000000000000000000000000000000000000100010000000000000000000100000000000000000100000001000000000000001000010001000000000000000000000000100001000000001000000001100000000000000000010101000000000000000000000000000000000000000000100000000000001010000000010000110000000001000000000000000010000000000000000000010000000000010010000000000000100001000000000000100100000100000000110000000000000000000000000000010100000000000000000010010000000000000001000000000000000000100010000000000000000001000000010000100000000010001000100001000000000001000000000100010010000100000000000001101000000000000000100000000010000000000000000000000000000111000110000000000000001000000000000000100000010000000011000001000000000000100100000000010010000000000010001000000000000000000000000000000010000011000000000010100000000000000000010000110000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000001000001001100000000010000010100010001001000100000000100100000101001000000000000000000111000000000000000000000110000010001000000000000101000000000010100000000101010110110000110000000000000000000000000000010000000000000000000000000000000000000000000010000000100000000000000100010100011010000000000001010000000000000000000100000000000000000000000100100000001000000000000000000100000000010000000000100000000000000000000000000000000000000001000000001010000000000000000000001000000100000010100010000000000000001000100000100000000000000000000000001000000000000010000000000000000010000000000000000000100000000000000000000000000100000111000010000000000100000000000000000001010000000001000000100111000100000000001001010100000000010100000000000000000000001000001000000000000000001000000000000000000000000000101000000000000000000000000000000000000000001000000000100100000000010000000000000000000001000010001000001100000000000010001001001000000001000000000000001000000000000000000000000001000000100000001000000000000000000000000000000000000000000000000000000000100000100000000000000000010100000000000001100000000000010000000000000010000000000000000001001000100000110001100000000001000000000000000000000100000000000000000000010000010100000000000110000000000000000000000100000000000001000010000000000000000000000000100000000100000000000000000000000101000000000000001001001000000001000000001000010000000000000000000000000000000100000000010100000000100001100000100000000100000000001000001000000000000100000000000000000000010000000000000000000000000000000001000000000000000000001000000000000100010010001000110000000101000010000000000000010000001000000000000000000000000000001000000010000000010000000110001000100000010000000000001000000000000001000000010000010100100000000001000000010000000000000100000000000000000000000000000000000000100000000000010000000000000000001000000100000000000100000000000000000100000",
	"gpu": "ANGLE (Intel(R) HD Graphics 520 Direct3D11 vs_5_0 ps_5_0)",
	"gpuimgs": "24_-666704790,25_182686738,26_-1525876703,27_1667567911,20_301413135,21_1857436101,22_-1754342325,23_-732263890,1_1162298933,0_-1914283016,3_1015470206,2_1699334155,5_959950211,4_-1892436752,7_-210705507,6_-1586769663,9_1371681631,8_1845374004,11_-906422261,10_278281231,13_1582080968,12_656514208,15_1499489935,14_-1476774810,17_1345892236,16_-457865815,19_-2023652240,18_-843376850",
	"inc": "Google Inc.",
	"langsdetected": null,
	"language": "en-US,en;q=0.8,cs;q=0.6",
	"localstorage": "True",
	"plugins": "Widevine Content Decryption ModuleShockwave FlashChrome PDF ViewerNative ClientChrome PDF Viewer",
	"resolution": null,
	"time": "Wed, 18 Jan 2017 17:38:05 GMT",
	"timezone": -60
}

Firefox

Chrome

 

Tuhý kořínek linux má

Zkoušeli jsme i různé alternativy, jako browser Midori, browser Chromium, Firefox ve virtualizovaném Ubuntu a zde si Uniquemachine neporadil. Prý mu chybí WebGL. Firefox to zase nutilo otevírat VLC plugin. Takže šanci uspět to má zatím hlavně na Windows. I tak je to děsivé.

Další test na virtualizovaném stroji byl již s WebGL a otisky se neshodovaly s Windows, ze kterého virtualizace probíhala.

Závěr

Funkčnost a rafinovanost počítání unikátních otisků na základě hardwarových komponent počítače je dechberoucí. Toto je technika, která staví na hlavu komplet záležitosti ohledně soukromí na internetu. A i přes to, že se jedná jen o proof of concept, jsou zde poklidně použitelné komponenty pro produkční nasazení.

Informace o tom, že se uživatel připojuje ze stejného zařízení, je nejen mnohem trvalejší než třeba cookie uložená v browseru (a kolem které se dělá takový humbuk EU Cookie Law), ale také mnohem zajímavější.

Využít se dá k dobrým věcem, třeba k lepšímu ověřování přístupu uživatelů ke službám (tedy security) či třeba personalizace služeb (o kterou mám zájem).

Zneužít se dá též a to třeba k vysledování indetity, lepší cílení reklamy a celkově k mega špehování.

Staví to na hlavu hromadu bezpečnostních návyků, které jsme si osvojili k ochraně svých osobních údajů. Je to jednak používání několika webových prohlížečů, kdy jeden slouží např.: k osobním účtům, druhý pro pracovní účty, třetí na porno, čtvrtý do banky a TOR browser pro objednávání kokainu na darknetu.

Nyní je to jedno. Na vše stačí Internet Explorer.

Navíc autoři tohoto software zmiňují, že se z hlediska detekce uživatele stále jedná jen o verzi detekce 2.5, kde za verzi 3 označují Cross-Device detekci. Takovou detekci, kterou si mohou dnes dovolit jen největší hráči jako Facebook či Google a to tím, že se mu sami napráskáte svým uživatelským jménem.

Východisko

Jediné, co odolalo této technice, bylo spustit druhý browser ve Virtual Boxu. Což je trochu nepraktické. Praktičtejší využití by mělo třeba používat linuxovou distribuci CubesOS.

K tématu

Článek na rootu k identifikaci na základě User Agentu (článek r.v. 2010, panopticum) – https://www.root.cz/clanky/vas-prohlizec-je-identifikovatelny-i-bez-cookies/

Panopticlick od Electonic Frontier Foundation – https://panopticlick.eff.org/

Evercookie, kam se dá všude narvat cookie, cross browser detekce přes flash cookie – http://samy.pl/evercookie/

Projekt Am I Unique? – https://amiunique.org/

 

1 komentář: „Cross Browser Detection – totální mazec!

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Tato stránka používá Akismet k omezení spamu. Podívejte se, jak vaše data z komentářů zpracováváme..