As the typical cyberattack kill chain follows the well-known schema, the response should follow it. This is also true in the “Local privilege escalation” scenarios, and it may be quite interesting in all cases, when the system needs to support unprivileged users, but such users reach sometimes for more than they should. Of course, such cases should be impossible, but they will occur, because admins make mistakes, and different bugs exist as well. Take a look at CVE-2020-1048 and the attack based on single “Add-PrinterPort” cmdlet described by Alex Ionescu, if you need an example how easy and unexpected such attacks are. If such incident happens, it must be processed its own way, especially during an investigation, and eradication phases. Investigators should focus not only on fixing the vulnerability, but also on identifying all “remains” an attacker left with regaining superpowers again in mind. There is a huge set of possibilities, an attacker can use for such purpose, such as:
- Adding his account to Administrators group,
- Creating new administrative account,
- Creating a Scheduled Task, providing a privileged access after the eradication,
- Installing specialized Windows Service,
- Installing DLLs, being automatically loaded by highly-privileged processes,
- Replacing legitimate files with malicious ones,
- Creating WMI event filters and consumers,
- Manipulating encryption keys needed for offline access,
Such backdoors make the administrative access possible, even if the attacker’s privileges are fixed, and the vulnerability itself is remediated. Some tools, like Sysinternals Autoruns, allow to take a quick look into most typical places, but such investigations are not very easy as all possible backdoor locations are nowhere listed as a complete set. What investigators do? They look for anomalies, like unusual settings, unusual files, etc. Fingers crossed, but there is still one thing left. With great exploiting potential, relatively easy to be planted within seconds, persistent, and effectively allowing an attacker to regain high privileges. It is object permission, also known as Access Control Lists or ACLs. Using ACLs as backdoors requires higher initial privileges, as the only reasonable scenario is transition from user to admin. But it is still quite a lot, and such escalation should not be possible without system’s owner approval. To quickly summarize ACL-based backdoors:
- Very quick to plant,
- No additional binaries/tools required, only built-in OS tools,
- Easy to plant remotely,
- Impossible to find, unless an admin looks specifically for them,
- Very rarely checked by scanning tools.
- Cover only “user to admin” privilege escalation scenarios.
And how such backdoor can be planted in practice? There is a quick scenario:
- User is an admin for a moment,
- User launches cmd.exe using its temporary superpowers,
- User modifies ACLs of utilman.exe, taking its ownership and adding himself to the list
- User removes his privileges, and behaves politely,
- Admins fix the vulnerability,
- User logs back on as regular user,
- User overwrites the original utilman.exe with cmd.exe, for example using “type c:\windows\system32\cmd.exe > c:\windows\system32\utilman.exe”
- User presses Ctrl+Alt+Del, and then Win+U and has admin access again.
Admins and investigators should stop here for a moment and honestly answer the question: do the existing incident response procedure has any chance to detect such backdoor before it’s exploited by rewriting the file? If user changes the file, the detection is relatively easy with system integrity checkers such as sfc.exe. But when it comes to the file permissions — typical procedures and tools are just blind.
Utilman.exe is a very simple example, but it works perfectly. Other possible locations for such scenarios include:
- Windows Operating System files, being used by highly privileged processes. Hundreds of EXE and DLL files actually. Some of them may be exploited easily, other may require dropping own binary file, but any approach based on comprehensive list and manual check is irrational.
- Program Files, and other non-windir locations, being used by highly privileged processes. Such locations are used typically by third-party software, and they exist on each Windows based machine. It may be slightly harder to pick ideal candidate, but at the same time, every single computer may be slightly different making the detection even harder.
- Registry permissions. Less known than file permissions, which makes them even more tempting to exploit. As registry settings determine the OS behavior, changes may disrupt security in multiple different ways. For example, the REG_MULTI_SZ value “Notification Packages” in the Control\Lsa determines which DLL is loaded by the lsass.exe. It allows to perform multiple sneaky attacks, but at the same time is a great backdoor, as the DLL added to the list by an attacker will be loaded at every boot, executing its code in the SYSTEM context.
- Windows Service permissions. Even less known, however easy to display with “sc.exe sdshow servicename”. Even if the result may be a bit intimidating at the first sight, it is perfectly precise, well documented and powerful. The only enigmatic part here is the way how it is displayed, as it is “Security Descriptor Definition Language” or SDDL. Under the hood, it is just an ACL, specifying who can start or stop the service, change its configuration etc. If an attacking user provides himself a possibility of changing the configuration, he owns the system forever. When he wants to re-gain admin superpowers, he can change the existing configuration to make Service Manager launch malicious executable, instead of legitimate one.
- System privileges. System privileges are not object permissions, but they may be treated as permissions for the entire Operating System. Some privileges are relatively harmless, as changing the timezone or even shutting down the server will not make user the admin again, while others may be dangerous. Especially SeRestorePrivilege, and SeTakeOwnershipPrivilege may be tempting for an attacker, as both allow to gain admin privileges with couple of command lines and no third-party tools. More complicated, but still successful scenarios rely on SeAssignPrimaryTokenPrivilege, SeCreateTokenPrivilege, SeDebugPrivilege, SeLoadDriverPrivilege, SeManageVolumePrivilege and SeTcbPrivilege. Restore and TakeOwnership privileges are used to gain control over sensitive Operating System files, and the attack itself resembles the scenario with utilman.exe, as described above.
- Active Directory. Even if out of scope (it is not a Windows object, and it cannot be called a local privilege escalation), Active Directory is mentioned here to remind, that it is vulnerable to the same type of permission-based attacks.
On the top of permissions allowing an attacker to manipulate objects, there is additional layer some could call “metapermissions”. It is a permission to manipulate existing permissions, or to take the ownership of the object, leading effectively to the permission manipulation as well. Sometimes “metapermissions” may be visible on the ACL (like WD, or WO in the SDDL for a service), and in other cases — not. For example, the powerful icacls.exe utility says nothing about the ownership of a file, and the owner can manipulate permissions to grant himself a write access. At the same time, PowerShell displays ownership with ease.
From the defenders’ perspective, two questions are most important: how to get notified when important object permissions change, and how to investigate and fix permissions after the attack. Theoretically, permission change for files, registry, and services can be audited and stored in the event log.
In practice, collecting audit events is not enough, and two additional solutions should be implemented:
- Log centralization — to prevent log manipulation by an unwanted admin, and to prevent old events overwriting if defenders analyze the case long time after the attack;
- Analytics — to avoid manual review of millions of entries, and to provide some alerting.
If the attack already happened, the best recommendation is to re-install the machine. If machine was compromised, it will remain compromised, despite all efforts to fix it. Even if audit trail is well preserved, it should not be taken as trusted, as local administrators have multiple possibilities of manipulating it, including disabling auditing entirely during the attack. One of the most interesting methods of disabling audit relies on setting the “MiniNT” Registry value. Such value makes auditing subsystem assume it is Windows installation, and not the regular operation, so auditing is pointless and just stops.
Of course, before the reinstallation, it makes sense to create an image of the compromised machine, and perform the detailed investigation. Investigators looking for permission-based attack, should focus on:
- Analyzing ACLs for files and directories. As manual review is pointless (fresh Windows installation may contain over 100k files), the only reasonable way relies on automation. PowerShell Get-Acl cmdlet exposes SDDL property of file objects. It is possible to look for anomalies, broken inheritance, unusual owners etc. The best result may be achieved when comparing the compromised state to the healthy one, taken from baseline, similar machine or a trusted backup. Get-Acl returns owners of filesystem objects as well, both as dedicated property, and as a part of the SDDL string.
- Analyzing ACLs for Registry keys. The same approach and set of scripts used for filesystem may be used, as PowerShell exposes both filesystem, and registry as PSDrive object.
- Analyzing Services ACLs. PowerShell may help with automation, but reading permissions is slightly more complex, as Get-Acl requires GetSecurityDescriptor method exposed by an investigated object, and Get-Service does not have it. One of the workarounds relies on WMI.
- Analyzing system privileges. As there is no official offline way to read privileges database, and no PowerShell or even .Net implementation, privileges are the hardest area for automated analysis. The evidence should be collected while system is still alive, and it may use secedit with /export parameter, or quite complex PowerShell wrapper for LsaEnumerateAccountsWithUserRight() API function.
As described above, object permissions can be used as a very special type of backdoor. Its functionality is limited to “admin for a moment” scenarios, but such situations happen as well. In practice, it means that incident response and investigation plans should include object permissions too. This is especially important when it comes to Windows Privileges, as (using official interfaces) these can be collected only while Operating System is still running. The most effective analysis way is the automated comparison against the healthy system, including both permissions, and the ownership of file, registry and service objects.