...
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);
}
|
...
This noncompliant code example is exactly the same as the first noncompliant code example but uses the POSIX function syslog() [Open Group 2004] 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);
}
|
...
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
Compass/ROSE |
| ||||||||
| Coverity | 6.5 | TAINTED_STRING_WARNING | Fully implemented. | ||||||
Fortify SCA | 5.0 | ||||||||
| GCC |
| Can detect violations of this rule when the | |||||||
| SV.FMTSTR.GENERIC | ||||||||
| 86 D | Partially implemented. | |||||||
Splint |
|
...