Taking A (Password) Hint

UPDATE: As of macOS 13.0 Ventura, it seems that password hints are no longer visible in dscl, unless you use the -u flag to authenticate as the user or else run it as root.

Recently on a red team engagement, I was given access to a customer environment via a MacBook Pro set up inside their corporate environment. To simulate a compromised machine, the customer ran my payload on this Mac (in this case, a JXA-based Mythic Apfell payload) and it phoned home to my C2 server. This is what’s commonly known as an “assumed breach” scenario.

In this case, the infected laptop was plugged into the office LAN, had the sleep function disabled, the screen locked, and was left sitting on a desk. From simple enumeration on the device itself, I knew the account whose context I was running in had sudo privileges (in macOS world, it was a member of GID 80, the admin group), but my customer point-of-contact hadn’t told me the password. I’m sure they would’ve told me the password had I asked, but I decided to go for realism and try to escalate privileges myself.

As this was basically a computer left by itself with no victim interacting with it, I wasn’t going to get the password via keystroke loggers or fake password prompts. There also wasn’t much in the way of user-created documents on the system to search through for credentials and it was running the latest version of macOS, with no publicly-known privilege escalation exploits either. I even tried some light brute-forcing via Apfell’s test_password function with common passwords to no avail.

One thing that did stick out in my mind was that the username of the compromised account I was running in was just the client company’s name, so it was a good bet this was a shared account, and employees usually don’t commit these sorts of credentials to memory. A feature of both the macOS and Windows GUI login screens is the “password hint” function, to jog a user’s memory. And while both OS’s are configured to not allow you to just put your plaintext password in that field, users often cheat and just give it away with slight modification. In the example below, the John Doe user has a password of simply “password”, and to get around the OS restriction, the hint is in pig Latin.

But I wasn’t sitting physically in front of this victim laptop and I otherwise had no access to the GUI, so I googled furiously for a way to see the user’s password hint from the command line. I actually came up empty-handed in my search, but ended up finding the answer almost by accident while enumerating other info on the system

Viewing Password Hints in macOS

By default, macOS uses its own LDAP implementation to store all user and group data, even just local accounts. The dscl utility can be used from the Mac terminal to interact with this directory service. One of the things you can do with it is view the LDAP data of any account on the system. And one of the values stored in users’ LDAP profiles is their password hint!

You can easily read it with the following command: dscl . -read /Users/[USERNAME] AuthenticationHint

Just to reiterate, as an unprivileged user, you can via the LDAP data of any other user on the system, so this also could be useful for lateral movement.

Sure enough, the account I was using had a password hint that made guessing the real password trivial, and I finally had root-level privileges on the machine!

Viewing Password Hints in Windows

Windows has also had a password hint system since Vista, but (unfortunately for pentesters and red teamers) it’s much better protected than it is in macOS. The password is stored as part of a Windows user’s data in the SAM hive and is only accessible by the NT AUTHORITY\SYSTEM user.

If you have SYSTEM-level access to a box, password hints could still be useful. Maybe its a shared account that doesn’t have administrator privileges (so you can’t just pass-the-hash with the user’s NTLM hash you could otherwise steal out of the SAM), but the same username/password might be reused on different machines that have RDP or SMB file share access enabled.

To view a user’s password hint, you can enter the following into a SYSTEM-level cmd.exe or PowerShell prompt: reg query HKLM\SAM\SAM\Domains\Account\Users\[USER ID] /v UserPasswordHint

The user ID will usually start with “000003” and then two additional hexadecimal numbers. The hint itself is stored as ASCII hex, padded with 00’s in between letters. In the above example, the hint decodes to “the usual”.

Remediation

In macOS, administrators can disable password hints from showing at the GUI login screen, but unfortunately this information is still recorded in users’ local LDAP information if they’ve set a password hint for themselves. Also, as far as I can tell, there isn’t any way to disable local password hints in Windows either.

But this is mostly a problem with local accounts. In both macOS and Windows, network logins, such as to an Active Directory domain, won’t even offer the option of password hints. For IT staff that might have local-only shared accounts on systems, it’s important to educate them on the dangers of using password hints and encourage them to use more secure solutions for sharing credentials instead, such as a password management platform.

Leave a comment