0

I was exploring around with C regarding strncpy since most people says that it is safer than strcpy (Additional parameter, length, to avoid buffer overflows). I also wanted to find out the effects of non-null terminated strings on a program. This is a snippet of the code that I have.

char password[5]="1234\0"; //Global variable

int main(int argc, char* argv[])
{
  int length = 5;
  char temp[5];

  strncpy(temp, argv[1], length);     //Possible problems?

  /* Safer alternative */
  //strncpy(temp, argv[1], length-1);
  //temp[4] = '\0';

  if(strncmp(password, temp, length) == 0) {
    printf("Success! \n");
  }
  else {
    printf("Error! Password is incorrect: %s\n", temp);
  }

  return 0;
}

As you can see, strncpy copies 5 characters and this will lead to non-null termination of variable temp if len(argv[1]) >= 5. I'm looking to see if I can use this property to read other memory regions such as the global variable password.

I've read up on strncpy being problematic causing the adjacent buffers to be affected if the string is not null-terminated, causing the next buffer to be read when it is referenced. Exploring Adjacent Memory: http://www.securiteam.com/securityreviews/5PP030KEUM.html

Meng Han
  • 3
  • 5
  • You could read whatever happens to be after `temp`. 99.999999% chance that's not `password`. But you could make it be the password! Something like `char password2[5]; char temp[5]; strcpy(password2, password);` (or maybe swap the order of `password2` and `temp`) – user253751 Sep 29 '15 at 03:03
  • actually - it does lead to a null terminated string :) he will strncpy will ommit the 5th character to replace it with a \0. If you want to have the behaviour you are describing would be with "length = 6". – EGOrecords Sep 29 '15 at 03:03
  • 1
    and also - you never have to include the \0 in your strings, the compiler does that for you! you could also go with `const char *password = "1234";`and have a more readable solution – EGOrecords Sep 29 '15 at 03:05
  • 1
    @immibis Global variables like `password` are 100% not readable from variables within a function, as global variables are not on the stack. – Corb3nik Sep 29 '15 at 03:07
  • @JohannesWalcher, you are mistaken. `strncpy()` will copy at most the specified number of `char`s, but it is explicitly [documented](http://pubs.opengroup.org/onlinepubs/009695399/functions/strncpy.html) that if the source string is that length or longer then it will *not* produce a null-terminated result. – John Bollinger Sep 29 '15 at 03:18
  • *Programming* is problematic. If you are not careful -- and often even if you are -- then your program may misbehave under certain circumstances. `strncpy()` is not a silver bullet, but it *is* a tool that, when used properly, can help you avoid problems. – John Bollinger Sep 29 '15 at 03:23
  • There is no such thing in C as a "non null terminated string". If it's not terminated by a null character, then by definition it's not a string. – Keith Thompson Sep 29 '15 at 04:22
  • I think the OP is trying to produce an exploit where he smashes the terminating null on a string, causing some function that doesn't check size to output bytes from the stack that contain sensitive information? `strncpy()` should not do this if the size is set correctly, but maybe the buffer previously held the password and was not zeroed out. – Davislor Sep 29 '15 at 05:54
  • Yes, let me correct my sentence that a non null-terminated array of characters is not considered a string by the definition of string. I was also reading up on polymorphic shellcode and whether or not I can apply it here to get the password: http://www.dmi.unipg.it/bista/didattica/sicurezza-pg/buffer-overrun/hacking-book/0x2a0-writing_shellcode.html – Meng Han Sep 30 '15 at 17:57

1 Answers1

2

The line

printf("Error! Password is incorrect: %s\n", temp);

will be a problem when temp is not null terminated. It will lead to undefined behavior since the format %s expects a null terminated string.

Use of

strncpy(temp, argv[1], length-1);
temp[4] = '\0';

will lead to erroneous outcome. The test will succeed if the user provides any password that starts with "1234".

R Sahu
  • 204,454
  • 14
  • 159
  • 270