Solo has asked for the wisdom of the Perl Monks concerning the following question:

Disclaimer: embedding passwords in scripts (or most things, for that matter) where they must be converted back into 'plaintext' is insecure, period. No amount of clever encryption or hoop-jumping can make it secure.


For reasons not worth getting into, we (at company X) end up embedding passwords in admin scripts a lot. We're finally getting around to trying to obfuscate the passwords some. It should be easy to convert existing scripts, etc.

So I took a spoonful of Acme::Bleach, a pinch of Exporter and here's what I got.

use My::Acme::Clutter qq[( test => 45, foo => 'bar')];

once cluttered (i.e. run once) becomes:

use My::Acme::Clutter '`282074657374203d3e2034352c20666f6f203d3e202762 +61722729';

It's a very simple encrypt/decrypt, but meets our level of "difficult". I need to add some error checks. And I'd like to use Exporter, but I couldn't get export_to_level to work :?

Besides that, all opinions desired!

package My::Acme::Clutter; use 5.006; sub encrypt { my $return; for ( split(//,shift) ) { $return .= sprintf("%02x",ord($_)); } return $return; } sub decrypt { my $return; for ( $_[0] =~ /.{2}/g ) { $return .= chr( hex $_ ); } return $return; } sub import { my $pkg = shift; my $callpkg = (caller)[0]; my $string = shift; if ($string =~ s/^`//) { $string = decrypt($string); } else { my $clutter = encrypt($string); open 0 or print "Can't clutter '$0'\n"; (my $file = join "", <0>) =~ s{^\s*use\s+My::Acme::Clutter.*?;\n}{use My::Acme::Clutter ' +`$clutter';}m; open 0, ">$0" or print "Cannot clutter '$0'\n" and exit; print {0} $file and exit; } # turn the string into a hash my %args = eval $string; # finally, do the import; for my $var (keys %args) { ${"${callpkg}::$var"} = $args{$var}; } } 1;
--Solo
--
There's no mystical energy field that controls my destiny. It's all a lot of simple tricks and nonsense.

Replies are listed 'Best First'.
Re: Embed passwords (Acme::Clutter idea)
by greenFox (Vicar) on Feb 21, 2003 at 07:37 UTC

    The way I have done this in the past is to put the password in a seperate file and limit access to the file- ie owned by root and only readable by root. That way if you change the password you only have to do so in one place and if you are editing the script the password is still not visible over your shoulder. If wider access to the script is required it is granted via sudo. If someone can get access to the file then your system is pretty much 0wned any-way.

    Note-

    • I am not saying this is more secure!
    • roots password should never be "scripted" in this way.
    • passwords for remote systems should not be stored, use ssh keys instead.

    --
    Life is a tale told by an idiot -- full of sound and fury, signifying nothing. William Shakespeare, Macbeth

      Hmm, what is using ssh keys going to gain you? To use the ssh keys to access another system, you either need the passphrase, or there should not be a passphrase. The former requires you to store the passphrase in the script (giving you the same problems as storing a password), the latter solution requires you to rely on the filesystem security - which gives you the same problems as storing passwords in a seperate file.

      It's easy to say that passwords should never be scripted. But it's a bit harder to avoid that. As a sysadmin, you will eventually get tired of driving to work every night at 2 am to type in the passwords for the nightly scripts that are run.

      I usually deal with the problem of chmodding the script to have permission 700. Along with a umask of 077. And of course, users don't belong on servers anyway.

      Abigail

        while not a complete and total solution, keyagent can help out alot. (Warning: IBM Developerworks link might require registration, don't remember but it's worth it if it does.)

        keyagent can replace the 'driving to work every night at 2 am to type in the passwords for the nightly scripts that are run.' with 'driving to work to type in the passwords after a nasty reboot.' (but you were on your way in already yes?).

        ssh includes built-in support that allows it to communicate with ssh-agent, allowing ssh to acquire your decrypted private keys without prompting you for a password for every single new connection. With ssh-agent you simply use ssh-add to add your private keys to ssh-agent's cache. It's a one-time process; after using ssh-add, ssh will grab your private key from ssh-agent, rather than bugging you by prompting for a passphrase.

        the other SSH related articles linked from the keyagent article are well worth a read.

        Hmm, what is using ssh keys going to gain you?

        I left out part of the explanation, sorry. SSH allows you to setup keys which are only able to run a single command which is specified along with the key in the AUTHORIZED_KEYS file. I wrote about it before with some code samples here. You are setting up levels of trust between machines any-way, this way the access is limited and controlled and login access is not allowed. I think a key without a passphrase that can only run one command is somewhat less nasty than having a passphrase/password in plain text which has login access to the remote machine.

        No disagreement from me on your other points :)

        --
        Life is a tale told by an idiot -- full of sound and fury, signifying nothing. William Shakespeare, Macbeth

Re: Embed passwords (Acme::Clutter idea)
by Coruscate (Sexton) on Feb 21, 2003 at 05:28 UTC

    This is hardly more secure than storing a plaintext password in the file. If you're just using a module to clutter/obfuscate the password text, then anyone who has your module source can de-clutter/de-obfuscate the password and have the password in their hand. My suggestion: simply store a crypt()ed password in the script instead of taking the approach you've posted. Granted, this method can be worked around via brute-force methods, but if you choose your passwords carefully, this will improve the situation.


    If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, reply to this node or /msg me to tell me what is wrong with the post, so that I may update the node to the best of my ability. If you do not inform me as to why the post deserved a downvote, your vote does not have any significance and will be disregarded.

Re: Embed passwords (Acme::Clutter idea)
by steves (Curate) on Feb 21, 2003 at 10:51 UTC

    There are things I don't like about this approach but I've been rolling similar ideas over in my head for a while now. It's the same basic issue: You need to code passwords in to allow for full automation, but you want to do that seamlessly and in a way that obscures the actual value as much as possible (realizing that nothing will hide them 100%).

    My thought was to force the passwords specified in the code to be encrypted, surrounding that encrypted value with some identifiable, unique pattern, then to write a source filter that decrypts them as the source is compiled. The encrypter would be a command line tool that would only encrypt. The decrypting source filter would follow the perlfilter guidelines for obscuring things as much as possible (such as writing the decrypter in C and linking it statically to Perl, etc.).

      You can obscure your decrypter as much as you want, but what would you gain? To decrypt the password, one doesn't need the source of the decryptor. All you need is a copy of the script, with the encrypted password. Somewhere in that script, the password will need to be decrypted before sending it to whatever application. Just put in a print $password near that place, and run the program. Or maybe you don't even need to modify the code. Running and tracing it may be more than enough.

      Abigail

        I agree. It's not so much for bullet-proof encryption as it is for obscuring it from the 98% of the people who can't think that far. The irony is that it's only that other 2% that will be able to do anything with the data anyway. The source never leaves our building and this is only for internal use. Part of the reasoning is that it just makes some people feel better to not have it right there in plain text. As an example, one of my POD tools allows you to see the docs from our intranet and offers a link to see the actual source. That exposes the plain text to a lot of people who just don't need to see that data, but who could benefit from the general ability to see the source.

        This is mostly why I've only thought about it and never implemented it. I don't really see much added value. But I suspect I will have to do something like this at some point for "other" reasons. We have some other very weak encryption methods that are used internally but the mere existence of them keeps some people happy.

        Boy that sounds pathetic ... too late to post anonymously. 8-)

Re: Embed passwords (Acme::Clutter idea)
by Solo (Deacon) on Feb 21, 2003 at 11:54 UTC
    I should mention for everyone that I'm dealing with a mix of Win32 & *nix, and with passwords beyond the OS (databases, LDAP, etc). I couldn't come up with a way to use crypt that could help, but I'm open to suggestions! :D

    Beyond security discussions, which I appreciate--my directive isn't to secure the passwords, only to eliminate their plaintextness. *shrug*

    --Solo

      You could just as well just put the password a central textfile, using the mod to get it.

      Also, I would suggest using a more serious encryption while you're at it.

      Maybe create a higher level connection module that creates the needed connections for you with the proper user and password, no user nor password in your script. And if you encrypt them both stored in a central file... might make it easier.

      Q: Why did the Perlmonk cross the road?
      A: He wanted to escape the match.