Ankündigung

Einklappen
Keine Ankündigung bisher.

Credentials möglichst sicher in der Session zwischenspeichern

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Credentials möglichst sicher in der Session zwischenspeichern

    Ich bin gerade dabei eine Intranet Plattform (Nachfolgend "Hub") zu planen, die verschiedene Anwendungen verbinden/zusammenfassen soll.
    Diese Anwendungen bieten unterschiedliche Schnittstellen zur Kommunikation, teils HTTP, teils WebDav, ggf. weitere.

    Die Benutzer stammen von einem LDAP Provider welcher jeweils getrennt mit der entsprechenden Plattform verknüpft ist.
    Auch mein Hub wird eine Authentifizierung darüber erfordern. Insgesamt hat jedenfalls jedes Interface seinen eigenen Auth Layer, basierend auf den selben Nutzerdaten.

    |---| <-> Wordpress
    |...| <-> Shopware

    |Hub| <-> PM-Tool
    |...| <-> WebDav
    |---| <-> FTP-Server

    Nun stehe ich etwas an, wie ich das nun sicherheitstechnisch am besten anstelle.
    Grundsätzlich wäre wohl OAuth oder SSO das Mittel der Wahl.
    Leider bieten manche angebundene Systeme dafür keine Unterstützung.

    Und zumindest OAuth wäre wohl auch eher eine Qual (Login/Erlauben -> Login/Erlauben -> Login/Erlauben -> ... bis alle Systeme autorisiert sind).

    Eine Authentifizierung via Username/Password funktioniert jedoch bei allen Systemen.
    Ich befürchte daher, es bleibt wohl nichts anderes übrig, als diese Daten beim Login auf dem Server zwischen zu speichern.

    Dass das ganze nicht sauber ist, ist mir klar.
    Um es aber zumindest etwas sicherer zu machen, habe ich mir folgenden Ablauf überlegt:


    1. Client übermittelt Login-Formular des Hubs
    2. Username und Password wird AES256(?) encrypted in der kurzlebigen (15min) Session abgelegt.
    3. Client erhält zusätzlich zur Session-ID den Decryption Key zurück. Auf dem Server wird dieser gelöscht.
    4. Nun muss der Browser mit jeder Request nicht nur die Session-ID mitgeben, sondern auch den Decryption Key, damit der Server die zwischengespeicherten Credentials lesen kann und in weiterer Folge mit den Systemen kommunizieren.
    5. (Sinnvoll?) Mit jeder Decryption wird wieder ein neuer Key generiert und der alte damit wertlos. (Vermutlich zu schlechte Performance)

    Insgesamt denke ich mir, dass das relativ bulletproof ist. Beide Parteien haben Informationen, die für sich alleine wertlos sind.
    In etwa wie ein Cloud-Passwordmanager mit Master-Passwort.
    Um das zu knacken, müsste man nicht nur Zugriff auf die Session Dateien erhalten, sondern auch noch den Decryption Key abfangen.
    Da kann man auch gleich die initiale Login-Payload abfangen. So zumindest meine Theorie.

    Mir bleibt eh nichts anderes übrig. Möchte das ganze aber dennoch in diesem Rahmen bestmöglich lösen.
    Wollte deshalb kurz eure Meinung dazu einholen, ob sich hier vielleicht noch ein Denkfehler versteckt oder Optimierung anbietet.

    Danke!

  • #2
    Wieso nutzt du nicht ein einfaches Loginfenster im Hub,
    welches nach der authetifizierung Auth Keys für jedes Programm in der jeweiligen Db hinterlegt,
    und links mit dem auth key im client darstellt.

    den link kann man ja mit automatisiert aufrufen und die nötige session für jedes ptogramm automatisiert erstellen.


    Kommentar


    • #3
      Zitat von sboesch Beitrag anzeigen
      Und zumindest OAuth wäre wohl auch eher eine Qual (Login/Erlauben -> Login/Erlauben -> Login/Erlauben -> ... bis alle Systeme autorisiert sind).
      OAuth bietet auch andere Verfahren an. Gerade bei der Kommunikation zwischen internen Apps kann mal ruhig die password_grant (Username/Passwort) Methode verwenden.
      Auch kann man (je nach OAuth Server) auch Standard-Clients definieren, wo der Benutzer nicht um Erlaubnis gefragt werden muss.

      Kommentar


      • #4
        Zitat von Zeichen32 Beitrag anzeigen
        Auch kann man (je nach OAuth Server) auch Standard-Clients definieren, wo der Benutzer nicht um Erlaubnis gefragt werden muss.
        Das wäre dann die client_grant Methode.

        Kommentar


        • #5
          Zitat von Dormilich Beitrag anzeigen

          Das wäre dann die client_grant Methode.
          Ne client_grant wäre es, wenn der Client (Also die App) sich mit ihrem secret und client id beim Ressourcen Server meldet.

          https://oauth.net/2/grant-types/

          Kommentar


          • #6
            Ist das nicht das, was du meintest?

            Kommentar


            • #7
              Zitat von Dormilich Beitrag anzeigen
              Ist das nicht das, was du meintest?
              Ne, da es beim TE zu aufwendig wäre den regulären Grant zu nehmen, habe ich vorgeschlagen password_grant zu nehmen, so dass er wie bei einem klassischen Login mit Username/Passwort arbeiten kann.

              Kommentar


              • #8
                Wie wäre es mit einem JWT?

                Kommentar


                • #9
                  Danke erst einmal allen für den Input.
                  Ich denke ich muss mich mit OAuth noch mal auseinandersetzen. Gerade auch was die Serverseite angeht.
                  Kenne ich bislang nur spärlich als "Consumer".

                  Das grundlegende Problem ist, dass mein Server (Hub) mit anderen Systemen kommunizieren muss, welche bereits seit Jahren bestehen und nur Username/Password Basic-Authentication unterstützen.
                  Diese Systeme werden nicht von mir betreut, weshalb ich auch nicht einfach die gesamte Infrastruktur umstrukturieren kann.
                  Bspw. ein klassischer FTP-Server.

                  Spätestens hier benötige ich also die Zugangsdaten des Nutzers um zugreifen zu können, wodurch ich auch gleich auf die anderen Systeme darüber zugreifen kann, statt extra OAuth zu implementieren.
                  Ich werde mir OAuth aber jedenfalls doch noch mal genauer ansehen.

                  xm22 JWT hilft mir hier denke ich auch nicht weiter. Enthält ja nur einen unverschlüsselten Claim.
                  Könnte zwar meine Cookies damit ersetzen, aber für das eigentliche Problem nützt es mir nichts.

                  Wie dem auch sei, hier zumindest mal meine Lösung für die verschlüsselte Session:

                  CredentialBag (Service):

                  PHP-Code:
                  public function storeCredentials(array $credentials)
                  {
                      
                  $iv openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->cipherMethod));
                      
                  $key bin2hex(openssl_random_pseudo_bytes($this->keyLength));
                      
                  $this->credentials $credentials;
                      
                  $decrypted json_encode($credentials);
                      
                  $encrypted openssl_encrypt($decrypted$this->cipherMethod$key0$iv);
                      
                  $this->session->set('credentials'$encrypted);

                      return 
                  base64_encode($key.':'.bin2hex($iv));
                  }

                  public function 
                  unlockCredentials(string $key)
                  {
                      
                  $key base64_decode($key);
                      
                  $parts explode(':'$key);
                      
                  $iv hex2bin($parts[1]);
                      
                  $encrypted $this->session->get('credentials');
                      
                  $decrypted openssl_decrypt($encrypted$this->cipherMethod$parts[0], 0$iv);

                      
                  $credentials json_decode($decryptedtrue);
                      
                  $this->credentials $credentials;

                      return 
                  $credentials;

                  LoginAuthenticator:

                  Nach erfolgreichem Login werden die Daten im im CredentialBag gespeichert und der Decryption Key als Cookie gesetzt.

                  PHP-Code:
                  public function onAuthenticationSuccess(Request $requestTokenInterface $token$providerKey)
                  {
                      
                  $key $this->credentialBag->storeCredentials([
                          
                  'username' => $request->get('username'),
                          
                  'password' => $request->get('password'),
                      ]);

                      
                  //...
                      
                  $response->headers->setCookie(new Cookie('credential-bag'$key));

                  RequestSubscriber (Middleware):

                  Hat eine Request den credential-bag Cookie gesetzt, wird damit der CredentialBag entsperrt, um später in der Anwendung darauf zugreifen zu können.

                  PHP-Code:
                  public function onRequestEvent(RequestEvent $event)
                  {
                      if(
                  $key $event->getRequest()->cookies->get('credential-bag')) {
                          
                  $this->credentialBag->unlockCredentials($key);
                      }

                  Kommentar


                  • #10
                    Naja - du könntest im jwt durchaus einen verschlüsselten claim haben.

                    Kommentar


                    • #11
                      Zitat von xm22 Beitrag anzeigen
                      Naja - du könntest im jwt durchaus einen verschlüsselten claim haben.
                      Können ja, aber ist ja nicht umbedingt Sinn von JWT.
                      Die Payload eines JWT soll ja gelesen werden, bzw. mit der Signatur verifiziert werden können.

                      Aktuell sende ich ja nur den Decryption Key an den Client, die verschlüsselten Daten bleiben aber auf dem Server.
                      Somit ist sichergestellt, dass bei einem Session-Hijacking nur die Session gestohlen, nicht aber das Passwort dekodiert werden kann.

                      Ob ich diesen Decryption Key nun aber via JWT oder Cookie transportiere ist eigentlich egal, da es sich nicht um einen Claim handelt.
                      Entweder ist der Key richtig oder nicht.

                      Kommentar

                      Lädt...
                      X