Forum Programmation.autre Comment stocker un mot de passe admin d'une application

Posté par  . Licence CC By‑SA.
Étiquettes :
4
5
sept.
2023

Bonjour,
je suis en train de développer une application (en Qt mais ça n'a pas d'importance je pense) qui permet à l'utilisateur de passer en mode « admin ».

Je ne veux pas que n'importe quel utilisateur puisse devenir admin donc je dois garder le mot de passe admin secret.

Quelle est la bonne manière de faire cela ?

  1. Si je code en dur le mot de passe (en clair) dans le code source, j'imagine qu'il sera possible de le retrouver en étudiant le binaire
  2. Si je passe par un fichier texte pour stocker une version chiffrée/hashée/autre du mot de passe admin, l'utilisateur pourrait modifier ce fichier texte pour remplacer cette version chiffrée/hashée/autre par son propre mot de passe (chiffré/hashé avec le même protocole).

Je n'ai pas forcément besoin d'une sécurité renforcée (le logiciel tourne en local uniquement avec des gens de confiance), mais juste que le mot de passe admin ne soit pas accessible.

  • # problème mal défini

    Posté par  (site web personnel) . Évalué à 4.

    Si tous les utilisateurs sont des « gens de confiance », tu peux aussi bien te passer de mot de passe. Si tu veux vraiment faire chier avec un mot de passe qui sert à rien, met le en clair dans un fichier à côté comme ça tout le monde peut l'examiner/changer facilement. C'est quoi le cas d'utilisation exactement ?

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: problème mal défini

      Posté par  . Évalué à 4.

      En gros l'application pilote du matériel.
      Passer en mode admin permet d'accéder aux réglages fins du matériel et potentiellement de l'endommager. C'est pour ça que je ne veux pas que n'importe qui puisse faire cela.

      Mais comme le logiciel pourrait atterrir dans les mains de personnes qui veulent vraiment bidouiller finement le matériel mais que je pense que ce n'est pas une bonne idée pour eux. Du coup, je pense que ces personnes pourraient essayer de trouver ce mot de passe admin, ce que je veux empêcher.

      • [^] # Re: problème mal défini

        Posté par  (site web personnel) . Évalué à 3.

        Celui qui veut vraiment bidouiller, s'il a accès au matériel de toute façon il finira par y arriver. Si le matériel lui appartient, lui mettre des bâtons dans les roues ne me semble pas une bonne idée. Si le matériel ne lui appartient pas, c'est plus un problème entre l'opérateur et le propriétaire et c'est pas avec du logiciel que tu vas le résoudre.

        Dans tous les cas, ça s'apparente à du DRM. Il y a plein de « solutions » techniques mais en gros ça va à l'encontre de ce pour quoi ce site a été crée (la promotion des Logiciels libres dont le but est fondamentalement de donner le contrôle à l'utilisateur bidouilleur).

        https://www.gnu.org/philosophy/opposing-drm.fr.html
        https://www.defectivebydesign.org/what_is_drm

        pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

      • [^] # Re: problème mal défini

        Posté par  . Évalué à 4.

        Même avec cette explication j'ai un peu de mal à comprendre. Celà dit j'ai peut-être une idée. Pour pouvoir faire ce genre de choses je pense qu'il faut splitter l'appli. : une partie "serveur/backend" qui tourne en mode privilégiée. et une partie "cliente/frontend" accessible aux utilisateurs.
        Tu définis deux profils : un profil par défaut (utilisateur simple) et un profil administrateur, qui nécessite d'entrer un mot de passe pour passer dans ce mode. Le mot de passe administrateur est stocké dans un fichier de conf qui n'est accessible que via le compte sous lequel tourne le backend.

        Tu peux aussi t'inspirer du fonctionnement de /etc/shadow et utiliser les suid/sgid bits pour empêcher les utilisateurs lambdas d'accéder au fichier contenant le mot de passe chiffré. Tu fais en sorte que seule ton appli (et un compte privilégié tel que root, ou autre) ne puisse accéder au mot de passe administrateur pour le lire/modifier. Et tu ne permet de modifier le mot de passe qu'aux utilisateurs connaissant le mot de passe administrateur (demande de l'ancien mot de passe avant de changer).

  • # Du plus simple au plus évolué

    Posté par  . Évalué à 2.

    Attention, ça n'est pas un domaine dans lequel je suis à l'aise, je n'ai pas beaucoup d'expérience.

    Ceci dit :

    • au plus simple : ton app pourrait stocker un hash du mot de passe. Ça n'est toujours pas hyper sécurisé j'imagine, mais ce sera un peu plus difficile à retrouver en disséquant le binaire. près, il faut coder une saisie, la même fonction de hash, et la comparaison
    • plus évolué : ça va dépendre évidement des circonstances, de où tu pars et où tu veux arriver, tu pourrais peut-être utiliser des certificats ou clés privée/publique. Je me rappelle vaguement avoir codé l'accès à un broker MQTT en Qt avec authentification par ce genre de mécanisme.

    Tout le monde : merci de confirmer / infirmer / compléter ça en oubliant pas mon avertissement préliminaire.

    • [^] # Re: Du plus simple au plus évolué

      Posté par  (Mastodon) . Évalué à 3. Dernière modification le 05 septembre 2023 à 13:55.

      [stocker le hash] Ça n'est toujours pas hyper sécurisé j'imagine

      c'est ce que fait le fichier /etc/password non ? J'imagine donc que c'est déjà une protection correcte.

      Sinon encore plus évolué : stocker dans un TPM (donc pas dans le binaire). Là oui t'es sécure :)

      En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

      • [^] # Re: Du plus simple au plus évolué

        Posté par  (site web personnel) . Évalué à 3. Dernière modification le 05 septembre 2023 à 15:04.

        Je sais pas sur quelle distribution tu trouves un /etc/password. Si tu fais référence à /etc/passwd, ce fichier ne contient plus de hash de mot de passe depuis environ 40 ans et les utilisateurs normaux n'y ont pas accès.

        stocker dans un TPM (donc pas dans le binaire). Là oui t'es sécure :)

        Ça dépend de ta définition de « sécure » : https://en.wikipedia.org/wiki/Trusted_Platform_Module#Attacks

        pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

        • [^] # Re: Du plus simple au plus évolué

          Posté par  (site web personnel, Mastodon) . Évalué à 3.

          Si tu fais référence à /etc/passwd, ce fichier ne contient plus de hash de mot de passe depuis environ 40 ans et les utilisateurs normaux n'y ont pas accès.

          Tsss, les yusers ont toujours accès à /etc/passwd, je pense que tu confonds avec /etc/shadow :)

          • [^] # Re: Du plus simple au plus évolué

            Posté par  (site web personnel) . Évalué à 2.

            Je la refais sans le pronom ambigu.

            Si tu fais référence à /etc/passwd, ce fichier ne contient plus de hash de mot de passe depuis environ 40 ans. Les utilisateurs normaux n'ont pas accès aux hashes.

            pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

          • [^] # Re: Du plus simple au plus évolué

            Posté par  (Mastodon) . Évalué à 2.

            les yusers ont toujours accès à /etc/passwd

            Oui j'ai fait un (gros) raccourcis. Mais du coup tiens, pourquoi les users ont besoin d'accéder à /etc/passwd ?

            En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

            • [^] # Re: Du plus simple au plus évolué

              Posté par  (site web personnel) . Évalué à 4.

              pourquoi les users ont besoin d'accéder à /etc/passwd ?

              A priori, je dirais pour faire le lien entre nom d'utilisateur et son uid/gid

            • [^] # Re: Du plus simple au plus évolué

              Posté par  . Évalué à 4.

              pour que le systeme trouve leur UID/GUID/Shell et HOME ?

              • [^] # Re: Du plus simple au plus évolué

                Posté par  (Mastodon) . Évalué à 3.

                le système n'a pas besoin que ce fichier soit lisible par les utilisateurs eux-même : /etc/shadow n'est pas lisible, alors que le système en a bien besoin pour vérifier le mot de passe.

                En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

                • [^] # Re: Du plus simple au plus évolué

                  Posté par  . Évalué à 2.

                  Oui, mais dans ce cas, il faut que l'utilitaire qui lit ces infos soit SUID root (exemple sudo).

                  C'est envisageable pour ce cas mais pas pour un simple ls -l par exemple (qui a besoin de résoudre le UID/GID) !

                  • [^] # Re: Du plus simple au plus évolué

                    Posté par  (Mastodon) . Évalué à 3. Dernière modification le 06 septembre 2023 à 08:57.

                    Ah mais oui bien sûr ^^

                    quel con :)

                    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

  • # Hash

    Posté par  (Mastodon) . Évalué à 6. Dernière modification le 05 septembre 2023 à 13:47.

    Tout simplement tu le mets en "dur" mais pas en "clair". Tu mets par exemple son SHA256 (et tu t'assures qu'il est vraiment, vraiment très long pour être robuste à l'attaque par force brute).

    Après ça reste une mauvaise idée de le mettre en "dur" : si pour une raison ou une autre il fuite, t'es mort, faut recompiler (et redéployer) l'appli.

    Autre chose, tout le monde aura le même, je ne sais pas si il y a plusieurs instances de ton applis (plusieurs clients), et donc si ça fuite, ça fuite en grand (tu peux être sûr que c'est demain sur les forums spécialisés).

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

    • [^] # Re: Hash

      Posté par  . Évalué à 3.

      Après ça reste une mauvaise idée de le mettre en "dur" : si pour une raison ou une autre il fuite, t'es mort, faut recompiler (et redéployer) l'appli.

      Qu'entends-tu par là ? Que si le hash fuite alors on peut considérer le mot de passe connu ? Avec une bonne fonction de hachage j'ai du mal à penser que quelqu'un pourrait remonter au mot de passe facilement…

      • [^] # Re: Hash

        Posté par  . Évalué à 5.

        Je pense que ce qu'il veut dire que si le mot de passe en clair fuite, alors il faut forcément recompiler l'application et la redistribuer pour changer le hash d'un nouveau mot de passe.

        • [^] # Re: Hash

          Posté par  (Mastodon) . Évalué à 7. Dernière modification le 05 septembre 2023 à 14:21.

          C'est ça. Parce que "Robert l'a dit à Gérard mais tu le dis à personne", ou parce que "Jean-René a été viré et a pas apprécié et du coup a cherché à foutre le bordel"… Si le mot de passe sort du cercle, c'est mort.

          Un mot de passe doit être révocable, tout comme un certificat.

          En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

    • [^] # Re: Hash

      Posté par  . Évalué à 2.

      Mettre le hash en dur dans le code source est effectivement une idée mais comme tu le dis, ça pose le problème de pouvoir changer ce mot de passe si besoin sans devoir recompiler le code et redistribuer l'exécutable.

      N'existe pas une solution qui n'a pas ce défaut ?

      • [^] # Re: Hash

        Posté par  (Mastodon) . Évalué à 6.

        Tu peux partir sur le hash dans un fichier texte. Tout comme ton /etc/passwd en fait ;)

        Mais attention, ça restera facile pour le hacker de générer un nouveau hash dans ce fichier et ainsi être admin.

        Du coup faudrait que tu signes ce fichier (avec ton certificat embarqué). Mais là aussi, le certificat ne doit pas être en clair dans le code sinon il pourra le modifier, ou s'en servir… Et de toutes façons, si c'est pour à la fin faire un simple if procedure_super_secure() un coup de debugger et toute ta procédure gicle.

        En gros, si tu mets le produit dans les mains du hacker, il arrivera tôt ou tard à le hacker (regarde les consoles de jeu…). C'est à toi de voir où tu mets la limite selon la situation que tu vises.

        Bon sinon :
        - si ton produit vaut cher, est sensible, a de fortes chances d'être une cible, alors rapproche-toi d'un cabinet de cybersécu, c'est leur métier
        - si c'est un produit maison et que tu veux juste pas que ce soit la fête du slip, un hash avec sel dans un fichier (et oui, le sel est en clair dans le binaire, tant pis… choisis un sel qui passe inaperçu quand tu fais un strings mon_appli.exe) ça me semblerait déjà pas dégueu.

        Encore une fois, en matière de sécu faut savoir de quoi on veut se protéger : quels scénarios. Sinon on fini par se protéger de la mauvaise menace.

        En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

        • [^] # Re: Hash

          Posté par  . Évalué à 3.

          Merci,
          du coup, je vais partir sur la solution suivante :
          Mettre le sel en dur dans le code source et stocker le hash du mot de passe salé dans le fichier de configuration (en clair).

          Ca permettra juste d'éviter que ce soit « la fête du slip » trop facilement et c'est suffisant à mon avis pour mon cas d'utilisation.

          • [^] # Re: Hash

            Posté par  . Évalué à 3.

            Voir mon commentaire plus haut si tu veux sécuriser un peu le truc, en t'inspirant du fonctionnement de /etc/shadow.

  • # admin / admin

    Posté par  . Évalué à 8.

    Perds pas de temps fais comme tout le monde de l'industrie (photocopieurs, routeurs, switchs, etc.) : utilise un mot de passe sécure selon les références des grands de ce monde, 0000, admin, password, 1234, 9999 …

    Plus sérieusement, si ton appli est vraiment autonome du genre sans accès réseau j'aurais l'approche suivante:
    - un mot de passe admin qui permet d'aller bidouiller les réglages avancés dont le hash est stocké dans le fichier de conf / base re registre ou je ne sais quoi et qui peut être changé
    - éventuellement un mot de passe superadmin avec une entrée dans l'interface qui permet de changer le mot de passe admin lorsque rené l'aura donné à jean ou que le mec qui était admin est sorti de l'entreprise

    et le mot de passe superadmin, ben 0000, ou superadmin ou un truc du genre … :-)

    ou alors tu fais un compte supersuperadmin qui peut changer le mot de passe de superadmin … bon ok ce n'est pas vendredi !

    Sinon une recherche sur l'internet pour avoir d'autres idées:
    - https://stackoverflow.com/questions/31382495/how-can-i-store-a-password-in-my-qt-application
    - https://github.com/frankosterfeld/qtkeychain/
    - https://forum.qt.io/topic/20954/how-to-store-passwords-in-a-qt-application
    - …/…

    eric.linuxfr@sud-ouest.org

  • # cas d'usage

    Posté par  . Évalué à 4.

    Quel est le mot de passe 'admin' dont tu parles?

    Je comprends peut-être mal, mais j'ai l'impression que tu as une appli qui parle à un matériel. Et tu ne veux pas que les users lancent des actions potentiellement dangereuses sur ce matériel.
    Du coup, implémentation d'un contrôle d'accès (password) dans le logiciel.

    Donc quelqu'un peut utiliser un autre programme que le tien et tout péter dans le matériel puisqu'apparemment il n'y a aucun contrôle à ce niveau?

    Ensuite si la gestion est faite dans le logiciel le user peut au choix:
    - lire le pass dans ton appli
    - modifier le pass (haché/en clair peu importe) dans l'appli ou un fichier à côté
    - dégager la condition dans l'appli (supprimer carrément la demande de password)

    La vraie solution c'est d'avoir un contrôle d'accès sur l'appli.

    Sinon, gérer des droits UNIX, le programme QT et le fichier de pass hachés ont des droits en lecture seulement pour tout le monde. Certes les uers peuvent lire le hash et tenter de le casser, mais avec un bon algo (genre bcrypt + bon mot de passe) ça devrait le faire. Ca empêchera pas quelqu'un de copier le fichier QT et modifier l'emplacement de fichier de pass hachés, mais bon…

    • [^] # Re: cas d'usage

      Posté par  . Évalué à 2.

      En fait mon application controle un équipement. Pour l'utilisateur standard, il a accès à des réglages pré-définis à partir d'une liste déroulante qui peuvent être envoyés au matériel.
      Mais, de notre côté, on pourrait avoir le besoin d'envoyer des réglages manuels qui peuvent endommager le matériel si on envoie n'importe quoi comme valeur. C'est l'accès à ce réglage manuel que je veux empêcher pour l'utilisateur lambda et que je veux protéger par un mot de passe admin.

      • [^] # Re: cas d'usage

        Posté par  . Évalué à 1.

        Ca sent l'applicationh qui a été développée sans penser à la sécurité "by design" …

        Résultat: potentiellement il va falloir redévelopper une rustine ne suffira certainement pas à avoir un truc correct).

      • [^] # Re: cas d'usage

        Posté par  . Évalué à -2.

        Fondamentalement, toutes les solutions qui te sont proposées ne sont absolument pas sécurisées. À partir du moment où tu as un code exécutable par l’utilisateur, même si l’interface bloque l’exécution il est possible d’exécuter ce code. Point. L’utilisateur peut totalement passer outre ton mot de passe, ta fonction de hachage, etc. Il a accès au code en lecture et c’est tout ce dont il a besoin pour l’exécuter. C’est même absolument trivial pour peu que tu aies laissé les symboles de debug dans ton binaire. Sinon avec un simple debuggeur/desassembleur ça se fera quand même (faut repérer l’instruction qui teste si le hash du pass saisi est conforme et modifier le flag/mémoire/registre à la volée ou désassembler le binaire pour enlever la condition).

        De deux choses l’une : dans un cadre pro. Si c’est possible de se contenter de la dissuasion : distribuer deux binaires. L’un pour les utilisateurs finaux, l’autre pour les privilégiés. Les binaires peuvent éventuellement être compilés à partir du même code (via des #ifdef en C par exemple). Si ce n’est pas possible, dans le pire des cas, la “sécurité” passera par des consignes claires de la hiérarchie et une interface parfaitement lisible, qui différentie bien l’utilisation néophyte de l’utilisation avancée. Ce n’est pas une sécurité hard. C’est contournable. Mais dans le cadre d’un contrôle hiérarchique ça peut être suffisant (tout dépend des responsabilités de l’employeur vis-à-vis des employés).

        Si tu veux aller plus loin et avoir une vraie politique de sécurité. Il faudra être plus sérieux. Il faut alors interdire la capacité de piloter le matériel par les utilisateurs. Complètement. Et donner le privilège à ton programme et seulement à ton programme.

        Dans le monde Unix, par exemple, ce sera du ressort des administrateurs de créer un groupe propre — pas root évidemment ! — qui aura, seul, les droits sur le “fichier” par lequel la couche user (et donc ton programme) communique avec le matos (typiquement ce qui est dans /dev). Ton programme tournera avec le bit setgid correctement positionné pour avoir les droits sur le matos. Il te suffira alors d’un simple fichier stockant le hash, en lecture seule pour le dit groupe, et modifiable par un utilisateur admin (qui peut si distinguer du précédent). Les utilisateurs n’ayant aucun droit en modification sur le programme privilégié, ils ne pourront exécuter que ce qui a été prévu pour eux (à la faille de sécurité près… ton programme exerçant en mode privilégié sur ton matos, il devient plus ou moins sensible et y’a tout un tas de technique de programmation à connaître).

        Je te dis en très gros, moi-même n’étant pas expert sécu, mais s’il y a de vrais enjeux derrière il faut impérativement traiter ça de manière beaucoup plus sérieuse et s’aider éventuellement d’un expert. Sinon, deux binaires, voir simple avertissement du logiciel (en gros en gras en rouge) et basta…

      • [^] # Re: cas d'usage

        Posté par  . Évalué à 2. Dernière modification le 06 septembre 2023 à 14:31.

        En fait mon application controle un équipement. Pour l'utilisateur standard, il a accès à des réglages pré-définis à partir d'une liste déroulante qui peuvent être envoyés au matériel.

        Grosso modo, ton matériel est piloté par un PC. Et ce PC est tout puissant sur le matériel.

        Ton espoir, c'est de forcer les utilisateurs de ce PC à passer par une appli qui va les brider dans les réglages qu'ils peuvent envoyer.

        Ca me parait mort dès la conception en fait. Qui force l'utilisateur à utiliser ton programme en fait? Tu auras beau le blinder dans tous les sens, je m'en vais développer un truc à l'arrache 'badaboum.py' qui va envoyer des réglages pourris au matériel. Le matériel 'truste' le PC, il va prendre les réglages, et crac.

      • [^] # Re: cas d'usage

        Posté par  . Évalué à 4. Dernière modification le 07 septembre 2023 à 13:32.

        Je suis peut-être lent à la comprenette, mais pourquoi ne pas stocker le fichier de conf dans un répertoire qui n'est modifiable que par root? Si tu peux empêcher quelqu'un qui est potentiellement admin sur la machine d'utiliser certaines fonctionnalités, le principe me parait défectueux dès le départ, puisqu'a priori, le droit d'accéder au matériel est déterminé par le statut de l'utilisateur sur la machine (être root donne justement ce droit).

        Ou alors, tu définis un utilisateur entre root et le basic user, style admin_montruc, et tu ne mets que certains utilisateurs de confiance dans le groupe qui va bien. Évidemment, root peut prendre les droits de admin_montruc, mais c'est encore une fois quelque chose qui me semble normal (ou alors je n'ai pas compris le problème).

        qui peuvent endommager le matériel si on envoie n'importe quoi comme valeur.

        Je me demande si ça n'est pas l'origine du problème, est-ce que ça n'est pas le firmware du matériel qui devrait de toutes manières bloquer les valeurs de paramètres qui peuvent l'endommager? Ça me semble super-dangereux d'avoir un matériel à la merci de n'importe quel bug du pilote… Ton utilisateur bricoleur pourra toujours flasher le firmware, mais là il sait ce qu'il fait.

  • # Une autre approche (complémentaire)

    Posté par  . Évalué à 3.

    Si ton application client lourd est sur une machine partagée, tu peux aussi utiliser les logs pour faire une analyse a posteriori de qui à planté la machine en envoyant n'importe quoi.

    Ainsi tu pourrais voir que Jean-Michel a cliqué sur le bouton "je veux débrayer les commandes spécifiques" puis a saisi la valeur -1 dans le paramètre "must_be_positive". Il te restera ensuite à présenter la facture à Jean-Michel et voilà !

    Si ton appli envoie les logs à syslog / journald, tu auras une bonne garantie d'intégrité dessus et donc tu pourras ainsi reconstruire le scénario. Si tes utilisateurs sont globalement de confiance, le simple fait de se savoir surveiller peut réduire fortement ton risque d'un apprenti sorcier

    Et idéalement, tu cumules les deux (authentification + logs) et tu as une bonne solution. Et tu peux te permettre de mettre le hash du mdp dans un fichier de conf. Si l'utilisateur le modifie, il sera doublement responsable

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.