Linux /tmp read-only nachträglich für Arme – ohne getrenntes Dateisystem

Temporär-Verzeichnisse wie /tmp oder /var/tmp auf Linux Rechnern read-only zu haben, kann einen vor den Folgen des einen oder anderen -meist automatischen- “Skriptkiddie” Angriffs schützen.

Im Rahmen einiger dieser Angriffe werden in einem für jedermann beschreibbaren Verzeichnis -also meist /tmp- ein Skript abgelegt, dass von dort ausgeführt wird, um weiteren Schaden zu verursachen.

Wenn dieses Verzeichnis nun mit der Option “noexec” gemounted ist, ist das Ausführen von Dateien dirkt aus dem Verzeichnis immerhin schwieriger. Unmöglich ist es jedoch nicht: Man könnte immer noch den notwendigen Befehlsinterpreter starten und das Skript als Parameter übergeben. Aber es geht hier einfach nur um eine weiter Hürde, die es für wenig Aufwand gibt und um automatische Angriffe, die ohne viel manuellen Zutun von nicht höchst fachlich fähigen Leuten ausgeführt werden.

Gut, ein Dateisystem kann man mit dem Parameter “-o noexec” mounten. – Was aber, wenn nun kein getrenntes Dateisystem für /tmp (und /var/tmp) bereit steht?

Hier lässt sich die Option “mount –bind” nutzen, um ein Verzeichnis in ein anderes zu mounten.

Vorbereitung. Kopien der Verzeichnisse /tmp und /var/tmp anfertigen. z.B. so:

cp -a /tmp /tmp-real
cp -a /var/temp /var/tmp-real

Dann lassen sich die “tmp-real” Verzeichnisse auf die “tmp” Verzeichnisse mounten:

mount -v --bind /tmp-real /tmp
mount -v -o remount,noexec,nosuid /tmp

Probe aufs Exempel:

$ ls -l /tmp
total 4
-rwxrwxr-x 1 testuser user 28 May 7 22:14 test.sh
$ cat /tmp/test.sh 
#! /bin/sh

echo Jaaaaaaaa

$ /tmp/test.sh
bash: /tmp/test.sh: Permission denied

Auch als root läßt es sich nicht ausführen:

~ # id
uid=0(root) gid=0(root) groups=0(root)
~ # /tmp/test.sh
-su: /tmp/test.sh: Permission denied

Jetzt noch alles zusammen: Ein Skript, um die Verzeichnisse read-only zu mounten:

~/bin # cat mount_tmp_noexec.sh
#!/bin/sh

echo noexec  to /tmp
mount -v --bind /tmp-real /tmp && mount -v -o remount,noexec,nosuid /tmp

echo
echo noexec to /var/tmp
mount -v --bind /var/tmp-real /var/tmp && mount -v -o remount,noexec,nosuid /var/tmp

echo 
echo Now mounted:
mount

…und eines das Ganze wieder rückgängig zu machen:

~/bin # cat mount_tmp_exec.sh 
#!/bin/sh

echo Umounting /tmp from noexec
# mount --bind /tmp-real /tmp && mount -o remount,exec,suid /tmp
umount /tmp

echo
echo Umounting /var/tmp from noexec
# mount --bind /var/tmp-real /var/tmp && mount -o remount,exec,suid /var/tmp
umount /var/tmp

echo 
echo Now mounted:
mount

Für das Einspielen von Paketen ist es zu empfehlen /tmp wieder read-write zu haben, da auch die Pakete vielfach Skripte zur Pre- oder Post-Installation dort ablegen und ausführen.

Beim Umounten kann es zu Problemen kommen, wenn Prozesse noch Dateien in dem Verzeichniss geöffnet lassen. Hier mit “lsof” o.ä. nachforschen.