Simon Szustkowski

Ein Blog über alles, was mir gerade so durch den Kopf geht

Aug 29, 2017

Amazon Dash Button Hacken - ohne ARP und UDP, aber mit OpenWRT und dnsmasq

Seit Amazon seine Dash Buttons vertreibt, gibt es Versuche, diese irgendwie zu hacken. Ein kleiner Button mit WLAN dran ist ja auch irgendwie praktisch.

Da die Dinger aber eine verschlüsselte Firmware haben, ist es nicht möglich, sie irgendwie neu zu flashen, daher muss man irgendwie kunstvoll abfragen, ob sie gedrückt wurden, und zusätzlich vermeiden, dass sie wirklich eine Bestellung bei Amazon auslösen. Die meisten Anleitungen hierzu arbeiten nach dem Prinzip, dass man dem Button auf gar keinen Fall irgendeinem Produkt zuordnen solle, und begnügen sich dann damit, per ARP oder UDP den DHCP-Request des Buttons, den er nach jedem Wakeup bei Aktivierung absendet, mitzusniffen, um darauf basierend eine Aktion auszuführen.

Das kann man schon so machen, hat aber einige Nachteile: Zum einen bekommt man dann immer von der Amazon-App auf seinem Handy eine Mitteilung, dass man doch bitte endlich mal dem Button ein Produkt zuweisen solle, zum zweiten erfordert dies eine weitere Software, die irgendwo mitlauscht, ob der Button gerade ein DHCPDISCOVER absendet, und zum dritten funktioniert dies schon gar nicht subnetübergreifend - wenn man also ein eigenes Subnet für Internet of Things angelegt hat, und da halt nicht zufällig noch einen Raspberry Pi drin hat, der auf DHCP-Traffic lauscht, hat man erstmal Pech gehabt. Dazu kommt noch, dass die meisten Tools, die für dieses Szenario geschrieben wurden, auf node.js basieren, und daher etwas fummelig zu administrieren sind, aber das ist Ansichtssache.

Ich stand vor dem gleichen Problem. Ich habe mein Netzwerk ebenfalls segmentiert, zum einen in ein VLAN für IoT-Geräte, zum anderen in ein VLAN für “echte” Computer. Mein Homeserver und der Dash Button sind also in verschiedenen Netzsegmenten, und daher klappt das nicht so gut mit dem DHCPDISCOVER-mitsniffen. Daher habe ich hier eine Lösung erarbeitet, die weitaus eleganter funktioniert. Man benötigt hier lediglich eine ordentliche Firewall (OpenWRT oder pfSense, ich habe es mit OpenWRT Chaos Calmer gemacht), sowie dnsmasq als DHCP-Server.

  1. dnsmasq hat eine dhcp-script-Option, mit der man ein Script übergeben kann, was immer dann ausgeführt wird, sobald dnsmasq eine IP via DHCP vergibt. Für OpenWRT legen wir dazu eine Datei namens /etc/dnsmasq.conf an (diese Option kann man nicht mittels UCI vergeben, andere Linuxsysteme mit dnsmasq haben diese Datei schon), und schreiben dort die Option hinein, z.B. dhcp-script=/root/dhcp-script.sh

  2. Nun muss man dieses dhcp-script natürlich auch noch anlegen. Ein Beispielinhalt sieht z.B. folgendermaßen aus:

      #!/bin/bash                                                 
    
      ACTION=$1                                                  
      MAC=$2                                                     
      IP=$3                                                      
      
      logger dhcpLog "New DHCP Request by $MAC: $IP"  
      
    Hier ist dann auch direkt sichtbar, welche Argumente dnsmasq diesem Script in welcher Reihenfolge mitgibt. Für OpenWRT muss man natürlich den Interpreter auf /bin/ash ändern, da OpenWRT keine Bash mitbekommt - auch ist das logger-Tool nur auf OpenWRT vorhanden. Aber anstatt einfach nur eine Zeile in ein Logfile zu schreiben kann man hier beispielsweise mit curl irgendeine API kontaktieren, etc. Hier passiert die eigentliche Action.

  3. Trotz alledem bekommt man weiterhin von seiner Amazon-App die Meldungen, dass noch kein Produkt mit dem Dash Button verknüpft wurde. Das nervt natürlich. Einfach den Traffic zu Amazon verbieten ist aber auch keine gute Idee, da der Dash Button dann bis zu 30 Sekunden lang versucht, die Bestellung abzuschicken, und während dieser Zeit nicht einsatzbereit ist. Besser ist es also, seine Anfragen auf einen anderen Webserver umzuleiten, der ihm mit einem Serverfehler antwortet. Hierdurch lässt sich die durchschnittliche Zeit, die der Dash Button aktiv ist, von 30 auf ca. 7 Sekunden reduzieren. Zuallererst leiten wir alle DNS-Abfragen auf unseren eigenen dnsmasq um. Ob das nötig ist, ist fraglich, aber es schadet bestimmt nicht, um ggf. hardcoded DNS-Server in den ganzen IoT-Devices außer Kraft zu setzen. Für OpenWRT tragen wir dazu folgendes in der /etc/config/firewall ein:1

      config redirect
              option name 'Override hardcoded DNS servers in IoT devices'
              option src 'iot'
              option proto 'tcpudp'
              option src_dport '53'
              option dest_ip '192.168.12.1'
              option dest_port '53'
      
    Nun wird jeglicher DNS-Traffic, der aus dem IoT-Netz entspringt, auf Port 53 des Routers umgebogen, wo er von einem DNS-Server unter unserer Kontrolle beantwortet wird.

  4. Das gleiche kann man auch noch mit NTP-Traffic machen. Ich glaube nicht, dass der Dash Button überhaupt NTP betreibt, aber es wurde in einem anderen Tutorial empfohlen, und es schadet bestimmt nicht.

      config redirect
              option name 'Override hardcoded NTP servers in IoT devices'
              option src 'iot'
              option proto 'tcpudp'
              option src_dport '123'
              option dest_ip '192.168.12.1'
              option dest_port '123'
      

  5. So, und last but not least: Der eigentliche HTTPS-Traffic muss umgeleitet werden. Damit andere IoT-Devices, die gewünschte HTTPS-Requests ins Internet senden, nicht auch davon gestört werden, weisen wir dem Dash Button dafür vorher eine feste DHCP-Lease zu, damit er immer dieselbe IP bekommt, in unserem Fall die 192.168.12.7. Der Traffic wird auf eine IP und einen Port umgeleitet, hinter dem dann auch tatsächlich ein Webserver lauschen muss, der HTTPS sprechen kann. In meinem Fall ist das einfach der Homeserver, der auf der 192.168.10.4 einen tatsächlichen Produktivserver laufen hat. Falls man so etwas nicht hat, habe ich ein kleines Tool geschrieben, was sich wahlweise mit oder ohne TLS an einen Port bindet, und auf jede beliebige Anfrage einfach nur “OK” antwortet, mit dem HTTP Statuscode 200. Der Statuscode ist hierbei nicht wichtig, auch nicht, ob das Zertifikat echt ist, es geht nur darum, dass der Dash Button eine HTTPS-Verbindung aufbauen kann, und eine Antwort bekommt. Die entsprechende Firewall-Regel für OpenWRT sieht so aus:

      config redirect
              option name 'Redirect HTTPS for Dash Button'
              option src 'iot'
              option proto 'tcpudp'
              option src_ip '192.168.12.7'
              option src_dport '443'
              option dest 'home'
              option dest_ip '192.168.10.4'
              option dest_port '443'
      
    Ihr müsst hier natürlich das Optionsfeld src_ip auf die quasi-feste IP eures Dash Buttons ändern, sowie dest_ip und dest_port auf die IP und den Port eures Fake-Webservers anpassen. Die Werte src und dest entsprechen den Zonen meiner Firewall, in der sich die beiden Geräte befinden, ändert sie auf die Namen eurer Firewall-Zonen. Es ist okay, wenn beide Geräte in der gleichen Zone liegen.

Das Resultat ist, dass bei einem Knopfdruck der Dash Button aufwacht, versucht Amazon zu kontaktieren (dessen LED blinkt solange smooth weiß), der Traffic dann aber umgebogen wird, der Fake-Webserver den Request beantwortet (in einem Format, was dem Dash Button einen Fehler suggeriert), der Dash Button dies visuell mit drei hektischen roten Blink-Sequenzen darstellt, und der Button sich danach wieder schlafen legt. Während des ganzen Vorgangs hat der DHCP-Server parallel schon das dhcp-script aufgerufen, hier müsst ihr nur noch eine Abfrage auf die MAC-Adresse des Dash Buttons (oder dessen fest zugeordnete IP) eintragen, da dieses Script bei jedem DHCP-Lease getriggert wird. Wer mag, kann hier also auch eine Logik einbauen, die beispielsweise zündet, wenn der Laptop angeschaltet wird, oder ähnliches.

Mit etwas Aufwand und Firewall-Jonglage lässt sich also das gleiche Resultat wie mit dem DHCP-Sniffing erzielen, ohne dass man hierzu weitere Software installieren muss, oder seine Firewall-Regeln unnötig weit aufbohren muss. Aber viele andere Blogs tippen halt auch nur größtenteils voneinander ab, und ergänzen sich.

Für die “herkömmliche” Methode mit dem Sniffen des DHCP-Requests empfiehlt es sich, einmal das hier anzusehen. Eine andere Lösung, die auch mit einem gefaketen HTTP-Server arbeitet, aber nicht mit dem dhcp-script, sondern den Request per Firewall-Regeln in einen Log-Daemon rein schreibt, findet sich hier.

Wählt einfach die Lösung, die euch am komfortabelsten vorkommt. Funktionieren tun sie alle.