vytal-io / vytal-extension

Browser extension to spoof timezone, geolocation, locale and user agent.
https://vytal.io
GNU General Public License v3.0
1.8k stars 95 forks source link

tor browser detection: false positives #5

Closed Thorin-Oakenpants closed 2 years ago

Thorin-Oakenpants commented 2 years ago

Hey there :)

I didn't look at the code, but I assume you are picking up on some privacy.resistFingerprinting (RFP) attributes: such as timezone is UTC0, inner window is 100's height x 200's width, etc. These are problematic - users can manipulate timezone via extensions for example, even if Tor Project do not recommend it, and window sizes and even letterboxing have edge case bugs and users could maximize or manually resize without letterboxing. But the biggest problem is RFP is maintained upstream at Mozilla, and thus available in Firefox

There's also a very simple way to detect is RFP is on. Tor Browser is not trying to hide it's Tor Browser, and RFP is not trying to hide itself either. If you want that snippet, ask :)


To detect Tor Browser, client side JS only, 100% reliably with zero false positives ...

isFF

personally I use a mix of some things in here to catch extra entropy with extension lies, but you can get away with a single wrapped error check (chromium and webkit produce different error messages, depending on the error of course)

var isFF = false
const newFn = x => typeof x != 'string' ? x : new Function(x)()
try {
    newFn("alert('A)")
} catch(e) {
    if e.name + e.message == "TypeErrorcyclic object value") {isFF = true}
}

isTB

var isTB = false
const set_isTB = () => new Promise(resolve => {
    if (!isFF) {return resolve()} // optional
    try {
        // extensions can block resources://
            // FF ~5ms, TB ~20ms
        setTimeout(() => resolve(), 100)
        let css = document.createElement("link")
        css.href = "resource://torbutton-assets/aboutTor.css"
        css.type = "text/css"
        css.rel = "stylesheet"
        document.head.appendChild(css)
        css.onload = function() {
            isTB = true
            return resolve()
        }
        css.onerror = function() {
            return resolve()
        }
        document.head.removeChild(css)
    } catch(e) {
        return resolve()
    }
})
// call the promise

enjoy

z0ccc commented 2 years ago

Cool thanks! I will implement this.