Update 27.01.2011: *übel_fluch*! Facebook hat ein Captcha eingebaut, dass diese Detection momentan nicht mehr funktionieren lässt. Das Prinzip bleibt ok, die Realisierung brauchte nun etwas mehr Zeit.
Eigentlich hätte ich ja ganz Anderes zu tun, aber per Zufall bin ich über den genialen Blogartikel von Mike Cardwell gestolpert. Er hat eine Idee gehabt, wie es möglich wird herauszufinden, ob Benutzer auf Facebook und Konsorten eingeloggt sind oder nicht.
Umgesetzt in eine kleine Library läuft es als Proof-of-Concept auf Firefox und sieht folgendermassen aus:
Grundsätzlich wäre es ja ganz einfach: Man schaut vom Client-Browser aus, ob man Zugriff auf Bilder oder Seiten hat, die nur für Eingeloggte zur Verfügung stehen. Leider gestaltet sich dieser simple Ansatz nicht so einfach, weil mit Ajax nur zur Domain der Website verbunden werden darf und nicht an einen x-beliebigen Ort. Ein Proxy hilft auch nicht weiter, da es die Cookies des Browsers braucht, und die werden nur an Facebook, etc direkt abgeliefert.
Wie kann man also diese Restriktion umgehen?
Der Trick
Die geniale Idee von Mike Cardwell war nun, CSRF etwas zu tunen: <img> und <script> Tags im Browser dürfen Dinge von überallher laden. Normalerweise ist das Handlungspotential damit sehr eingeschränkt, ausser man nutzt die onerror und onload Attribute clever aus. Mit diesen Attrbuten können abhängig davon, ob ein Bild oder ein Script erfolgreich eingebunden werden konnte, JavaScript-Funktionen ausgeführt werden. onerror feuert normalerweise bei den HTTP-Status Codes 404, 403, 406 oder 500.
Was tun wir also? Wir binden auf unserer „bösen“ Seite ein Bild ein oder laden ein Script (kann auch eine Website sein), das sich unterschiedlich verhält, je nachdem ob man eingeloggt ist oder nicht. In einem der Fälle muss ein Fehler auftreten, damit dieser Trick klappt. Über das aufgerufene JavaScript senden wir das Resultat an den Server und schwuppdiwupps sind wir informiert.
Praktisch sieht das in etwa so aus: Mein Facebook-Profil ist nur für eingeloggte sichtbar, ansonsten gibt es ein 404.
src="https://www.facebook.com/Skaldrom.Y.Sarg"
onload="alert('Eingeloggt')"
onerror="alert('Nicht eingeloggt')"
></script>
Genau gleich läuft es mit Bildern.
Proof of Concept
Ich habe das Ganze etwas dynamisiert und in eine PHP-Bibliothek gefasst (die auch in diesem Beitrag für das obige Beispiel verwendet wird). Dafür gibt es eine Demo mit Minimalanleitung. Als grundlos bösartiger Mensch habe ich das in einen Moodle-Block gepackt. Die Kursteilnehmer werden dabei höflich gefragt, ob sie durch das Facebook vielleicht abgelenkt sind:
Heruntergeladen werden kann der Block von oncode.info.
Hilfe
Im Moment erkennt die Library Facebook, Google (gmail), Digg und Twitter. Sehr interessant wären YouTube, Reddit, … Wenn also jemand hier Bilder oder Seiten findet, die abhängig davon, ob man eingeloggt ist oder nicht, einen Fehler-Statuscode zurückgeben oder nicht, wäre ich sehr dankbar für eine Mitteilung.
Die img-Attacke scheint auf allen Browsern zu funktionieren, die script-Attacke leider nicht. Wenn jemand kompetentes es auf sich nehmen möchte und MSIE oder Opera auch integriert, fände ich das genial…
Happy Hacking :)….
Very nice 🙂
Coole Idee 🙂 Nur „eingeloggt“ muss nicht „aktiv“ bedeuten. Es können einfach noch Cookies übrig sein, welche den Benutzer immer eingeloggt lassen.
Aber nichts desto trotz: In welchem Kurs kann ichs testen? 😀
grz
Ja, und mit Schnaps muss nicht besoffen und überfahren nicht tot heissen, oder 🙂 ? Aktiv ist es im Kurs 151 und auf der Demo-Site.
Touché!
Im Wasser heisst auch nass aber noch nicht ertrunken 😉
Die Idee ist super, freue mich schon, das im ganzen Moodle anzutreffen.
Ein nerfendes Popup alles 2 Minuten würde die Effektivität noch steigern 😉
Eine wahrhaft teuflische Idee, passt! Oder Audio „Ich, -NAME-, bin im FAAAAISBUUUUUCK!“
Mit diesem schönen Code könnte man sicher viele „nette“ Sachen anstellen. Da kann man der Fantasie freien Lauf lassen.
Echt genialer code. Nur weiß ich noch nicht, wie ich es auf meiner Seite anwenden soll.
Hm, es ist nicht ganz trivial, aber auch nicht allzu schwierig. Auf der Demo-Site hat es eine Minimalanleitung. Hilft die?
Das klingt interessant. Das ist eine tolle Möglichkeit um zu überprüfen ob man noch auf seinen Seiten angemeldet ist oder ob die Session schon automatisch beendet wurde. Das könnte vieles ein wenig erleichtern. Vorallem sieht die Lösung gar nicht so umfangreich aus.