Shell-Konfigurationsdateien erkennen: Persistenz über .bashrc, .profile und /etc/profile.d

Kurzfassung: Jede Login- und jede interaktive Shell unter Linux führt beim Start Konfigurationsdateien aus - /etc/profile und /etc/profile.d/ für alle, ~/.bashrc, ~/.bash_profile oder ~/.profile für den einzelnen Nutzer. Eine Zeile an der richtigen Stelle, und der Code eines Angreifers läuft bei jeder Anmeldung wieder, ohne Cron, ohne systemd, ohne Root. Erkennung aus Verteidigersicht: die Änderung an diesen Dateien über auditd-Dateiwatches und Sysmon for Linux Event 11, der ungewöhnliche Schreiber und die Kommandozeile in der Prozess-Telemetrie, und vor allem der Prozess, der beim nächsten Login aus der Shell heraus entsteht. Weil Nutzer diese Dateien ständig legitim anpassen, zählen Inhalt, Konto und Folgeprozess - die Änderung allein beweist nichts. Drei sigma-cli-validierte Sigma-Regeln, Härtung, eine Analysten-Checkliste und der Test im Lab. Serie "Angriff erkennen".

Shell-Konfigurationsdateien erkennen heißt, die leiseste Form der Linux-Persistenz sichtbar zu machen. Nach dem ersten Zugriff über eine Unix-Shell hat ein Angreifer mehrere Wege, wiederzukommen: Cron und systemd sind laut und werden überwacht, SSH authorized_keys ebenso. Die Shell-Konfiguration dagegen ändert sich im Alltag so oft, dass eine zusätzliche Zeile kaum auffällt - und sie braucht keine besonderen Rechte, weil jeder Nutzer seine eigenen Dateien schreiben darf. Dieser Beitrag aus der Serie "Angriff erkennen" zeigt aus Verteidigersicht, welche Dateien es sind, wann sie laufen, wo die Änderung Spuren hinterlässt und wie sich der Angriff vom normalen Customizing trennen lässt. Die Telemetrie-Grundlagen stehen unter Linux-Sicherheitsmonitoring.

Einordnung in ATT&CK: MITRE führt die Technik als Unix Shell Configuration Modification (T1546.004), eine Sub-Technik von Event Triggered Execution (T1546). Im ATT&CK-v19-Datensatz trägt sie die Taktiken Persistence und Privilege Escalation - Letzteres, weil eine manipulierte Konfiguration auch mit den Rechten eines anderen, höher privilegierten Nutzers ausgeführt wird, sobald der sich anmeldet. In dieser Serie steht der Beitrag in der Spalte Persistence. Die Sigma-Regeln sind mit attack.persistence, attack.privilege-escalation und attack.t1546.004 getaggt.

Welche Dateien wann laufen

Die Erkennung steht und fällt mit dem Wissen, welche Datei bei welcher Art von Shell gelesen wird - denn der Angreifer wählt die Datei nach dem Login-Weg, den er erwartet:

  • Login-Shell (SSH, Konsole, su -). bash liest zuerst /etc/profile, das seinerseits alle Skripte in /etc/profile.d/ ausführt, und danach die erste vorhandene der drei Nutzerdateien ~/.bash_profile, ~/.bash_login, ~/.profile. Wer über SSH wiederkommt, trifft also genau diese Kette.
  • Interaktive Nicht-Login-Shell (neues Terminal, Subshell). bash liest /etc/bash.bashrc (Debian-Familie) beziehungsweise /etc/bashrc (Red-Hat-Familie) und dann ~/.bashrc. Weil die meisten Distributionen ~/.bashrc zusätzlich aus ~/.bash_profile oder ~/.profile heraus einbinden, ist ~/.bashrc die Datei, die praktisch bei jeder Shell läuft - und deshalb das beliebteste Ziel.
  • Nicht-interaktive Shell. Skripte und Cron-Jobs lesen diese Dateien nicht; bash wertet dort nur die Variable BASH_ENV aus. Eine Persistenz über Shell-Konfiguration wartet also auf einen Menschen, der sich anmeldet - das ist ihr Blindspot und zugleich ihr Vorteil, weil sie im Prozesskontext dieses Menschen läuft.
  • zsh als Abgrenzung. zsh hat eigene Dateien (/etc/zshenv, /etc/zprofile, /etc/zshrc, auf Debian unter /etc/zsh/, sowie ~/.zshenv, ~/.zprofile, ~/.zshrc, ~/.zlogin); ~/.zshenv läuft bei jedem zsh-Start, auch nicht-interaktiv. Unter Linux ist zsh die Ausnahme, unter macOS seit Catalina die Standard-Shell - dort gilt dieselbe Technik, aber mit der macOS-Telemetrie aus dem macOS-Sicherheitsmonitoring (ESF-Dateiereignisse statt auditd). Die Regeln hier decken die zsh-Dateien unter Linux mit ab.

Was der Angreifer tut

Die Technik ist eine Zeile Text an der richtigen Stelle. Bewusst auf der Ebene des Prinzips, nicht als Anleitung:

  • Nachladen oder Rückverbindung beim Login. Eine Zeile in ~/.bashrc, die per curl ein Skript holt und ausführt oder eine Reverse Shell im Hintergrund startet - meist mit nohup und Umleitung nach /dev/null, damit der Nutzer nichts merkt. Bei jedem neuen Terminal meldet sich das System beim Angreifer.
  • Passwort abfangen über einen sudo-Alias. Ein alias sudo= auf ein eigenes Skript, das die Passworteingabe mitschreibt und dann das echte sudo aufruft. Das ist der Weg, über den diese Technik zur Rechteausweitung wird: Der Angreifer wartet, bis der Nutzer das nächste Mal sudo tippt.
  • Umgebung vergiften. Ein vorangestelltes Verzeichnis in PATH, ein gesetztes LD_PRELOAD oder ein PROMPT_COMMAND, das vor jedem Prompt läuft - alles unauffällige Variablen, die Code in jede folgende Aktion einschleusen.
  • Systemweit mit Root. Hat der Angreifer Root, legt er ein Skript in /etc/profile.d/ ab oder ergänzt /etc/profile beziehungsweise /etc/bash.bashrc. Dann trifft die Persistenz jeden Nutzer, der sich anmeldet - auch den Administrator, der den Vorfall untersucht.

Der gemeinsame Nenner: eine geänderte Konfigurationsdatei und, beim nächsten Login, ein Prozess, der aus einer frischen Shell heraus etwas tut, was ein Prompt nicht tun sollte. Beide Spuren tragen die Erkennung - aber erst zusammen.

Welche Logquellen die Technik zeigt

  • auditd (die wichtigste Quelle für die Änderung). Datei-Watches auf die systemweiten Dateien sind eindeutig und leise: -w /etc/profile -p wa -k shellrc, -w /etc/profile.d/ -p wa -k shellrc, -w /etc/bash.bashrc -p wa -k shellrc (beziehungsweise /etc/bashrc) und die zsh-Gegenstücke. Der PATH-Datensatz nennt die Datei, der SYSCALL-Datensatz den schreibenden Prozess (exe), das Konto (auid) und die Elternkette (ppid). Für die Nutzerdateien gibt es kein Globbing: Entweder ein Watch je Konto (per Skript aus /etc/passwd erzeugt, etwa -w /home/alice/.bashrc -p wa -k shellrc), oder eine Syscall-Regel auf das Home-Verzeichnis (-a always,exit -F arch=b64 -F dir=/home -F perm=wa -k homewrite; der perm-Filter wählt die passenden Schreib-Syscalls selbst, ein zusätzliches -S ist dort nicht nötig), die dann im SIEM auf die Dateinamen gefiltert wird - deutlich lauter, aber vollständig. Der Unterschied: Ein Watch (-w) hängt am Inode der konkreten Datei und meldet jede Schreiboperation darauf, die Syscall-Regel erfasst alle schreibenden Aufrufe unterhalb des Verzeichnisses und braucht die Filterung nachgelagert. Die Watches erfassen jede Schreiboperation, auch das Anhängen per >>.
  • Sysmon for Linux. Event 11 (FileCreate) zeigt die neu angelegte Datei in /etc/profile.d/ oder eine neu geschriebene ~/.bashrc samt erzeugendem Prozess. Ob das bloße Anhängen an eine vorhandene Datei ein Event 11 auslöst, hängt davon ab, wie das Werkzeug die Datei öffnet, und ist im Lab zu prüfen - verlässlich bleibt dafür der auditd-Watch. Event 1 (Prozesserstellung) trägt die zweite Hälfte: den Einzeiler mit der Umleitung und, beim nächsten Login, den Prozess, den die manipulierte Shell startet.
  • journald, gezielt. Für die Änderung selbst liefert journald nichts. Hilfreich ist es für den Auslöser: Der sshd-Eintrag Accepted publickey oder Accepted password und die Session-Meldungen von systemd-logind markieren den Login, nach dem die Konfiguration ausgeführt wurde. Wer die Dateiänderung und den nächsten Login desselben Kontos zusammenlegt, hat den Zeitpunkt, an dem die Persistenz scharf wurde.
  • Dateiinhalt und Integrität. Die Datei selbst bleibt das belastbarste Artefakt: Ein FIM-Werkzeug wie AIDE auf /etc/profile, /etc/profile.d/ und den Shell-Dateien der privilegierten Konten meldet jede Abweichung vom Soll-Zustand, und der Vergleich mit der Paketversion (dpkg -V, rpm -V) zeigt, ob eine Systemdatei vom Original abweicht.

Das Muster im Log

Die systemweiten Dateien sind einfach: Sie ändern sich außerhalb von Paketinstallationen und Konfigurationsmanagement praktisch nie, jede andere Änderung ist ein Prüffall, und eine neue Datei in /etc/profile.d/, die kein Paket mitbringt, ist ein starkes Signal. Die Nutzerdateien sind schwer: Entwickler pflegen ihre .bashrc wöchentlich, Installer von Werkzeugen wie nvm, pyenv, rustup oder conda hängen selbst Zeilen an, und das alles sieht in der Dateisicht genauso aus wie der Angriff. Drei Fragen trennen das Customizing vom Angriff: Wer hat geschrieben - der Editor oder die Shell des Nutzers, oder curl, python, ein Webserver-Kind oder ein Dienstkonto, das gar keine interaktive Shell haben sollte? Was steht in der Zeile - ein Alias für ls oder ein curl mit Pipe an bash, ein /dev/tcp, ein base64-Blob, ein nohup, ein sudo-Alias, ein LD_PRELOAD? Und was passiert beim nächsten Login - startet die frische Shell innerhalb von Sekunden ein Netzwerkwerkzeug oder einen Interpreter, der nichts mit einem Prompt zu tun hat? Die Änderung allein ist ein Hinweis; die Änderung plus verdächtiger Inhalt plus der Folgeprozess nach dem Login ist der Fall.

Drei Sigma-Regeln

Die Regeln sind mit sigma-cli validiert und nutzen die Linux-Logquellen file_event und process_creation. Die erste fängt jede Änderung an den systemweiten Dateien, die zweite den untypischen Schreiber einer Nutzerdatei, die dritte den Einzeiler mit Umleitung. Keine davon erkennt den Inhalt der angehängten Zeile - das bleibt der Analyse vorbehalten. Die Übersetzung ins SIEM steht unter Sigma-Regeln. sigma-cli-validiert heißt dabei: syntaktisch und gegen das verwendete ATT&CK-Dataset geprüft, nicht produktiv getestet. Image, CommandLine, ParentImage und TargetFilename sind die portable Sigma-Abstraktion, keine nativen auditd-Felder - Sysmon for Linux liefert sie direkt, bei auditd muss der Mapper sie aus exe, a0 bis aN, ppid und den PATH-Datensätzen aufbauen; ParentImage braucht dazu eine Prozessbaum-Anreicherung. Weitere Techniken dieser Taktik führt das Lexikon nach Taktik unter Persistence.

1. Systemweite Shell-Konfiguration geändert (T1546.004). Jede Schreiboperation außerhalb des Paketmanagers ist ein Prüffall, auf level: high.

Sigma
title: Systemweite Shell-Konfiguration geaendert
id: b0b6a6fe-0488-4ece-9961-e5970ab09246
status: experimental
description: |
  Erkennt das Anlegen oder Aendern einer systemweiten Shell-Konfigurationsdatei
  (/etc/profile, /etc/profile.d/, /etc/bash.bashrc, /etc/bashrc, /etc/zshenv,
  /etc/zprofile, /etc/zshrc). Diese Dateien fuehrt jede Login- oder interaktive Shell
  aller Nutzer aus; ein Angreifer mit Root hinterlegt dort Code, der bei jeder
  Anmeldung wieder startet (Unix Shell Configuration Modification). Ausserhalb von
  Paketinstallationen und Konfigurationsmanagement aendern sich diese Dateien
  praktisch nie. Die Aenderung allein ist noch kein Beweis - der Inhalt (Download,
  Reverse Shell, PATH- oder LD_PRELOAD-Manipulation, sudo-Alias) und der Prozess, der
  beim naechsten Login daraus entsteht, entscheiden.
references:
  - https://attack.mitre.org/techniques/T1546/004/
author: blue-team.net
date: 2026-10-09
tags:
  - attack.persistence
  - attack.privilege-escalation
  - attack.t1546.004
logsource:
  product: linux
  category: file_event
detection:
  sel_system:
    TargetFilename|startswith:
      - '/etc/profile'
      - '/etc/bash.bashrc'
      - '/etc/bashrc'
      - '/etc/zshenv'
      - '/etc/zprofile'
      - '/etc/zshrc'
      - '/etc/zsh/'
  filter_pkg:
    Image|endswith:
      - '/dpkg'
      - '/rpm'
      - '/dnf'
      - '/yum'
      - '/apt'
      - '/apt-get'
      - '/zypper'
  condition: sel_system and not filter_pkg
falsepositives:
  - Paketinstallationen und Updates, die /etc/profile.d/ bedienen, sowie Konfigurationsmanagement (Ansible, Puppet, Chef) - deren Prozesse und Wartungsfenster als Baseline ausnehmen
level: high

2. Benutzer-Shell-Konfiguration von einem Downloader oder Interpreter geschrieben (T1546.004). Der untypische Schreiber als Unterscheidungsmerkmal zum Customizing, auf level: medium.

Sigma
title: Benutzer-Shell-Konfiguration von einem Downloader oder Interpreter geschrieben
id: 65b5178b-2dcd-4fc7-9b3f-c76eb82ff647
status: experimental
description: |
  Erkennt das Schreiben einer Shell-Konfigurationsdatei im Benutzerprofil (.bashrc,
  .bash_profile, .bash_login, .profile, .zshrc, .zshenv, .zprofile) durch ein
  Download-Werkzeug oder einen Skript-Interpreter statt durch einen Editor oder die
  Shell des Nutzers. Normales Customizing laeuft ueber vim, nano oder ein echo aus
  der eigenen Shell; curl, wget, python oder perl als Schreiber deuten auf eine
  automatisiert eingerichtete Persistenz hin (Unix Shell Configuration
  Modification). Die Regel fasst nur diesen untypischen Schreiber; eine Aenderung
  aus der Shell heraus bleibt mehrdeutig und braucht die Inhalts- und
  Folgeprozess-Pruefung.
references:
  - https://attack.mitre.org/techniques/T1546/004/
author: blue-team.net
date: 2026-10-09
tags:
  - attack.persistence
  - attack.privilege-escalation
  - attack.t1546.004
logsource:
  product: linux
  category: file_event
detection:
  sel_file:
    TargetFilename|endswith:
      - '/.bashrc'
      - '/.bash_profile'
      - '/.bash_login'
      - '/.profile'
      - '/.zshrc'
      - '/.zshenv'
      - '/.zprofile'
  sel_writer:
    Image|endswith:
      - '/curl'
      - '/wget'
      - '/python'
      - '/python3'
      - '/perl'
      - '/php'
      - '/node'
      - '/nc'
      - '/ncat'
  condition: sel_file and sel_writer
falsepositives:
  - Dotfile-Installer und Entwicklungswerkzeuge (nvm, pyenv, rustup, conda), die per Skript Zeilen in die Shell-Konfiguration eintragen - bekannte Installer als Baseline ausnehmen
level: medium

3. Zeile per Kommandozeile an eine Shell-Konfiguration angehängt (T1546.004). Der Einzeiler nach dem Shell-Zugriff, auf level: medium, weil Installer dasselbe tun.

Sigma
title: Zeile per Kommandozeile an eine Shell-Konfiguration angehaengt
id: a8560e80-ee80-4bf6-a1c0-f33fea2b686b
status: experimental
description: |
  Erkennt eine Shell-Kommandozeile, die per Umleitung (>>), tee -a oder sed -i in
  eine Shell-Konfigurationsdatei schreibt. Das ist der klassische Einzeiler, mit dem
  Angreifer nach einem Shell-Zugriff eine Zeile in .bashrc, .profile oder
  /etc/profile hinterlegen (Unix Shell Configuration Modification). Nutzer und
  Installationsskripte tun dasselbe legitim, deshalb traegt der Treffer erst mit
  Konto, Elternprozess (Webserver, sshd-Sitzung eines Dienstkontos) und Inhalt der
  angehaengten Zeile Gewicht. Die Regel setzt voraus, dass die Kommandozeile der
  Shell mit dem Umleitungsausdruck protokolliert wird (bash -c "..."); eine
  interaktiv getippte Umleitung erscheint nicht als Prozessstart.
references:
  - https://attack.mitre.org/techniques/T1546/004/
author: blue-team.net
date: 2026-10-09
tags:
  - attack.persistence
  - attack.privilege-escalation
  - attack.t1546.004
logsource:
  product: linux
  category: process_creation
detection:
  sel_target:
    CommandLine|contains:
      - '.bashrc'
      - '.bash_profile'
      - '.bash_login'
      - '.profile'
      - '.zshrc'
      - '.zshenv'
      - '.zprofile'
      - '/etc/profile'
      - '/etc/bash.bashrc'
      - '/etc/bashrc'
  sel_write:
    CommandLine|contains:
      - '>>'
      - 'tee -a'
      - 'sed -i'
  condition: sel_target and sel_write
falsepositives:
  - Installationsskripte von Entwicklungswerkzeugen und Dotfile-Manager, die Zeilen per Umleitung eintragen
  - Administratoren, die Shell-Konfigurationen per Skript ausrollen - bekannte Skripte und Konten als Baseline ausnehmen
level: medium

Härtung

  • Systemdateien unter Integritätskontrolle. /etc/profile, /etc/profile.d/, /etc/bash.bashrc und die zsh-Dateien per AIDE oder Paketprüfung gegen den Soll-Zustand halten; Änderungen nur über Konfigurationsmanagement ausrollen, damit jede andere Änderung ein Alarm ist.
  • Dienstkonten ohne Shell. Konten wie www-data, nobody oder Datenbankkonten bekommen /usr/sbin/nologin. Dann gibt es für sie keine Shell, die eine Konfiguration lesen könnte - und ein Schreibzugriff auf eine .bashrc in deren Home ist eindeutig fremd.
  • Privilegierte Konten besonders schützen. Die Shell-Dateien von root und von Administratoren sind die wertvollsten Ziele (sudo-Alias). Sie gehören auf die auditd-Watchliste und ins FIM, und sudo sollte mit use_pty und einem fest gesetzten secure_path laufen, damit ein vergifteter PATH nicht bis zum sudo-Aufruf reicht.
  • Egress begrenzen. Die meisten Zeilen in einer manipulierten .bashrc wollen nach außen - Nachladen oder Rückverbindung. Eine Default-Deny-Regel für ausgehenden Verkehr auf Servern lässt sie ins Leere laufen und macht den Versuch in der Firewall sichtbar.

Der Test

Die Erkennung lässt sich im Lab gefahrlos prüfen, auf einer isolierten VM mit auditd-Dateiwatches und Sysmon for Linux - die Testzeilen danach wieder entfernen:

  • Für Regel 1 eine harmlose Testdatei in /etc/profile.d/ anlegen (etwa ein echo). Der auditd-PATH-Datensatz muss die Datei und exe zeigen, Sysmon for Linux Event 11 den erzeugenden Prozess, die Regel greifen.
  • Für Regel 2 eine Zeile per python3 -c an die ~/.bashrc eines Testkontos anhängen und prüfen, dass python als Schreiber im Ereignis steht; dieselbe Zeile per vim schreiben und prüfen, dass die Regel dann nicht auslöst.
  • Für Regel 3 den Einzeiler als bash -c "echo '# test' >> ~/.bashrc" absetzen und den Prozesstreffer kontrollieren. Dabei auch prüfen, ob Event 11 beim Anhängen an die vorhandene Datei auslöst oder erst beim Neuanlegen - das zeigt, wie weit die file_event-Regeln auf der eigenen Pipeline tragen.
  • Für die zweite Hälfte der Erkennung eine Testzeile eintragen, die beim Login ein harmloses Programm startet, sich neu anmelden und prüfen, dass Event 1 das Programm als Kind der frischen Login-Shell zeigt - unmittelbar nach dem sshd-Eintrag in journald.
  • Breiter wird der Test mit den Fällen zu T1546.004 aus Atomic Red Team.

Fehlalarme und Tuning

  • Normales Customizing ist der Normalfall. Nutzer ändern ihre .bashrc laufend, und das ist auf Entwicklungssystemen kein Signal. Die Regeln 2 und 3 nicht auf alle Hosts gleich scharf stellen: Auf Servern mit wenigen interaktiven Konten sind sie präzise, auf Entwickler-Arbeitsplätzen brauchen sie eine Baseline je Host und Konto.
  • Werkzeug-Installer. nvm, pyenv, rustup, conda, sdkman und Dotfile-Manager hängen per Skript Zeilen an und lösen Regel 3 legitim aus. Ihre typischen Zeilen (export PATH, source-Aufrufe auf bekannte Pfade) und Installer-Prozesse als Baseline hinterlegen, nicht die Regel entschärfen.
  • Paketverwaltung und Konfigurationsmanagement. Pakete schreiben legitim nach /etc/profile.d/, Ansible und Puppet pflegen Shell-Konfigurationen zentral. Deren Prozesse und Wartungsfenster gehören in die Baseline von Regel 1.
  • Höher gewichten statt breiter alarmieren. Systemdateien, Shell-Dateien von root und Administratoren, Schreiber aus einem Webserver- oder Dienstkontext und Inhalte mit Netzwerkbezug wiegen schwer. Eine Alias-Zeile in der .bashrc eines Entwicklers wiegt leicht - außer sie betrifft sudo.

Analysten-Checkliste

  • Welche Datei wurde geändert - systemweit (/etc/profile, /etc/profile.d/, /etc/bash.bashrc) oder im Profil eines Nutzers? Wessen Profil, und ist das Konto interaktiv?
  • Wer hat geschrieben (exe, auid, Elternkette)? Editor oder Shell des Nutzers, Installer, Konfigurationsmanagement - oder curl, python, ein Webserver-Kind, ein Dienstkonto?
  • Inhalt der neuen Zeilen prüfen (diff gegen Backup oder Paketversion): curl oder wget mit Pipe, /dev/tcp, base64, nohup, Pfade in /tmp, alias sudo, export PATH oder LD_PRELOAD, PROMPT_COMMAND, BASH_ENV?
  • Gab es seit der Änderung einen Login des betroffenen Kontos (sshd, logind), und was hat die Login-Shell unmittelbar danach gestartet?
  • Welcher vorangehende Shell-Zugriff führt zu der Änderung - Webshell, Reverse Shell, gestohlener SSH-Schlüssel?
  • Weitere Persistenz im selben Zeitfenster: neue Cron-Einträge, Units, authorized_keys-Zeilen oder Konten?

Fazit

Die Shell-Konfiguration ist die Persistenz, die sich hinter dem Alltag versteckt: eine Zeile zwischen Aliassen und PATH-Einträgen, ausgeführt von jedem Nutzer, der sich anmeldet, und ohne jedes besondere Recht. Die systemweiten Dateien sind dabei dankbar, weil sie sich fast nie ändern; die Nutzerdateien sind schwer, weil sie sich ständig ändern. Wer die Systemdateien mit auditd und FIM festnagelt, bei den Nutzerdateien auf den Schreiber und den Inhalt schaut und vor allem den Prozess erfasst, den die Login-Shell beim nächsten Mal startet, trennt den Angriff vom Customizing. Der Zugang davor läuft meist über eine Unix-Shell; die lauteren Geschwister dieser Persistenz stehen unter Cron- und systemd-Persistenz und SSH authorized_keys. Weitere Techniken dieser Taktik führt das Lexikon nach Taktik unter Persistence.

NH

$ whoami

Norbert Hofmann

Cyber Defense Analyst im Security Operations Center eines Managed Security Service Providers. Red und Blue Teaming, Malware-Analyse, Incident Response und Security-Awareness-Trainings. Finalist bei „Deutschlands bester Hacker“ 2022, mehrere CVE-Einträge für WordPress-Plugins.