lsof: Unterschied zwischen den Versionen

Aus Mikiwiki
Zur Navigation springen Zur Suche springen
 
(35 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
<b>lsof</b> ("list open files") zeigt dem unprivilegierten Benutzer alle geöffneten Dateien - also sowohl reguläre Dateien wie auch spezielle Blockdateien, ausführbare Programme, Bibliotheken, Verzeichnisse, rechnerinterne Datenströme (Unix Domain Sockets) und Netzwerkverbindungen. Dem Benutzer "root" zeigt lsof dagegen alle geöffneten Verbindungen, Ports und Dateien im Netzwerk.
Der [[Shell-Befehl]] <b>lsof</b> (list open files) zeigt dem unprivilegierten Benutzer alle geöffneten Dateien - also sowohl reguläre Dateien wie auch spezielle Blockdateien, ausführbare Programme, Bibliotheken, Verzeichnisse, rechnerinterne Datenströme (Unix Domain Sockets) und Netzwerkverbindungen. Dem Benutzer "root" zeigt lsof dagegen alle geöffneten Verbindungen, Ports und Dateien im Netzwerk.


Mit Hilfe der Befehle [[fuser]], [[ps]], [[netstat]] und [[top]] können ähnliche Informationen gesammelt werden - allerdings weit weniger bequem.
Mit Hilfe der Befehle [[fuser]], [[ps]], [[netstat]] und [[top]] können ähnliche Informationen gesammelt werden - allerdings weit weniger bequem.


[[Glsof]] und [[JLsof]] sind grafische Oberflächen für lsof.  
[[Glsof]] und [[Jlsof]] sind grafische Oberflächen für lsof.
 
== Funktionsweise ==
 
Im sicheren Modus informiert lsof nur den Benutzer "root" umfassend. Aber auch im unsicheren Modus darf nur der Benutzer "root" auf alle Details im Verzeichnis "/proc" zugreifen.
 
lsof gibt die je nachden verwendeten Optionen gefilterten Informationen der gerade geöffneten Dateien in einem tabellarischen Format aus. Per Vorgabe werden folgende Spalten angezeigt:
 
{| class=wiki
! Spalte !! Beschreibung
|-
| <tt>COMMAND</tt> || Name des Prozesses
|-
| <tt>PID</tt> || [[Prozessnummer]]
|-
| <tt>USER</tt> || Name des Systembenutzers, unter dem der Prozess läuft
|-
| <tt>FD</tt> || Dateideskriptor
|-
| <tt>TYPE</tt> || [[Dateiformat]]
|-
| <tt>DEVICE</tt> || Gerät
|-
| <tt>SIZE</tt> || Dateigrösse
|-
| <tt>NODE</tt> || Verbindung
|-
| <tt>NAME</tt> || Vollständiger Name
|}
 
Ein Aufruf von lsof ohne Parameter liefert zu viele Informationen, um sie zu überschauen. Mit gezielt gewählten Optionen beschränkt sich lsof auf die gerade gewünschten Daten. Bei der Kombination mehrerer Optionen verknüpft lsof diese per Vorgabe mit ODER-Logik. Um sicherzustellen, dass <i>alle</i> Bedingungen erfüllt sind, muss zusätzlich die Option "-a" (UND-Verknüpfung) angegeben werden.


== Installation ==
== Installation ==


Systemkompatibilität und Sicherheit sprechen gegen vorkompilierte Versionen. lsof sollte deshalb in einer aktuellen Version auf dem Zielsystem selber kompiliert werden, um den vollen Funktionsumfang und beste Stabilität zu garantieren.
Systemkompatibilität und Sicherheit sprechen gegen vorkompilierte Versionen. lsof sollte deshalb im Idealfall in einer aktuellen Version auf dem Zielsystem selber kompiliert werden, um den vollen Funktionsumfang und beste Stabilität zu garantieren.


Holen der Quellen aus dem Netz, Prüfen der Signatur mit GNU PG, Konfiguration der Quellen und Kompilierung. Während der Konfiguration muss der Anwender interaktiv Entscheidungen treffen: die Antworten [y], [y], [y], [n], [n], [n] und [y] erzeugen eine typische Umgebung mit Blick auf Sicherheit. Wichtig sind die Optionen "HASSECURITY" und "HASNOSOCKSECURITY": um nur dem Benutzer "root" die Anzeige einer Liste aller offenen Dateien und Sockets aller Benutzer zu erlauben, muss hier mit [y] und [n] geantwortet werden.
Folgende Befehle holen die Quellen aus dem Internet, prüfen die Signatur mit GNU PG, konfigurieren die Quellen und kompilieren sie.


  $ <b><nowiki>wget ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof.tar.bz2</nowiki></b>
  $ <b><nowiki>wget ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof.tar.bz2</nowiki></b>
Zeile 19: Zeile 49:
  $ <b>tar xf lsof_4.77_src.tar</b>
  $ <b>tar xf lsof_4.77_src.tar</b>
  $ <b>cd lsof_4.77_src</b>
  $ <b>cd lsof_4.77_src</b>
Während der Konfiguration muss der Anwender interaktiv Entscheidungen treffen: die Antworten [y], [y], [y], [n], [n], [n] und [y] erzeugen eine typische Umgebung mit Blick auf Sicherheit. Wichtig sind die Optionen "HASSECURITY" und "HASNOSOCKSECURITY": Um nur dem Benutzer "root" die Anzeige einer Liste aller offenen Dateien und Sockets aller Benutzer zu erlauben, muss hier mit [y] und [n] geantwortet werden.
  $ <b>./configure linux</b>
  $ <b>./configure linux</b>
  $ <b>make -s</b>
  $ <b>make -s</b>


Um lsof an einem sicheren Ort aufzubewahren, genügt es, nach dem Kompilieren auf "make install" zu verzichten und die Binärdatei auf einem schreibgeschützten Datenträger unterzubringen, etwa auf einer CD-ROM. Sollte allerdings ein Eindringling den Kernel (etwa mit einem Kernel-[[Rootkit]]) ändern, so ist leider auch den Ausgaben des unveränderten lsof nicht mehr zu trauen...
Um lsof an einem sicheren Ort aufzubewahren, genügt es, nach dem Kompilieren auf "make install" zu verzichten und die Binärdatei auf einem schreibgeschützten Datenträger unterzubringen, etwa auf einer CD-ROM. Sollte es allerdings einem Eindringling gelingen, den Kernel (etwa mit einem Kernel-[[Rootkit]]) zu ändern, so ist leider auch den Ausgaben des unveränderten lsof nicht mehr zu trauen.


Anzeige der Optionen, mit denen lsof übersetzt wurde. Die Ausgabe "Only root can list all files" bedeutet, dass normale Benutzer lsof nicht verwenden können, um systemkritische Informationen einzusehen.
Anzeige der Optionen, mit denen lsof übersetzt wurde. Die Ausgabe "Only root can list all files" bedeutet, dass normale Benutzer lsof nicht verwenden können, um systemkritische Informationen einzusehen.
Zeile 30: Zeile 63:
== Optionen ==
== Optionen ==


{| class=wikitable
{| class=wiki width=100%
! width=10% | Option !! Beschreibung
! width=15% | Option
! Beschreibung
|-
|-
| <tt>-i4</tt> || Anzeige aller IPv4-Verbindungen.
| || Ohne Option werden sämtliche offenen Dateien angezeigt, die gerade von irgendeinem Prozess geöffnet sind.
|-
 
| <tt>-n</tt> || Unterdrücken der Namensauflösung.
$ <b>lsof</b>
 
|-
|-
| <tt>-P</tt> || Unterdrücken der Portnamensauflösung.
| <tt><i>Datei</i></tt> || Anzeige der Prozesse, die gerade auf die angegebene Datei zugreifen. Im Beispiel werden die Prozesse angezeigt, die gerade auf die Datei "/usr/bin/vim" zugreifen (also mit [[vi]] arbeiten).
|}


== Verwendung ==
$ <b>lsof /usr/bin/vim</b>


Im sicheren Modus informiert lsof nur den Benutzer "root" umfassend. Aber auch im unsicheren Modus darf z. B. nur der Benutzer "root" auf alle Details im Verzeichnis "/proc" zugreifen.
|-
| <tt><i>Gerätedatei</i></tt> || Anzeige der Prozesse, die gerade auf die angegebene Gerätedatei zugreifen. Im Beispiel werden alle Prozesse angezeigt, die gerade auf die CD-ROM-Gerätedatei "/dev/hdc" zugreifen.


lsof gibt die je nach Parameterliste gefilterten Informationen der offenen Dateien in einem tabellarischen Format aus. Per Vorgabe zeigt es folgende Spalten:
$ <b>lsof /dev/hdc</b>


{| class=wikitable
! width=10% | Spalte !! Beschreibung
|-
|-
| <tt>COMMAND</tt> || Name des Prozesses
| <tt>-a</tt> || UND-Verknüpfung.
|-
|-
| <tt>PID</tt> || Prozess-ID
| <tt>-d <i>Dateideskriptor</i></tt> || Anzeige aller gerade geöffneten Dateien, wobei anstatt der sonst üblichen Prozessnummer der angegebene Dateideskriptor aufgelistet wird. Dadurch ergibt sich eine ähnlcieh Liste, wie sie mit "[[ps]] aux" zu sehen ist. "txt" steht für Programmtext (weitere Dateideskriptoren finden sich über "man lsof").
 
$ <b>lsof -d txt</b>
 
|-
|-
| <tt>USER</tt> || Name des Systembenutzers, unter dem der Prozess läuft
| <tt>+D <i>Verzeichnis</i></tt> || Anzeige aller gerade geöffneten Dateien im angegebenen Verzeichnis und seinen Unterverzeichnissen, ohne dabei auf symbolische Links zu achten.
 
$ <b>lsof +D /tmp</b>
 
|-
|-
| <tt>FD</tt> || Dateideskriptor
| <tt>-F <i>Felder</i></tt> || Diese besonders formatierte Ausgabe sorgt dafür, dass nachgeschaltete Programme einzelne Felder besser parsen können. Details dazu finden sich im Manpage-Abschnitt "Output for other programs".
|-
|-
| <tt>TYPE</tt> || Dateityp
| <tt>+L <i>Linkzähler</i></tt> || Anzeige aller gelöschten Dateien, die noch geöffnet sind und daher Plattenplatz verbrauchen, aber in keinem Verzeichnis erscheinen (im Beispiel Dateien mit weniger als einem Link).
 
$ <b>lsof +L 1</b>
 
|-
|-
| <tt>DEVICE</tt> || Gerät
| <tt>-i</tt> || Anzeige aller gerade geöffneten netzwerkrelevanten Dateien.
|-
 
| <tt>SIZE</tt> || Dateigrösse
$ <b>lsof -i</b>
|-
| <tt>NODE</tt> || Verbindung
|-
| <tt>NAME</tt> || Vollständiger Name
|}


Die Ausgabe lässt sich über "lsof -F <Felder>" auch für die Übergabe an weiterverarbeitende Programme aufbereiten. Eine spezielle Formatierung sorgt dafür, dass die nachgeschalteten Tools einzelne Felder besser parsen können. Details dazu finden sich im Manpage-Abschnitt "Output for other programs".
Anzeige aller gerade vom Benutzer "www-data" geöffneten Netzwerkdateien (UND-Verknüpfung durch "-a").


Ein Aufruf ohne Parameter liefert zu viele Informationen, um sie zu überschauen. Mit gezielt gewählten Aufrufparametern beschränkt sich lsof auf die gerade gewünschten Daten. Bei der Kombination mehrerer Parameter verknüpft lsof diese per Vorgabe mit ODER-Logik. Um sicherzustellen, dass alle Bedingungen erfüllt sind (UND-Verknüpfung), muss zusätzlich die Option "-a" angegeben werden.
$ <b>lsof -a -i -u www-data</b>


Anzeige aller Prozesse, die gerade auf Dateien zugreifen.
Anzeige aller gerade geöffneten netzwerkrelevanten Dateien, ohne die Portnummern als Dienstbezeichnung auszuschreiben und ohne die Hostnamen aufzulösen (daher deutlich performanter).


  $ <b>lsof</b>
  $ <b>lsof -i -P -n</b>


Anzeige aller Prozesse, die gerade auf die Datei "/usr/bin/vim" zugreifen (also mit [[vi]] arbeiten).
Anzeige aller aktiven Verbindungen.


  $ <b>lsof /usr/bin/vim</b>
  $ <b>lsof -i | grep '\->'</b>


Anzeige aller Prozesse, die gerade auf die CD-ROM-Gerätedatei "/dev/hdc" zugreifen.
|-
| <tt>-i4</tt> || Anzeige aller gerade geöffneten [[IPV4]]-bezogenen Dateien.


  $ <b>lsof /dev/hdc</b>
  $ <b>lsof -i4</b>


Beenden aller Prozesse, die noch auf ein ins CD-ROM-Laufwerk eingelegtes Medium zugreifen.
|-
| <tt>-i6</tt> || Anzeige aller gerade geöffneten [[IPV6]]-bezogenen Dateien.


  $ <b>kill $(lsof -t /cdrom)</b>
  $ <b>lsof -i6</b>


Anzeige aller offenen Dateien des Prozesses mit der PID 2326.
|-
| <tt>-n</tt> || Unterdrücken der Namensauflösung.
|-
| <tt>-p <i>Prozessnummer</i></tt> || Anzeige aller Dateien, die gerade vom Prozess mit der angegebenen Prozessnummer (PID) geöffnet sind.


  $ <b>lsof -p 2326</b>
  $ <b>lsof -p 2326</b>


Anzeige aller offenen Dateien im Verzeichnis "/tmp" und seinen Unterverzeichnissen, ohne dabei auf symbolische Links zu achten.
Anzeige aller Dateien, die gerade von den Prozessen mit den angegebenen Prozessnummern (PID) geöffnet sind.


  $ <b>lsof +D /tmp</b>
  $ <b>lsof -p 2326,5400,5720</b>


Anzeige aller vom Benutzer "max" geöffneten Dateien.
|-
| <tt>-P</tt> || Unterdrücken der Portnamensauflösung.
|-
| <tt>-u <i>Benutzername</i></tt> || Anzeige aller Dateien, die gerade vom angegebenen Benutzer geöffnet sind.


  $ <b>lsof -u max</b>
  $ <b>lsof -u max</b>


Anzeige aller offenen Dateien, die nicht der Benutzer "root" geöffnet hat.
Anzeige aller offenen Dateien, die <i>nicht</i> der Benutzer "root" geöffnet hat.


  $ <b>lsof -u ^root</b>
  $ <b>lsof -u ^root</b>


Anzeige einer ähnlichen Prozessliste wie [[ps|ps aux]] durch Auflisten der Einträge mit Dateideskriptoreintrag "txt" statt der sonst üblichen Nummer ("txt" steht für Programmcode und Daten, also eine ausgeführte Datei).
|}


$ <b>lsof -d txt</b>
== Verwendung ==


Anzeige aller gelöschten Dateien, die noch geöffnet sind und daher Plattenplatz verbrauchen, aber in keinem Verzeichnis erscheinen (Dateien mit weniger als einem Link).
=== Identifikation der einen Datenträger blockierenden Prozesse ===


$ <b>lsof +L1</b>
lsof kann auch zur Identifikation von Prozessen dienen, die verhindern, dass der Benutzer einen Datenträger aushängen kann. Der lsof-Aufruf mit der Option "-t <i>Verzeichnis</i>" liefert eine Liste numerischer Prozess-IDs, die auf die CD-ROM zugreifen. Die Methode ist ebenso drastisch wie wirkungsvoll.
 
Anzeige aller netzwerkrelevanten Dateien.
 
$ <b>lsof -i</b>
 
Anzeige aller netzwerkrelevanten Dateien, ohne die Portnummern als Dienstbezeichnung auszuschreiben und ohne die Hostnamen aufzulösen (daher deutlich performanter).
 
$ <b>lsof -i -P -n</b>
 
Anzeige aller IPv6-bezogenen Dateien.
 
$ <b>lsof -i6</b>
 
Anzeige aller aktiven Verbindungen.
 
$ <b>lsof -i | grep '\->'</b>
 
Anzeige aller derzeit vom Benutzer "www-data" geöffneten Netzwerkdateien (UND-Verknüpfung durch "-a").
 
$ <b>lsof -a -i -u www-data</b>
 
=== Identifikation von Prozessen, die verhindern, dass der Benutzer einen Datenträger aushängen kann ===
 
Der lsof-Aufruf mit der Option "-t <Verzeichnis>" liefert eine Liste numerischer Prozess-IDs, die auf die CD-ROM zugreifen. Die Methode ist ebenso drastisch wie wirkungsvoll.


  $ <b>umount /dev/cdrom</b>
  $ <b>umount /dev/cdrom</b>
Zeile 148: Zeile 169:
=== Stark angestiegene Netzwerklast auf LAMP-System ===
=== Stark angestiegene Netzwerklast auf LAMP-System ===


Angenommen wird, dass die zusätzliche Last nicht über Seitenzugriffe, sondern durch einen Eindringling verursacht wird, der Dateien übers Netzwerk kopiert, verteilte Netzattacken ausführt oder Spam-E-Mails verschickt. In einer LAMP-Umgebung ist die Schnittstelle von PHP zum System eines der Hauptangriffsziele, da PHP an etlichen konzeptionellen Schwächen leidet, auch schlampig geschriebene Skripte laden Angreifer ein. Der Webserver Apache läuft standardmässig als eigener Benutzer (als "www-data", "apache", "httpd" oder gar als "nobody"). In der Regel laufen zusätzliche Prozesse als Benutzer "root", um privilegierte Ports und die Logdateien zu öffnen. Die Datenkommunikation dagegen wird durch unprivilegierte Prozesse erledigt. Auf einem Webserver gibt es also einen bestimmten Erwartungshorizont an Kombinationen aus Benutzern, auszuführenden Dateien und geöffneten Ports.
Angenommen wird, dass die zusätzliche Last nicht über Seitenzugriffe, sondern durch einen Eindringling verursacht wird, der Dateien übers Rechnernetz kopiert, verteilte Netzattacken ausführt oder Spam verschickt. In einer LAMP-Umgebung ist die Schnittstelle von PHP zum System eines der Hauptangriffsziele, da PHP an etlichen konzeptionellen Schwächen leidet, auch schlampig geschriebene Skripte laden Angreifer ein. Der Webserver Apache läuft standardmässig als eigener Benutzer (als "www-data", "apache", "httpd" oder gar als "nobody"). In der Regel laufen zusätzliche Prozesse als Benutzer "root", um privilegierte Ports und die Protokolldateien zu öffnen. Die Datenkommunikation dagegen wird durch unprivilegierte Prozesse erledigt. Auf einem Webserver gibt es also einen bestimmten Erwartungshorizont an Kombinationen aus Benutzern, auszuführenden Dateien und geöffneten Ports.


So führt etwa der Benutzer "www-data" unter Debian das Programm "/usr/bin/apache2" aus. Der Aufruf "lsof -a -d- txt -u www-data" darf in dieser Umgebung nur Prozesse listen, die "/usr/bin/apache2" als Benutzer "www-data" ausführen (Die Option "-a" sorgt für UND-Verknüpfung, "-d txt" listet nur ausgeführte Dateien, "-u www-data" beschränkt die Ausgabe auf den Benutzer "www-data"). Normalerweise trifft das nur auf die Apache-Prozesse zu.
So führt etwa der Benutzer "www-data" unter Debian das Programm "/usr/bin/apache2" aus. Der folgende Aufruf darf in dieser Umgebung nur Prozesse listen, die "/usr/bin/apache2" als Benutzer "www-data" ausführen. Normalerweise trifft das nur auf die Apache-Prozesse zu. Die Option "-a" sorgt für UND-Verknüpfung, "-d txt" listet nur ausgeführte Dateien und "-u www-data" beschränkt die Ausgabe auf den Benutzer "www-data".


Ist es einem Angreifer gelungen, PHP oder PHP-Skripte zu manipulieren und Systembefehle und Programme auf dem Server auszuführen, so laufen diese üblicherweise als derselbe Benutezr wie Apache - ausser wenn der Eindringling über weitere Lücken die Rechte von Benutzer "root" erlangen und seine eigenen Spuren verschleiern konnte. Zeigen sich Prozesse des Apache-Benutzers, die auf anderen Binärdateien basieren oder unerwartete Ports offenhalten, so ist Vorsicht angebracht: mit "lsof -p <PID>" können verdächtige Prozesse detailliert auf Netzwerkverbindungen, geladene Bibliotheken, geöffnete Dateien und mehr untersucht werden.
$ <b>lsof -a -d txt -u www-data</b>
 
Ist es einem Angreifer gelungen, PHP oder PHP-Skripte zu manipulieren und Systembefehle und Programme auf dem Server auszuführen, so laufen diese üblicherweise als derselbe Benutzer wie Apache - ausser wenn der Eindringling über weitere Lücken die Rechte von Benutzer "root" erlangen und seine eigenen Spuren verschleiern konnte. Zeigen sich Prozesse des Apache-Benutzers, die auf anderen Binärdateien basieren oder unerwartete Ports offenhalten, so ist Vorsicht angebracht: mit "lsof -p <i>PID</i>" können verdächtige Prozesse detailliert auf Netzwerkverbindungen, geladene Bibliotheken, geöffnete Dateien und mehr untersucht werden.


Da Cracker gerne ihre eigenen Server für [[FTP]], [[IRC]], [[Telnet]] oder [[SSH]] mitbringen, gehört zur Erstanalyse auch die Suche nach offenen Ports. Folgender Aufruf listet alle IP-Sockets ("-i"), die der Apache-Benutzer ("-u www-data") geöffnet hat und die als Server auf Verbindungen warten (daher "grep LISTEN").
Da Cracker gerne ihre eigenen Server für [[FTP]], [[IRC]], [[Telnet]] oder [[SSH]] mitbringen, gehört zur Erstanalyse auch die Suche nach offenen Ports. Folgender Aufruf listet alle IP-Sockets ("-i"), die der Apache-Benutzer ("-u www-data") geöffnet hat und die als Server auf Verbindungen warten (daher "grep LISTEN").
Zeile 158: Zeile 181:
  $ <b>lsof -a -i -u www-data | grep LISTEN</b>
  $ <b>lsof -a -i -u www-data | grep LISTEN</b>


Alles abseits der Ports 80 (HTTP) und 443 (HTTPS) ist verdächtig. Ähnliche Resultate liefert zwar auch [[netstat]], doch hilft lsof auch bei der weiteren Analyse und erspart somit einen Programmwechsel.
Alles usser den Ports 80 (HTTP) und 443 (HTTPS) ist verdächtig. Ähnliche Resultate liefert zwar auch [[netstat]], doch hilft lsof auch bei der weiteren Analyse und erspart somit einen Programmwechsel.


Mit Hilfe eines kleinen Skripts kann ein vordefinierter Systemzustand mit dem aktuellen Zustand verglichen und bei Abweichungen nach vordefinierten Regeln behandelt werden. Folgende Zeile weist lsof an, netzwerkbezogene Dateien auszugeben ("-i TCP"), ohne dabei Portnummern asls Servicename auszuschreiben ("-P") und ohne IP-Adressen in Hostnamen aufzulösen ("-n"). [[awk]] fahndet in der Ausgabe nach Ports im Status "LISTEN" und formatiert sie neu als "Benutzername/Prozessname/IP:Port", wobei die IP-Adresse "*" für Server steht, die auf allen Schnittstellen lauschen. Das abschliessende [[sort]] ordnet die Ausgabe alphabetisch und sorgt dafpr, dass jede Benutzer-Dienst-Kombination nur einmal erscheint ("-u").
Mit Hilfe eines kleinen Skripts kann ein vordefinierter Systemzustand mit dem aktuellen Zustand verglichen und bei Abweichungen nach vordefinierten Regeln behandelt werden. Folgende Zeile weist lsof an, netzwerkbezogene Dateien auszugeben ("-i TCP"), ohne dabei Portnummern als Servicename auszuschreiben ("-P") und ohne IP-Adressen in Hostnamen aufzulösen ("-n"). [[awk]] fahndet in der Ausgabe nach Ports im Status "LISTEN" und formatiert sie neu als "Benutzername/Prozessname/IP:Port", wobei die IP-Adresse "*" für Server steht, die auf allen Schnittstellen lauschen. Das abschliessende [[sort]] ordnet die Ausgabe alphabetisch und sorgt dafür, dass jede Benutzer-Dienst-Kombination nur einmal erscheint ("-u").


  $ <b>lsof -i TCP -n -P | awk '/LISTEN/ { print $1"/"$3"/"$8 }' | sort -u</b>
  $ <b>lsof -i TCP -n -P | awk '/LISTEN/ { print $1"/"$3"/"$8 }' | sort -u</b>


Folgendes lsof-Mini-[[IDS]]-Skript merkt sich die aktuelle Port-Konfiguration. Alle 10 Sekunden ("while sleep 10; do") holt lsof die Liste der geöffneten Ports und vergleicht sie mit dem vorigen Status. Hat sich etwas verändert, so wird eine E-Mail mit dem Vorher-Nachher-Status geschickt und der neue Status als neue Basis für weitere Vergleiche benutzt.
Folgendes lsof-Mini-[[IDS]]-Skript merkt sich die aktuelle Port-Konfiguration. Alle 10 Sekunden ("while sleep 10; do") holt lsof die Liste der geöffneten Ports und vergleicht sie mit dem vorigen Status. Hat sich etwas verändert, so wird eine E-Mail mit dem Vorher-Nachher-Status geschickt und der neue Status als neue Basis für weitere Vergleiche benutzt.
<pre>
<pre>
#!/bin/bash
#!/bin/bash
Zeile 176: Zeile 200:
OLD="$(getports)"
OLD="$(getports)"
echo -e "Beginne mit folgender Port-Belegung:\n$OLD"
echo -e "Beginne mit folgender Port-Belegung:\n$OLD"
while sleep 10; do
while sleep 10
  do
   NEW="$(getports)"
   NEW="$(getports)"
   if test "$OLD" != "$NEW"; then
   if test "$OLD" != "$NEW"; then
     echo "Aenderung der Portbelegung! Informiere Systemverwalter per E-Mail"
     echo "Aenderung der Portbelegung! Informiere Systemverwalter per E-Mail"
     mail -s "Achtung: $HOSTNAME LISTEN-Status geaendert" $MAILTO <<EOF
     mail -s "Achtung: $HOSTNAME LISTEN-Status geaendert" $MAILTO <<- EOF-EOF
Status vor der Aenderung:
    Status vor der Aenderung:
$OLD
    $OLD
 
   
Status nach der Aenderung:
    Status nach der Aenderung:
$NEW
    $NEW
EOF
EOF-EOF
   fi
   fi
   OLD="$NEW"
   OLD="$NEW"
done
  done
</pre>
</pre>


Zum Testen der Anomalie-Erkennung kann der Systemverwalter einen Port öffnen. Folgender Befehl startet Netcat im Mosus "LISTEN" ("-l") und hält den Port 12345 offen. Nach spätestens zehn Sekunden sollte das in seiner Schleife verharrende Shellskript die Veränderung bemerken und mit einer entsprechenden Warn-E-Mail reagieren.
Zum Testen der Anomalie-Erkennung kann der Systemverwalter einen Port öffnen. Folgender Befehl startet [[nc]] im Modus "LISTEN" ("-l") und hält den Port 12345 offen. Nach spätestens zehn Sekunden sollte das in seiner Schleife verharrende Shellskript die Veränderung bemerken und mit einer entsprechenden Warn-E-Mail reagieren.


  $ <b>nc -l -p 12345</b>
  $ <b>nc -l -p 12345</b>


Achtung: Manche Prozesse verändern ihre für lsof sichtbare Portbelegung, z. B. E-Mail-Server, die je nach dem Zustand der eingehenden Verbindungen zusätzliche Prozesse forken und sie unter anderen Namen laufen lassen. Unter Umständen lösen also auch solche Prozesse einen (falschen) Alarm aus. Das ist durch eine Anpassung in der Abfragelogik des obigen Skripts aber rasch zu unterbinden: ein angehängtes "| grep -v <Temporärer Dienst>" in der Funktion "getports()" sollte genügen.
Achtung: Manche Prozesse verändern ihre für lsof sichtbare Portbelegung, so beispilsweise E-Mail-Server, die je nach dem Zustand der eingehenden Verbindungen zusätzliche Prozesse forken und sie unter anderen Namen laufen lassen. Unter Umständen lösen also auch solche Prozesse einen (falschen) Alarm aus. Das ist durch eine Anpassung in der Abfragelogik des obigen Skripts aber rasch zu unterbinden: ein angehängtes "| grep -v <i>Temporärer Dienst</i>" in der Funktion "getports()" sollte genügen.
 
== FAQ ==
 
=== ... ===
 
* https://linuxize.com/post/check-listening-ports-linux/
 
$ <b>lsof -i -P -n</b>
COMMAND  PID    USER  FD  TYPE  DEVICE SIZE/OFF NODE NAME
rspamd    568  _rspamd    8u  IPv4  16578      0t0  TCP 127.0.0.1:11332 (LISTEN)
rspamd    568  _rspamd    9u  IPv6  16579      0t0  TCP [::1]:11332 (LISTEN)
rspamd    568  _rspamd  11u  IPv4  17475      0t0  TCP 127.0.0.1:11334 (LISTEN)
rspamd    568  _rspamd  13u  IPv6  17476      0t0  TCP [::1]:11334 (LISTEN)
rspamd    568  _rspamd  15u  IPv4  17481      0t0  TCP 127.0.0.1:11333 (LISTEN)
rspamd    568  _rspamd  17u  IPv6  17482      0t0  TCP [::1]:11333 (LISTEN)
dovecot  571    root  21u  IPv4  15535      0t0  TCP *:110 (LISTEN)
dovecot  571    root  22u  IPv6  15536      0t0  TCP *:110 (LISTEN)
...


== Weblinks ==
== Weblinks ==


* [http://www.jfranken.de/homepages/johannes/vortraege/lsof_inhalt.de.html lsof] (JFranken.de) - Anwendungsbeispiele für lsof
{{Weblinks}}
{{enwi|lsof|lsof}}
{{url|DE|Johannes Franken|eng, ger|http://www.jfranken.de/homepages/johannes/vortraege/lsof_inhalt.de.html|lsof|Anwendungsbeispiele für lsof}}
{{url_enwikipedia|lsof|lsof}}
{{Fuss}}




{{cat|Datei}}
{{cat|Datei}}
{{cat|Shell-Befehl}}
{{cat|Shell-Befehl}}

Aktuelle Version vom 26. Juli 2021, 06:56 Uhr

Der Shell-Befehl lsof (list open files) zeigt dem unprivilegierten Benutzer alle geöffneten Dateien - also sowohl reguläre Dateien wie auch spezielle Blockdateien, ausführbare Programme, Bibliotheken, Verzeichnisse, rechnerinterne Datenströme (Unix Domain Sockets) und Netzwerkverbindungen. Dem Benutzer "root" zeigt lsof dagegen alle geöffneten Verbindungen, Ports und Dateien im Netzwerk.

Mit Hilfe der Befehle fuser, ps, netstat und top können ähnliche Informationen gesammelt werden - allerdings weit weniger bequem.

Glsof und Jlsof sind grafische Oberflächen für lsof.

Funktionsweise

Im sicheren Modus informiert lsof nur den Benutzer "root" umfassend. Aber auch im unsicheren Modus darf nur der Benutzer "root" auf alle Details im Verzeichnis "/proc" zugreifen.

lsof gibt die je nachden verwendeten Optionen gefilterten Informationen der gerade geöffneten Dateien in einem tabellarischen Format aus. Per Vorgabe werden folgende Spalten angezeigt:

Spalte Beschreibung
COMMAND Name des Prozesses
PID Prozessnummer
USER Name des Systembenutzers, unter dem der Prozess läuft
FD Dateideskriptor
TYPE Dateiformat
DEVICE Gerät
SIZE Dateigrösse
NODE Verbindung
NAME Vollständiger Name

Ein Aufruf von lsof ohne Parameter liefert zu viele Informationen, um sie zu überschauen. Mit gezielt gewählten Optionen beschränkt sich lsof auf die gerade gewünschten Daten. Bei der Kombination mehrerer Optionen verknüpft lsof diese per Vorgabe mit ODER-Logik. Um sicherzustellen, dass alle Bedingungen erfüllt sind, muss zusätzlich die Option "-a" (UND-Verknüpfung) angegeben werden.

Installation

Systemkompatibilität und Sicherheit sprechen gegen vorkompilierte Versionen. lsof sollte deshalb im Idealfall in einer aktuellen Version auf dem Zielsystem selber kompiliert werden, um den vollen Funktionsumfang und beste Stabilität zu garantieren.

Folgende Befehle holen die Quellen aus dem Internet, prüfen die Signatur mit GNU PG, konfigurieren die Quellen und kompilieren sie.

$ wget ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof.tar.bz2
$ tar xjf lsof.tar.bz2
$ cd lsof_4.77
$ wget ftp://lsof.itap.purdue.edu/pub/Victor_A_Abell.gpg
$ gpg --import Victor_A_Abell.gpg
$ gpg --verify lsof_4.77_src.tar.sig lsof_4.77_src.tar
$ tar xf lsof_4.77_src.tar
$ cd lsof_4.77_src

Während der Konfiguration muss der Anwender interaktiv Entscheidungen treffen: die Antworten [y], [y], [y], [n], [n], [n] und [y] erzeugen eine typische Umgebung mit Blick auf Sicherheit. Wichtig sind die Optionen "HASSECURITY" und "HASNOSOCKSECURITY": Um nur dem Benutzer "root" die Anzeige einer Liste aller offenen Dateien und Sockets aller Benutzer zu erlauben, muss hier mit [y] und [n] geantwortet werden.

$ ./configure linux
$ make -s

Um lsof an einem sicheren Ort aufzubewahren, genügt es, nach dem Kompilieren auf "make install" zu verzichten und die Binärdatei auf einem schreibgeschützten Datenträger unterzubringen, etwa auf einer CD-ROM. Sollte es allerdings einem Eindringling gelingen, den Kernel (etwa mit einem Kernel-Rootkit) zu ändern, so ist leider auch den Ausgaben des unveränderten lsof nicht mehr zu trauen.

Anzeige der Optionen, mit denen lsof übersetzt wurde. Die Ausgabe "Only root can list all files" bedeutet, dass normale Benutzer lsof nicht verwenden können, um systemkritische Informationen einzusehen.

$ ./lsof -v

Optionen

Option Beschreibung
Ohne Option werden sämtliche offenen Dateien angezeigt, die gerade von irgendeinem Prozess geöffnet sind.
$ lsof
Datei Anzeige der Prozesse, die gerade auf die angegebene Datei zugreifen. Im Beispiel werden die Prozesse angezeigt, die gerade auf die Datei "/usr/bin/vim" zugreifen (also mit vi arbeiten).
$ lsof /usr/bin/vim
Gerätedatei Anzeige der Prozesse, die gerade auf die angegebene Gerätedatei zugreifen. Im Beispiel werden alle Prozesse angezeigt, die gerade auf die CD-ROM-Gerätedatei "/dev/hdc" zugreifen.
$ lsof /dev/hdc
-a UND-Verknüpfung.
-d Dateideskriptor Anzeige aller gerade geöffneten Dateien, wobei anstatt der sonst üblichen Prozessnummer der angegebene Dateideskriptor aufgelistet wird. Dadurch ergibt sich eine ähnlcieh Liste, wie sie mit "ps aux" zu sehen ist. "txt" steht für Programmtext (weitere Dateideskriptoren finden sich über "man lsof").
$ lsof -d txt
+D Verzeichnis Anzeige aller gerade geöffneten Dateien im angegebenen Verzeichnis und seinen Unterverzeichnissen, ohne dabei auf symbolische Links zu achten.
$ lsof +D /tmp
-F Felder Diese besonders formatierte Ausgabe sorgt dafür, dass nachgeschaltete Programme einzelne Felder besser parsen können. Details dazu finden sich im Manpage-Abschnitt "Output for other programs".
+L Linkzähler Anzeige aller gelöschten Dateien, die noch geöffnet sind und daher Plattenplatz verbrauchen, aber in keinem Verzeichnis erscheinen (im Beispiel Dateien mit weniger als einem Link).
$ lsof +L 1
-i Anzeige aller gerade geöffneten netzwerkrelevanten Dateien.
$ lsof -i

Anzeige aller gerade vom Benutzer "www-data" geöffneten Netzwerkdateien (UND-Verknüpfung durch "-a").

$ lsof -a -i -u www-data

Anzeige aller gerade geöffneten netzwerkrelevanten Dateien, ohne die Portnummern als Dienstbezeichnung auszuschreiben und ohne die Hostnamen aufzulösen (daher deutlich performanter).

$ lsof -i -P -n

Anzeige aller aktiven Verbindungen.

$ lsof -i | grep '\->'
-i4 Anzeige aller gerade geöffneten IPV4-bezogenen Dateien.
$ lsof -i4
-i6 Anzeige aller gerade geöffneten IPV6-bezogenen Dateien.
$ lsof -i6
-n Unterdrücken der Namensauflösung.
-p Prozessnummer Anzeige aller Dateien, die gerade vom Prozess mit der angegebenen Prozessnummer (PID) geöffnet sind.
$ lsof -p 2326

Anzeige aller Dateien, die gerade von den Prozessen mit den angegebenen Prozessnummern (PID) geöffnet sind.

$ lsof -p 2326,5400,5720
-P Unterdrücken der Portnamensauflösung.
-u Benutzername Anzeige aller Dateien, die gerade vom angegebenen Benutzer geöffnet sind.
$ lsof -u max

Anzeige aller offenen Dateien, die nicht der Benutzer "root" geöffnet hat.

$ lsof -u ^root

Verwendung

Identifikation der einen Datenträger blockierenden Prozesse

lsof kann auch zur Identifikation von Prozessen dienen, die verhindern, dass der Benutzer einen Datenträger aushängen kann. Der lsof-Aufruf mit der Option "-t Verzeichnis" liefert eine Liste numerischer Prozess-IDs, die auf die CD-ROM zugreifen. Die Methode ist ebenso drastisch wie wirkungsvoll.

$ umount /dev/cdrom
umount: /cdrom: device is busy
$ kill -15 $(lsof -t /dev/cdrom)
$ umount /dev/cdrom
$ eject

Wiederherstellung gelöschter Daten

Dies klappt mit lsof und cat, solange irgendein Prozess die Dateien noch geöffnet hält. lsof ermittelt dann Datei und Prozess und je nachdem, auf welche Weise der Prozess die Datei geöffnet hat, ist ihr Inhalt an einer anderen Stelle im "/proc"-Dateisystem noch zugänglich.

Stark angestiegene Netzwerklast auf LAMP-System

Angenommen wird, dass die zusätzliche Last nicht über Seitenzugriffe, sondern durch einen Eindringling verursacht wird, der Dateien übers Rechnernetz kopiert, verteilte Netzattacken ausführt oder Spam verschickt. In einer LAMP-Umgebung ist die Schnittstelle von PHP zum System eines der Hauptangriffsziele, da PHP an etlichen konzeptionellen Schwächen leidet, auch schlampig geschriebene Skripte laden Angreifer ein. Der Webserver Apache läuft standardmässig als eigener Benutzer (als "www-data", "apache", "httpd" oder gar als "nobody"). In der Regel laufen zusätzliche Prozesse als Benutzer "root", um privilegierte Ports und die Protokolldateien zu öffnen. Die Datenkommunikation dagegen wird durch unprivilegierte Prozesse erledigt. Auf einem Webserver gibt es also einen bestimmten Erwartungshorizont an Kombinationen aus Benutzern, auszuführenden Dateien und geöffneten Ports.

So führt etwa der Benutzer "www-data" unter Debian das Programm "/usr/bin/apache2" aus. Der folgende Aufruf darf in dieser Umgebung nur Prozesse listen, die "/usr/bin/apache2" als Benutzer "www-data" ausführen. Normalerweise trifft das nur auf die Apache-Prozesse zu. Die Option "-a" sorgt für UND-Verknüpfung, "-d txt" listet nur ausgeführte Dateien und "-u www-data" beschränkt die Ausgabe auf den Benutzer "www-data".

$ lsof -a -d txt -u www-data

Ist es einem Angreifer gelungen, PHP oder PHP-Skripte zu manipulieren und Systembefehle und Programme auf dem Server auszuführen, so laufen diese üblicherweise als derselbe Benutzer wie Apache - ausser wenn der Eindringling über weitere Lücken die Rechte von Benutzer "root" erlangen und seine eigenen Spuren verschleiern konnte. Zeigen sich Prozesse des Apache-Benutzers, die auf anderen Binärdateien basieren oder unerwartete Ports offenhalten, so ist Vorsicht angebracht: mit "lsof -p PID" können verdächtige Prozesse detailliert auf Netzwerkverbindungen, geladene Bibliotheken, geöffnete Dateien und mehr untersucht werden.

Da Cracker gerne ihre eigenen Server für FTP, IRC, Telnet oder SSH mitbringen, gehört zur Erstanalyse auch die Suche nach offenen Ports. Folgender Aufruf listet alle IP-Sockets ("-i"), die der Apache-Benutzer ("-u www-data") geöffnet hat und die als Server auf Verbindungen warten (daher "grep LISTEN").

$ lsof -a -i -u www-data | grep LISTEN

Alles usser den Ports 80 (HTTP) und 443 (HTTPS) ist verdächtig. Ähnliche Resultate liefert zwar auch netstat, doch hilft lsof auch bei der weiteren Analyse und erspart somit einen Programmwechsel.

Mit Hilfe eines kleinen Skripts kann ein vordefinierter Systemzustand mit dem aktuellen Zustand verglichen und bei Abweichungen nach vordefinierten Regeln behandelt werden. Folgende Zeile weist lsof an, netzwerkbezogene Dateien auszugeben ("-i TCP"), ohne dabei Portnummern als Servicename auszuschreiben ("-P") und ohne IP-Adressen in Hostnamen aufzulösen ("-n"). awk fahndet in der Ausgabe nach Ports im Status "LISTEN" und formatiert sie neu als "Benutzername/Prozessname/IP:Port", wobei die IP-Adresse "*" für Server steht, die auf allen Schnittstellen lauschen. Das abschliessende sort ordnet die Ausgabe alphabetisch und sorgt dafür, dass jede Benutzer-Dienst-Kombination nur einmal erscheint ("-u").

$ lsof -i TCP -n -P | awk '/LISTEN/ { print $1"/"$3"/"$8 }' | sort -u

Folgendes lsof-Mini-IDS-Skript merkt sich die aktuelle Port-Konfiguration. Alle 10 Sekunden ("while sleep 10; do") holt lsof die Liste der geöffneten Ports und vergleicht sie mit dem vorigen Status. Hat sich etwas verändert, so wird eine E-Mail mit dem Vorher-Nachher-Status geschickt und der neue Status als neue Basis für weitere Vergleiche benutzt.

#!/bin/bash
MAILTO="root"
HOSTAME=$(hostname)

getports() {
  lsof -i -n -P | awk '/LISTEN/ { print $1"/"$3"/"$8 }' | sort -u
}

OLD="$(getports)"
echo -e "Beginne mit folgender Port-Belegung:\n$OLD"
while sleep 10
  do
  NEW="$(getports)"
  if test "$OLD" != "$NEW"; then
    echo "Aenderung der Portbelegung! Informiere Systemverwalter per E-Mail"
    mail -s "Achtung: $HOSTNAME LISTEN-Status geaendert" $MAILTO <<- EOF-EOF
    Status vor der Aenderung:
    $OLD
    
    Status nach der Aenderung:
    $NEW
EOF-EOF
  fi
  OLD="$NEW"
  done

Zum Testen der Anomalie-Erkennung kann der Systemverwalter einen Port öffnen. Folgender Befehl startet nc im Modus "LISTEN" ("-l") und hält den Port 12345 offen. Nach spätestens zehn Sekunden sollte das in seiner Schleife verharrende Shellskript die Veränderung bemerken und mit einer entsprechenden Warn-E-Mail reagieren.

$ nc -l -p 12345

Achtung: Manche Prozesse verändern ihre für lsof sichtbare Portbelegung, so beispilsweise E-Mail-Server, die je nach dem Zustand der eingehenden Verbindungen zusätzliche Prozesse forken und sie unter anderen Namen laufen lassen. Unter Umständen lösen also auch solche Prozesse einen (falschen) Alarm aus. Das ist durch eine Anpassung in der Abfragelogik des obigen Skripts aber rasch zu unterbinden: ein angehängtes "| grep -v Temporärer Dienst" in der Funktion "getports()" sollte genügen.

FAQ

...

$ lsof -i -P -n
COMMAND   PID     USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
rspamd    568  _rspamd    8u  IPv4   16578      0t0  TCP 127.0.0.1:11332 (LISTEN)
rspamd    568  _rspamd    9u  IPv6   16579      0t0  TCP [::1]:11332 (LISTEN)
rspamd    568  _rspamd   11u  IPv4   17475      0t0  TCP 127.0.0.1:11334 (LISTEN)
rspamd    568  _rspamd   13u  IPv6   17476      0t0  TCP [::1]:11334 (LISTEN)
rspamd    568  _rspamd   15u  IPv4   17481      0t0  TCP 127.0.0.1:11333 (LISTEN)
rspamd    568  _rspamd   17u  IPv6   17482      0t0  TCP [::1]:11333 (LISTEN)
dovecot   571     root   21u  IPv4   15535      0t0  TCP *:110 (LISTEN)
dovecot   571     root   22u  IPv6   15536      0t0  TCP *:110 (LISTEN)
...

Weblinks

Herausgeber Sprache Webseitentitel Anmerkungen
Johannes Franken eng, ger lsofwbm Anwendungsbeispiele für lsof
Wikipedia eng lsofwbm Enzyklopädischer Artikel