Website-Besucher durch Timing-Attacken auf Facebook deanonymisieren

Durch neue Timing-Attacken können Website-Besucher teilweise deanonymisiert werden, sofern sie parallel bei Facebook eingeloggt sind. Der Website-Betreiber kann über geschickte Anfragen an Facebook das Geschlecht, das Alter und den Wohnort des Users ermitteln.

Wenn jemand eine Website besucht, kann der Betreiber normalerweise aufgrund diverser Sicherheitsvorkehrungen nicht auf personenbezogene Daten des Besuchers zugreifen, die er auf anderen Websites hinterlassen hat. Dafür sorgt unter anderem die Same-Origin-Policy. Durch neue Timing-Attacken gelingt es aber, in Spezialfällen daran vorbeizukommen.

Drink

Wie immer empfehle ich nach alter Fravia-Tradition einen Drink zu diesem Hack:
Beim Thema „3rd-Party“ passt jeder Drink, Hauptsache jemand anderes hat ihn ausgegeben.

Demo-Exploit

Der Exploit funktioniert aktuell nur in Chrome und Firefox. Edge und Safari haben die dazu notwendigen Browser-APIs (noch) nicht implementiert. Es kann generell zu ungenauen Werten kommen, da mit Zeitmessungen gearbeitet wird. Die Wohnort-Angaben sind auf Deutschland beschränkt.

Die Demo ist hier per iframe eingebettet, hier gibt es die pure Seite und hier den Javascript-Code.

Es sei darauf hingewiesen, dass das hier nur Forschungszwecken dient. Ich speichere die ermittelten Daten in keinster Weise ab.

Technik

Die Idee ist, im Hintergrund Requests zu Facebook im Namen des besuchenden Users auszuführen und irgendwie an diesen zu erkennen, welche Eigenschaften der User bei Facebook hat. Den Inhalt oder sogar die Größe eines solchen Requests darf der Website-Betreiber aufgrund der Same-Origin-Policy nicht auslesen. Die Browser machen an der Stelle auch einen guten Job. Was allerdings nicht verhindert werden kann, ist, dass man die Zeit misst, die solch ein Request braucht.

Nun sind solche Timing-Attacken nicht neu, waren aber nie wirklich gefährlich, weil sie viel Zeit kosteten und sehr ungenau waren. Zu viele externe Faktoren beeinflussen die Zeit, die während eines Requests bei der Reise durch das Internet vergeht. Nach Forschungsarbeiten von Tom van Goethem gibt es jetzt aber z.B. die Möglichkeit, die Response des Requests in den Browser-Cache zu stecken und die dafür benötigte Zeit sehr exakt zu messen. Dies tut man mehrfach und nimmt am Ende den Median, um Extremwerte auszuschließen und erhält einen guten Messwert.

Wie ermittelt man damit nun die Eigenschaften eines Facebook-Users? Facebook bietet die Möglichkeit, Targeted Posts zu erstellen, also Posts, die nur User mit bestimmten demografischen Merkmalen lesen können. Da kann man also etwas posten, das z.B. nur eine 35jährige Frau aus Berlin lesen darf. Wenn ein User einen Post lesen kann, ist die Response-Size des Requests deutlich größer als wenn er nicht gelesen werden kann. Und an dem Punkt kann man die Messung ansetzen und Rückschlüsse auf den User ziehen.

In meinem Exploit habe ich für jeden dieser Fälle Posts bei Facebook angelegt. Also für Frauen und Männer, diverse Altersgruppen und Orte. Mehrere Alternativen einer Eigenschaft treten dann sozusagen gegeneinander an und die Messwerte ergeben dann die konkrete Eigenschaft.

Optimierungen

Ein anständiger Exploit ist nur dann etwas wert, wenn er praxistauglich ist. Dafür muss er einigermaßen schnell ablaufen und Ergebnisse liefern. Mit einer normalen Internetverbindung sollte die Demo nur ein paar Sekunden dauern, auch in der U-Bahn funktionierte es auf dem Smartphone ziemlich schnell. Es waren einige Tweaks nötig, um auf Geschwindigkeit zu kommen:

Anzahl der Requests

Es darf nur die geringstmögliche Anzahl an Requests im Hintergrund ausgeführt werden. Daher musste ich beim Alter und beim Wohnort vom Großen ins Kleine vorgehen. Es boten sich dafür Binärbäume mit 3 Ebenen an:

13-39
    13-26
        13-19
            => 13, 14, 15, 16, 17, 18, 19
        20-26
            => 20, 21, 22, 23, 24, 25, 26
    27-39
        27-33
            => 27, 28, 29, 30, 31, 32, 33
        34-39
            => 34, 35, 36, 37, 38, 39
40-65
    40-52
        40-46
            => 40, 41, 42, 43, 44, 45, 46
        47-52
            => 47, 48, 49, 50, 51, 52
    53-65
        53-59
            => 53, 54, 55, 56, 57, 58, 59
        60-65
            => 60, 61, 62, 63, 64, 65

Von größeren Altersgruppen wird also auf kleinere geschlossen, bis man ein konkretes Alter ermittelt hat.

Beim Wohnort ist es schwieriger, da Facebook innerhalb von Deutschland nur Bundesländer, Städte und Postleitzahlen anbietet. Weil ich nicht viel Lust hatte, für jede der ca. 14.000 Postleitzahlen einen Post bei Facebook anzulegen (auch wenn ich das teilautomatisiert habe), ist die Ortserkennung hier beschränkt auf Städte mit mehr als 100.000 Einwohnern. Vom Bundesland-Level auf die konkrete PLZ zu kommen, hätte zudem auch mehrere tausend Requests gebraucht, um sie zu ermitteln. PLZ-Prefixes unterstützt Facebook leider nicht, sonst wär ich dabei gewesen.

Synchron vs. asynchron

Um Zeit zu sparen, sollten die Downloads asynchron ablaufen, die Zeitmessungen müssen aber synchron vonstatten gehen, damit sie einander nicht zu sehr beeinflussen. Jeder, der mal exzessiv asynchron gecodet hat, kennt die async-Hölle. Der konnte ich nur mit old-school-Semaphoren und einer Mainloop entkommen, um manche Dinge geregelt nacheinander ablaufen zu lassen. Es geht sicherlich auch irgendwie eleganter, aber für die Demo reicht es, denke ich.

Mobile-Endpoint

Für bessere Messwerte habe ich die Requests zu Facebook nicht auf den normalen Endpoint „www.facebook.com“ geschickt, sondern auf den entschlackten mobilen: „m.facebook.com“. Das bringt meines Erachtens einiges an Effizienz.

Gegenmaßnahmen

Die bösen 3rd-Party-Cookies mal wieder… Die Werbewirtschaft steht auf sie, weil man damit so schön Benutzerverhalten tracken kann. Daher wird es sie wohl auch noch lange geben. Die EU wollte sie soweit ich weiß mal bekämpfen, daraus ist aber nichts geworden. Standardmäßig sind sie in allen gängigen Browsern leider immer noch aktiviert. Wer weiterhin tolle, auf den User abgestimmte Produktvorschläge bekommen möchte, kann die Einstellung ja so lassen, alle anderen sollten sie deaktivieren.

Warum ist das schlimm, wenn man so genaue personenbezogene Daten von einem User herausfinden kann? Ihr habt wieder mal nichts zu verbergen? Nun, wenn man weiß, dass ein 29jähriger Mann aus Bottrop kommt, wie viele Leute bleiben dann noch übrig, um die konkrete Person zu ermitteln? Grob überschlagen mit der Altersverteilung in Deutschland kommen dann nur noch ca. 727 Personen in Frage. Mit jedem weiteren Kriterium sinkt die Zahl – Rasterfahndung on-the-fly für jedermann.

Soziale Netzwerke wie Facebook wissen einfach unglaublich viel über ihre Nutzer. Wenn diese Daten dann auch noch fürs Targeting freigegeben werden, wird es langsam eng mit dem Datenschutz. Man muss mittlerweile sehr gut aufpassen, was man alles an welchen Stellen im Netz preisgibt, denn nicht alle Anbieter haben es drauf, diese Daten gegen so eine „information leakage“ adäquat zu beschützen.

Also: Entweder 3rd-Party-Cookies deaktivieren (z.B. mit dem Disconnect-Plugin oder Privacy Badger) oder mit dem Tor-Browser auf Nummer Sicher gehen. Und an meine Worte denken, wenn Ihr demnächst mal wieder auf einer Gesundheitsseite nach Behandlungsmethoden für eine Geschlechtskrankheit sucht.

Berichterstattung

Heise News
Engadget

18 Gedanken zu „Website-Besucher durch Timing-Attacken auf Facebook deanonymisieren“

  1. I’m officially well over 65 years old on FB 😉 . So 65 doesn’t really cover me. Please change the output of the script to „65 or older“. I never told FB where I live. Still the script answers „Berlin“, which is not far from the truth (Magdeburg). Bummer!

  2. age20, male, sachsen, chemnitz…

    Naja, zumindest EINES davon stimmt, aber das war ne 50/50 Chance.

  3. raffiniert, aber hier dreht sich das f und dreht und dreht…
    oh, da steht’s ja auch, der Privacy Badger funkt dazwischen.

  4. Cool! Aber wie kann man bei Facebook Beiträge anlegen die nur für einen bestimmten Personenkreis gedacht sind? Ich hab bei der Funktion „Beitrag bewerben“ mal was gesehen. Hast du Geld in die Hand gekommen? Danke!

  5. „Du bist nicht bei Facebook eingeloggt.“ – das ist in meinem Fall (leider) falsch.

  6. referrerPolicy: ’no-referrer‘ gibt dem ganzen noch ein bisschen mehr anonymität für den script hoster 😉

    1. That’s why I mentioned and linked him in the text… I just optimized and completed the approach.

  7. Das Logo dreht sich und nichts passiert. Könnte es daran liegen, dass ich Facebook auf Third-Party-Websites blockiert habe?

Kommentare sind geschlossen.