2013-06-17 5 views
11

Je produis un module Perl qui fournit une interface OO pour une API tierce. Je veux capturer et stocker le mot de passe de l'utilisateur dans un format crypté avant qu'il ne soit transmis à l'API tierce. Le module est destiné à être exécuté uniquement sur des systèmes basés sur UNIX.Perl chiffrage des mots de passe STDIN

J'ai créé le script suivant qui exécute la fonction de capture - est-ce correct dans le sens où il stocke uniquement la variable de mot de passe dans un format crypté? Je suis inquiet que le mot de passe puisse être disponible en mémoire ailleurs (par exemple sous $ _ bien que $ _ soit undef).

NB. J'utilise STDIN plutôt que @ARGV avec l'hypothèse que le système d'exploitation ne consignera pas l'entrée ou n'inclura pas le mot de passe dans le nom du processus. J'utilise une regex de remplacement plutôt que chomp afin que l'entrée ne soit pas stockée dans une variable temporaire non chiffrée. Je suppose également qu'il n'est pas possible d'être complètement sécurisé dans le sens où le logiciel de capture d'entrée pourrait toujours capturer l'entrée de l'utilisateur.

Merci à l'avance

use strict; 
use warnings; 
use Crypt::CBC; 
use 5.14.0; 

print 'Please enter your password: '; 
system('tty -echo'); 
my $key = Crypt::CBC->random_bytes(56); 
my $iv = Crypt::CBC->random_bytes(8); 
my $cipher = Crypt::CBC->new(-key => $key, 
          -cipher => 'Blowfish', 
          -salt => 1, 
          ); 
my $ciphertext = $cipher->encrypt(<STDIN> =~ s/\n$//r); 
system('tty echo'); 
+0

vous devriez probablement vérifier la longueur du mot de passe, et que signifie '/ r'? –

+1

@mpapec '/ r' est une substitution non destructive introduite dans perl 5.14 (voir perlop) - elle ne modifie pas la chaîne en place mais renvoie une copie modifiée à la place (fonction très pratique). – Xaerxess

+2

De qui es-tu en train de protéger? Si quelqu'un peut jeter un coup d'œil à votre mémoire de processus pour lire le mot de passe crypté, vous devez supposer qu'il peut également lire la clé et la source de votre programme. Lire le mot de passe de stdin plutôt que comme un argument de ligne de commande protégera des navigateurs occasionnels, et est probablement le meilleur que vous pouvez vous attendre. –

Répondre

6

C'est dur.

Exécutez votre code de cryptage en tant que processus séparé, enfant du code principal, lequel processus lit à partir de STDIN et renvoie le mot de passe crypté (et éventuellement la clé). De cette façon, le code utilisant votre module ne tiendra jamais lui-même le texte en clair. Bien sûr, le suivi et l'inspection de la mémoire (et système inspection de la mémoire après la mort du processus) de l'assistant de l'enfant révélera le texte en clair. Les mêmes techniques révèlent aussi la clé et le texte chiffré lus par un assistant enfant. Cependant, si le scénario contre lequel vous souhaitez défendre est la rétention accidentelle du texte en clair dans votre processus - dans un objet complexe ou une fermeture ou I-didn't-savoir-a-temp-var-was-alloué-là - alors faire le travail dans un processus dédié et de courte durée.

9
$ strace perl -E '<STDIN>' 
.... scroll, scroll, scroll .... 
read(0, 
... type, type, type .... 
"secret\n", 4096)    = 7 
exit_group(0)       = ? 

Je ne pense pas que vous pouvez empêcher une personne avec des droits d'accès suffisants de jeter un oeil à l'intérieur de vos appels système ou mémoire.

3

On dirait que vous implémentez le Password Anti-pattern. C'est une idée terrible - il enseigne aux utilisateurs d'être phishing. S'il vous plaît ne faites pas ça. Vous devriez plutôt utiliser OAuth.

+0

S'il vous plaît éclairer moi comment je peux utiliser OAuth sur les applications en ligne de commande? Surtout si l'API que OP est en train d'encapsuler attend un * mot de passe * chiffré? – amon

+0

C'est certainement possible (j'ai des programmes Twitter en ligne de commande qui utilisent OAuth) mais la configuration de l'OAuth peut être un peu complexe et nécessitera un navigateur. Voir https://github.com/davorg/localtwits/blob/master/build.pl pour un exemple. Mais même si c'était impossible, ce n'est pas une excuse pour encourager les utilisateurs à enfreindre la première règle de sécurité sur Internet - Ne partagez jamais un mot de passe avec un tiers. –

+0

Merci - l'utilisation de cette approche supprimerait beaucoup de risques de sécurité. Je me rends compte que ce n'était pas dans mon message, mais j'ai besoin de générer un modèle XML qui est envoyé via https à l'API tierce partie.Si l'API tierce ne prend pas en charge explicitement OAutho, puis-je toujours l'utiliser pour résoudre ce problème? –