...
| Wiki Markup |
|---|
This noncompliant code example shows the {{incorrect_password()}} function, which is called during identification and authentication if the specified user is not found, or the password is incorrect, to display an error message. The function accepts the name of the user as a null-terminated byte string referenced by {{user}}. This is an excellent example of data that originates from an untrusted, unauthenticated user. The function constructs an error message which is then output to {{stderr}} using the C99 standard {{fprintf()}} function \[[ISO/IEC 9899:1999|AA. Bibliography#ISO/IEC 9899-1999]\]. |
| Code Block |
|---|
|
void incorrect_password(const char *user) {
int ret;
/* user names are restricted to 256 characters or less */
static const char msg_format[] = "%s cannot be authenticated.\n";
size_t len = strlen(user) + sizeof(msg_format);
char *msg = (char *)malloc(len);
if (msg == NULL) {
/* Handle error */
}
ret = snprintf(msg, len, msg_format, user);
if (ret < 0) /* Handle error */ ;
else if (ret >= len) /* Handle truncated output */ ;
fprintf(stderr, msg);
free(msg);
}
|
...
This compliant solution fixes the problem by replacing the fprintf() call with a call to fputs(), which does not treat msg like a format string, but outputs it to stderr as is.
| Code Block |
|---|
|
void incorrect_password(const char *user) {
int ret;
/* user names are restricted to 256 characters or less */
static const char msg_format[] = "%s cannot be authenticated.\n";
size_t len = strlen(user) + sizeof(msg_format);
char *msg = (char *)malloc(len);
if (msg == NULL) {
/* Handle error */
}
ret = snprintf(msg, len, msg_format, user);
if (ret < 0) /* Handle error */ ;
else if (ret >= len) /* Handle truncated output */ ;
if (fputs(msg, stderr) == EOF) {
/* Handle error */
}
free(msg);
}
|
...
This simpler compliant solution passes the untrusted user input as one of the variadic arguments to fprintf() and not as part of the format string, eliminating the possibility of a format-string vulnerability.
| Code Block |
|---|
|
void incorrect_password(const char *user) {
static const char msg_format[] = "%s cannot be authenticated.\n";
fprintf(stderr, msg_format, user);
}
|
...
| Wiki Markup |
|---|
This noncompliant code example is exactly the same as the first noncompliant code example but uses the POSIX function {{syslog()}} \[[Open Group 2004|AA. Bibliography#Open Group 04]\] instead of the {{fprintf()}} function, which is also susceptible to format-string vulnerabilities. |
| Code Block |
|---|
|
void incorrect_password(const char *user) {
int ret;
/* user names are restricted to 256 characters or less */
static const char msg_format[] = "%s cannot be authenticated.\n";
size_t len = strlen(user) + sizeof(msg_format);
char *msg = (char *)malloc(len);
if (msg != NULL) {
/* Handle error */
}
ret = snprintf(msg, len, msg_format, user);
if (ret < 0) /* Handle error */ ;
else if (ret >= len) /* Handle truncated output */ ;
syslog(LOG_INFO, msg);
free(msg);
}
|
...
This compliant solution passes the untrusted user input as one of the variadic arguments to syslog() instead of including it in the format string.
| Code Block |
|---|
|
void incorrect_password(const char *user) {
static const char msg_format[] = "%s cannot be authenticated.\n";
syslog(LOG_INFO, msg_format, user);
}
|
...