How do I get the name of a SID, and what does it mean when the conversion fails?

Raymond Chen

A customer had a file share, and they couldn’t figure out who has access to some of the files. They pulled the access control list (ACL), extracted the security IDs (SIDs), converted them from binary to string form, and the result was S-1-5-21-2127521184-1604012920-1887927527-72713. “Why didn’t the conversion work?”

This is a rather confusing question, because the conversion did work. You have the answer: It’s S-1-5-21-2127521184-1604012920-1887927527-72713.

After some back-and-forth we learned that what the customer really meant was “How can we take this SID and convert it to something semantically meaningful to humans, like a person’s name?”¹

Programmatically, you can use LsaLookupSids2 to ask the local system to find a friendly name for a SID. It will consult its local account database, the domain’s account database, and maybe some other stuff. But sometimes it just shrugs its shoulders and says, “Sorry, I can’t come up with a better name for this one.”

The customer was confused by the possibility of a SID with no known name. How can the security system work if it doesn’t know who a SID represents?

The security system doesn’t care who a SID represents. When somebody tries to access a resource, it looks for matches between that person’s SIDs and the SIDs in the ACL, and follows the instructions associated with those matches. For example, there may be an access control entry (ACE) that says “Allow S-1-5-21-2127521184-1604012920-1887927527-72713 to have read-only access.” The security system doesn’t know or care who S-1-5-21-2127521184-1604012920-1887927527-72713 is.

By analogy, suppose your IT department locks down your phone by pushing a list of phone numbers from whom it will accept calls. The phone doesn’t know the names of the callers, but it doesn’t need to know. It just takes every incoming phone call and sees if the number is on the “Allow” list. (This also avoids problems if somebody calls who happens to have the same name as a person on your allow list. Since the phone number doesn’t match, the call is not let through.) As a courtesy, your phone tries to find a name for the incoming call by looking in the phone’s contacts or maybe by contacting a service. But that is best effort, and sometimes you just get “Unknown caller”. Your phone doesn’t know who they are, but the phone doesn’t need to know who they are in order to make a block/allow decision.

You don’t know who this 555-1212 number is, but it’s on your Allow list. And you don’t know who this S-1-5-21-2127521184-1604012920-1887927527-72713 SID is, but it’s there on the file’s Allow list.

The customer said that they were using the Advanced Security Settings property sheet to look up the SIDs. That property sheet already uses LsaLookupSids2 to look up friendly names for every SID, if known. If something shows up in S-... format, then it means that the system couldn’t find a friendly name.

At this point, you need to follow the money backward. If you want to know who this 555-1212 number is, you can ask your IT administrator, since they are the ones who added that number to the Allow list. If you want to know who this S-1-5-21-2127521184-1604012920-1887927527-72713 SID is, you can ask the file share owner or the file owner who it is. Presumably whoever put it on the access control list knows who it is. Otherwise, why would they have added it?

¹ It’s not clear to me how they expected the manual algorithm to produce something semantically meaningful, since the manual algorithm consists of counting things and inserting dashes. Nowhere in the algorithm does a number like “72713” turn into a name like “Chris”.


Leave a comment

  • Michael Taylor 1

    What is really frustrating about the lack of mapping is when the account is removed. It is good security practice to remove user accounts when the user is no longer working. It is also good practice to keep your ACLs cleaned up. Unfortunately Windows requires that we do this mapping manually.

    Let’s ignore for a minute the fact that you should be using a group instead of a user for permissions. You have user X who needs access to certain resources (files, groups, etc). You set NTFS permissions for their account and perhaps add them to groups and everything is fine. When the user leaves you remove their account. Since the SID is tied to the account and unique then it is gone. There is no way to get it back unless you keep a manual list of SID -> user names (which Windows has at least while the account is available). If you want to “clean up” the user’s account you cannot simply search for their user name as only the SID is stored and Windows can’t map it back anymore. So when you look at NTFS permissions (or group permissions or whatever) all you get is the SID or “unknown account”. You don’t know who it was.

    In general this probably doesn’t matter but there are cases where somebody may not have cleaned up the user’s access properly and you might need to review other areas (that may or may not use the SID) to see if they were properly cleaned up. Another aspect is related to auditing to see why this account has access when it shouldn’t have anymore. The event log stores the username indefinitely. It would be nice if Windows had some “store” where it permanently stored the SID to username mapping so we didn’t have to do it ourselves. Of course there are the issues around local accounts vs domain accounts, etc but if Windows can already do the mapping then why not expand that to include an additional source?

    • Joshua Hudson 0

      It does exist; there’s just not any APIs that get at it.

      It is so much a thing the resurrect AD object tool didn’t have to ask for both name and SID but just one or the other and it would find the record and resurrect it.

    • Antonio Rodríguez 0

      It is technically very difficult or impossible to remove deleted SSIDs from ACLs, and it could cause problems with auditing. Think about a multi-Terabyte drive with hundreds of thousands of directories and millions of files. Deleting an account would involve a transverse all the online partitions, fixing all affected ACLs. That would take tens of minutes or even several hours in slow drives or the filesystem is being accessed by other processes. And in the case of an external drive that is not plugged in, or an offline network share, it is physically impossible.

      Not allowing programmatic access to that supposed database of deleted accounts may be due to compliance with data protection laws. Here in the EU, an organization is banned from keeping data from an old member or employee, save for those cases required by other laws. That API would mean Windows could not be used in most organizations in the EU.

      • Michael Taylor 1

        >> It is technically very difficult or impossible to remove deleted SSIDs from ACLs

        I never asked for Windows to clean up all the permissions of a SID. All I said was that when we look at the permissions for an object AND it has a SID for an account that is no longer valid then without a manual mapping there is no way to know what that account originally was. It would be nice if Windows was able to say the the account XYZ is no longer available and show the user name.

        >> Not allowing programmatic access to that supposed database of deleted accounts may be due to compliance with data protection laws

        In that case you cannot use Windows at all. Event log entries, audit records and many other places in Windows store user names permanently. They are not wiped out when a user account is deleted. You could argue that audit records may be covered by other laws but I doubt task scheduler history is and it stores the user name of the user who ran the task.

      • Neil Rashbrook 0

        Another reason why I liked Novell’s Directory Services and file system – it does have ACLs, but they always inherit, so you don’t need to store a copy on every single object, just one at the top of the tree. (You can still change the rights at a point in the tree by specifying new ACL(s) for the entities whose rights have changed, plus you can disallow inheritance of some or all rights if you really need to.) Usually there are so few ACLs that it is typically trivial to remove ACLs on all mounted drives on all servers when you delete an entity (all servers watch for deletion of entities for which they have ACLs).

        • Almighty Toomre 0

          This is how the VAX/VMS RMS permissions worked. I was absolutely flabbergasted that there were any permissions systems that didn’t automatically work that way.

          • 紅樓鍮 0

            Windows supports hard links, meaning the same file node can appear under multiple different paths, and given a file node there generally isn’t a way to say canonically “what’s the path to this file”. And if what this blog says is true (which it is on Linux, for both regular file permissions and SELinux contexts), ACLs apply to file nodes, not individual links, meaning there generally isn’t a canonical parent directory from which a file can dynamically inherit ACLs either.

          • word merchant 0

            Does that mean VAX/VMS has to search towards its root directory (maybe not that far) every time a file’s ACL is needed? Presumably NTFS does not need to do this.

          • Chris Iverson 0

            Agreed with word merchant.

            The VAX way (I’m guessing) optimized for data storage size, in times when storage was expensive.

            NTFS optimized for access check time.

            The VAX way, you store less data on the disk, and it’s faster to change inherited permissions. However, when you need to perform an access check, I’d imagine you wind up potentially needing to check in multiple areas to grab the data needed to perform the check.

            The NTFS way, you only grab data from one place to perform the access check.

            And access checks happen far more often than permissions changes.

          • David Hayman 0

            Does NDS and/or VAX/VMS support hard links? If a single file is in multiple directories that each have conflicting inheritable ACEs, which directory wins?

            This is one reason why NT only inherits permissions at file creation time and why later changes to inheritable permissions need to propagate to child objects.

    • Péter Ádám 0

      You want to access the details? Do not delete the user. Do not turn the pointer into a dangling one.

  • Antonio Rodríguez 0

    In some cases this can happen even with local accounts. I have seen it on my computers, moving a drive from one computer to another. The files and directories show SSIDs that I do know they are mine. But, as they were assigned in a different computer, they aren’t in the local account database and don’t show names. It may happen with deleted local accounts too, but I haven’t tested it.

    • Michael Taylor 0

      Yes, local accounts are created with a SID that is unique to the machine it was created on. Moving such drives to other machines would “invalidate” any local account that isn’t a well known SID.

  • Ian Boyd 0

    We also have to remember that an SID may not even represent a user. Or a group.

    It can be a “virtual” user, or a “virtual” group; an SID that is based on:

    – the hash of the name of a scheduled task
    – the hash of the name of a service
    – the hash of the name of an application pool (AppPool) in IIS

    In which case you’ll never find a user account, because there is none.

    • aaaaaa 123456789 0

      I had to write a tool to translate all sorts of SID to some readable representation (a best-effort translation, of course), and these SIDs were obviously a pain point. My solution was to just enumerate all the relevant tasks/services/etc. and see if one matches the hash. But of course, there’s no guarantee one will.

Feedback usabilla icon