FREIHEIT FÜR HASEN

Die Idee

Ich geb ja zu, die initiale Idee stammt nicht von mir, sondern von EpicMonkey. Allerdings ist seine Implementierung bei weitem nicht so elegant wie meine ;) Und da er meinen Löt-Hack geklaut hat (ja, ich war nachweislich der Erste, der ihn veröffentlicht hat), halte ich es für fair, dass ich hier auch auf seiner Arbeit aufsetze. ;-)

Voraussetzungen

Du brauchst nicht viel, um diesem Hack nachzumachen. Du brauchst einen Rechner mit installiertem telnet (alternativ, oder noch besser: putty) einen FAT32 formatierten USB-Stick und natürlich einen Karotz mit Firmware 12.07.19.00 (Stand 10/2014). Wie Du einen Hasen auf Werkseinstellung zurücksetzt und dann bis zur aktuellsten Firmware aktualsierst, habe ich hier beschrieben.

Der Hack

Schritt 1: die Theorie

Der Hack basiert auf einem Fehler im Update-Mechanismus des Karotz. Wenn beim Bootvorgang ein USB-Stick am Hasen angeschlossen ist, so überprüft das Script linuxrc, ob sich auf dem Stick eine Datei namens autorun befindet und ob deren Signatur mit der Signatur in der Datei autorun.sig übereinstimmt. Wenn die Überprüfung positiv war, dann wird das Skript autorun auf dem Stick ausgeführt. Die Gemeinheit dabei (aus unserer Sicht) ist, dass als gültiger öffentlicher Schlüssel nur der Schlüssel der Karotz-Entwickler akzeptiert wird. Sonst hätten wir das Ding ja mal schnell selbst signiert…

# if there is a signed autorun in a usb key, let's run it
# the directory in which the autorun is located
GNUPGHOME=/karotz/etc/gpg
GPG="/bin/gpg -quiet --lock-never --ignore-time-conflict --homedir $GNUPGHOME"
if [ -x /mnt/usbkey/autorun -a -f /mnt/usbkey/autorun.sig ] ; then
   echo "Launching autorun if present"
	$GPG --verify /mnt/usbkey/autorun.sig 2>/dev/null && /mnt/usbkey/autorun
fi

Und hier steckt nun der Fehler im Detail: das Kommando gpg –verify kennt zwei Modi: bei dem einen wird eine Datei daraufhin überprüft, ob die in einer zweiten Datei gespeicherte Signatur zur Datei passt und gültig ist. Das ist das Verhalten, welches die Entwickler des Karotz eigentlich nutzen wollten. Passt die Signatur in der Signaturdatei zur zu überprüfenden Datei, so wird der Returncode 0 ausgegeben.

Der zweite Modus von gpg –verify dient zur Überprüfung signierter Zeichenfolgen. So kann z.B. eine signierte Email ihre eigene Signatur enthalten. Durch Prüfung der Signatur kann dann festgestellt werden, ob die Signatur bzw. die Mail/Zeichenfolge/Datei unverändert und gültig ist. In diesem zweiten Modus steckt also der „Content“ und die Signatur in der gleichen Datei. Hätten wir also solch eine Datei zur Verfügung und würden diese als autorun.sig auf den Stick kopieren, so wäre die Überprüfung positiv (Returncode 0) und das Skript autorun würde ausgeführt - und zwar ohne gültige Signatur. Was wir jetzt noch brauchen ist eine gültige und mit dem Karotz-Schlüssel signierte Zeichenfolge. Und da sind uns die Karotz-Entwickler erfreulicherweise (unbewusst) entgegen gekommen. Befragt man den Webserver nach der aktuellen Firmware-Version so erhält man tatsächlich eine solche, von Mindscape signierte, Zeichenfolge zurück!

Quelle: http://update.karotz.com/eabi/rootfs_version

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

12.07.19.00
http://update.karotz.com/eabi/rootfs/rootfs-12.07.19.00.tar.gz ecc92baed07352d670be4d8c9beeb5d0
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)

iQEcBAEBAgAGBQJQB9NiAAoJEDV3C7tYF9eUXG0H/jkq/UZmSbOClPiRu+XhtTfn
4kR4lRdlEU9CFuiTzkWrrUJ7g/klvyEm8ecAH7UZGkeq/xfhjDeWJZqZnd6SZHyx
By39r54cxIxiI8w3mxdloFF1NwqywvRlx4cExwpi/ku5MpLwy1nXmMTHGSuSezeh
/HTugyPmXuu9Nr/Kjv1YxC8wBU5XalQXl0qptt9JVGXJn+oNi7wNNHay8R0WY2xv
CZRmdCrBtE8+383J7tN6mUzTxYZZsb8tL+OSjLLAICsRLBAUXCS2ZxjnsMOPEvGG
FmKVP6U9FQ4uZqROGGnvFqERD3wBDL6yqlBu3Mmk15bkpkcSelQw/Ei3FJ/mfU0=
=eM43
-----END PGP SIGNATURE-----

Jagt man die obige Zeichenfolge (auf einem bereits gehackten Hasen) durch gpg –verify, so erhält man eine positive Bestätigung und den benötigten Returncode 0. Das funktioniert nur auf einem Hasen, da dort der Public Key der Signatur bekannt ist.

gpg: Signature made Fri 01 Apr 2011 05:08:28 PM MSK using RSA key ID 5817D794
gpg: Good signature from "KarotzDevTeam <admin@mindscape.fr>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: C2A2 8CEE 04C3 4712 F371  6E58 3577 0BBB 5817 D794

Schritt 2: die Praxis bzw. der erste Start mit Stick

Auch wenn der erste Teil ziemlich theoretisch war, ist es bis zum ersten Erfolgserlebnis nicht mehr weit. Nimm einen FAT32-formatierten USB-Stick und speichere die oben gezeigte, signierte Zeichenfolge als autorun.sig im Root des Sticks. Alternativ kannst Du auch eine funktionierende Version weiter unten herunterladen.
Als nächstes musst Du ebenfalls im Root des Sticks die Datei autorun anlegen und mit Leben füllen. Fangen wir mal ein wenig Nasengeblinke und einem coolen Spruch beim Booten an:

#!/bin/bash
export HOME=/tmp


# OPENRABBIT - beeing a little bit funny ;)
# LED rot pulsieren 
/karotz/bin/led -l FF0000 -p 000000 -d 700 &
sleep 3

# Generator: http://www.fromtexttospeech.com/
/usr/bin/madplay /mnt/usbkey/media/iwashacked.mp3

Schalte nun Deinen Hasen aus, stecke den Stick ein und starte den Hasen wieder. Die Nase sollte nach einiger Zeit komisch rot pulsieren und der Hase irgendwann postulieren, er sei gehackt worden. Dann wird er mit seinem ganz normalen Hasenkram weitermachen. Herzlichen Glückwunsch - Du bist (fast) root! Du kannst jetzt noch ein wenig mit den Farben spielen (das Kommando led akzeptiert RGB-Codes in hex. 00FF00 für grün, 0000FF für blau…) und damit sicherstellen, dass Du es warst, der die Nase zum Blinken gebracht hat.

Hier findest Du die drei benötigten Dateien als ZIP-Paket (openrabbit_base.zip) - einfach herunterladen und auf den Stick entpacken.

Schritt 3: Feinschliff

Bisher kann der Hase noch nix neues. Er bootet, führt aber schon mal unser Skript aus. Unser Ziel ist ja aber, eine Konsole bereitzustellen, die wir über telnet erreichen können. Dazu sind noch ein paar Anpassungen am System nötig. Bei meinem Hardware-Hack habe ich mir die Mühe gemacht, die geänderten Dateien in eine Firmware einzuarbeiten und diese dann auf den Hasen zu flashen. Jetzt, wo wir aber einen USB-Stick im Zugriff haben, können wir es uns einfacher machen. Eigentlich wollte ich das gesamte Filesystem des Hasen auf den Stick kopieren und diese Kopie dann während des Bootens transparent über das interne Filesystem drüber mounten. Leider klappt das in der Busybox des Hasen nicht. Was aber sehr wohl funktioniert, ist das Übermounten von einzelnen Dateien mittels mount –bind. Die nachfolgenden Kommandos veranlassen das autorun Skript, die Hasenumgebung nach unserem Gusto umzubauen.

# inittab auf den Stick verlinken
# darin wird eine bash gestartet
mount --bind /mnt/usbkey/root/usr/etc/inittab /usr/etc/inittab

Die beim Hasen verwendete Busybox arbeitet beim Boot u.a. die inittab ab. Dieser inittab habe ich den Start einer bash an der seriellen Konsole hinzugefügt. Das ist nur für die von Euch interessant, die den Hardware Hack durchgeführt und die Serielle Konsole aktiviert haben.

# passwd auf den Stick verlinken
# Benutzer toor/toor wird hinzugefügt
mount --bind /mnt/usbkey/root/usr/etc/passwd /usr/etc/passwd

Da ich das root Passwort des Hasen nicht kenne, habe ich meiner passwd einfach einen neuen Benutzer toor mit dem Passwort toor hinzugefügt. Irgendwie müssen wir uns ja später via telnet auch anmelden ;)

# inetd auf den Stick verlinken
# darin wird telnet gestartet
mount --bind /mnt/usbkey/root/usr/etc/inetd.conf /usr/etc/inetd.conf

Die Entwickler bei Mindscape haben sich einige Mühe gegeben, eventuell gestartete Telnet-Prozesse beim Bootvorgang zu killen. Also starten wir doch einfach telnet nach dem eigentlichen Bootvorgang über den inetd Dämon.

# yaffs_start.sh verlinken, dort wird inetd neu gestartet
mount --bind /mnt/usbkey/root/usr/yaffs_start.sh /usr/yaffs_start.sh

Damit die obige Anpassung greift, muss inetd neu gestartet werden. Das passiert am Ende des Bootvorgangs in der Datei yaffs_start.sh. Und jetzt, wo wir fertig sind und auch eine Internetverbindung nutzen können, lassen wir den Hasen noch seine IP vorlesen ;)

# motd auf den Stick verlinken
# Message of the Day anpassen ;)
mount --bind /mnt/usbkey/root/karotz/motd /karotz/motd

Ganz am Schluß - nachdem das YAFFS gemounted wurde - passen wir noch die message of the day an.

Schritt 4: Feinschliff in den Tiefen des Systems

In den Erläuterungen zum autorun Skript habe ich die Anpassungen im System nur kurz angerissen. Hier folgen nun die Details

/usr/etc/inittab

#OPENRABBIT - added bash for wired serial connection
::askfirst:/bin/bash     

Der inittab wird dadurch ein Kommando zum Starten einer bash hinzugefügt. 'askfirst' führt das Kommando erst nach einem Tastendruck aus - Du benötigst also wie oben beschrieben eine serielle Konsole. Details zur Busybox und der inittab findest Du z.B. hier: understanding busybox inittab

/usr/etc/passwd

toor:$1$7JeaZ8jB$g4grftuQIwXv4xRrbGj75.:0:0:root:/usr/karotz:/bin/bash

Diese Zeile fügt den neuen Benutzer toor/toor hinzu. Wenn Du dir eigene Benutzer anlegen willst, dann google mal nach passwd. Aber vorsicht, diese Datei ist sehr streng mit ihrem Syntax ;)

/usr/etc/inetd.conf

# <service_name> <sock_type> <proto> <flags> <user> <server_path>        <args>
#OPENRABBIT - added telnet
telnet           stream      tcp     nowait  root   /sbin/telnetd        telnetd 

Tja, was soll ich dazu sagen? Selbsterklärend, oder? Nein?! ⇒ the inetd

/usr/yaffs_start.sh

[...]
#OPENRABBIT - Auto-Update disabled                                                          
# [ "$AUTO_UPDATE" = "yes" ] && check_updates        
[...]
# OPENRABBIT - restart inetd with changed config
# at this point, networking should already be working
# "restart" is not implemented, so kill...
killall inetd
# ...and restart inetd
/sbin/inetd

# OPENRABBIT - tell the world that i am free 
mplayer "http://translate.google.com/translate_tts?ie=UTF-8&tl=en&q=i+am+not+a+number+i+am+a+free+rabbit+i+am+a+free+open+rabbit"

# and my IP.. ;)
mplayer "http://translate.google.com/translate_tts?ie=UTF-8&tl=de&q=meine+ei+pie+lautet$( ifconfig | grep wlan0 -A 1 | grep inet | cut -d : -f 2 | cut -f 1 -d " " )" 

# USB-Stick remounten  
# der initiale Mount geht irgendwo beim Booten verloren
mount /dev/uba1 /mnt/usbkey

# Message of the Day anpassen
mount --bind /mnt/usbkey/root/karotz/etc/motd /karotz/etc/motd

yaffs_start.sh bindet das Benutzer-Filesystem des Hasen ein und der Bootvorgang endet anschließend. Damit unsere Anpassungen an der inetd.conf greifen, wird der inetd Dämon gekillt und neu gestartet. Anschließend folgt ein wenig Blahblah und der Hase liest uns seine IP vor. Zu guter letzt wird noch die Nachricht des Tages angepasst :) Außerdem deaktivieren wir noch die automatische Updatefunktion des Hasen, damit Mindscape uns nicht einfach eine neue, sichere Version der Firmware auf den Hasen schiebt.

Schritt 5: Und jetzt?

Tja, jetzt ist Dein Hase gehackt und der telnet Dämon läuft. Jetzt kannst Du dich per Telnet mit Deinem Hasen verbinden! Die IP hat er Dir ja eben laut und (mehr oder weniger deutlich) vorgelesen… ;)

Schritt 6: Dein Hase will auch?

Ich muss Dir an dieser Stelle empfehlen, das hier Aufgezeigte nur als Anreiz, als Idee zum Nachmachen zu sehen. Wenn Du dir die Skripte zeilenweise zu Gemüte führst, dann verstehst Du auch, was hier genau passiert. Wenn Du einfach nur einen gerooteten Hasen haben willst und Dich der eigentlich Hack nicht interessiert, so kannst Du das hier eine vollständige Dateisammlung zum Kopieren auf einen USB-Stick herunterladen: openrabbit_full.zip

Ausblick

Im Moment bastele ich an einem simplen, in Python geschriebenen Webserver, der automatisch beim Booten gestartet wird und (noch nicht näher definierte) Befehle annimmt. Außerdem denkbar wäre ein Paketmanagement nach dem Vorbild von Optware. Schauen wir mal…

Blick über den Tellerrand

Feedback? Feedback!

Über Feedback in jeder Form würde ich mich natürlich freuen. Du kannst mich per Mail [mc @ conzi . com] erreichen, oder mir bei Twitter folgen. Und seit ein paar Minuten hat auch OpenRabbit einen eigenen Twitteraccount ;)