• केवल indexedDB.databases() के return order से Firefox-आधारित ब्राउज़रों में process lifetime के दौरान कायम रहने वाला स्थिर identifier बनाया जा सकता है
  • यह identifier origin scope से बाहर साझा होता है, इसलिए असंबंधित साइटें भी उसी browser runtime के भीतर एक ही value देख सकती हैं और इसे cross-origin tracking में इस्तेमाल कर सकती हैं
  • Firefox Private Browsing में सभी private windows बंद करने के बाद भी, अगर process ज़िंदा है तो identifier बना रहता है; Tor Browser में New Identity के बाद भी यह जारी रहता है
  • कारण Gecko के IndexedDB implementation में private database names को UUID-आधारित filenames से map करना और उस result को बिना sort किए expose करना है
  • Mozilla ने Firefox 150 और ESR 140.10.0 में fix जारी किया है, और internal storage order को बाहर प्रकट न करने वाला design privacy protection के लिए महत्वपूर्ण है

भेद्यता का अवलोकन

  • सभी Firefox-आधारित ब्राउज़रों में indexedDB.databases() द्वारा लौटाई गई items की order से process lifetime के दौरान स्थिर रहने वाला identifier निकाला जा सकता है
    • अगर कोई वेबसाइट कई IndexedDB databases बनाकर return order देखे, तो वह चल रहे browser process के लिए एक unique और deterministic identifier बना सकती है
    • यह behavior origin scope पर नहीं बल्कि process scope पर दिखता है, इसलिए एक-दूसरे से असंबंधित साइटें भी उसी browser runtime के भीतर एक जैसा identifier देख सकती हैं
  • Firefox Private Browsing में सभी private windows बंद हो जाने के बाद भी, अगर Firefox process चलता रहता है तो identifier बना रहता है
    • Tor Browser में cookies और browsing history साफ कर नई Tor circuit इस्तेमाल करने वाले New Identity के बाद भी यह स्थिर identifier बना रहता है
    • यह उस उम्मीद के विपरीत है कि बाद की browser activity को पहले की activity से नहीं जोड़ा जा सके, और इससे users जिस unlinkability पर भरोसा करते हैं वह कमजोर पड़ती है
  • Mozilla और Tor Project को responsible disclosure किया गया
    • Mozilla ने Firefox 150 और ESR 140.10.0 में fix जारी किया
    • patch को Mozilla Bug 2024220 में track किया जा रहा है, और root cause Gecko के IndexedDB implementation में होने की वजह से Tor Browser तथा अन्य Firefox-आधारित ब्राउज़रों पर भी इसका असर पड़ता है
  • fix का सिद्धांत सरल है
    • browser को process-scope internal storage order बाहर expose नहीं करना चाहिए
    • results को normalize या sort करके लौटाने से entropy हटाई जा सकती है और इस स्थिर identifier के दुरुपयोग को रोका जा सकता है

यह क्यों महत्वपूर्ण है

  • private browsing mode और privacy-focused browsers का उद्देश्य अलग-अलग contexts में users की पहचान करना कठिन बनाना है
    • सामान्य अपेक्षा 1: shared storage या explicit identity mechanism के बिना, असंबंधित साइटों को यह पता नहीं चलना चाहिए कि वे उसी browser instance से interact कर रही हैं या नहीं
    • सामान्य अपेक्षा 2: private session खत्म होने पर उससे जुड़ी जानकारी भी खत्म हो जानी चाहिए
  • यह behavior इन दोनों अपेक्षाओं को तोड़ देता है
    • साइटें cookies, localStorage या किसी explicit cross-site channel के बिना भी, केवल browser के internal storage behavior से identifier निकाल सकती हैं
    • API द्वारा लौटाए गए database names की order से high-capacity identifying signal हासिल किया जा सकता है
  • developers के लिए इसमें एक सबक है
    • privacy vulnerabilities सिर्फ identifying data तक सीधे access से नहीं होतीं
    • जब internal implementation details deterministically expose हो जाती हैं, तब भी privacy leak हो सकती है
  • security और product perspective से मुख्य बात
    • ऊपर से harmless दिखने वाला API भी, अगर वह स्थिर process-level state leak करे, तो cross-site tracking vector बन सकता है

IndexedDB और indexedDB.databases()

  • IndexedDB client-side structured data storage के लिए browser API है
    • web applications इसका उपयोग offline support, caching, session state और अन्य local storage उद्देश्यों के लिए करती हैं
    • हर origin एक या अधिक named databases बना सकता है, और object stores तथा बड़े data blobs store कर सकता है
  • indexedDB.databases() मौजूदा origin से दिखने वाले database metadata को लौटाता है
    • developers इसका उपयोग existing databases जांचने, storage usage debug करने और application state manage करने के लिए कर सकते हैं
  • सामान्य privacy expectations के तहत, इस API की return order में खुद कोई identifying information नहीं होनी चाहिए
    • database metadata का representation neutral या normalized होना चाहिए
    • असली समस्या यह थी कि Firefox-आधारित ब्राउज़रों में return order बिल्कुल भी neutral नहीं थी

indexedDB.databases() कैसे स्थिर identifier बन गया

  • Firefox Private Browsing में indexedDB.databases() metadata को database creation order में नहीं, बल्कि internal storage structure से निकली order में लौटाता है
    • संबंधित implementation dom/indexedDB/ActorsParent.cpp में है
  • Private Browsing में database names को सीधे disk identifiers के रूप में इस्तेमाल नहीं किया जाता
    • इसके बजाय global hash table StorageDatabaseNameHashtable = nsTHashMap<nsString, nsString> के जरिए उन्हें UUID-आधारित filename base से map किया जाता है
    • यह mapping OpenDatabaseOp::DoDatabaseWork() के भीतर GetDatabaseFilenameBase() में की जाती है
  • जब aIsPrivate true होता है, तो site द्वारा दिया गया database name generated UUID से replace कर global StorageDatabaseNameHashtable में store किया जाता है
    • key के रूप में केवल database name string का उपयोग होता है
    • यह IndexedDB QuotaClient lifetime तक बना रहता है
    • यह सभी origins के बीच साझा होता है
    • यह केवल Firefox को पूरी तरह restart करने पर reset होता है
  • बाद में indexedDB.databases() call होने पर Firefox, GetDatabasesOp::DoDatabaseWork() में QuotaClient::GetDatabaseFilenames(...) के जरिए database filenames collect करता है
    • database base names को nsTHashSet में insert किया जाता है
    • iterate करने से पहले किसी तरह की sorting नहीं की जाती
  • अंतिम result order hash set के internal bucket layout को traverse करने से तय होती है
    • क्योंकि UUID mapping Firefox process lifetime तक स्थिर रहती है, इसलिए return order भी generated UUID values, hash function behavior, hash table capacity और insertion history का deterministic function बनी रहती है
    • यह order tabs और private windows के पार बनी रहती है, और केवल Firefox के पूरी तरह restart होने पर reset होती है
    • UUID mapping और hash set traversal दोनों origin scope नहीं बल्कि process scope के हैं

पुनरुत्पादन का तरीका

  • एक साधारण PoC से इस behavior को साबित किया जा सकता है
    • दो अलग origins वही script host करते हैं
    • हर script fixed names के set वाले databases बनाती है, indexedDB.databases() call करती है, return order निकालती है और उसे print करती है
  • प्रभावित Firefox Private Browsing और Tor Browser builds में, दोनों origins उसी browser process lifetime के दौरान एक जैसी permutation देखती हैं
    • browser restart करने पर permutation बदल जाती है
  • conceptual output का उदाहरण
    • creation order: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
    • return order: g,c,p,a,l,f,n,d,j,b,o,h,e,m,i,k
  • मुख्य बात exact order नहीं है
    • यह मूल creation order से अलग होती है
    • असंबंधित origins पर वही order दिखती है
    • refresh, नई private window, और सभी private windows बंद करने के बाद भी बनी रहती है
    • केवल पूरे browser restart पर नई order बनती है
    • इससे privacy perspective से अवांछित गुण सीधे देखे जा सकते हैं

privacy पर प्रभाव

  • यह vulnerability एक ही browser runtime के भीतर cross-origin tracking और same-origin tracking दोनों को संभव बनाती है
  • cross-origin प्रभाव

    • असंबंधित websites स्वतंत्र रूप से वही identifier निकाल सकती हैं और यह अनुमान लगा सकती हैं कि वे उसी चल रहे Firefox या Tor Browser process से interact कर रही हैं
    • cookies या किसी अन्य shared storage के बिना भी domains के बीच activity को जोड़ा जा सकता है
  • same-origin प्रभाव

    • Firefox Private Browsing में, अगर Firefox process चलता रहे तो सभी private windows बंद करने के बाद भी identifier बना रहता है
    • कोई site बाद की visit को, जो देखने में नई private session जैसी लगे, फिर से पहचान सकती है
    • Tor Browser में यह स्थिर identifier चल रहे browser process के भीतर New Identity isolation को प्रभावी रूप से निष्प्रभावी कर देता है
    • यह उन sessions के बीच link बनाने देता है जिन्हें पूरी तरह अलग होना चाहिए
  • Tor Browser में यह खास तौर पर गंभीर क्यों है

    • Tor Browser को cross-site linkability घटाने और browser-instance-level identification कम करने के लिए design किया गया है
    • process lifetime तक बना रहने वाला स्थिर identifier इस design goal से सीधा टकराता है
    • भले ही यह केवल पूरे process restart तक ही क्यों न टिके, सक्रिय उपयोग के दौरान unlinkability को कमजोर करने के लिए इतना काफी है

entropy और fingerprinting क्षमता

  • यह signal सिर्फ स्थिर नहीं है, इसकी capacity भी ऊंची है
    • अगर कोई site N database names नियंत्रित कर सकती है, तो देखी जा सकने वाली permutations की संख्या N! होगी
    • सैद्धांतिक entropy log2(N!) है
  • 16 controllable names होने पर theoretical space लगभग 44 bits होती है
    • यह real-world में एक साथ चल रहे browser instances को अलग पहचानने के लिए पर्याप्त है
  • internal hash table behavior के कारण, वास्तव में हासिल की जा सकने वाली permutations कुछ कम हो सकती हैं
    • लेकिन security के लिहाज़ से मुख्य बात नहीं बदलती
    • exposed order फिर भी मजबूत identifier की तरह काम करने लायक पर्याप्त entropy देती है

fix कैसे किया गया

  • सही fix यह है कि internal storage layout से निकले entropy exposure को बंद किया जाए
    • सबसे साफ mitigation यह है कि results को lexicographic sorting जैसी canonical order में लौटाया जाए
    • इससे developers के लिए API की उपयोगिता बनी रहती है और fingerprinting signal हट जाता है
  • हर call पर output को randomize करने का तरीका भी स्थिर order छिपा सकता है
    • लेकिन sorting ज्यादा सरल, predictable और developers के लिए समझने में आसान विकल्प है
  • security engineering perspective से ideal fix की शर्तें
    • conceptual complexity कम
    • compatibility risk न्यूनतम
    • privacy leak सीधे खत्म

responsible disclosure

  • Mozilla और Tor Project को responsible disclosure किया गया
    • Mozilla ने Firefox 150 और ESR 140.10.0 में fix जारी किया
    • patch को Mozilla Bug 2024220 में track किया जा रहा है
  • इस behavior की जड़ Gecko के IndexedDB implementation में है
    • इसलिए Tor Browser सहित Gecko-आधारित downstream browsers भी, अगर उनके पास अपनी mitigation नहीं है, तो प्रभावित हो सकते हैं

privacy-focused design

  • implementation की छोटी-सी detail भी अर्थपूर्ण privacy समस्या बन सकती है
    • असंबंधित websites उसी browser runtime के दौरान origin के पार activity को जोड़ सकती हैं
    • identifier user expectations से ज्यादा समय तक जीवित रहकर private session boundaries को कमजोर कर सकता है
  • सकारात्मक बात यह है कि fix सरल और प्रभावी है
    • return से पहले output normalize करके इस entropy source को हटाया जा सकता है
    • अपेक्षित privacy boundaries को बहाल किया जा सकता है
  • यह ऐसी vulnerability है जिसे नज़रअंदाज़ करना आसान है, लेकिन प्रभाव बड़ा है, और privacy-sensitive features बनाते समय इस पर विशेष ध्यान देना चाहिए

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.