Skip to content

#62732 Fix password validation in PasswordHasher`1: add bound check for salt size before array allocation #62734

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

Merged
merged 3 commits into from
Jul 18, 2025

Conversation

navferty
Copy link
Contributor

Add bound check for salt size before array allocation

Description

To prevent memory allocation of arbitrary-sized array, in case when password hash is corrupted or intentionally modified.

Bytes 9-13 of password hash (AspNetUsers.PasswordHash) contain a 32-bit number. It is read during password verification, and array of that size is immediately allocated.

Fixes #62732

@Copilot Copilot AI review requested due to automatic review settings July 15, 2025 18:20
@github-actions github-actions bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Jul 15, 2025
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jul 15, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds an upper bound check on the salt length in VerifyHashedPasswordV3 to prevent unbounded memory allocation when verifying a potentially corrupted or malicious password hash.

  • Introduces a new MaxSaltSize constant (8 KiB)
  • Extends the existing salt-length validation to fail if saltLength exceeds MaxSaltSize
Comments suppressed due to low confidence (1)

src/Identity/Extensions.Core/src/PasswordHasher.cs:252

  • Add unit tests for VerifyHashedPasswordV3 to cover cases where saltLength exceeds MaxSaltSize, verifying that the method returns false and avoids allocating large arrays.
        const int MaxSaltSize = 1024 * 8; // 8 KiB

@@ -260,7 +262,7 @@ private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string passwor
int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);

// Read the salt: must be >= 128 bits
if (saltLength < 128 / 8)
if (saltLength < 128 / 8 || saltLength > MaxSaltSize)
Copy link
Preview

Copilot AI Jul 15, 2025

Choose a reason for hiding this comment

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

Extract the minimum salt size value (128 / 8) into a named constant (e.g., MinSaltSize) to avoid magic numbers and improve readability.

Suggested change
if (saltLength < 128 / 8 || saltLength > MaxSaltSize)
if (saltLength < MinSaltSize || saltLength > MaxSaltSize)

Copilot uses AI. Check for mistakes.

@martincostello martincostello added area-identity Includes: Identity and providers and removed needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically labels Jul 15, 2025
@@ -260,7 +262,7 @@ private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string passwor
int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);
Copy link
Member

Choose a reason for hiding this comment

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

As stated in the issue, this isn't a real problem. However, I do appreciate being cautious as we've been bit by overallocating arrays before.

Having an arbitrary upper limit though isn't super clean. If someone wants to use a massive salt then we shouldn't disallow them unless it's part of the spec.

If we incorporated something like the below, that would be much better as the bounds checking would be more implicit and actually based on the data present.

byte[] salt = hashedPassword.Slice(13, saltLength).ToArray();
byte[] expectedSubkey = hashedPassword.Slice(13 + saltLength).ToArray();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, the ArraySegment and Slice are not fully supported for target frameworks other than .net10, so I just added the hashedPassword.Length - 13 as an upper-bound check for the salt size, which would have same logic as suggested Slice approach.

Copy link
Member

Choose a reason for hiding this comment

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

Use hashedPassword.AsSpan(13, saltLength).ToArray() instead.

…or upper bound for salt size before allocation an array
@navferty navferty force-pushed the 62732-check-salt-size branch from 742f022 to a6489b1 Compare July 17, 2025 10:26
Verification should fail if salt size is less that minimum allowed (16 bytes) or greater that entire data lenght
@navferty
Copy link
Contributor Author

@dotnet-policy-service agree

@@ -260,7 +260,7 @@ private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string passwor
int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);

// Read the salt: must be >= 128 bits
if (saltLength < 128 / 8)
if (saltLength < 128 / 8 || saltLength + 13 > hashedPassword.Length)
Copy link
Member

Choose a reason for hiding this comment

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

FYI this second clause should read (long)saltLength + 13 > hashedPassword.Length or saltLength > hashedPassword.Length - 13. Otherwise you're potentially subject to integer overflow.

@BrennanConroy BrennanConroy merged commit fff3131 into dotnet:main Jul 18, 2025
27 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the 10.0-preview7 milestone Jul 18, 2025
@navferty navferty deleted the 62732-check-salt-size branch July 19, 2025 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-identity Includes: Identity and providers community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No check for salt size before allocating array when validating password
4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy