-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
iOS 17 Safari Anti-Fingerprinting #235
Comments
Interesting, I'll take a look. I'm thinking we can plan to feature detect iOS 17 and remove audio from the fingerprints. I like the idea of checking read back functions, but it can make things too slow. This would be a good idea to showcase on a test page. |
For what its worth, it looks like the service-worker functions are the time-vampires in your script. Running everything in parallel is pretty zippy, fwiw: Also, here's my diffing function - suboptimal I'm sure, but it seems to work with the snippet above: function deepEqual(obj1, obj2) {
// Handle primitive types
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
return obj1 === obj2;
}
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
for (const key of keys1) {
if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) return false;
}
return true;
}
function removeDifferences(obj1, obj2) {
// If obj1 and obj2 are primitive types and equal, return obj1
if (typeof obj1 !== 'object' || obj1 === null) {
return deepEqual(obj1, obj2) ? obj1 : null;
}
// If obj1 is an array, handle it as an array
if (Array.isArray(obj1)) {
const result = [];
for (const key of Object.keys(obj1)) {
if (obj2.hasOwnProperty(key) && deepEqual(obj1[key], obj2[key])) {
result[key] = removeDifferences(obj1[key], obj2[key]);
}
}
return result;
}
// Default object handling
const result = {};
for (const key of Object.keys(obj1)) {
if (obj2.hasOwnProperty(key) && deepEqual(obj1[key], obj2[key])) {
result[key] = removeDifferences(obj1[key], obj2[key]);
}
}
return result;
}
export {removeDifferences}
|
The technique is useful. I'm thinking we could try something like this on a test page to show when there's a random per-execution leak. Since the worker does not block the main thread, it is not an issue. But response time is awful. I need to optimize or compress how much data is sent via messages. We could also phase out workers. It's non-essential. WebGL, canvas, DOM element can add up and block other operations, so running twice is probably too much. At some point, I want to move away from detecting lies on the client and instead let as much randomness as possible and just use simple server-side anomaly detection. We can move the lie detection stuff to test pages and the main script should run a lot faster. |
It looks like the audio on iOS 17 is a bug? There are a handful of recent issues reported. |
If browser juking becomes a problem in the future and it's worth the effort, maybe A/B test running 1x vs 2x?
A lot of your stuff is over my head, so I apologize if you cover this elsewhere - how would this work? Profile a bunch of browsers and get a range for a bunch of tests - and anyone who identifies as ${x} that falls out of those norms has their credibility decremented?
I'm fine if you want to close this btw. Maybe worth coming back to to when iOS takes 17 out of beta? |
It can be useful for classifying the behavior, but it's simple to get around via session-based fingerprints. The main issue with putting all traffic through lie detection on the client is it bloats the code, maps all the steps needed to reverse it, and uses an unnecessary degree of computation for normal traffic. There is a place for it, but it's much quicker to generate a lite fingerprint, check for anomalies on the server, and conditionally respond with more fingerprinting scripts, perhaps dozens.
Every site is different, so ideally the site determines what is and what is not normal and how to react to it. Traffic on site A can be 100% legit there, but not entirely if it shows up on site B. How to handle that is also a site decision. Credibility is one way, but it could be something more welcoming, like taking additional site-based steps to learn more about the traffic. I'll leave this open for a bit and may skip audio for iOS 17 if the issue persists. There's also an issue with lack of OffscreenCanvas that has been unresolved for some time now. |
I have iOS 17 (beta) installed on my phone, and noticed erratic fingerprints. Digging into the issue, it looks like Safari is somehow adding noise in the
offlineAudioContextComputed
so that the hash is variable with every run.Rather than fiddling too much with that section, what are your thoughts on doing something like this?
Compute each section twice.
If there's a difference between them, something is intentionally adding noise.
Remove the noisy bits.
Retain a fairly stable fingerprint.
The text was updated successfully, but these errors were encountered: