Search code examples
cstringargv

C argument with semicolon appears truncated


I am working on an assignment that's related somewhat to the OWASP command injection Example 1. In short, I accept an argument (a filename) that is then appended to the string "cat ", so my program cats the supplied file. If I pass the user input directly to the system() function, the user can sneak in another command separated by a semicolon ;. For example:

./commandinject Story.txt;whoami

will cat Story.txt and print the current user.

I am just asked to detect a semicolon, and if found, error and request another file - looping until valid input is given.

This is pretty straightforward with strchr(), at least, it should be. My issue is that when processing the string argv[1], anything from the semicolon on is invisible. I have some debug code that prints out all argv array values, and I stepped through gdb and the injected command is invisible, as far as I can tell.

For example, when given the input above, the code

printf ("This is the command->%s\n", argv[1]);

will print out

This is the command->Story.txt

What is really weird is that

system(argv[1]); 

still executes the injected code. I am sure it is a simple c-ism that I am missing, but I would appreciate some help with this.

I should note, if I use quotes around the argument, my code works properly and catches the semicolon.

#include <stdio.h>
#include <unistd.h>

#define COMMAND_SIZE 4096

int main(int argc, char **argv) {
  char cat[] = "cat ";
  char *command;
  char *commandRepeat;
  size_t commandLength;

  commandLength = strlen(cat) + strlen(argv[1]) + 1;
  command = (char *) malloc(commandLength);
  strncpy(command, cat, commandLength);
  strncat(command, argv[1], (commandLength - strlen(cat)) );

  // Search command string for ';'
  while(strchr(command, ';') != NULL){
    // ERROR, ask for filename again.
    // Use temporary buffer for user input
    commandRepeat = (char *) malloc(COMMAND_SIZE);
    printf("You used an invalid character ';'\nPlease enter the filename again: ");
    fgets(commandRepeat, COMMAND_SIZE, stdin);
    // Trim newline that fgets includes
    commandRepeat[strcspn(commandRepeat, "\n")] = '\0';

    // Prepare command string
    commandLength = strlen(cat) + strlen(commandRepeat) + 1;
    free(command);
    command = (char *) malloc(commandLength);
    strncpy(command, cat, commandLength);
    strncat(command, commandRepeat, (commandLength - strlen(cat)) );
    free(commandRepeat);
  }

  printf ("This is the command->%s\n", command);
  system(command);

  return (0);
}

Solution

  • The shell is interpretting the ; and running the next command. You'll need to put it in quotes if you want it sent to your program.

    If your program ends normally, you should see the bit after the ; executed.

    ./commandinject "Story.txt;whoami"