What’s the issue?
SQL Server stores the passwords for SQL authentication logins as salted hashes in the password_hash column of sys.sql_logins. The hashing algorithm changed with SQL Server 2012, which moved from SHA-1 to SHA-512. The version of the algorithm used for a given login is encoded in the first bytes of the stored hash, with 0x0100 indicating the older SHA-1 format and 0x0200 indicating SHA-512.
The algorithm is applied when the password is set, not when the instance is upgraded. A login created on SQL Server 2008 R2 or earlier retains its SHA-1 hash indefinitely after the instance is upgraded, and the same is true for logins migrated to a newer instance by script or by copying the hash directly.
This finding identifies SQL logins whose stored password hash still uses the SHA-1 algorithm, detected by examining the version prefix of the password_hash value in sys.sql_logins.
Why is this a problem?
SHA-1 is significantly faster to compute than SHA-512, which makes offline cracking of a stolen hash correspondingly faster. An attacker who obtains the hash, whether through a compromised backup of the master database, a stolen copy of the data files, or access to the instance, can attempt far more password guesses per second against a SHA-1 hash than against a SHA-512 hash.
The weakness compounds with any password quality issues. A SHA-1 hash of a short or predictable password is a very short path from theft to compromise, and logins carrying legacy hashes are often the same ones that were created years ago under weaker password policies and have never been rotated.
This condition is also a strong indicator of password age. A hash still in the SHA-1 format means the password has not been changed since the instance ran SQL Server 2008 R2 or earlier, which means the credential could have been static for well over a decade. Password age alone is a finding in most compliance frameworks, independent of the hashing algorithm.
What should you do about this?
Identify affected logins by querying sys.sql_logins and examining the leading bytes of password_hash for the 0x0100 version prefix. Capture the login name, the creation and modification dates, and the current role memberships and permissions for each, since a legacy hash on a privileged login is the highest priority.
Change the password on each affected login using ALTER LOGIN [LoginName] WITH PASSWORD = N'<new strong password>';, which rehashes the credential using the current algorithm. Coordinate with the application owners and any scheduled jobs that use each login so connection strings and stored credentials are updated at the same time.
Consider enabling password policy enforcement while you are making the change, using ALTER LOGIN [LoginName] WITH CHECK_POLICY = ON; so complexity requirements are applied going forward. Add CHECK_EXPIRATION = ON where the use case tolerates it, since expiration is what prevents credentials from becoming this stale again.