Q:

Vulnerability using printf/scanf and %s

Why does C tell me this is unsafe even when I try to give the correct input?
#include <stdio.h> 
#include <stdlib.h>

int main(void) {
    char id[8];

    printf("Your ID:");
    scanf("%s", id);

    printf("%s", id);

    return 0; 
}

I'm assuming because it could be exploited? How so?

A:

scanf() doesn't set any bounds on what it takes as input, so it's easy to overflow you id[] buffer.
Modern compilers will likely have stack smashing detection enabled, so if you compile via gcc without setting the -fno-stack-protector flag, the program will deliberately crash early rather than run with such a nasty bug going without being noticed.
You're best off using fgets() and then sscanf() or some other mechanism to parse the input so you can guarantee extra input is discarded.

A:

id is 8 characters long buffer. scanf("%s", id); is not checking the length of the input string. So if the user is entering a string longer than 7 characters long (+1 for null-terminator), it will overflow the allocated buffer and break the program. If the string is crafted in a special way, it might allow a hacker to gain some priveleges, such as executing an arbitrary code.

A:

In addition to over running id[] with too much data, another vulnerability:
Not checking the input function's return value.
User could close stdin causing scanf("%s", id) to return EOF and not put anything in id[].  The following printf("%s", id); then attempts to print an uninitialized buffer.
char id[8];
scanf("%s", id);  // Bad, return value not checked.
printf("%s", id);

// Better
if (1 == scanf("%7s", id)) {
  printf("%s", id);
}

// even better
if (fgets(id, sizeof id, stdin)) {
  id[strcspn(id, "\n")] = '\0'; // lop off potential \n
  printf("%s", id);
}

