Ermöglichen Sie regulären Benutzern SSH mit einem privaten Schlüssel, den sie nicht lesen können

8

Angenommen, ich habe eine Reihe von Maschinen (hier die Maschinen der Kunden genannt), auf die nur eine kleine Liste von Personen (die als Support-Mitarbeiter bezeichnet werden) SSH ausführen kann, wobei nur ein Konto pro Maschine (das Support-Zugriffskonto) verwendet wird.

Das Support-Personal soll sich nur mit Schlüsseln bei den Kunden anmelden. Darüber hinaus kann sich das Support-Personal weiterentwickeln, sodass sich jemand, der das Support-Personal verlässt, nicht bei einem Kundencomputer anmelden darf. Daher ist es Mitarbeitern untersagt, die privaten Schlüssel zu lesen, mit denen sie sich bei den Computern der Kunden anmelden. Es ist auch verboten, die authorized_keysDatei auf den Computern der Kunden zu ändern .

Um diese Konfiguration zu realisieren, hatte ich die Idee, einen SSH-Proxy zu verwenden, bei dem sich die Support-Mitarbeiter anmelden (mit LDAP-Authentifizierung, aber das ist ein weiteres Problem) und der die privaten Schlüssel enthält.

Die Frage ist: Wie erlaube ich Supportmitarbeitern, den privaten SSH-Schlüssel zu verwenden, ohne ihn lesen zu können?

Ich glaube, dass ich einen Daemon als Root auf dem Proxy-Computer ausführen muss, der die Anforderung eines Benutzers akzeptiert und eine SSH-Sitzung für ihn öffnet, aber ich habe keine Ahnung, wie das geht. Irgendwelche Ideen?

Raspbeguy
quelle
Die Frage wurde bearbeitet, da "Clients-Computer" schwer zu verstehen sein können (bedeutet nicht das Gegenteil von Server).
Raspbeguy
Das ist sehr mutig, und das meiste davon scheint irrelevant zu sein. Es lenkt ab. Denken Sie, dass Sie in Zukunft viel weniger Mut gebrauchen könnten? Vielen Dank.
DW
Ich gehe davon aus, dass sich die Einschränkung " authorized_keys" nur auf dynamische Änderungen bezieht (z. B. wenn ein neues Support-Mitglied beitritt / verlässt), da Sie eine Erstkonfiguration auf dem Kundencomputer benötigen .
Ángel

Antworten:

6

Ich würde ein paar Optionen vorschlagen.

  1. Schützen Sie den SSH-Schlüssel und fordern Sie die Verwendung sudoauf der Seite Ihres Support-Teams. Sie können dies transparent mit einem Wrapper tun. Rufen Sie den Wrapper an /usr/local/bin/ssh-supportund lassen Sie ihn so etwas enthalten (ungetestet):

    #!/bin/bash
    export PATH=/usr/local/bin:/usr/bin:/bin
    export IFS=$' \t\n'
    export SUSER=ssupport
    
    # Restart if not running under sudo
    test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@"
    shift
    export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)"
    
    # Extract single argument as hostname LABEL and validate that we have
    # an RSA private key for it. The target username, real hostname, port,
    # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport)
    label="$1"
    idfile="$SUSER/.ssh/id_rsa_for_$label"
    cgfile="$SUSER/.ssh/config"
    
    ok=true
    [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; }
    [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; }
    [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; }
    
    if test -n "$ok"
    then
        logger -t ssh-support "$SUDO_USER requested ssh to $label"
        exec ssh -i "$idfile" -F "$cgfile" "$label"
    fi
    exit 1
    

    Dies würde einen Eintrag in der sudoersDatei erfordern , der es Benutzern in der supportGruppe ermöglicht, das Tool zu verwenden. Mit diesem Befehl können sie das ssh-supportTool als ssupportBenutzer ausführen - was Sie erstellen müssen. Es ist nicht verleihen jede Root - Rechte.

    %support ALL = (ssupport) /usr/local/bin/ssh-support

    Wenn Sie zufrieden sind, dass die Support-Benutzer kein eigenes Kennwort angeben müssen, um das Tool auszuführen (wie vom sudoAufruf im Skript selbst angefordert ), können Sie die sudoersDefinition folgendermaßen ändern :

    %support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support

    Angenommen, PATHenthalten /usr/local/bin/würden Sie es dann mit nennen ssh-support clientname. Angenommen, Sie haben den ssupportBenutzer so erstellt, wie /home/ssupportSie ihn erstellen würden, /home/ssupport/.ssh/id_rsa_clientnameund /home/ssupport/.ssh/id_rsa_clientname.pubals Zertifikatspaar, und einen Hosteintrag /home/ssupport/.ssh/configfür clientnameden Benutzer, den Host, den Port usw. für den Zielcomputer definiert. Sie würden wahrscheinlich die X11-Weiterleitung, die Portweiterleitung usw. explizit deaktivieren. Wie üblich /home/ssupport/.sshmüsste das Verzeichnis mit Berechtigungen geschützt werden 0700.

  2. Geben Sie jedem Support-Mitglied ein eigenes lokales Benutzerkonto und lassen Sie jede Person ihren eigenen privaten SSH-Schlüssel verwenden, um auf die Server des Clients zuzugreifen. Wenn eine Person die Support-Gruppe verlässt, entfernen Sie ihren SSH-Schlüssel von den Servern des Clients. Dies bedeutet, dass Sie sich nicht mehr darum kümmern müssen, dass Ihre Mitarbeiter den privaten SSH-Schlüssel nicht kennen.

Roaima
quelle
Die zweite Option ist ungültig. Wie gesagt, es gibt nur ein Support-Konto auf den Client-Servern und Sie können der SSH-Konfiguration keine öffentlichen Schlüssel hinzufügen. Das sind die Regeln. Tatsächlich können Sie nichts an der SSH-Konfiguration auf den Client-Computern ändern.
Raspbeguy
4
Diese Antwort ist übrigens ein typisches Beispiel für (ab) die Verwendung von sudo. Ich habe einen Artikel zum Thema geschrieben ( dmitry.khlebnikov.net/2015/07/… ). Es scheint, dass es einen Trend gibt, alles mit sudo zu lösen. Dies schwächt jedoch nur die Sicherheit Ihrer Systeme und verbessert sie nicht.
Galaxie
1
@Raspbeguy natürlich werden sie nicht. Die sudoersZeile beschränkt den Zugriff auf den einzelnen Befehl
Roaima
1
Sie übergeben ssh ungeprüfte Optionen mit "$ @", das als root ausgeführt wird! Ich kann mir verschiedene Möglichkeiten -E-L,-R,-D-o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'
vorstellen, um beschädigte Systemdateien zu ätherisieren
1
@roaima: Wie auch immer, Ihre Sudo-to-Root-Idee hat Probleme, aber sie sind andere Probleme als die, über die der Blog-Beitrag der Galaxie gesprochen hat. Er redet ssh root@somewheremit Schlüsseln und ssh user@somewheredann mit Sudo. Es ist eigentlich ein wirklich guter Punkt. Die einzige Möglichkeit für diesen Fall ist ssh keyowner@localhost ssh_to_client client.example.org jedoch eine Alternative zu sudo -u keyowner ssh_to_client client.example.org. Ähnlich wie bei sudo kann SSH die Befehle einschränken, die ein Benutzer ausführen darf. Wir sprechen über passwortloses Sudo für Nicht-Root-Benutzer, nicht für den Anwendungsfall von Galaxy.
Peter Cordes
11

Was Sie wirklich tun möchten, ist, die SSH-Zertifizierungsstelle zu verwenden und die von jeder Support-Person verwendeten Schlüssel zu signieren (sie sollten ihre eigenen SSH-Schlüssel haben, wie z. B. Pässe) und die Server Ihrer Clients so zu konfigurieren, dass sie die TrustedUserCAKeys /etc/ssh/users_ca.pubin der Datei / etc / ssh / sshd_config verwenden. Auf diese Weise akzeptiert der Server alle vom CA-Schlüssel signierten Schlüssel (auf die Sie Zugriff haben) und Sie können Schlüssel von Personen widerrufen, die nicht mehr unterstützt werden, ohne auch nur autorisierte_Tasten zu berühren.

Eine schnelle Suche nach "ssh ca" zeigte auf dieses Tutorial: https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with -ubuntu (scrollen Sie nach unten zu "So konfigurieren Sie Benutzerschlüssel") - Obwohl im Lernprogramm Ubuntu erwähnt wird, ist es verteilungsunabhängig, aber Sie benötigen eine neue Version von OpenSSH, die SSH CA unterstützt

Ein weiterer guter Blogeintrag zum Thema ist https://ef.gy/hardening-ssh (scrollen Sie nach unten zu "SSH-Zertifikate").

Achten Sie besonders darauf, dass Sie den Schlüssel für eine begrenzte Zeit unterschreiben können, damit er automatisch abläuft!

Galaxis
quelle
Es wäre eine gute Idee, wenn die Maschinen der Kunden Zugang zum Internet hätten (um die Gültigkeit einer Signatur zu aktualisieren), was nicht immer der Fall ist. Wir verbinden uns mit diesen Maschinen über ein vom Kunden bereitgestelltes VPN.
Raspbeguy
Nun, das ist so nah wie möglich, ohne einen Schlüssel mit einer Person zu verlieren, die Ihr Unternehmen verlässt. Ich habe Ihnen den Mechanismus zur Verfügung gestellt, Sie können ihn automatisieren, z. B. können Sie einen Duty Officer haben, der Ihre Personalabteilung unterstützt, wenn Mitarbeiter das Unternehmen verlassen, und Sie können ein Verfahren zum Widerrufen von Schlüsseln definieren.
Galaxie
1
Darüber hinaus können Sie einen Schlüssel (einen Support-Mitarbeiter) für eine begrenzte Zeit signieren - z. B. können Sie ihn nur für 8 Stunden (für ihre Schicht) signieren, nach 8 Stunden läuft er ab und der Server lässt sie nicht herein.
Galaxie
3
In Bezug auf Ihren LDAP-Teil - Ich arbeite derzeit in einem Unternehmen, das Hunderte von Instanzen verwaltet, und wir arbeiten an einer Open Source-Lösung zur Integration von SAML 2.0 und SSH CA. Die Idee ist, dass sich eine Person mit SSO authentifiziert und wenn sie autorisiert ist, ihre Schlüssel für einen definierten Zeitraum (z. B. 5 Minuten) signiert bekommt. All dies ist für den Benutzer ziemlich transparent und wird mit dem ProxyCommand von ~ / .ssh / config implementiert.
Galaxie
2

Es gibt verschiedene Antworten, die ein Wrapper-Skript für ssh betreffen, das über sudo oder setuid-executeable (für ein spezielles Nicht-Root- Konto) aufgerufen wird . Wie nkms sagt , kann der Benutzer durch Übergeben aller Argumente an ssh beliebige Dinge mit den ssh-Schlüsseln tun, die wir schützen möchten . Das andere Extrem, das sich einige ausgedacht haben, ist, nur einen Hostnamen zuzulassen.

Das OP sagt, dass Administratoren in der Lage sein müssen, Dinge hochzuladen.

Sie könnten zwei verschiedene Wrapper mit festen Argumenten zu SSH haben. Eine für eine Login-Shell, eine andere für scp. Keine vom Benutzer angegebenen Argumente außer Hostname (und Dateiname zum Hochladen).

Oder ein Wrapper-Skript, das sich getoptselbst verwendet, um sehr eingeschränkte Optionen zu analysieren und Dinge in einen meist festen ssh-Befehl einzufügen. Das Ignorieren (oder Fehler) bei nicht erkannten Optionen wäre der richtige Weg.

Versuchen Sie nicht, "gefährliche" SSH-Optionen herauszufiltern, sondern schreiben Sie einfach einen Wrapper, der zwei Dinge tun kann: interaktive Anmeldung oder Hochladen einer Datei (lokale und entfernte Dateinamen). Sie müssen dort noch einige Desinfektionsarbeiten durchführen, denke ich.

Eigentlich ist das immer noch leicht falsch zu verstehen. Sie müssen einen Weg finden, um den Benutzer daran zu hindern, die Datei mit den SSH-Schlüsseln als lokale Datei anzugeben. Sie versuchen also immer noch, an alles zu denken, was nicht zugelassen werden muss, anstatt zunächst nichts zuzulassen. Es wäre ein Anfang, um sicherzustellen, dass die Dateinamen keine @oder enthalten :.

Peter Cordes
quelle
Die Wrapper-Idee ist in der Tat die Lösung, aber das impliziert eine Sicherheitsverletzung, die behoben werden muss.
Raspbeguy
Ich bin erstaunt, wie die Leute das Rad neu erfinden, wenn es nicht nötig ist. Die SSH-CA-Funktionalität wurde genau aus den Gründen und der Situation wie in der ursprünglichen Frage in OpenSSH eingeführt. Meine Lösung verwendete keine Wrapper und erreichte genau das, was gefragt wurde. Aus irgendeinem Grund entschied sich @Raspbeguy jedoch für den DIY-Weg mit fragwürdigen Auswirkungen auf die Sicherheit. :)
Galaxie
@galaxy: Ja, Ihre SSH-CA-Lösung ist mit Sicherheit die beste, es sei denn, Sie haben die absolute Anforderung, dass Sie keine einmaligen Änderungen an den Remote-Systemen vornehmen können, um deren SSHD für die Verwendung zu konfigurieren. Es klingt perfekt und leicht richtig zu machen.
Peter Cordes
@galaxy: Ihre Lösung ist wirklich elegant, aber in meinem Fall nicht anwendbar, wie ich Ihnen zuvor sagte. Ich mag die Idee wirklich, ich habe mit meinem Chef darüber gesprochen, aber es ist immer noch unmöglich. Keine Notwendigkeit, sich aufzuregen.
Raspbeguy
1
@Raspbeguy, ich bin nicht verärgert, ich verstehe nur nicht, warum Ihr Unternehmen seine Sicherheit opfern und etwas mit "Klebeband" implementieren möchte, wenn es einen geeigneten Weg gibt, dies zu tun. Und Ihr Kommentar war, dass es eine gute Lösung wäre, aber es hat Ihnen nicht gefallen, dass Sie den Widerruf nicht automatisieren konnten - und ich habe Ihnen auch die Lösung dafür bereitgestellt (indem Sie Schlüssel nur für die Schicht signiert haben). Wie auch immer, du hast deine Antwort gewählt, lass uns weitermachen :)
Galaxie
1

Wenn Sie einen SSH-Proxyserver einrichten, können Sie festlegen, dass die Shell (in /etc/passwd) Ihrer Mitarbeiter nicht auf eine Shell wie bash festgelegt ist, sondern auf ein einfaches Skript, das keinen Shell-Zugriff zulässt. Stattdessen würde dann nach einem Zielhostnamen ( read target) gefragt exec ssh "support@$target".

Beachten Sie, dass die Verwendung eines solchen Proxys die Verwendung von Tools wie scpdas Übertragen von Dateien auf / von den Kundencomputern möglicherweise erschwert . Dies kann ein Problem oder ein Vorteil sein!

Toby Speight
quelle
Diese Wrapper-Script-Idee ähnelt der Idee von @ roaima. Sie geben mit ssh Zugriff darauf, sudofunktionieren aber auch. Seine Antwort schlägt vor, den lokalen Root-Benutzer zu verwenden, aber ein Nicht-Root-Benutzer würde auch funktionieren. Siehe meine Kommentare zu seiner Antwort zur Diskussion darüber. (Meine ssh keyowner@localhostIdee ist die gleiche wie Ihre Idee.)
Peter Cordes
@Peter - ganz richtig: root ist absolut der falsche Benutzer dafür!
Toby Speight
Unterstützt Jungs müssen Dinge hochladen, so dass diese Lösung möglicherweise nicht funktioniert.
Raspbeguy
@Raspbeguy: hat eine Antwort gepostet, die dies anspricht. Verwendung in Kombination mit dem Roaima- sudoSetup ohne Rootberechtigung .
Peter Cordes
0

Ihre Support-Mitarbeiter stellen immer eine Verbindung über diesen Proxy-Computer her und nur von diesem aus, sodass die Clients den Proxy-Computer einfach mithilfe von HostbasedAuthentication authentifizieren können .

Angenommen, der Proxy-Computer ist supporters.pcund Sie bieten Unterstützung fürcustomer.pc

customer.pc hat HostbasedAuthentication yes in /etc/ssh/ssd_config, Supporters.pc in /etc/ssh/shosts.equivund seinen öffentlichen Schlüssel in /etc/ssh/ssh_known_hosts.

Wenn sich Ihre Support-Mitarbeiter bei [email protected] anmelden und ausführen ssh customer.pc, wird ssh-keysign (8) (das gesetzt werden muss) erzeugt, das die Schlüsselsignatur mit der Datei behandelt, die Sie nicht lesen können, und Geben Sie den Anhängern den Beweis, dass die Verbindung tatsächlich von den Anhängern stammt . Als customer.pc vertraut supporters.pc , wird Ihr Mitarbeiter angemeldet als Unterstützung .

Engel
quelle
Dies ist aus Sicherheitsgründen eine schreckliche Lösung, da Sie den Zugriff auf eine Maschine als Ganzes gewähren und die Verantwortung dafür verlieren, wer was getan hat. Das Vertrauen von Maschine zu Maschine sollte aus der modernen Welt verbannt werden, in der die IT-Sicherheit zu einem ziemlich heißen Thema wurde.
Galaxie
@galaxy, aus dem OP ist mein Verständnis, dass sie das im Grunde schon tun. Das Vertrauen in diese Maschine ist in der Spezifikation . Beachten Sie insbesondere, dass sie "nur ein Konto pro Computer verwenden (das Support-Zugriffskonto)". Möglicherweise verwenden sie ein freigegebenes Konto in customer.pc, stellen jedoch als eigener Benutzer eine Verbindung zum Server her. Das Ändern der Berechtigungen von ssh und ssh-keygen, um eine sudo -u-Unterstützung zu erzwingen, würde dies lösen und auch einen Protokolleintrag hinzufügen.
Ángel
0

Verwenden Sie eine Wrapper-Binärdatei

Für diesen speziellen Anwendungsfall (siehe den wichtigen Hinweis unten) besteht eine Möglichkeit darin, einen Benutzer (z. B. support-ssh) speziell für diese ausgehenden SSH-Verbindungen zu erstellen und dann eine kleine Wrapper-Binärdatei zu installieren, die ausgeführt wird /usr/bin/ssh.

  • Kopieren Sie die sshBinärdatei selbst nicht + chmod , da Sie nicht daran denken, sie jedes Mal neu zu kopieren, wenn Sie Sicherheitsupdates anwenden.
  • Und verwenden Sie es nicht rootals privilegierter Benutzer, da Gründe, denen ich vertraue, offensichtlich sind.

Dies ist eine funktional äquivalente Alternative zur Verwendung sudo, um die Berechtigungen auf die des support-sshKontos mit den folgenden Kompromissen zu erhöhen :

  • Dies ist kleiner und schlanker als sudo, sodass das Risiko von Konfigurationsfehlern geringer ist als beabsichtigt.
  • Es liegt in Ihrer Verantwortung, es richtig zu codieren - tun Sie dies nur, wenn Sie äußerst vorsichtig sind und (im Idealfall) Erfahrung mit sicherheitskritischer Codierung haben.
  • Es kann spezifischer angepasst werden als sudo(aber je mehr Code Sie schreiben, desto mehr müssen Sie auf Sicherheit prüfen).

Die Wrapper-Binärdatei sollte HOMEauf das support-sshHome-Verzeichnis des Benutzers eingestellt sein, damit sshder entsprechende ssh_configund private Schlüssel abgerufen wird. Dem aufrufenden Benutzer sollte jedoch nicht gestattet werden, ~support-ssh/.ssh/dessen Inhalt zu lesen .

Der Wrapper kann so einfach sein wie:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    setenv("HOME", "/home/support-ssh", 1);
    /* allow only a single, non-option argument */
    if (argc!=2 || *argv[1]=='-') {
        fprintf(stderr, "Usage: %s <hostname>", argv[0]);
        exit(EXIT_FAILURE);
    }
    execv("/usr/bin/ssh", argv);
    return EXIT_FAILURE;
}

Möglicherweise möchten Sie restriktiver sein und überprüfen, ob sich das Argument argv[1]in einer Reihe zulässiger Hostnamen befindet. Oder weniger restriktiv und erlauben (eine Teilmenge von) Optionsargumenten. Vielleicht möchten Sie auf Umgebungsvariablen vollständig ersetzen (aber tigeren halten wie TERM, LC_*usw.); Beachten Sie, dass LD_LIBRARY_PATHund LD_PRELOADsind besonders gefährlich.

scpBei Bedarf kann ein ähnliches Wrapper-Programm bereitgestellt werden.

Ein Hinweis zur Anwendbarkeit

Diese Antwort befasst sich mit den besonderen Umständen der Frage, unter denen die Benutzer vertraglich verpflichtet sind, Verfahren einzuhalten, und es gibt Sanktionen (z. B. Entlassung) für Verstöße gegen diese. Es wird davon ausgegangen, dass Sie verhindern möchten, dass die Mitarbeiter zufällig private Schlüssel kopieren, anstatt zu verhindern, dass ein entschlossener Angreifer unbefugten Zugriff erhält.

Ich bin der Ansicht, dass Sicherheit sowohl durch technische als auch durch nichttechnische Abwehrmaßnahmen erreicht wird und dass das hier oder durch Verwendung erzielte Gleichgewicht sudofür die dargestellte Situation angemessen ist.

Toby Speight
quelle
Sie übergeben ungeprüfte Argumente an ssh, das als anderer Benutzer ausgeführt wird. Siehe meinen Kommentar zur obigen Antwort. Ich kann den Schlüssel immer noch lesen ... und ich würde nicht mit strengen Argumentprüfungen rechnen, ssh soll nicht auf diese Weise ausgeführt werden.
nkms
@nkms - Ich habe den Wrapper restriktiver gemacht. Es kann bei Bedarf offener gemacht werden, aber Sie haben das Recht, Dinge zu sperren, sofern nicht anders angegeben, und nicht umgekehrt.
Toby Speight
@ TobySpeight: Ja, sieht gut aus. Ich habe das meiste, was ich in Kommentaren gesagt habe, sowieso in meine eigene Antwort eingefügt.
Peter Cordes
1
Es wäre besser, sudo als einen binären Wrapper zu verwenden. Im Gegensatz zu Ihrer Behauptung ist die Verwendung von sudo viel weniger riskant als das Rollen Ihres eigenen. Sudo hat sichere Standardeinstellungen. Wie sicher sind Sie, dass Sie nicht vergessen haben, eine Umgebungsvariable zu entfernen, die ssh beeinflussen würde?
Gilles 'SO - hör auf böse zu sein'