Beschreibung:
Das Ziel ist es, einen Linux-Benutzer anzulegen, der sich per SSH anmelden kann, aber nur ausführbare Skripte aus bestimmten Verzeichnissen starten darf.
Der Artikel zeigt eine einfache Variante (ein Verzeichnis) und eine erweiterte Variante (mehrere Verzeichnisse).
Optional werden Sicherheitsprüfungen angeboten: (A) Skript muss root-Eigentümer sein, (B) Gruppe/Other dürfen keine Schreibrechte haben.
INHALTSVERZEICHNIS
- Benutzer anlegen
- Grundlegende SSH-Konfiguration (ForceCommand)
- Einfacher Wrapper (ein Verzeichnis)
- Erweiterter Wrapper (mehrere Pfade) + optionale Sicherheitsprüfungen
- Tests und Beispielaufrufe
- Hinweise & weiterführende Sicherheitsempfehlungen
- Weiteres / FAQs
Benutzer anlegen
Option 1:
Wir legen einen Benutzer an, der sich per SSH anmelden darf, aber keine interaktive Shell bekommen soll.
Vorher wird noch ein SSH Schlüsselpaar nach dem OpenSSH Standard erzeugt.
# Beispiel: Benutzer "servereye": sudo adduser --disabled-password --gecos "" servereye # Alternativ systemuser ohne Home (falls das gewünscht ist): sudo useradd -m -s /usr/sbin/nologin servereye # Erstelle SSH-Verzeichnis und setze Rechte: sudo -u servereye mkdir -p /home/servereye/.ssh sudo chmod 700 /home/servereye/.ssh # Neues Schlüsselpaar für den erstellten Benutzer erzeugen (Platzhalter austauschen): ssh-keygen -t ed25519 -C "servereye@example" # Den generierten Public Key zu authorized_keys hinzufügen und Rechte setzen cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys # Wichtig: Zuvor erzeugtes Schlüsselpaar außerhalb vom Server abspeichern und vom Server löschen. # Rechte anpassen sudo chmod 600 /home/servereye/.ssh/authorized_keys sudo chown -R servereye:servereye /home/servereye/.ssh
Option 2:
Wir legen einen normalen Benutzer (nicht Systemuser, sondern einen regulären Account, mit Passwort und Home-Verzeichnis) an, der sich per SSH anmelden darf.
# Beispiel: Benutzer "servereye" (normaler Benutzer mit Passwort): sudo adduser servereye # Danach wirst du interaktiv nach Passwort und Benutzerinfos gefragt. # Ab diesem Punkt optional: Falls du den Benutzer automatisch ohne interaktive Eingabe anlegen willst: # (z. B. mit einem voreingestellten Passwort) # ACHTUNG: Das Passwort steht hier im Klartext – besser nur für Skripte oder Tests verwenden! sudo adduser --gecos "" --disabled-password servereye echo "servereye:meinpasswort" | sudo chpasswd
Hinweis:
--disabled-password verhindert Passwortlogins für den neuen Account (nur Schlüssel oder ForceCommand).
Wenn du Passwort-Logins erlauben willst, musst du /etc/ssh/sshd_config entsprechend konfigurieren (nicht empfohlen).Grundlegende SSH-Konfiguration (ForceCommand)
Wir verwenden ForceCommand in sshd_config, damit alle Logins dieses Benutzers durch unseren Wrapper laufen.
Bitte folgende Schritte durchführen:
- Öffne /etc/ssh/sshd_config (als root):
sudo nano /etc/ssh/sshd_config - Füge am Ende (oder an geeigneter Stelle) Folgendes ein:
# Für den einfachen Wrapper: Match User servereye ForceCommand /usr/local/bin/ssh-wrapper-einfach.sh PermitTTY no AllowTcpForwarding no X11Forwarding no # Für den erweiterten Wrapper: Match User servereye ForceCommand /usr/local/bin/ssh-wrapper-erweitert.sh PermitTTY no AllowTcpForwarding no X11Forwarding no - SSH neu starten:
sudo systemctl restart ssh # oder: sudo service ssh restart
Warum ForceCommand? Dadurch wird unabhängig davon, was der SSH-Client anfordert, unser Wrapper ausgeführt. Das verhindert interaktive Shells, sofern der Wrapper dies unterbindet.
Einfacher Wrapper (ein Verzeichnis)
Das Minimalziel: Der Benutzer darf nur ausführbare Dateien aus einem einzigen Verzeichnis starten, z. B. /usr/local/nagios/libexec.
Installation & Rechte
# Skript auf das System herunterladen: sudo curl "https://servereye.freshdesk.com/helpdesk/attachments/14168053951" --output "/usr/local/bin/ssh-wrapper-einfach.sh" -L # Berechtigungen setzen: sudo chmod 755 /usr/local/bin/ssh-wrapper-einfach.sh sudo chown servereye /usr/local/bin/ssh-wrapper-einfach.sh # Optional, wenn nur root Benutzer Skripte ausführen dürfen: sudo chown root:root /usr/local/bin/ssh-wrapper-einfach.sh
Das Verzeichnis, aus dem Skripte ausgeführt werden dürfen, wird durch die Skriptvariable "ALLOWED_DIR" im einfachen Wrapper konfiguriert.
Standardmäßig ist dort folgender Pfad eingetragen: /usr/local/nagios/libexec
Erweiterter Wrapper (mehrere Pfade) + optionale Sicherheitsprüfungen
Nachfolgend ein Wrapper, der
- mehrere erlaubte Verzeichnisse unterstützt, und
- optional (konfigurierbar) prüft, dass Skripte root-Eigentümer sind, sowie dass Group/Other keine Schreibrechte haben.
Installation & Rechte
# Skript auf das System herunterladen: sudo curl "https://servereye.freshdesk.com/helpdesk/attachments/14168053953" --output "/usr/local/bin/ssh-wrapper-erweitert.sh" -L # Berechtigungen setzen: sudo chmod 755 /usr/local/bin/ssh-wrapper-erweitert.sh sudo chown servereye /usr/local/bin/ssh-wrapper-erweitert.sh # Optional, wenn nur root Benutzer Skripte ausführen dürfen: sudo chown root:root /usr/local/bin/ssh-wrapper-erweitert.sh
Konfiguration anpassen
- ALLOWED_DIRS anpassen (Pfadliste)
Standardmäßig sind als Beispiel folgende Pfade eingetragen:
"/home/servereye/scripts""/usr/local/nagios/libexec"
"/srv/other-scripts"
- REQUIRE_ROOT_OWNER und REQUIRE_NO_GRP_OTHER_WRITE auf false setzen, falls du diese Prüfungen nicht möchtest.
Tests und Beispielaufrufe
Beispielskript anlegen
sudo mkdir -p /home/servereye/scripts
sudo tee /home/servereye/scripts/hello.sh > /dev/null <<'EOF'
#!/bin/bash
echo "hello from wrapper"
EOF
sudo chmod 755 /home/servereye/scripts/hello.sh
sudo chown root:root /home/servereye/scripts/hello.sh # falls REQUIRE_ROOT_OWNER=trueTest mit SSH
Erlaube deinem Client, sich per Schlüssel zu verbinden oder nutze eine Testumgebung.
Auf dem Client:
ssh servereye@server " /home/servereye/scripts/hello.sh"Erwarte: Ausgabe hello from wrapper.
ssh servereye@server " /usr/local/nagios/libexec/check_disk -w 10% -c 5% -p / "Erwarte: DISK OK - free space: / 106155 MiB (89,96% inode=96%);| /=11837MiB;111919;118137;0;124355
Negativtests
- Aufruf eines Skripts außerhalb der erlaubten Pfade → abgelehnt.
- Skript nicht ausführbar → abgelehnt.
- Skript mit falschen Rechten/Eigentümer → abgelehnt (falls Option gesetzt).
Hinweise & weiterführende Sicherheitsempfehlungen
- Whitelist vs. Directory: Am sichersten ist es, konkrete Basenames zu whitelisten (z. B. nur backup.sh, report.sh) statt ganze Verzeichnisse freizugeben. Verzeichnisse sind praktischer, aber riskanter.
- Skript-Eigentum & Berechtigungen: Stelle sicher, dass nur privileged Admins Skripte in den erlaubten Verzeichnissen ablegen oder ändern können.
- Sudo: Wenn sudo verwendet wird, konfiguriere /etc/sudoers restriktiv — z. B. servereye ALL=(root) NOPASSWD: /usr/bin/some-specific-command.
- Logging & Monitoring: Logge jeden Aufruf (logger) und überwache /var/log/auth.log bzw. ein zentrales Logging
- Keine interaktiven Pagers: Vermeide less/more mit Shell-Escape; verwende bei Bedarf sed/awk/tail.
Weiteres / FAQs
Q: Kann der Benutzer durch ein erlaubtes Skript die Shell trotzdem ausbrechen?
A: Ja, ein erlaubtes Skript kann weitere Binaries aufrufen (z. B. bash, python) sofern diese im System verfügbar sind. Daher sind Eigentums-/Berechtigungsprüfungen und/oder Sandboxing wichtig.
Q: Kann ich Pipes/if-Statements erlauben?
A: Ja, dazu muss der Wrapper erlauben, dass SSH_ORIGINAL_COMMAND Shell-Ausdrücke (wie if ...; then ...; fi oder grep ... | wc -l) ausführt, und dabei alle verwendeten Binaries prüfen. Das erfordert komplexere Parsing-Logik (siehe vorherige Konversation). Eine sicherere Alternative ist, solche Logik in vertrauenswürdige Skripte im erlaubten Verzeichnis auszulagern.