Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl encrypting STDIN passwords

I'm producing a Perl module that provides an OO interface for a 3rd party API. I want to capture and store the user's password in an encrypted format before it is transmitted to the 3rd party API. The module is intended to be run on UNIX-based systems only.

I've produced the following script that performs the capture function - is this correct in the sense that it only stores the password variable in an encrypted format? I'm concerned that the password may be available in memory elsewhere (e.g. under $_ although $_ is undef).

NB. I'm using STDIN rather than @ARGV with the assumption that the OS will not log the entry or include the password in the process name. I'm using a substitute regex rather than chomp so that the input would not have to be stored in a temporary non-encrypted variable. I'm also assuming that it is not possible to be completely secure in the sense that input capture software could still capture the user's input.

Thanks in advance

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');
like image 712
David Farrell Avatar asked Jun 17 '13 17:06

David Farrell


3 Answers

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

I don't think that you can prevent someone with sufficient access rights from peeking inside your system calls or memory.

like image 71
innaM Avatar answered Nov 01 '22 08:11

innaM


That's tough.

Run your encrypting code as a separate process, child of the main code, which process reads from STDIN and returns the encrypted password (and perhaps key). In that way, the code using your module will itself never hold the plaintext in memory.

Sure, tracing and memory inspection (and system memory inspection after process death) of the child helper will reveal the plaintext. The same techniques will reveal key and ciphertext read from a child helper, too. However, if the scenario against which you wish to defend is accidental retention of the plaintext in your process — in a complex object or a closure or I-didn't-know-a-temp-var-was-allocated-there — then do the work in a dedicated, short-lived process.

like image 39
pilcrow Avatar answered Nov 01 '22 07:11

pilcrow


Sounds like you're implementing the Password Anti-pattern. That's a terrible idea - it teaches users to be phished. Please don't do that. You should look at using OAuth instead.

like image 44
Dave Cross Avatar answered Nov 01 '22 09:11

Dave Cross