r4wsec

Created and published on 10 April 2022
Author: Sebastián Castro @r4wd3r

Suborner: A Windows Bribery for Invisible Persistence

Whenever an attacker is trying to persist the access on a compromised machine, the first offensive approach usually involves the creation of a new identity. Nevertheless, this may not work with ease under hardened environments with diverse detection mechanisms against common attack vectors.

What if we "suborn" Windows to create our own hidden account that will grant us total access to a victim while impersonating any account we want without triggering any alerts?

Now it is possible with Suborner.

This technique will dynamically create an invisible machine account with custom credentials and custom properties without calling any user management Win32 APIs (e.g., netapi32.dll::netuseradd) and therefore evading detection mechanisms (e.g., Event IDs 4720, 4741). By "suborning" Windows, we can also impersonate any desired account to keep our stealthiness even after a successful authentication/authorization.

What has been done before?

As far as I know, there is currently no public solution that crafts local users as the legitimate OS without calling APIs specifically designed for this purpose. Recently, some security researchers (like Ben Ten) have pinpointed ways to leverage the dollar sign $ to create "hidden accounts". Nevertheless, these approaches use the netuseradd API either through a call to net user /add or by directly invoking the API function. This results in partial stealthiness, but still noise because:

This is why I decided to create the Suborner Attack.

Attack Overview

The attack is simple: Persist the access on a compromised machine by creating a hidden account without triggering any alert on the victim. Moreover, by suborning the Windows victim, this new stealthy account can also impersonate any existing enabled/disabled local account after each authentication.

All this magic is done by:

As far as I can tell, this attack works for every Windows version since NT. This attack has been tested across multiple Windows versions: manually tested for XP, 7, Server 2008R2 and automatically on Windows 10, 11 and Server 2019.

Demo

To show the attack effectiveness, we will use the suborner technique to create a local account that will be considered as a machine account, and will by default impersonate the disabled Administrator built-in account (500). Yes, disabled. Meaning that there is no need to add the invisible account to any group with high privileges to become an admin.

For this purpose, I have developed a C# program called Suborner: The Invisible Account Forger that will implement the attack automatically for us. At the time of the release of this entry, the program dynamically creates an invisible account by using an existent account as a template. In the future, I will update Suborner to allow the customization of  all possible attributes (and use this to try new different attacks >:) )

MODULE OPTIONS

The Suborner C# program currently accepts 5 possible arguments to craft the values needed to forge the invisible account and its attributes:

You can download the latest module from my GitHub repository.

PRE-ATTACK

First things first. This is the initial state of the victim machine: An up to date Windows 11 with the default built-in accounts and only a custom account named user. We can see from here that the local administrators are only this user custom account and the default Administrator. We can notice as well that there are currently no logs regarding user account creations.

ATTACK

We can use any username we want. By default, the program that automatizes the attack will use the hostname value to create this invisible account, but we will stick to the suborner$ name just for the sake of learning.

We will create this suborner$ account as a machine account with the super complex password Password.1. The account will impersonate the built-in Administrator every time we log in with its credentials, but remember that we can decide what account we want to impersonate... And yes, including the "useless" Guest (501) or any other custom account.

From a privileged powershell prompt, we run our Suborner C# assembly specifying the username and the password we want (remember this can be "filelessly" loaded through stuff like reflection if you don't want to deal with the .exe on disk ;) ).

POST-ATTACK

After we successfully created the invisible account, we first look if there is any particular change that may raise an alert. However, this new account does not appear either on the output of net users, the local user manager lusrmgr.msc, nor the default account management interface for Windows 11. The attack does not log any account creation, which is always good for our nefarious purposes >:)

Now from a remote attacking machine we try to access to the victim machine through the Impacket's version of  PSExec, and dump the LSA secrets with the amazing crackmapexec. This is possible because we are impersonating the built-in Administrator, even if we are authenticating with the suborner$ credentials.

DEFAULT SCENARIO: A SUBORNER MACHINE ACCOUNT

The Suborner attack allows to create any type of local account, including one that assigns the username as the victim's hostname, as if it were the legitimate machine account of the victim. Although this setup does not overwrite the default machine account hash (preventing possible problems for domain-joined machines), it is possible to authenticate with the credentials we set even without changing the original machine account hash.

The magic behind the trick: Suborner demystified

In order to successfully craft an account with all the attributes I wanted, I tried again to study how the authentication process works. I have spent many long nights reversing, analyzing and poking on the internet to barely improve my understanding about it. After all that crazy work, I eventually could forge an account “almost” from scratch without calling the Windows APIs.

This is an attack that leverages the way the MSV1_0 authentication package works. At this moment, I am not going to explain all the authentication models that Windows systems encompass, but instead, I will focus on what I am doing with this piece of software. In the future, I will include more details about how each key is crafted.

SUBORNER OVERVIEW

The current version of the program (1.0.1) has the following schema:

  1. Validate if the program is running in a high integrity context (specifically, as SYSTEM). This is needed because Suborner will forge the registry keys and values needed for the account and store them in the respective SAM key paths
  2. Validate user arguments and current context to confirm that what user inputs makes sense. For now, Suborner will always look for the dollar sign $ appended to the username. If it is not there, it will append it automatically
  3. The program will craft 2 keys: one inside Domains\Account\Users\Names and the other only one level above (Domains\Account\Users)
  4. The first key will contain a binary value, taking as data type the RID of the new account
  5. The second key will contain 2 values. F and V. These are copied from an existent account that the user specify via the /template argument
  6. Crafting the F and V values is probably the most challenging thing I did with the software. There are not so many resources specifying their structure, but I ended up figuring out the things I needed thanks to the hard work of people way smarter than me (special thanks to Benjamin Delpy @gentilkiwi).
  7. Write the changes to disk to persist the access!

What's next?

I believe this is an introduction to a new world of user-mode persistence on Windows machines. Right now, there are many solutions to detect uncommon identities with weird attributes like the dollar sign (which made me think about the bribery thing lol) or detecting new account creations. If we do not rely on the operating system to do the nasty stuff, but instead we manually craft the things we need just as we want, we surpass the limits imposed by the OS and its restricted APIs.

Suborner can be the origin of a new way for attackers to create new accounts in a stealthy manner. Now it is just a neat persistence technique I am really proud to release, though am sure it can be leveraged to practically forge any account with any attribute we want, opening the door to a myriad of attacks that are waiting to be unveiled.

This is only the beginning...

¬#r4wd3r'