Ergebnis 1 bis 10 von 10

Baum-Darstellung

  1. #1
    Wiederbelebt Avatar von Cystasy
    Registriert seit
    08.05.2015
    Beiträge
    685

    Standard Reverse Engineering - Fitbit API's

    Heute geht es darum die Fitbit Web API's zu reversen.
    Warum? Nun - Fitbit hat sein Geschäftsmodell darauf aufgebaut, das sie eure Fitness Armband Daten auf ihren Servern speichern.
    Diese Daten könnt ihr dann nur durch eine Premium Mitgliedschaft exportieren - ergo lässt sich Fitbit von euch dafür bezahlen,
    euch eure Daten auszuhändigen die ihr selbst aufgezeichnet habt. Das muss man sich erstmal auf der Zunge zergehen lassen.
    Man zeichnet Tag für Tag seine Fitness Daten auf.. und um dann an diese Daten zu kommen soll man zahlen? Na! So gehts ja mal nich.

    Da ich gerne mit meinen (!) Daten einige Analysen durchführen würde (und kb hab Premium zu kaufen um an meine Daten zu kommen),
    werde ich mir die Daten auf dem klassischen Weg besorgen - Ich werde die API reversen und mir meine Daten selbst holen.

    Wo fangen wir an? Ersteinmal müssen wir uns anschauen wie das ganze bei Fitbit mit den Daten funktioniert:

    Man trägt den jeweiligen Fitness Tracker (meistens Armbänder) bei sich. Dieser Tracker besitzt einen internen Speicher auf dem bis zu
    7 Tage eure Daten (Ruhepuls, Herzfrequenz allgemein, Schlafqualität & co.) gespeichert werden. Nun kann man den Tracker
    per Smartphone App oder einer Desktop Anwendung mit den Fitbit Servern Syncronisieren woraufhin diese Daten aus dem Internen
    Speicher des Trackers auf den Servern von Fitbit landen. Anders als auf diesem Weg kommt man nicht an seine Daten ran.
    Die Datenübertragung vom Tracker zur App / Desktop Anwendung läuft über Bluetooth 4.0 und ist verschlüsselt.
    Ein Abgreifen der Daten per Bluetooth ist also ohne größeren Aufwand nicht drin (zu aufwändig).

    Jedoch gibt es von Fitbit ein Dashboard für den Browser in dem man seine Daten anschauen kann, das sieht dann folgendermaßen aus:



    Wie wir hier sehen gibt es hier eine Repräsentation von unseren Daten, die auf dem Server abgespeichert sind.
    Ergo muss es eine Art Schnittstelle geben, worüber der Browser dann die ganzen Daten vom Server abrufen & anzeigen kann.
    Zunächst dachte ich das diese Daten einfach über Javascript im JSON Format in die Webseite eingebunden sind.
    Deshalb hatte ich mir zunächst den Quellcode der jeweiligen Startseite zum Dashboard genauer angesehen.. doch
    leider fand ich dort nichts. Über meine Schlafqualität hätte ich jedoch über Umwege dann die Daten über meine Schlafqualität auslesen
    können. Mich interessierte aber vielmehr mein Herzschlag (mein Fitness Armband von Fitbit zeichnet 24/7 meinen Puls auf).
    Da ich nach ner halben Stunde rumsuchen nicht die benötigten URLs gefunden hatte um näher zu reversen woher die ganzen
    Daten kamen, entschied ich mich zu drastischeren Mitteln ...

    Und diese lauten.. Javascript Funktions Hooks.
    Wem dieser Begriff nichts sagt -> Ein Javascript Funktion Hook bedeutet, das wir eine bereits existierende Funktion durch unsere eigene ersetzen.
    Dadurch erlangen wir kompletten Zugriff auf die jeweilige Funktion (und der Daten die an sie übergeben werden).
    Doch welche Funktion könnten wir denn Hooken um bei unserem Reversing weiter zu kommen?

    Nun - was möchten wir denn erreichen? Grundsätzlich gesehen möchten wir einen Link rausfinden, unter dem wir dann
    unsere Daten abrufen können. Dieser Link muss existieren da sonst unser Browser die Daten die er zum Rendern der Graphen
    und Daten nicht abrufen könnte. Wenn wir diesen Link also finden, haben wir die Daten in unseren Händen - und das ganz ohne für Premium zu blechen.

    Bevor wir nun jedoch weiter machen, muss ich kurz einige Grundlagen für Webanwendungen erklären damit ihr meine Gedankengänge besser nachvollziehen könnt.
    Also - wenn man in einer Webanwendungen mit einem Server kommunizieren möchte, geht dies über 2-3 verschiedene Arten.
    Die eine nennt sich Ajax, die andere Websockets. Websockets besitzen ähnlichkeiten mit Winsockets und Sockets im allgemeinen.
    Man kann Verbindungen öffnen, Daten senden und natürlich auch empfangen. Websockets werden meistens eher von Multiplayer Spielen wie Agar.io benutzt.
    Ajax ist eher dafür geeignet Daten von einer URL abzurufen (meist formatiert in JSON oder XML Format).
    Ajax bietet genauso wie Websockets eine Möglichkeit eine Verbindung zu öffnen und Daten zu senden und zu empfangen.
    Im Quellcode von Fitbit sah ich das Fitbit für die Kommunikation mit ihren Server Ajax (XMLHttpRequest) verwendet - und genau hier wollte ich ansetzen.
    Ich habe die jeweiligen API Urls nicht im Quellcode gefunden, also entschied ich mich die

    Code:
    XMLHttpRequest.prototype.open
    Funktion von Ajax zu hooken.

    Zunächst - weshalb gerade diese Funktion und keine andere?
    Nun, diese Funktion ist für einen Verbindungsaufbau da - mit dieser Funktion stellt man die Verbindung mit einem Server her.
    Die Funktion ist folgendermaßen aufgebaut:


    Code:
    void open(
       DOMString method,
       DOMString url,
       optional boolean async,
       optional DOMString user,
       optional DOMString password
    );
    Wir sehen hier das unteranderem die Request Methode, die jeweilige URL und 3 weitere Variablen die für diesen Fall unwichtig sind an diese
    Funktion übergeben werden. Möchte also jemand über Ajax eine Verbindung aufbauen, muss er diese Funktion mit den entsprechenden Parametern
    wie beispielweise der URL aufrufen. Wir sehen hier also - Fitbit muss diese Funktion aufrufen um eine Verbindung mit ihren Servern aufzunehmen
    um an meine Daten zu kommen. Ergo.. hooken wir diese Funktion, kommen wir auch gleichzeitig an die URL die wir soooo sehnlichst wollen!

    Wie das Hooking dieser Funktion nun im Detail funktioniert, werde ich hier in diesem Thread jedoch NICHT erwähnen da ich hierzu schon
    eine HowTo verfasst habe in dem ich dies schildere. Falls ihr mehr dazu lesen wollt, empfehle ich euch mein HowTo

    https://free-hack.com/showthread.php...-Hooking-HowTo

    So.. verfassen wir nun mal unseren Hooking Javascript Code um die Funktion zu hooken:

    Code:
    var xml_open = XMLHttpRequest.prototype.open; //Alte Funktion zwischenspeichern
    XMLHttpRequest.prototype.open = function(method, url, async, user, password) //Funktion Hooken
    {
     console.log(method+": "+url+" (async: "+async); //Daten in Webconsole ausgeben
     xml_open(method, url, async, user, password); //Zwischengespeicherte Funktion abrufen damit die Serverkommunikation funzt
    }
    Kurzgesagt tut der obige Code folgendes:

    1) Wir kopieren die Funktion die wir hooken wollen und geben der Kopie den Namen "xml_open" (xml_open(method,url,async,user,password))

    2) Wir Hooken die Funktion die wir benötigen und Manipulieren sie.
    Die Manipulation besteht darin, das die Funktion nun alle Parameter die an sie übergeben werden in unserer Webconsole ausgeben.

    3) Nun rufen wir die im 1. Schritt kopierte Funktion mit den entsprechenden Parametern auf damit die Serverkommunikation
    trotz unserer Manipulation weiterhin funktioniert (und der Browser an seine Daten kommt ).

    Dieses Script packe ich nun in ein Greasyemonkey Script für Firefox und rufe Fitbit.com (natürlich eingeloggt) auf.
    Nun.. schauen wir mal in die Webconsole!



    Wir sehen hier nun eine vielzahl von URLs über die jeweils eine Kommunikation stattfand.
    Hier sticht mir direkt folgende URL ins Auge:

    Code:
    https://web-api.fitbit.com/1/user/*ZENSIERT*/activities/heart/date/2016-10-13/2016-10-06.json
    Rufen wir diese Url auf, sehen wir folgende Meldung:

    Code:
    {"errors":[{"errorType":"invalid_client","message":"Invalid authorization header format. Visit https://dev.fitbit.com/docs/oauth2 for more information on the Fitbit Web API authorization process."}],"success":false}
    Dang it! Was tun wir jetzt? Eine Fehlermeldung..hmm!
    errorType: invalid_client? Soso.. falscher Client also!
    Schauen wir doch mal den Request genauer an der von Fitbit gemacht wird - hier wird sehr wahrscheinlich
    über die GET Parameter etwas mitgeschickt das dem Server sagt was für ein Client unsere Daten abrufen möchte.
    Diese Daten müssen wir nun ebenfalls in unserem Request senden (ein einfaches aufrufen der URL im Browser genügt hier nicht mehr).

    Tamper Data zeigte mir bei einer näheren Analyse, das bei jedem Request 3 Parameter mitgeschickt werden.
    Der 1. Parameter ist zur Authentifizierung des Requests (das selbe wie die öffentliche API),
    die anderen 2 um den Referrer und die Origin anzugeben.

    Um nun einen Request an den Server zu machen, müssen wir zunächst einmal ein bisschen Javascript Code
    aufschreiben - denn ein einfacher Aufruf der URL reicht hier nicht aus.

    Code:
    var s = new XMLHttpRequest();
    s.open("GET","https://api.fitbit.com/1/user/-/activities/heart/date/2016-10-13/1d/1sec.json");
    s.setRequestHeader("Authorization","Bearer *ZENSIERT*");
    s.setRequestHeader("Referer","https://www.fitbit.com/");
    s.setRequestHeader("Origin","https://www.fitbit.com/");
    s.send();
    setTimeout(function(){console.log(s.responseText);},1000);
    Was macht dieser Code? Nun - im Prinzip ist dieser Code enorm simpel.
    Mal der Ablauf was hier im Code passiert:

    1) Wir erstellen unseren eigenen XMLHttpRequest und stellen ein das wir gerne unseren Request an die URL https://api.fitbit.com/1/user/-/acti...3/1d/1sec.json schicken möchten
    Diese URL ist quasi die URL, an der wir meine Herzschlag Daten von Heute (13.10.2016) in einer Auflösung von 1 Sekunde pro Datenpunkt abrufen können.

    2) Nun bauen wir unseren eigenen Header zusammen, dort geben wir unseren Authentifizierungs Code ein und den Referrer und die Origin.
    Dies ist dazu da um sich zu Authentifizieren & damit der Server weiß das wir berechtigt dazu sind die Daten abzurufen.
    Den Auth Code habe ich jeweils mit Tamper Data mitgeschnitten (Theoretisch hätte ich auch über das DEV Programm von Fitbit nen API Acces beantragen können).

    3) Nun senden wir den Request an den Server

    4) Nach 1 Sekunde lesen wir nun die Antwort des Servers aus. Wieso 1 Sekunde? Nunja.. der Server braucht einige ms bis er Antwortet.. und deshalb warten
    wir 1 Sekunde bevor wir versuchen die Variable auszulesen in der dann die Antwort des Servers steht (s.responseText).
    Würden wir keine Sekunde warten, wäre diese Variable leer da wir noch garkeine Antwort erhalten hätten wenn versucht
    wird die Variable auszulesen.

    Nun fragt ihr euch vielleicht wo ich diese URL im obigen Code habe.. die ist ja nicht im Bild von vorhin zu sehen.
    Die Antwort ist einfach.. aus der API Dokumentation von Fitbit die unter https://dev.fitbit.com/docs/heart-rate/ zu finden ist^-^*
    Dabei fand ich übrigens auch raus, das man mittlerweile scheinbar für Persönlichen Gebrauch über die API die jeweiligen Daten nutzen darf.
    Das heißt im Grunde genommen das ich mir ziemlich umsonst die Mühe gemacht habe die API ein bisschen zu reversen und ich einfach
    die normale API Schnittstelle nutzen hätte können. Das gute daran? Ich habe etwas Produktives getan & brauchte auf diesem Wege
    kein eigenen API Zugriff bei Fitbit beantragen.. ich nutze für den Zugriff auf die API einfach den API Key der auch vom Browser benutzt wird.
    Das ganze ist nun nicht ideal, aber angenehmer als durch den Prozess der beantragung eines API Schlüssels gehen zu müssen usw.

    Nun.. in s.responseText steht nun die Antwort des Fitbits Servers an uns.. und diese Antwort ist JSON Formatiert und enthält meine gewollten
    Daten (Herzschlag für Heute). Theoretisch könnte man nun sich in Javascript ein Tool schreiben was die Daten von einem beliebigen Zeitabschnitt
    abfrägt und exportiert. So könnte man dann Analysen über sein Schlafverhalten, Gesundheit und weiteres erledigen.
    Die API Schnittstelle von Fitbit bietet noch viele mehr Datenpunkte die man anfragen kann - beispielweise Schlafqualität, gelaufene Schritte etc.

    Kurzfassung: Nun steht uns die Welt offen.. auch wenn wir es uns hier ein bisschen komplizierter gemacht haben als es nötig gewesen wäre.
    Dadurch haben wir immerhin ein BISSCHEN produktives getan & ein bisschen mehr gelernt. Und das wichtigste daran?
    Ich konnte nochmals zeigen wie ich in etwa beim Reversen von Web Anwendungen vorgehe, was meine Schritte sind und wie sowas im Groben funktionieren kann.

    Bei Fragen oder Anregungen stehe ich gerne zur Verfügung^-^*

    grüße, Cy
    Geändert von Cystasy (13.10.2016 um 13:16 Uhr)

  2. Folgende Benutzer haben sich für diesen Beitrag bedankt:

    Alucart (14.10.2016), Dailox (13.10.2016), gORDon_vdLg (13.10.2016), sn0w (13.10.2016), zzurc (13.10.2016)

Ähnliche Themen

  1. Reverse Engineering
    Von boris14 im Forum Mobile Devices
    Antworten: 2
    Letzter Beitrag: 08.11.2007, 22:21
  2. reverse engineering
    Von errox im Forum C, C++
    Antworten: 7
    Letzter Beitrag: 14.08.2007, 20:03

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •