Previous Entry Share Next Entry
Tips and Tricks for C: Bashing Sensitive Command-line Arguments Like Mysqldump
Universal #2
guypaddock
While working at Red Bottle, I recently learned that the mysqldump command, which is used to dump a MySQL database to a text file, will intelligently hide passwords that it is passed on the command-line.

Don't believe me? Try it. Run mysqldump with appropriate arguments, including a password argument in the format --password=<YOUR PASSWORD> or -p<YOUR PASSWORD>, and then look at the output of ps aux. You should see that the mysqldump command line looks something like this:

mysqldump -h localhost -u username -px_xxxxxxxxxxxxx the_database

I didn't add in the xxxxxxxxxxxxx part in the above example output – the mysqldump process actually bashed that argument after processing it.

How?

Well, as we all know, the standard declaration for the C main function goes like this:
int main( int argc, const char* argv[] )
{
  ... your main code ...
}

Usually, you declare the argv[] parameter array to be const to prevent yourself from accidentally bashing parameters. But, as it turns out, you can omit const, and the compiler will still be happy with you.

This is essentially what mysqldump does – if you grab a copy of any recent version of the mysqldump source code, and look in the get_one_option() function (around line 570 in the copy I link to), you'll see code like this:
if (argument)
{
  char *start=argument;
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
  opt_password=my_strdup(argument,MYF(MY_FAE));
  while (*argument) *argument++= 'x';   /* Destroy argument */
  if (*start)
    start[1]=0;  /* Cut length of argument */
  tty_password= 0;
}

else
  tty_password=1;
break;

It loops through, replacing password characters with "x", and attempting to shorten the length so that malicious users on the same system don't know exactly how long the real password is.

Applying this knowledge, we can do something like this:
int main(int argc, char* argv[])
{
  if (argc > 1)
  {
    char *start = argv[1];
    
    /* ...you would store the password somewhere internal to the application here... */

    // Bash the password
    while (*argv[1]) *argv[1]++= 'x';
    
    if (*start)
      start[1]=0;
  }
  
  // Give us time to look at the process list
  sleep(10);
}

If you compile and run the above program with a command-line argument, you will see that the argument is replaced with "x"s in the output of "ps aux", just like with mysqldump. Neat, huh?

A word of caution: The documentation for mysqldump does say that passing the password on the command-line is still insecure, and I would agree. I am sure that mysqldump only uses the practice described above for users who insist on passing the password in this fashion; in your own applications, I would provide users with a safe alternative way to specify passwords, and rely only on the practice of bashing passwords on the command-line as a last resort.

Consider that, even with the above code, there is a period of time between the program starting and the end of the while loop, during which the password has not been bashed. If your own application does checks and additional logic before processing command-line arguments, this window of time is even longer.

To see a demonstration of what I mean, add a sleep call before the code that bashes the argument, as follows:
int main(int argc, char* argv[])
{
  // Simulate application processing before arguments are bashed.
  sleep(5);

  if (argc > 1)
  {
    char *start = argv[1];
    
    while (*argv[1]) *argv[1]++= 'x';
    
    if (*start)
      start[1]=0;
  }
  
  // Give us time to look at the process list
  sleep(10);
}

If you compile and run the above program with an argument, you'll find that for the first five seconds the program is running, the argument you passed is available raw in the process list output of ps aux!

So, the moral of the story is that bashing sensitive command-line arguments is a useful tool as part of a larger set of security practices you can adopt in your application to try and safeguard information from users who are not security-conscious, but it is foolhardy to rely on it as your only safeguard.

?

Log in