Von Arne
In diesem Artikel werde ich beschreiben, wie man einen Unreal Tournament Dedicated Server unter Linux in einem Chroot-Gefängnis ausführt. Wie sich gezeigt hat funktioniert das selbe Vorgehen auch mit dem UT2004 Server.
Chroot steht für change root. Mit root ist hiermit gemeint welchen Teil des Dateisystems ein Prozess als Wurzel ( / ) sieht. Normalerweise sieht jeder Prozess als root die Wurzel des Dateisystems. Wird nun eine Sicherheitslücke in einem Programm entdeckt und ein Hacker kann diese aussuchen so hat er im schlimmsten Fall zugriff auf das gesammte Dateisystem des betroffenen Rechners. Hier kommt nun das Tool chroot ins Spiel. Mit chroot wird es möglich einem Prozess nur einen Teil des Dateisystems sehen zu lassen. Somit könnte dieser Prozess dann im schlimmsten Fall auch nur Daten aus diesem Bereich des Dateisystems lesen.
Betrachten wir einen Teil eines Dateisystems aus der Sicht der Tatsächlichen Verzeichniswurzel:
/ /bin /boot /dev /etc /home /lib /mnt /proc /root /sbin /tmp /usr `--local .....`--gameserver ..........`--ut2003 /var
Damit ein Prozess in einer Chroot-Umgebung laufen kann müssen einige Voraussetzungen erfüllt sein. Da das Programm in der Chroot-Umgebung keinen Zugriff mehr auf Daten hat, die außerhalb liegen müssen Kopien dieser Dateien im Chroot-Gefängnis vorhanden sein, und zwar in einer Verzeichnis-Hierachie in der sie das Programm vermuten würde, wenn es ohne chroot ausgeführt werden würde.
Ein Beispiel für eine Datei die sehr häufig benötigt wird ist das Device /dev/null. In unserem Fall wollen wir den UT2003 Server unter
/usr/local/gameserver/ut2003
chrooten, d.h. oben genannter Pfad wird zum / des Prozesses. Damit der Server das /dev/null findet müssen wir es an folgender Stelle anlegen:
/usr/local/gameserver/ut2003/dev/null
Zuerst legen wir den Ordner "dev" an, danach erstellen wir das null-device:
# cd ./dev && mknod ./null c 1 3
# chmod 0666 ./null
Die Server-Binary braucht noch eine Reihe von Bibliotheken, die zur Laufzeit geladen werden. Eine Großzahl davon bringt der Server schon mit, sie befinden sich im "/System" Verzeichnis, unter anderem z.B. Engine.so (Man erkennt die Bibliotheken an der Dateiendumg .so). Außerdem kann man mit strace noch herausfinden welche Systembibliotheken gebraucht werden. Und der "Loader" für das Laden der Bibliotheken wird benötigt.
Wir legen zunächst ein "lib" Verzeichnis an:
# mkdir /usr/local/gameserver/ut2003/lib
ld-linux.so.2 libc.so.6 libdl.so.2 libm.so.6 libnsl.so.1 libpthread.so.0 libresolv.so.2 libnss_dns.so.2 libnss_files.so.2
Da einige Bibliotheken auf bestimmte Dateien in /etc zugreifen, kann es Vorteile haben, wenn diese Dateien auch vorhanden sind. Nicht dass es nicht auch ohne diese Dateien ginge, aber z.B. die korrekte Zeitzone oder ein paar Informationen zum DNS-Setup des Rechners können hilfreich sein.
Wir legen uns also folgenden Ordner an: /usr/local/gameserver/ut2003/etc:
# mkdir /usr/local/gameserver/ut2003/etc
etc/localtime etc/resolv.conf etc/nsswitch.conf etc/hosts etc/protocols etc/services
Nornalerweise wird der UT2003-Dedicated Server über das Script ucc gestartet, dies fehlt zwar in der 2225er Version, funktioniert aber trozdem noch. Das Script bereitet ein paar Einstellungen für die dynamischen Bibliotheken vor und reicht ansonsten die Optionen für den Server einfach weiter und startet danach die ucc-bin Binary im System-Verzeichnis.
Wollen wir dieses Script im chroot benutzen, dann benötigen wir eine bash-shell um das Script auszuführen, das ist aber eine Sicherheitslücke, da wir einem Angreifer der den UT2003 Server kompromittiert keine Shell zur verfügung stellen wollen, also können wir das Script nicht benutzen.
Schwierig wird es beim Starten der ucc-bin Binary, diese erwartet es im System-Verzeichnis gestartet zu werden und nicht aus dem übergeordneten Verzeichnis, also habe ich ein kleines C-Program ( utwrapper ) geschrieben, welches erst das Verzeichnis wechselt (nach /System) und danach ucc-bin startet. Argumente werden einfach an die ucc-binary durchgereicht um kompatibel mit dem ucc-script zu bleiben. Somit gibt es keine Probleme mit den Pfaden zu Bibliotheken.
Der UT2003 Server soll mit möglichts wenig Rechten laufen, also müssen wir einen eigenen User für den Server anlegen. In diesem Fall nennen wir ihn ut und ebenfalls wird die Gruppe ut benötigt.
Zum Starten des Servers im Chroot benutzen wir das Programm chrootuid und zwar sieht der Aufruf zum Starten so aus:
# chrootuid /usr/local/gameserver/ut2003 ut utwrapper <server-options>
Prozesse in einem Chroot-Gefängnis auszuführen macht die Prozesse nicht sicherer, kann aber größeren Schaden verhindern, für den Fall dass das Program eine Sicherheitslücke aufweist. Das ausbrechen aus einem Chroot-Gefängnis ist relativ schwer, solange man keine Root-Rechte hat, deshalb sollten die Prozesse im Chroot nie mit Root-Rechten laufen.
Prozesse in Chroot-Gefängnisse zu sperren sollte nicht als Möglichkeit gesehen werden, auf Updates oder eine sichere und fehlerfreie Konfiguration zu verzichten, es ist eher so dass ein Chroot-Gefängnis eine letzte Abwehrlinie ist, wenn es eigentlich schon zu spät ist. Der Schaden wird begrenzt, aber nicht verhindert.
Ob man den Mehraufwand der Chroot-Konfiguration in kauf nehmen will sollte davon abhängen wie sehr man dem Program vertraut. Wäre man 100% sicher, dass das Programm sicher ist dann könnte man sehr wohl auf das Chroot-Gefängnis verzichten.