Wie man die TMP Ramdisk entfernt

Auf normalen Desktopsystemen ist es eine gute Sache, wenn der /tmp/ Ordner im RAM liegt. Auf /tmp/ wird sehr häufig und meistens eher kleinteilig zugegriffen, so das man diese Zugriffe  am besten von der Festplatte oder der SSD fern hält. Auf einem Server kann das aber auch von Nachteil sein.

[root@server ~]# df -h
Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
devtmpfs        5,0G       0  5,0G    0% /dev
tmpfs           5,0G       0  5,0G    0% /dev/shm
tmpfs           5,0G    532K  5,0G    1% /run
tmpfs           5,0G       0  5,0G    0% /sys/fs/cgroup
/dev/xvda1      245G    178G   56G   77% /
tmpfs           5,0G     38M  5,0G    1% /tmp
tmpfs          1012M       0 1012M    0% /run/user/0

Im obigen Beispiel von einem unserer Server, kann man sehen, daß für die „tmpfs“ Laufwerke 5 GB maximale Größe angegeben ist. DEV, RUN, SYS werden das niemals erreichen, die sind eher im KB Bereich angesiedelt. Über die Sinnhaftigkeit, dann 5 GB als MAX Größe zu nehmen, kann man sicher streiten. Ist aber für die Betrachtung egal, denn es handelt sich um eine dynamische Speicherbelegung, deswegen auch „maximale Größe“. In Real sind die genau so groß, wie die Daten darin das brauchen. Lege ich dort 1 MB ab, ist es 1 MB und ein bisschen was für die Verwaltung groß.

An der „Verwendung“ in Prozent bzw. „Benutzt“ kann man auch sehen, das oben keins der TmpFS Ramdrives übermäßig belegt war. Die Ramdrives haben also bei dem Stand zusammen grade mal 39 MB echten Speicher belegt.

So weit, so gut.

Das obige Serversystem hat 10 GB Speicher zur Verfügung, was es üblicherweise auch braucht. d.h. es sind permanent mehrere GB an RAM in realer Benutzung.

Datenbankserver wie MariaDB erlauben es den Benutzern bei Abfragen sogenannte TEMP-Tables zu erstellen. Das wird vorzugsweise im RAM gemacht. Wenn aber das RAM nicht reicht, weil jemand einen TEMP-Table zusammen baut, der mehrere GB groß ist, dann wird das in den /tmp/ Ordner ausgelagert. Und man glaubt gar nicht wie unsensible mache Anwendungsentwickler im Umgang mit solchen Temp-Tables sind. „Killer SQL-Anweisungen“ in Shops, die „ein bisschen mehr und schneller“  gewachsen sind, als die Hersteller das erwartet haben, sind keine Seltenheit. Schlechtes Datenbankdesign sowieso nicht 😉  Und damit fängt der Ärger dann üblicherweise auch an.

Was bei einem Killer-SQL passieren kann …

Der Hauptspeicher des Datenbankserver hatte schon nicht ausgereicht um den Temp-Table anzulegen, und über die Ramdisk wird jetzt versucht den Speicher zusätzlich nochmal zu belegen, der vorher schon nicht ausreichend da war. Der Kernel wird jetzt versuchen diese Datenmengen zu swappen und kann das vielleicht nicht, weil die SWAP Partition zu klein ist. Nun kommt es zum „OOM“ dem Out-of-Memory-Error. d.h. der Kernel fängt an, scheinbar wahllos Prozesse zu killen, die viel Speicher belegen, aber noch nicht lange laufen. Eine genauere Analyse nimmt der Kernel leider nicht vor.

Wie kommt man jetzt aus der Falle wieder raus ?

Verantwortlich für das Erzeugen der Ramdisk ist diese Systemd Unit : /usr/lib/systemd/system/tmp.mount

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Temporary Directory
Documentation=man:hier(7)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
ConditionPathIsSymbolicLink=!/tmp
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target

[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime

Die kann man mit einem kurzen Befehl an den Systemd abschalten, allerdings erst ab dem nächsten Bootvorgang:

# systemctl mask tmp.mount
Created symlink from /etc/systemd/system/tmp.mount to /dev/null.
# ls -la /etc/systemd/system/tmp.mount
lrwxrwxrwx 1 root root 9 14. Nov 11:45 /etc/systemd/system/tmp.mount -> /dev/null

Danach muß man das also Rebooten. Am Ende ist /tmp/ dann wieder ein normaler Ordner auf der Festplatte, der keiner Größenbeschränkung unterliegt und in dem der Datenbankserver dann auch wieder fast beliebig große Temp-Tables erzeugen kann, ohne das gleich ein unschuldiger Prozess dran glauben muß.

 

Designfehler in TCP RFC

Moin,

wer gestern und heute die News gelesen hat, der wird über den Beitrag zum TCP Fehler in Linuxkernel gestolpert sein.

Was ist passiert ?

Einigen findigen Forschern/Hackern ist es gelungen, einen Designfehler in einem per RFC vorgegebenen Standard zu finden. Damit ist es möglich eine TCP Verbinden zu beeinflussen z.b. Sie von extern zu beenden oder Daten einzuschleusen. Wählt der Angreifer das Paket günstig aus, kann er z.b. Schadcode in eine Webseite einschleusen auf dem Web von Server zum Betrachter. Er kann auch herausbekommen, ob Server A mit einer xbeliebigen anderen IP Adresse grade eine Kommunikation hat.  Was aber nicht geht ist, herauszubekommen, mit wem ein an der Verbindung beteiligter spricht, wenn man nicht genau auch der IP sucht. Mit anderen Worten, man müßte sehr viele Kombinationen durchprobieren, und zwar genau während eine Verbindung besteht.

Möglich wird das über einen festen globalen Zähler, der es durch geschicktes Ausnutzen von Datenpaketen und deren Antworten erlaubt, vorherzusehen, wie die nächste gültige Sequenznummer in einem TCP Paket aussehen wird, so daß man als Angreifer genau diese Sequenznummer benutzen kann.

Die Bewertung

Gerade bei Webseiten werden die TCP Verbindungen aber i.d.R. sehr schnell wieder geschlossen, so daß der Angreifer schon verdammt viel Glück haben muß. Interessanter sind Angriffe schon auf Downloadportale, wo die Verbindungen auch mal eine Stunde vorhanden sind, weil GBweise Daten transportiert werden. Allerdings dabei einen funktionierenden INJECT hinzubekommen, in eine unbekanntfortgeschrittene Datenübertragung, wäre praktisch unmöglich.

Der Angriffsvektor ist zwar heftig, aber muß schon genau wissen wen man angreifen will. Zufällige Besuche von IP A auf Server B beim Surfen sind also extrem unwahrscheinlich als Ziel.

Zudem kommt ein Laufzeitproblem im Netz dazu, so daß man selbst als Angreifer in der Nähe des Ziels  sein müßte, da mit jedem HOP im Netz, die Laufzeitschwankung größer wird und man ungenauere Werte ermittelt. Je ungenauer der Wert den man als Angreifer für die nächsten Sequenznummer ermittelt, desto niedriger die Erfolgsrate.

Gegenmaßnahnen

Serveranbieter, die Linux einsetzen, können jetzt einfach den globalen counter individuell hochsetzen, so daß ScriptKids, die Tools zum Injecten einsetzen werden, eine schlechte Ausgangsbasis haben. Und das geht so :

Fedora/RedHat/CentOS:

  1. echo “net.ipv4.tcp_challenge_ack_limit = 999999999”  > /etc/sysctl.d/1-tcp-challenge-ack.conf
  2.  “sysctl -p” zum Updaten der Konfiguration eingeben.

Ubuntu/Debian/Mint:

  1. Open /etc/sysctl.conf, append a command “net.ipv4.tcp_challenge_ack_limit = 999999999”.
  2. Use “sysctl -p” to update the configuration.

Ich für meinen Teil würde empfehlen, den Wert nicht auf 99999999 zusetzen, sondern den Wert per $Random zu setzen. Das verwirrt die Angreifer noch viel mehr. Und per Cronjob einmal die Minute den Randomwert ändern 😀 Dann hat man schon genau das, was den Kernelpatch später auch ausmachen wird 😀