Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hardening: negative snprintf return values #182

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

ep69
Copy link

@ep69 ep69 commented Feb 7, 2024

snprintf returns negative values in case of errors, as found out by SAST (Static Application Security Testing)

@@ -165,8 +165,10 @@ crypt_sha1crypt_rn (const char *phrase, size_t phr_size,
hmac_sha1_process_data (hmac_buf, SHA1_SIZE, pwu, pl, hmac_buf);
}
/* Now output... */
pl = (size_t)snprintf ((char *)output, out_size, "%s%lu$%.*s$",
magic, iterations, (int)sl, setting);
dl = snprintf ((char *)output, out_size, "%s%lu$%.*s$",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's another one above (L156)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only looked in the ones that are casted to size_t, but you are right, it might make sense to go through all snprintf calls and make sure return value is checked for negativity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the iffiness is slightly above:

  sl = (size_t)(sp - setting);

Shouldn't this be bounded to a reasonable value? If I read the sources correctly, it currently isn't, although the documentation comment suggests it can be at most 64? Then the snprintf below cannot fail with EOVERFLOW (or otherwise) anymore.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fweimer-rh thanks for looking, I'll check.

@@ -165,8 +165,10 @@ crypt_sha1crypt_rn (const char *phrase, size_t phr_size,
hmac_sha1_process_data (hmac_buf, SHA1_SIZE, pwu, pl, hmac_buf);
}
/* Now output... */
pl = (size_t)snprintf ((char *)output, out_size, "%s%lu$%.*s$",
magic, iterations, (int)sl, setting);
dl = snprintf ((char *)output, out_size, "%s%lu$%.*s$",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the iffiness is slightly above:

  sl = (size_t)(sp - setting);

Shouldn't this be bounded to a reasonable value? If I read the sources correctly, it currently isn't, although the documentation comment suggests it can be at most 64? Then the snprintf below cannot fail with EOVERFLOW (or otherwise) anymore.

size_t written = (size_t) snprintf ((char *)output, o_size,
"%s,rounds=%lu$", SUNMD5_PREFIX, count);
int written = snprintf ((char *)output, o_size,
"%s,rounds=%lu$", SUNMD5_PREFIX, count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an actual snprintf implementation that can fail with these inputs? I don't think so. There are many tricky cases in for printf processing (allocations in argument list and long double processing, return value exceeding INT_MAX), but they don't seem to apply here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fweimer-rh might be extremely unlikely, but things may break elsewhere and it is legit for snprintf to return negative values according to documentation.

To be honest, I don't know. Is there some good practice about how paranoid and double-checking is it worth to be (vs. not complicating the code)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fweimer-rh I would like to hear and follow your opinion. Shall we be more paranoid and expect that snprintf might return negative values as documented, or less paranoid and rely on no libc implementation failing for some specific arguments?

"$%c$rounds=%lu$", tag, count);
{
int w = snprintf ((char *)output, output_size,
"$%c$rounds=%lu$", tag, count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise I believe this invocation cannot fail.

@ep69
Copy link
Author

ep69 commented Apr 11, 2024

@fweimer-rh @besser82 I am sensing reluctance to this change. Would it be easier for everybody to just close it and never look back?

@@ -148,13 +148,15 @@ crypt_sha1crypt_rn (const char *phrase, size_t phr_size,
}

sl = (size_t)(sp - setting);
assert (sl <= CRYPT_SHA1_SALT_LENGTH);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this assert can be hit by crafted inputs, then this change might be problematic. Is there a way to return an error for this?

The remaining asserts look fine.

In my previous comments, I probably got carried away by our internal analysis tool discussion, sorry.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fweimer-rh You are right, this assert could be hit if long enough input is provided. I'll remove it. The limit CRYPT_SHA1_SALT_LENGTH is actually used only when generating the salt and hashing works fine with longer salts UNTIL CRYPT_OUTPUT_SIZE (384) starts to be a problem - in that case only the salt is present in crypt_sha1crypt_rn. This is an issue in my opinion, but probably for another PR.

I'll remove this assert.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fweimer-rh could you have a look now?

snprintf returns negative values in case of errors, as found out by
SAST (Static Application Security Testing)
@ep69
Copy link
Author

ep69 commented May 14, 2024

@fweimer-rh could you please have another look if all your concerns are fixed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants