Usermanagement / updateuserpwdh / hashing

Einklappen
X
 
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge
  • Stevets
    Azubi
    • 10.04.2021
    • 8

    Usermanagement / updateuserpwdh / hashing

    Edit: Lösung im vorletzten Post.

    Hallo zusammen,

    ich finde leider nichts, keine vernünftige Doku, keine Codebeispiel oder Beiträge irgendwo.
    Alles was ich habe, sind die beiden PDFs von Loxone in v13 (1300_Usermanagement.pdf, 1300_Communicating-with-the-Miniserver.pdf).

    <domain>/jdev/sps/updateuserpwdh/{uuid}/{value} ist soweit klar und funktioniert auch. Ich sehe in der Loxone Config, dass das Passwort geändert wurde und ich mich nicht mehr einloggen kann

    In 1300_Usermanagement.pdf steht nicht viel. Es wird nur auf Hashing in 1300_Communicating-with-the-Miniserver.pdf verwiesen.
    {value}: hashed password-value

    Edit: Im aktuelleren Dokument von 2022.07.20 steht, genauer erklärt, wie man den Hash berechnet. Zu finden unter Loxone API, Ports und Domains

    In 1300_Communicating-with-the-Miniserver.pdf steht schon mehr, lässt aber meiner Meinung nach viel Interpretationsspielraum

    1. the key from the “jdev/sys/getkey”, “jdev/sys/getkey2” or “jdev/sys/getvisusalt” responses are hex-encoded
    getkey2 liefert als einziges key und hashAlg, worauf später verwiesen wird.
    Außerdem kann ich nur vermuten, ob ich den key erst decodieren muss oder nicht.

    2. create a hash from the desired text (user : passHash, visuPwHash, token) using HMAC-SHA1 or HMAC-SHA256 with the {key} received in the answer
    Hier steht nicht genau, was mit user : passHash gemeint ist, aber in einem anderen Abschnitt ("Acquiring tokens") wird es klarer: {user}:{pwHash}
    Ich gehe mal davon aus, dass ist hier auch gemeint.

    Zum Testen nehme ich einfach einen online hmac-sha256.

    2.a. To create ‘passHash’ & ‘visuPwHash’ use the hashing algorithm {hashAlg} that is defined in the answer of the corresponding requests
    hashAlg habe ich von getkey2 bekommen. In meinem Fall SHA256.
    In einem anderen Abschnitt ("Acquiring tokens") wird verlangt, dass der pwHash uppercase sein soll.
    Ist das hier auch der Fall?

    3. encode the hash back to hex
    Merkwürdig, aber auch kein Problem.

    Funktioniert nur leider alles nicht

    getkey2:key direkt oder hex decoded.
    pwHash uppercase oder lowercase.
    Und in Kombination. Auch mit getkey.
    Ich kann nicht sagen, ich habe wirklich alle Kombinationen abgedeckt, aber sehr viel probiert.

    Ich bin mir nicht mal sicher, wie lange die Keys gültig sind. Aber ich habe immer einen 200er bekommen und es war ein neues Passwort gesetzt.

    Habe auch schon probiert den hash, also {value} nicht in hex umzuwandeln.
    Habe auch probiert für {value} direkt der pwHash zu verwenden.

    Keine Chance. Login klappt nicht und wenn ich nicht alle paar Versuche über die Config ein Passwort setze und mich erfolgreich einlogge, dann hab ich permanent Zwangpausen, weil ich das Passwort falsch eingebe

    Kennt jemand ein Beispiel, das ich mir anschauen kann oder hat das schon jemand gelöst. Mir egal welche Programmiersprache oder welche Ideen ihr habt, ich nehme alles

    Grüße,
    Steve​
    Zuletzt geändert von Stevets; 07.06.2023, 10:06.
  • Stevets
    Azubi
    • 10.04.2021
    • 8

    #2
    Ich sehe gerade, dass ich vermutlich im falschen Bereich bin und es in "Software: Konfiguration, Programm und Visualisierung​" besser aufgehoben wäre. Kann es jemand verschieben bitte. Sorry
    Zuletzt geändert von Stevets; 01.06.2023, 15:15.

    Kommentar

    • maxw
      Lox Guru
      • 26.08.2015
      • 1351

      #3
      Ich habe ehrlich gesagt nicht verstanden was dein konkretes Problem ist bzw. was du eigentlich machen willst.

      Kommentar

      • Stevets
        Azubi
        • 10.04.2021
        • 8

        #4
        Ich setze das Passwort über die API, kann mich danach aber nicht einloggen.

        Also vermute ich, dass beim Hashing etwas nicht so läuft, wie es soll und dadurch ein falscher Passwort Hash gesetzt wird - ich mich nicht mit dem gewünschten Passwort einloggen kann.

        Kommentar

        • maxw
          Lox Guru
          • 26.08.2015
          • 1351

          #5
          Ah ja. Wenn das reproduzierbar so ist, würde ich bei Loxone ein Ticket aufmachen.

          Kommentar


          • maxw
            maxw kommentierte
            Kommentar bearbeiten
            Eine Frage noch. Ein Encoding Problem kannst du ausschließen? Das heißt, es funktioniert auch dann nicht, wenn du ein ganz einfaches Passwort aus dem ASCII Zeichensatz nimmst? ZB „abcdef“

          • Stevets
            Stevets kommentierte
            Kommentar bearbeiten
            Ja. Nur alpha numerisch. Habe auch geprüft, ob die Config es erlauben würde.

            Könnte auch der online hmac-sha256 nicht korrekt sein.
            Ich kann nichts ausschließen.
        • Stevets
          Azubi
          • 10.04.2021
          • 8

          #6
          Gute Idee. Ich werde morgen nochmal systematisch ran gehen, ein Ticket erstellen und dann kann sich das ja mal ein Entwickler anschauen. Hatte gehofft, etwas simples übersehen zu haben oder auf ein funktionierendes Beispiel hingewiesen zu werden, aber die Funktion scheint nicht groß Anwendung zu finden.

          Kommentar

          • Stevets
            Azubi
            • 10.04.2021
            • 8

            #7
            Habe ein Ticket bei Loxone geöffnet. Nun abwarten

            Edit: Ein uppercase salted password hash ist ausreichend. Der hash bracht nicht verschlüsselt (hmac) werden.

            Hier das korrigierte Beispiel (Python), falls es jemandem hilft.

            import requests
            import json
            import hashlib

            auth = '<user>:<password>'
            miniserver = '<domain>'
            base_url = f'https://{auth}@{miniserver}'


            def get_salt_and_hash_algorithm():
            url = f'{base_url}/jdev/sys/getkey2/{username}'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['code']) == 200:
            response_json = response.json()
            salt = response_json['LL']['value']['salt']
            hash_algorithm = response_json['LL']['value']['hashAlg']
            return salt, hash_algorithm
            else:
            raise Exception('Fehler beim Abrufen des Keys und des Hash-Algorithmus.')


            def get_user_uuid(username):
            url = f'{base_url}/jdev/sps/getuserlist2'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['Code']) == 200:
            response_json = response.json()
            user_list = json.loads(response_json['LL']['value'])
            for user in user_list:
            if user['name'] == username:
            return user['uuid']
            raise Exception('Benutzer nicht gefunden.')
            else:
            raise Exception('Fehler beim Abrufen der Benutzerliste.')


            def get_group_uuid(group_name):
            url = f'{base_url}/jdev/sps/getgrouplist'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['Code']) == 200:
            response_json = response.json()
            group_list = json.loads(response_json['LL']['value'])
            for group in group_list:
            if group['name'] == group_name:
            return group['uuid']
            raise Exception('Gruppe nicht gefunden.')
            else:
            raise Exception('Fehler beim Abrufen der Gruppenliste.')


            def hash_password(password, hash_algorithm, salt):
            if hash_algorithm == 'SHA256':
            hashed_password = hashlib.sha256(f'{password}:{salt}'.encode()).hexdigest().upper()
            elif hash_algorithm == 'SHA512':
            hashed_password = hashlib.sha512(f'{password}:{salt}'.encode()).hexdigest().upper()
            else:
            raise Exception('Nicht unterstützter Hash-Algorithmus.')
            return hashed_password


            def create_user(username):
            url = f'{base_url}/jdev/sps/createuser/{username}'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['Code']) == 200:
            print('Benutzer erfolgreich angelegt.')
            else:
            print('Fehler beim Anlegen des Benutzers.')


            def assign_user_to_group(user_uuid, group_uuid):
            url = f'{base_url}/jdev/sps/assignusertogroup/{user_uuid}/{group_uuid}'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['Code']) == 200:
            print('Benutzer erfolgreich zur Gruppe hinzugefügt.')
            else:
            print('Fehler beim Hinzufügen des Benutzers zur Gruppe.')


            def update_password(username, password):
            salt, hash_algorithm = get_salt_and_hash_algorithm()
            user_uuid = get_user_uuid(username)
            hashed_password = hash_password(password, hash_algorithm, salt)
            url = f'{base_url}/jdev/sps/updateuserpwdh/{user_uuid}/{hashed_password}'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['Code']) == 200:
            print('Passwort erfolgreich aktualisiert.')
            else:
            print('Fehler beim Aktualisieren des Passworts.')


            def check_login(username, password):
            auth = f'{username}:{password}'
            base_url = f'https://{auth}@{miniserver}'
            url = f'{base_url}/jdev/sps/getuserlist2'
            response = requests.get(url)
            if response.status_code == 200:
            print('Login erfolgreich.')
            else:
            print('Login nicht erfolgreich.')
            print(f'Antwort: {response.text}')


            def delete_user(user_uuid):
            url = f'{base_url}/jdev/sps/deleteuser/{user_uuid}'
            response = requests.get(url)
            if response.status_code == 200 and json.loads(response.json()['LL']['Code']) == 200:
            print('Benutzer erfolgreich gelöscht.')
            else:
            print('Fehler beim Löschen des Benutzers.')


            username = 'test'
            password = 'test12345'
            create_user(username)
            user_uuid = get_user_uuid(username)
            group_uuid = get_group_uuid('Vollzugriff')
            assign_user_to_group(user_uuid, group_uuid)
            update_password(username, password)
            check_login(username, password)
            delete_user(user_uuid)
            Zuletzt geändert von Stevets; 07.06.2023, 10:07.

            Kommentar

            • Stevets
              Azubi
              • 10.04.2021
              • 8

              #8
              Gelöst.
              Lösung im letzten Post mit Beispiel-Code.

              Kommentar

              Lädt...