There are several different types of accounts one should be aware of: Virtual Accounts, Managed Service Accounts & Group Managed Service Accounts. Today, in part 1 of this blog series, we will discuss Virtual Accounts.
Virtual Accounts were introduced in Windows 7 and have been progressively extended in subsequent releases. A Virtual Account has a well-known SID (or more accurately a well-known SID prefix), just like the predefined local accounts that pre-dated them (e.g LocalSystem, whose well-known SID is S-1-5-18).
Incidentally, I say ‘well known’, but in some cases, this corresponds to ‘undocumented but well known to the authors of the Windows codebase’.
Virtual Accounts, unlike predefined accounts, are rather peculiar beasts. Like many Windows enhancements over the years (the 8.3 filename hack in particular) they are a cunning hack on top of an existing infrastructure.
A Virtual Account consists of two parts, just like any other built-in account, i.e., for a pre-existing predefined local account we have, for example, the two-part name:
NT AUTHORITY\Network Service
And for Virtual Accounts, we have the same naming convention i.e.:
Account Class\Account Name
Virtual Accounts are defined for a fixed set of class names – which are (I believe) hard-wired into the OS and can’t be extended by the user – but – and this is the critical difference – the account NAME isn’t defined. Instead, an infinite number of accounts within a class is available. You don’t create or delete Virtual Accounts, they just ‘are’.
How this works has to do with the cunning hackery I referred to earlier. Everything in Windows revolves around the concept of a security principal and in general, this is associated with a SID. So Virtual Accounts start with a distinct SID prefix (allocated to the account class) and then add a unique suffix for each account. Unlike ‘real’ accounts, the Virtual Accounts don’t exist as such. They aren’t created or deleted and can’t be managed through the GUI. Instead, a SID is calculated dynamically, so that for an account:
Account Class\xxyyzzz
we can get a unique SID. This is done by computing the SHA-1 hash of the name (in this case xxyyzzz).
Now you can allocate permissions to this SID, just like any other SID. Hence, Virtual Accounts give you an infinite number of local accounts, each of which can be given permissions separately because it maps to a distinct SID. Thus, the problem of services sharing a built-in account and thus having cross-service permissions they shouldn’t have is solved.
Also, another advantage of this approach is that the SID is fixed across machines – unlike a true local account created on the machine, where, apart from the built-in accounts, the SID associated with that account would be specific to that machine. This has advantages when you need to migrate secured resources since the SIDs associated with the ACLs for the resources will now remain constant. However, as discussed at the end of this document, a Virtual Account uses the computer account to access external resources, so although the SID is invariant, this doesn’t mean that a secured resource can be migrated seamlessly if external resources are involved. (this is one reason why MSAs and then gMSAs were invented. They are domain-level accounts, however, and beyond the scope of this discussion).
As stated previously, the set of Virtual Account classes is hard-wired into the OS. The best-documented of these classes is the Virtual Service Account. This uses the class name:
NT SERVICE
Consequently, all Virtual Service Accounts will be in the form
NT SERVICE\xxyyzzz
Microsoft has embraced these enthusiastically so you’ll find SQL Server using them, for instance. For example, on my lab machine, I have an instance of SQL Server running under the Virtual Account NT Service\MSSQL$SQL2014STD
Now the xxyyzzz name is just the name of the service. Critically it DOES NOT NEED TO EXIST. You can see this by using the ‘sc’ utility to show you the calculated SID for a service ‘xxyyzzz’ which does not exist. You can see here that the NT SERVICE well-known SID prefix (S-1-5-80) is suffixed with the dynamically-calculated part, which as mentioned is derived from the SHA1 hash of the service name.
The ‘sc’ utility only knows how to calculate SIDs for virtual service accounts. So, although other classes of Virtual Accounts are believed to have the SID suffix calculated in the same way, you have to resort to PowerShell to figure out what the SID might be. I believe, given an *instance* of a Virtual Service Account that corresponds to a running service, it should be possible to call the Win32 API to translate the name to a SID. I haven’t tried this, however.
Just like real accounts, there are also Virtual Account groups. There is, accordingly, a well-known SID S-1-5-80-0 which corresponds to the virtual group NT SERVICE\ALL SERVICES.
All virtual service accounts will belong to this group, so you could allocate permissions to the group, which would, in turn, affect the permissions associated with any group member. Of course, unlike real accounts, those members are an infinite set of Virtual Accounts.
However, you *could* also assign one or more Virtual Service Accounts to a *real* group, i.e. one created in the normal way. IIS does this, for example.
In the screenshot below you can see how in my lab I could add the above Virtual Service Account to the real administrator's group. This only works if the Virtual Service Account is associated with an actual running service. For the scenario above where I retrieved the SID for a fictitious service ‘xxyyzzz’ it is not possible to select the account from the GUI and add it to the administrator's group. However, I have no idea whether in code, given a calculated SID for the non-existent service, you could do this. After all, at some point, you could delete the real SQL Server service and in that case, I *assume* the group membership of its calculated SID remains valid. These are interesting questions but you will look in vain for any documentation on this, as far as I can see.
You can see the start of the calculated SID. As expected, if you run “sc showsid mssql$sql2014std” on another machine, you get the same SID value; it’s not specific to a particular machine.
You may wonder if you can assign the Virtual Account GROUP as a member of another (real) group. The answer is no, but interestingly this is true even for real local groups. The UI won’t let you do it but “net localgroup” will (for real groups). Microsoft, however, points out that this doesn’t work properly. You can’t nest local groups; you can only make DOMAIN groups a member of a local group.
Over the years, other Virtual Account classes have been progressively added. For each class, the amount of documentation progressively diminishes, as far as I can determine. This seems to be a disturbing recent trend at Microsoft. Unfortunately, the quality and amount of the documentation are inversely proportional to its age.
The IIS AppPool Virtual Account class
The next most popular Virtual Account class was introduced for use with IIS. This Virtual Account class is called IIS AppPool and again, its members will correspond to various named App Pool Identities. Most commonly there will be at least one account for the default app pool, called, not surprisingly, DefaultAppPool.
It’s SID prefix is:
S-1-5-82
Now you may wonder if there’s a Virtual Account group for this class. It’s well-known SID would be S-1-5-82-0 but, while that *probably* is the logical group to which these accounts belong, I can’t find any documentation on this at all.
There are, however, groups associated with IIS AppPool identities. These are conventional built-in account groups, NOT Virtual Account groups.
The IIS_IUSRS group has the SID S-1-5-32-568. When App Pools are associated with Virtual Accounts, the Virtual Account SIDs are automatically made a member of the IIS_IUSRS group when the pool is started up. This is done by dynamically munging the token associated with the Virtual Account SID.
I imagine all this was done as a backward-compatible hack for IIS, so here we have a ‘hack on top of a hack’.
The NT Virtual Machine class
Hyper-V uses this Virtual Account class to manage a set of accounts whose names will be
NT Virtual Machine\{GUID}
Where GUID is the GUID associated with the Hyper-V VM. The well-known SID prefix for this class is S-1-5-83
There *is* a documented group for this class. The SID S-1-5-83-0 is documented as the group NT VIRTUAL MACHINE\Virtual Machines
We can see that this group IS used to allocate permissions, by running cacls on one of the VM folders, as shown below: