Canvas Fingerprinting מעבר ליסודות: למה שני עותקי Chrome זהים מרנדרים פיקסלים שונים
שני מכשירים עם אותו Chrome, אותה מערכת הפעלה ואותו GPU עדיין מרנדרים פיקסלים שונים ב-canvas. למה צינור הרינדור אינו דטרמיניסטי, למה הזרקת רעש לפרטיות מתהפכת, ואיפה canvas משתלב בסטאק זיהוי מודרני.
Canvas fingerprinting נמצא בשימוש בפרודקשן מאז 2012. הרעיון פשוט: לבקש מהדפדפן לרנדר תוכן דו-ממדי, לקרוא בחזרה את הפיקסלים, ולחשב מהם hash. מכשירים שונים מייצרים פיקסלים מעט שונים עבור אותן הוראות, וההבדלים האלה יציבים מספיק כדי לזהות מכשיר לאורך סשנים.
כל זה ידוע היטב. מה שפחות מובן הוא למה הטכניקה עובדת — למה קונפיגורציות תוכנה זהות על חומרה זהה עדיין מייצרות פלט פיקסלים שונה. התשובה נמצאת בנקודת המפגש של מנהלי התקן GPU, רינדור פונטים ואריתמטיקה של נקודה צפה.
צינור הרינדור אינו דטרמיניסטי
כאשר JavaScript קורא ל-context.fillText("Cwm fjord bank glyphs vext quiz", 4, 45), Chrome אינו מרנדר את הפיקסלים בעצמו. הוא מייצר הוראות עבור Skia — ספריית הגרפיקה הדו-ממדית — שבתורה מנפיקה פקודות ציור ל-backend מואץ-GPU (בדרך כלל ANGLE ב-Windows, Metal ב-macOS, או software fallback במכולות).
בכל שלב מצטברים הבדלי מימוש קטנים:
-
תת-המערכת של הפונטים ב-Skia בוחרת משפחת פונטים. אם Arial אינו מותקן, היא נופלת חזרה לחלופה — וה-fallback משתנה לפי הפונטים המותקנים במערכת.
-
הפונט שנבחר מרונדר בגודל המבוקש באמצעות FreeType (ב-Linux), DirectWrite (ב-Windows) או Core Text (ב-macOS). לכל ספרייה יש אלגוריתמי hinting שונים.
-
מיושם מיקום subpixel. כאן פונטים זהים מתחילים לייצר פיקסלים שונים — האלגוריתם מעגל מיקומים להיסטים חלקיים של פיקסל, וכללי העיגול שונים בין הפלטפורמות.
-
הטקסט המרוסטר מורכב (composited) על ה-canvas. המיזוג נעשה באמצעות GPU shaders במערכות עם האצת חומרה, ובאמצעות קוד CPU במצב fallback.
כל אחד מהשלבים האלה יכול להכניס הבדלים של ערך פיקסל אחד או שניים. בלתי נראים בפני עצמם. ייחודיים במצטבר.
גרסאות מנהל התקן GPU שולטות בטביעת האצבע
שני מחשבי Windows 11 עם שבבי Intel UHD Graphics 620 יכולים לייצר פלטי canvas שונים אם מנהלי התקן ה-GPU שלהם שונים. Intel משחררת עדכוני מנהל התקן מספר פעמים בשנה, וכל עדכון יכול לשנות סינון subpixel, תיקון גמא והחלקת קצוות (anti-aliasing) של טקסט.
משמעות הדבר שיציבות טביעת האצבע של ה-canvas מוגבלת על ידי תדירות עדכוני מנהל ההתקן. משתמש שמשדרג את מנהל ההתקן הגרפי שלו — לעיתים קרובות בשקט, דרך Windows Update — יראה את טביעת האצבע של ה-canvas שלו משתנה.
מערכות זיהוי מתמודדות עם זה על ידי התייחסות לטביעת האצבע של ה-canvas כאחד מסיגנלים רבים, ולא כמזהה עצמאי. כאשר היא משתנה אך סיגנלים אחרים נשארים יציבים (טביעת אצבע של TLS, WebGL renderer, אזור זמן, פונטים מותקנים), המבקר עדיין מזוהה.
רינדור אימוג'י הוא מכרה זהב
האלמנט המזהה ביותר בטביעת אצבע של canvas הוא לעיתים קרובות לא טקסט או צורות אלא אימוג'י. רינדור אימוג'י תלוי בפונט האימוג'י המסופק עם מערכת ההפעלה — Segoe UI Emoji ב-Windows, Apple Color Emoji ב-macOS, Noto Color Emoji ב-Android.
אפילו בתוך מערכת הפעלה אחת, רינדור אימוג'י משתנה בין גרסאות. הרינדור של אימוג'י קשת ב-Windows 10 שונה מזה של Windows 11. לפרצוף המחייך של iOS 16 יש anti-aliasing שונה מזה של iOS 17.
סקריפטים מודרניים של canvas fingerprinting מרנדרים באופן ספציפי רצפים של אימוג'י כולל תוספות חדשות ל-Unicode. מבקר שטוען שהוא מריץ iPhone Safari אך אינו מסוגל לרנדר אימוג'י שנוסף ב-iOS 17 מריץ iOS ישן יותר — או משקר לגבי הפלטפורמה.
פריימוורקים של אוטומציה מייצרים טביעות אצבע ייחודיות
Headless Chrome, שרץ במכולת Docker ללא GPU, משתמש ב-SwiftShader לרינדור. SwiftShader מייצר פלטי canvas שהם עקביים פנימית אך שונים מכל Chrome עם האצת חומרה.
החתימה ניתנת לזיהוי: anti-aliasing נקי בצורה חריגה, ערכי צבע ספציפיים באזורי גרדיאנט, וקצוות טקסט שאינם תואמים לשום מנהל התקן GPU מוכר. טביעת אצבע של canvas שתואמת ל-SwiftShader ב-Chrome 124 במכולת Linux היא כמעט בוודאות אוטומציה — אף משתמש אמיתי אינו מריץ דפדפן בדרך הזו.
Puppeteer-extra-stealth מנסה לזייף פלט canvas על ידי יירוט toDataURL() והחזרת נתונים מעובדים. אך העיבוד מכניס לעיתים קרובות ארטיפקטים משלו — דפוסי רעש שחוזרים על עצמם בין סשנים, שבאופן פרדוקסלי הופכים את מאמץ ה-anti-fingerprinting לניתן לזיהוי יותר מאשר לא לעשות דבר.
למה הזרקת רעש אינה עובדת היטב
דפדפנים ממוקדי פרטיות כמו Brave מזריקים רעש לפלט ה-canvas כדי למנוע מעקב. הרעיון הוא להוסיף שינויים אקראיים קטנים לערכי הפיקסלים כך שאותו מכשיר יפיק טביעות אצבע שונות בכל סשן.
בפועל, להזרקת הרעש יש שלוש בעיות:
1. הרעש עצמו הוא טביעת אצבע. מבקר שפלט ה-canvas שלו משתנה בכל טעינה, אך יתר הסיגנלים שלו נשארים זהים, ניתן לזיהוי כדפדפן מזריק-רעש. זה כשלעצמו מזהה.
2. אלגוריתם הרעש יציב. המימוש של Brave מייצר דפוסי רעש ספציפיים שאינם תואמים לשונות הטבעית של רינדור GPU. מערכות זיהוי יכולות לזהות פלטי canvas שנראים מוזרקי-רעש לעומת כאלה שנראים טבעיים.
3. מערכות מתוחכמות משלבות דגימות. ניתן למצע מספר רינדורים על אותו עמוד, או בין סשנים. אם הרעש קטן, הממוצע מתכנס לטביעת האצבע הדטרמיניסטית הבסיסית.
מה Canvas Fingerprinting לוכד
מעבר לפלט החזותי המובן מאליו, canvas fingerprinting יכול לחלץ מספר מאפייני מכשיר כתופעות לוואי:
זמן רינדור — משך הזמן שלוקח ל-canvas לרנדר חושף את יכולת ה-GPU. שולחן עבודה 4K עם GPU נפרד מרנדר מהר יותר ממחשב נייד מדרג ביניים.
מדדי טקסט — measureText() מחזירה רוחבי פיקסלים מדויקים שמשתנים לפי רינדור הפונט. ניתן להשתמש ברוחב טקסט כטביעת אצבע אפילו ללא רינדור.
תמיכה בפעולות composite — חלק מהדפדפנים או קונפיגורציות GPU תומכים במצבי composite מורחבים. בדיקת תמיכה חושפת את גבולות היכולת.
אפקטי filter — פילטרים בסגנון CSS המיושמים על canvas מייצרים פלט שונה בין GPU-ים, במיוחד פילטרים של blur ו-drop-shadow.
איפה Canvas Fingerprinting משתלב בסטאק זיהוי
לבדו, canvas fingerprinting אינו מזהה חסין. מנהלי התקן משתנים. משתמשים מחליפים דפדפנים. הזרקת רעש נפוצה בקהלים ממוקדי פרטיות.
החוזק האמיתי שלו הוא כבדיקה צולבת. כאשר סשן טוען שהוא משתמש חוזר על סמך cookies או התחברות לחשבון, טביעת האצבע של ה-canvas משמשת כסיגנל שני — התאמה לטביעת האצבע ההיסטורית מאשרת את הטענה, אי-התאמה מסמנת השתלטות על חשבון או חטיפת סשן.
לצורך bot detection, canvas fingerprinting מצטיין בתפיסת אוטומציה במכולות. למשתמשים אמיתיים יש GPU-ים אמיתיים. GPU-ים אמיתיים מייצרים חתימות רינדור מזוהות. כל דבר שמרנדר כמו SwiftShader, או כמו canvas מזויף גרוע, יושב בדלי של כמעט-בוודאות-בוט.
הטכניקה מ-2012 עדיין עובדת ב-2026 מאותה סיבה: הרינדור דטרמיניסטי לכל סביבה אך כמעט בלתי אפשרי לזייף במלואו. כל ניסיון להסתתר משאיר עקבות של הניסיון עצמו.