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);
}
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"