tags:

views:

122

answers:

8

Hi everyone,

I have an executable that accepts certain command line arguments. Any user on the machine can find the arguments by doing a ps (Unix) or procexp (Windows). Some of these arguments are things like passwords. I know we should not be passing in passwords like that.

Is there any way in code of the executable that I can change so that other users doing a ps/procexp cannot see the command line arguments used to start the executable?

I am sure there is no platform independent way to do this but even if there is any API specific to each platform to do this that will be a good starting point. I look forward to hearing any comments/suggestions or thoughts.

Regards,

Ash

+2  A: 

You could write the password to a read-protected file, then access it from the new executable, rather than passing it as an argument. ps is not your only enemy as is obvious from meagar's comment.

Kedar Soparkar
+5  A: 

You're trying to make an insecure solution slightly more secure. Why not just make it more secure?

A quick hack would be to write the password to a file which is set to restricted permissions, and delete it immediately after it is read by the called executable. If the file is written to disk, you still have the risk that the bits still exist on the hard drive. But you could eliminate this problem by using a ramdisk.

Or you could give the executable a private key, and encrypt the password using the corresponding public key. This is a bit more work, but much more secure. Then of course you have the problem of key management.

RyanHennig
+1  A: 

Any method that relies on clearing the argv shown in ps output will have a race condition, so it cannot be secure. That is, there's an interval of time after the process starts but before it can clear its publicly visible arguments.

If you need this functionality (passing passwords on the command line, which is a very very bad idea), you should use a hardened kernel that allows you to completely disable the reading of command line arguments, or even disables ps functionality completely. One cheap way of doing this (but it might break things) is just unmounting /proc.

R..
+1  A: 

Some versions of init overwrite their command line so that they appear as init in a ps listing.

int main(int argc, char * argv[]) {
   // process the arguments or make a copy of them
   // and then

   char * argv0 = argv[0];
   while (*argv++) {
      size_t len = strlen(*argv);
      memset(*argv, 0, len);
   }
   strcpy(argv0, "init");

I was surprised to see this type of thing being used and that a *nix could be designed in such a way that it could work. I haven't tested to see if it does work, btw, but I did read that it has to be the actural memory that the arguments are in, and that copying over just the pointer array to those arguments would not work.

It's still a broken way of doing things to pass sensitive information via command line (or environmental variables, since those are accessible in /proc/<pid>/environ just as argv is in /proc/<pid>/cmdline under Linux).

nategoose
A: 

If the password command line is used, you could have the program re execute itself and pass the information over to the second instance and kill the first, thus reducing the time the command line information is present.

The only good answer is don't let them pass the info on the command line.

Greg Domjan
+1  A: 

That init example gives me segmentation fault

This one, however, works:

int main(int argc, char *argv[])
{
    char * argv0 = argv[0];
    int i;
    size_t len;
    for (i = 0; i <argc; ++i)
    {
        len = strlen(argv[i]);
        memset(argv[i], 0, len);
    }
    strcpy(argv0, "Hey, can you see me?");
    for (;;);
    return 0;
}
ecik
A: 

I usually read all sensitive data from stdin. For example, in isql (Sybase SQL shell) on Linux, I do something like

isql -U username <<EOD
password
select * from whatever
go
Arkadiy
+1  A: 

I think the basic answer is probably to not pass the data on the command line, and use a RPC instead. stdin is a poor-man's RPC, as is writing to a file which you then delete, and there are more sophisticated methods.

On Windows, for example, if you were really concerned about security, I'd suggest using a named pipe, which you could apply security permissions to and encrypt the data over, if you desired. You could probably also use shared memory, for a somewhat more portable approach.

Any RPC solution requires modifying both side of the communication, however, obviously. Trying to obfuscate data by modifying the OS to prevent normal operations, or relying on undocumented runtime behavior, seems like a bad idea security-wise, though.

Hope that helps.

Nick