arkenfox / TZP

https://arkenfox.github.io/TZP
MIT License
8 stars 0 forks source link

notes #4

Open Thorin-Oakenpants opened 4 years ago

Thorin-Oakenpants commented 4 years ago

various notes from the old repo


Promises

words of wisdom from kkapsner

That's doable but a better way would be to have eight promises - one for each test. Then you can combine them with Promise.all in all the configurations you need them. Something like this (please use better names!):

var p1 = getWorker1Promise();
...
var p5 = getWorker5Promise();
var p6 = getIframe1Promise();
...
var p8 = getIframe3Promise();

Promise.all([p1, ..., p5]).then(outputWorkerData);
Promise.all([p6, p7, p8]).then(outputIframeData);
Promise.all([p1, ...., p8]).then(combineAndCompareAll);

FP scripts


WASM

abraham: There are ways to use WASM to interact with browser APIs, but does WASM make way to create a virtual context or scope? Iframes have their own browsing context/document environment, and Workers have their own global scope/event loop.

Here's an example of canvas fingerprinting in Rust.

kkapsner: The timings in the script are too tight for Firefox. If you set a debugger break point at line 441 it works. AND CB is protecting against it!


DOMRect / SVG

Links

Note that source

As of Firefox 76, the IntersectionObserver() constructor now accepts a Document object as its root, as well as an Element object. This lets you explicitly use a window's entire content area as the intersection bounds. We should verify that this does not allow someone to defeat the protections provided by letterboxing (probably it does not)


canvas stability

I see changes in some canvas results across FF releases. The hashes that change are

for example: for me on windows

60
==
      3x a5ad50aa3a7411825a4c0b...
getImage e7209e6a032dddcd83f6bb...

61-71
==
      3x 4c406afafa6f85d3f152ea...
getImage 094f27144dd0e3c0a20a14...

72-73
==
      3x 98a30b2999315acb01047a...
getImage 197bbc428ccd88b6a75b3f...

74-76, Beta77, Nightly (the hash changed, not just dropping mozGetAsFile)
==
      2x 3cc435fec7e69a56f50420...
getImage 1230e7b2c39c38540940a5...

Dev77.0b9 (sometimes Beta)
==
      2x 2cc1b50af4dfc47ba1b35b...
getImage 904fc496441e05e2f41d1c...

I wonder what causes these changes


widgets

from tom: Had someone look at this, and they had the following to say:

  1. "I assume these five items are not widgets? (progress bariframe, image, datetime and text area)" - actually only iframe and image are not technically widgets.
  2. Without running a lot of tests himself, he couldn't say off-hand if the CSS is successfully leveling the playing field as asked in the "Help" section.
  3. Regarding any other widgets to add: :shorlander put together a comprehensive page with our widgets. You may want to take a look at it: http://stephenhorlander.com/form-controls.html
  4. We're working on removing native styling for our widgets and using our own, consistent styling. It would be very interesting to know whether "unstyled" widgets also suffer from fingerprinting issues. You can try this by setting the widgets to "-moz-appearance: none;", which is what :shorlander did on the left side of his page.

line breaking

Article: https://www.otsukare.info/2020/08/21/khmer-line-breaking

Can be used to?:

Pitfalls?

Notes:

example test: https://w3c.github.io/i18n-tests/css-text/line-breaking/exp-km-line-break-000.html

Thorin-Oakenpants commented 4 years ago

@abrahamjuliot : two questions

q1: is there a better way to do this: rather than rely on a hardcoded count of promises, how would I do a "for each promise" "for each result"

    Promise.all([
        functionA(),
        function99(),
        funtionSomethingElse(), // <-- three promises: but what if I add more
    ]).then(function(result){
        for (let i=0; i < 3; i++) {  // <-- I would have to update the < number
            myarray.push(result[i])
        }
        // do stuff with myarray
    })

q2: is there a cleaner way to specify a variable: e.g. compare = chk+i

    if (i == 0) { compare = chk0
    } else if (i == 1) {compare = chk1
    } else if (i == 2) {compare = chk2
    } else if (i == 3) {compare = chk3
    }

-tia

abrahamjuliot commented 4 years ago

q1

let collection = [
    functionA,
    function99,
    functionA
    // add as many as you like
]

Promise.all(
    // compile array with each promise called
    collection.map(function(fn) {
        return fn()
    })
).then(function(result) {
    // for loop
    let len = promises.length
    for (let i = 0; i < len; i++) {
        myarray.push(result[i])
    }

    // or forEach 
    collection.forEach(function(currentValue, index) {
        myarray.push(result[index])
    })
})

q2

I'm terrible at naming variables. It usually takes x number of revisions till I can make sense of it. But, I like starting with a comment on what it holds or what it should do and then my goal is to find a name that makes the comment unneeded. For example, chk1 = [ ] // holds cat and mouse checks could instead be named catMouseChecks.

EDIT: I think I answered the wrong question. Let me try again...

chk+1 converts the array to a string: [1,2,3]+1 == "1,2,31". But, you could use chk[i] format if chk is an object of numeric property names, like chk = { 0: [ ], 1: [ ] }.

let chk = {
    0: [], // access with chk[0]
    1: [],
    2: [],
    3: []
}

if (i == 0) {
    compare = chk[i]
} else if (i == 1) {
    compare = chk[i]
} else if (i == 2) {
    compare = chk[i]
} else if (i == 3) {
    compare = chk[i]
}

// shorter single assignment
compare = (
    i == 0 ? chk[i] :
    i == 1 ? chk[i] :
    i == 2 ? chk[i] :
    chk[i] // i == 3
)
kkapsner commented 4 years ago

DOMRect / SVG

I'm working on that (there are some bugs in the CB code). Stay tuned.

kkapsner commented 4 years ago

Please check the updated test page.

Thorin-Oakenpants commented 4 years ago

Awesome: I've been wanting to dig into this for ages. TB has open tickets about some SVG items. It's all on my ToDo list. So much to do, so little time. Imma just going to keep plodding away getting existing things finished before I add more things: and really dig into your test but it looks exciting 💋 How much entropy is gained would be interesting

Thorin-Oakenpants commented 3 years ago

@kkapsner .. this didn't affect your tests did it? I remember you saying in the old repo something about bugs and MDN documentation not matching

kkapsner commented 3 years ago

No - it was something different. The used classes did not match MDN and the bugs were in CB.

Thorin-Oakenpants commented 3 years ago

@kkapsner I assume there's no point in looking at DOMRectReadOnly vs DOMRect

... anyway .. it says Available in workers in FF69+ ... can that be used to unmask real measurements? .. also @abrahamjuliot (who is always busy)

kkapsner commented 3 years ago

DOMRectReadOnly and DOMRect should behave the same (unless an addon messes with one but forgot the other). In fact DOMRect inherits from DOMRectReadOnly: image

it says Available in workers in FF69+ ... can that be used to unmask real measurements?

I don't think so. There is no document in the worker and no rendering of HTML.

Thorin-Oakenpants commented 3 years ago

Thanks

This is what I thought ... a worker runs in a global context which is different from the current window - so I was surprised to see that listed there and wondered if there was some "workaround" like passing a "context" or "element" reference?

unless an addon messes with one but forgot the other

Yup, that was my point. We test things, like iframe access methods .. and whammo, someone forgot something (I see Brave still hasn't patched those iframes with canvas - etc see https://github.com/brave/brave-browser/issues/12453 ).

So if domrect was altered, the "parent" domrectreadonly might not be? We should make a test for that, right?

kkapsner commented 3 years ago

We should make a test for that, right?

Should be easy enough.

Thorin-Oakenpants commented 3 years ago

@kkapsner It's going to take me a while before I get around to the SVG and other "domrect" stuff, but I had a sneaky thought about css aspect-ratio ...

not sure what it could be used with, and I'm yet to try .. but I'm thinking this could be used to generate boxes with known decimals to detect spoofing - it's on my massive ToDo list, but I just thought I'd throw this idea at you

kkapsner commented 3 years ago

I think it will behave similar to a height or width set with decimals: up to certain precision the browser will match that but will do other numbers beyond it.

Thorin-Oakenpants commented 3 years ago

Yeah, it's in my notes: I was thinking I could force something like 1/3 and the result should be 1.3333333333 or whatever, but it may depend on the limitations of the API (not the measuring one) and variables such as pixel snapping, rounding, devicePixelRatio/subpixels, zoom/css-devicePixels (I think I could work around this) .. just something devious I thought about last night as I went to sleep

Thorin-Oakenpants commented 3 years ago

@abrahamjuliot iframe.contentWindow properties change if the console (both web console or browser console) is open: I'm about to head off, so I haven't debugged what changes - the counts stayed the same

edit: diff is diff

I don't know if you sort yours: I obviously don't: and I wonder if there is a workaround: such as always put Event last: i.e remember it and append it to the array at the end

edit2: https://github.com/arkenfox/TZP/commit/3c34ae7dac288e8a3557e190450e2ee740417a3c - but I wonder if anything else can affect the order: I don't like sorting if I can help it, as I want max entropy

abrahamjuliot commented 3 years ago

I leave it unsorted. Moving Event is nice workaround for the console issue. There might also be a number of prefs that remove/add properties and/or change the order, and sorting might not handle these. I've noticed a change in these modes:

Thorin-Oakenpants commented 3 years ago

If RFP removes items (which is what I suspect), then sorting isn't going to do jack shit. It's not like prefs change all the time - e.g. RFP changes lots of metrics and is not something that users would generally toggle: it's not available yet per ELTD+1 and users would/should be selective in what they disable it on: and when RFP is off, this might break linkability with previous FP's: but smart backend algorithms can still linkify stuff - and it's also likely to be sites they log into, such as twitter/imgur to upload images, or gmail to get their timestamps in sync with gmail app etc.

But other factors are a concern: I wonder what headless does for example: that would be cool to catch. Needs a bit more investigation - e.g safer vs standard might be some SVG items getting removed - nothing you can do about that. It's really only when the order changes - like consoles .. damnit

Maybe it's just better to sort it: because there are too many unknowns - what do you think?

abrahamjuliot commented 3 years ago

I think sorting is good to handle the console issue. We could capture both and then leave the unsorted in the loose fingerprint.

Thorin-Oakenpants commented 3 years ago

items are removed at a minimum: so sorting won't do anything (but would if TB didn't change WASM)

Tor Browser of course diff-slider

FF+RFP diff-RFP


order is changed: and it goes a bit deeper

If you ever select the storage tab in web console, Location is also moved to the end (not sure if before or after Event as my code is making Event last) .. and until you close the web console, regardless if the storage tab is selected, Location is always moved. Closing the console clears it.

Not sure where to find responsive design mode.

So depending on what a dev is doing (I'm not sure what these are called: JS actors?) .. some properties get loaded first/last, used last or something

Thorin-Oakenpants commented 3 years ago

I think sorting is good to handle the console issue. We could capture both and then leave the unsorted in the loose fingerprint.

There's too many unknowns as to what affects order. I was using this to check for changes between releases (to see if anything popped out for a version check) ... I'll think I'll check diffs per release (constant, no console etc) vanilla profiles to see what diffs there are - maybe sorting doesn't really affect entropy (it probably shouldn't: i.e if wasm affects those other items, but wasm is missing, it's already different - if you get my drift)

Thorin-Oakenpants commented 3 years ago

some tests: windows, practically vanilla profiles (but I do have some tweaks, but they're all the same: mostly UI stuff)

no sorting:
=======
- checked 78->79, 79->80, 80->81
- always something added/removed (ughh I guess not in 80->81: I have a shitty diff utility)
- sorting is about 50 to 70 items in different positions (moved in several clumps)

ESR78.5/FF78
- a80ba2970933d469aae7931685b177ff714d68a4 [813]
FF79
- bfd5ad71cda7986c335f6588dda93b2b0383c30c [816]
FF80
- 1c1e85c5750649a399583735983d544d36611fc2 [816]
FF81
- bf3506af3c49786155c0eb820afe853a968ed17c [816]
FF82
- 533f018257c32c37ac04480ae7e968ac387b94f2 [820]
FF83
- ee628954b9e5b2880bda2b12578f727cccefa6ba [819]
FF84Dev + Beta
- 0070d3816d8503d0068112e5a82e6c03a51369c6 [820]
FF85
- edcb17d31555f464f9fdf4a676cded1748b215b4 [836]

sorted
======
78
- eb06d1c4372efeef24c472f28b152f19323ced86 [813]
79, 80, 81
- 4cf8663aa364f09b2608623274e3f8c08a81c867 [816]
- diffs: 79 added 3 new props
82
- 3d4dbd0937be983cbd6ec05307f12693723fae4d [820]
- diffs: 82 added 4 new props
83
- 2056b9319ff50c03f328dcfab6dac98560401596 [819]
- diffs: 83 removed one of the 4 new props added in 82
84
- 0d2d1b2452e598d1c039f9a79fb3e2641a5e1599 [820]
- diffs: 84 added a new prop
85
- c273969d358ba2f0615e1becabb8fb68417e6379 [836]
- diffs: lots .. it's nightly with loads of testing new shit

So as you can see, the order is different per release (at least on windows, but I don't see why that wouldn't be the same on any platform). But when we sort then there may be no differences: it depends if the stable release gets some new feature - e.g. 79, 80 and 81 were the same for me

That said .. I already have a version number from feature detection - so I'm know I'm good for the overall FP in that regard. I'm just going to sort it and be done - but I do wonder if this cuts possible extra "stable" entropy.

I did notice that the only items ever affected started with a capital (AFAICT, didn't take notes or always check 100%)

abrahamjuliot commented 3 years ago

responsive design mode

It's the tiny phone/tablet icon in the console menu (or ctrl+shift+M).

Thorin-Oakenpants commented 3 years ago

stuff I need to learn about: https://palant.info/2020/12/10/how-anti-fingerprinting-extensions-tend-to-make-fingerprinting-easier/ - @abrahamjuliot FYI

also: https://news.ycombinator.com/item?id=25374383

gorhill

This bind() call makes sure the getter looks like a native function. Exactly what we needed.

Even the example given as finally working will show difference with the native method, the bound function will have a property name set to bound, while the native one has a name property set to get width.

Thorin-Oakenpants commented 3 years ago

bots: https://www.tomanthony.co.uk/blog/googlebot-javascript-random/

I'm not sure this holds any more, not that I particularly care about bot detection

edit: there's always a xkcd for everything: https://xkcd.com/221/

Thorin-Oakenpants commented 2 years ago

good article - https://www.otsukare.info/2022/10/25/css-values-definitions - @abrahamjuliot FYI

Thorin-Oakenpants commented 1 year ago

heh

Can you explain why someone would want to scale an image to over 17 million pixels high? On a 96dpi screen, that's over four kilometers high