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');
$ 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With