Octoberfest7 / Proxy_Egress_Persistence

A post-exploitation strategy for persistence and egress from networks utilizing authenticated web proxies

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Proxy_Egress_Persistence

Introduction

As an upfront warning, this research contains no hard code samples which is a departure from most of the other research/tools I have published. There are technical details included, but this post covers more of the concepts and considerations side of tool development than it does hard product that readers can take and use immediately.

I recently encountered an environment in which a web proxy (that could NOT be bypassed and traffic routed directly to the internet) was being used that added some extra wrinkles to the post-exploitation game. The proxy required network credentials in order to authenticate to and traverse, as well as certain registry keys being set for the user in order to direct traffic to the proxy in the first place. With a user-context beacon this was of course no concern, as both of these conditions were naturally fulfilled by nature of running the beacon as a user; however it presented a new challenge when it came to talking about privileged persistence and/or remote access. It is suspicious/not desirable to have a Domain Admin or a Workstation Admin or any other flavor of privileged user account calling out via HTTPS given potential GPO's that limit (or try to limit) such behavior, and the local SYSTEM account on a given workstation has neither credentials to authenticate to the proxy with, nor the registry settings required to utilize the proxy. Both of these issues can be overcome, but the real question becomes how to do so intelligently.

For the purposes of this research it is assumed that one has already compromised a workstation in a network and has privilege escalated/obtained code execution as local SYSTEM; in addition, CobaltStrike will be the C2 this research is based around however several other C2's have the same/similar functionality that would work just as well.

image

The wish list for the eventual product to address this problem is as follows:

  1. Obtain an HTTPS beacon that is able to traverse the proxy
  2. Maintain privileged access to the workstation
  3. Maintain HTTPS beacon access to workstation regardless of whether a user is logged in (this one was not achieved but the theory will be covered)

Maintaining Privileged Access

Regardless of how we eventually end up egressing through the proxy, being that code execution as local SYSTEM has been obtained on the compromised host we really want to maintain that level of access. The easy answer of "just spawn a new HTTPS beacon as SYSTEM" of course doesn't apply here, as our inability to do so is the entire basis of this research.

CobaltStrike (as well as most major C2's) support a variety of different protocols for C2 communications, SMB being a popular choice for intra-network communications between devices. It is far preferable to have one (or maybe two for redundancy) actual network egress points, with other compromised machines communicating out to the C2 infrastructure via intranet SMB connections to the egress host(s). Computer role also becomes a consideration here; user workstations regularly initiate connections to the internet, domain controllers and file servers do not.

A simple way around the issue we face is rather than spawning an HTTPS beacon as SYSTEM, we can spawn an SMB one. This will not provide remote access to the compromised host, but it will give us a way to continue to execute code as SYSTEM by linking the spawned SMB beacon to the HTTPS beacon we end up spawning. Critically, because this SYSTEM integrity beacon will reside in session 0 (a bit more on sessions later), this SMB beacon will persist across user sessions; as long as the computer remains powered on, this SYSTEM SMB beacon will be present and accessible.

HTTPS Egress Beacons

As previously mentioned, domain users naturally have the ability to communicate with and traverse the web proxy. While it is possible to edit the registry settings for the SYSTEM account in order to configure the proxy, and it may even be possible to utilize another account's network credentials (if we had either a TGT or plain text creds) with the SYSTEM account, the path of least resistance is to just utilize a domain user's context in order to run the HTTPS egress beacon. The biggest issue with doing so is that unless we have the plain text credentials for a user (in which case we could use the LogonUser windows API) we are forced to spawn the HTTPS beacon either by doing so from the context of that user, or by stealing their token from an active process in their session.

I always like to make my tools/solutions as modular and situation-agnostic as possible; to this end, having to have recovered plain text credentials for a user account is not a viable solution. Given that we also want to spawn and maintain a SYSTEM SMB beacon, the eventual product of this work will need to run in an elevated context so the token stealing option will likely be the easiest to work with. I am going to assume familiarity with the concept of token stealing and will not delve deeply into it here, but bottom line if we are local SYSTEM and there is a user account logged into the machine, we can steal the token of that user and create new processes in their context. Doing so in this case will provide the HTTPS beacon with both the HKCU settings required for the process to locate the proxy, and the network credentials required to authenticate to it.

The major, glaring issue with the course outlined thus far is that should the user whose token we have stolen log off, all of their processes (including our HTTPS beacon) will exit and we will lose the ability to communicate with the SYSTEM SMB beacon (although it will remain running on the machine, as it exists in session 0). Requiring a user be logged into the machine in order to have remote access certainly isn't ideal, which led me to spend some time exploring alternative solutions. An interesting idea that I had and spent some time exploring was trying to spawn a HTTPS beacon as a domain user using a stolen token, in session 0. Session 0 is reserved for system processes, purposefully isolated from each user's logon session (session 1, session 2, etc).

A Quick Note on Running User-Level Processes in Session 0

I did find a way to accomplish spawning a process as a user in session 0 and for a moment thought I was onto something pretty cool; while from a detection standpoint having a user-level process running in session 0 is super weird and suspicious, it opened the door to keeping a process running as a user alive even after that user had logged off/exited their logon session. The technical details of doing so involved following the traditional token-stealing API path of OpenProcess -> OpenProcessToken -> DuplicateTokenEx with an added call to SetTokenInformation, in which the TokenSessionId value was changed from the user's original session ID to 0, the system session. While this did succeed in spawning an HTTPS beacon as a domain user in session 0, and that beacon process staying alive even after the user had logged off, the network credentials associated with the process were invalidated because the user closed their logon session. Will Burgess over at Elastic published a really good article about Windows tokens and the background of the issue I ran into here which I encourage the curious reader to take a look at, as he goes into great technical detail which might prove useful to you in a future situation.

This major setback led me to do a lot of research into windows authentication and read a little bit further into the actual technical details of things like pass the hash, pass the ticket, and other windows authentication abuse. After consulting the source code of Rubeus I think there might be a path forward along the lines of "Steal a user's TGT and pass that in order to create an HTTPS beacon which (maybe?) would be able to traverse the proxy even after the user has logged off", but there are then additional considerations like that the default lifetime of a TGT is 10 hours, after which it must be renewed. This line of thinking quickly becomes burdensome trying to figure out how such a technique would be sustainable in different situations and environments, not to mention the mammoth task of actually writing the code to accomplish all of it (even though if I were to do so I would shamelessly rip a lot of it from Rubeus).

A Path Forward

With what I would have considered the cleanest solution (a user-level process in session 0) off the table, we now have to consider how to most effectively sustain access to the compromised host when it is going to require a user be logged in. The product is going to need to spawn both a SYSTEM SMB beacon as well as a user-context HTTPS one; in addition, what happens if the user logs out and then logs back in? How will our tool continually identity new logon sessions and spawn new HTTPS beacons to ensure remote access to the SYSTEM SMB beacon? Additionally, measures need to be taken to ensure that our tool does not spawn additional unnecessary HTTPS or SMB beacons.

The final tool/payload format I landed on was an executable that contains both HTTPS and SMB stageless CobaltStrike shellcode, the necessary functions to spawn a new process and inject said shellcode into it, as well as control functions to:

A. Identify new user logon sessions and spawn an HTTPS beacon on this event

B. Continually check for the presence of a SYSTEM SMB beacon and spawn a new one if one is not located

C. Eliminate the possibility of spawning a duplicate beacon for the same user logon session or a duplicate SYSTEM SMB beacon.

As of publication I have only created the tool in a .exe format, but it could certainly be ported to a DLL or service exe, opening the door to DLL hijacking and/or sideloading attack vectors. A pseudo-code rendition of the payload format can be seen below:

image

For simplicity this executable can be set to run as a scheduled task as SYSTEM on machine startup; after initial AV evasion measures and a few setup functions, it enters an endless loop in which it alternates between checking for the existence of a SYSTEM SMB beacon as well as user sessions and a corresponding HTTPS beacon, and sleeping for a specified period of time. This cycle continues as long as the machine is turned on, continually monitoring for new user logins (as determined by the presence of explorer.exe processes) and spawning a new HTTPS beacon using a token stolen from that user's explorer.exe process in order to utilize that individuals network credentials and HKCU settings in order to navigate the web proxy server. When a user logs off the HTTPS beacon will die, however as soon as they log back in or an entirely different user logs into the machine (in the case of a shared machine in a public space), a new HTTPS beacon will spawn and restore access to the SYSTEM SMB beacon which provides far greater capability for further post-exploitation. For good measure, Egress.exe can be implanted on several workstations within the network to hopefully ensure that at any given time there is at least one user logged into a machine from which other implants within the target scope can be linked to and operated through.

image

Technical Details

As established early on, there will not be much in the way of code samples related to this project as the vast majority of the code is involved in AV evasion/beacon spawning which I am not publicly disclosing; that being said, it is really just a conglomerate of publicly available techniques put together, so nothing crazy special anyways. What I do want to discuss here are some of the technical requirements/details of this tool and what someone would need to consider should they decided to implement their own version of it.

Spawning Beacons

I am going to borrow a diagram I created and published as part of my research into Mutants, Sessions, and Self-Deletion. Don't pay too much attention to the API's or processes listed, the important part is the overall concept illustrated. image

Because this tool must continually run and spawn multiple different beacons, the local injector payload model is incompatible. The remote spawn injector model will allow our tool to "spin-off" each beacon it creates into a new process independent of the Egress.exe control process; this is desirable for many reasons, to include that if a post-exploitation command ran by one of the beacon processes is detected by AV/EDR and results in the beacon process being terminated, we are not also losing the Egress.exe process automatically. I will make a concession and say that even when implementing PPID spoofing (which I have done here, so spawned user-level HTTPS beacon processes appear to be children of one of that user's processes as opposed to Egress.exe, with similar logic taking place for the SYSTEM SMB beacon) modern AV and EDR's are very adept at tracing out series of events on compromised systems and it would not be super difficult to identify Egress.exe as the process which spawned the identified malicious beacon process. Even so, it is an intelligent and at this point pretty industry standard step to take as you never know what kind of endpoint detection you will run up against.

The CreateProcessAsUser (rather than the normal CreateProcess) API will be needed when spawning the user-level HTTPS beacons, as doing so requires duplicating the user's token and using it during the creation process so that the beacon runs in that user's context. PPID spoofing and (technique dependent) injecting into the newly created process will also require the "EXTENDED_STARTUPINFO_PRESENT | CREATE_SUSPENDED" flags be used in the API as well; there are numerous examples of using these API's to do these things that are publicly available with a little googling.

When it comes to performing PPID spoofing of the SYSTEM SMB beacon, ideally we want to select a parent process in session 0 where the SYSTEM SMB beacon will ultimately reside; due to PPL protection, most all of the processes we might select in session 0 cannot be used for PPID spoofing, with a few exceptions to include spoolsv.exe. A complication arises in that spoolsv.exe has very limited token privileges (likely because it is such an often abused system integrity and session process), and that limited set of privileges will be passed on to the SYSTEM SMB beacon when PPID spoofing is performed; this can be mitigated by also using the CreateProcessAsUser API for the SYSTEM SMB beacon. While PPL protected processes cannot be used for PPID spoofing, their tokens are accessible for duplication and use with the aforementioned API. The resulting SYSTEM SMB beacon will have all the privileges of a more capable session 0 system integrity process (like csrss.exe), but appear to be a child of spoolsv.exe. This is probably an IOC in of itself, as I cannot imagine there are many if any benign examples of a child process's token having more privileges than that of it's parent, but from an operational perspective it is desirable that our beacon process be able to do as much as possible on the compromised machine.

Mutexes and Control

A critical part of this tool is identifying existing beacons and controlling the creation of new ones. To complicate matters, multiple different users and beacon types must be tracked; each unique domain user, the SYSTEM account, as well as both HTTPS and SMB shellcode. Mutexes provide an easy way to do so; for a far more comprehensive (and relevant) discussion and code sample on the topic, I will again link the previous research I did on the topic which can be found Here. The general idea though is that each beacon process that is created by Egress.exe will carry with it an identifier (mutex) that is visible system-wide. We can control the name of this mutex and create it in such a way so as to represent the identity/function of the beacon process to which it is attached (attached being rather simplistic, in reality our beacon process will hold an open handle to this mutex).

The relevant identifiers for each beacon process are the user account the beacon is running in the context of, and the protocol (HTTPS or SMB) that the beacon is using for communications. By combining these values and using the result in each case as the name of the mutex, we can easily assign an "identity" to each beacon spawned by Egress.exe and on subsequent loops through the main control process look for the existence of these mutexes, using their presence or absence as the method by which it is determined whether or not to spawn a new beacon. To add a little more obfuscation to what is going on, the combined name/protocol value (e.g. lisa.taylorHTTPS) can be transformed via a hashing function into a "random" string of numbers (this is discussed a bit more in the above linked research).

This rather simple method of flow control all relies on the CreateMutex API. The desired mutex name is passed as a parameter to the API, and should a mutex by that name already exist the API returns the error "ERROR_ALREADY_EXISTS". By looking for the presence of this error it can be determined if there is a process running on the machine that has a handle to a mutex of the same name (username + protocol) already; meaning that a beacon already exists running in the context of that user, using the specified protocol for communications. The combination of these two pieces of information allows for several different HTTPS beacons to run simultaneously on the same machine as different users, and the same user to run two beacons using different protocols, but prohibits the same user from running more than one beacon using the same protocol, which achieves the control we need in this tool.

Closing

While a little sparse on actual code or technical details and far from any kind of major breakthrough in tradecraft, this research and development of a tool to overcome the challenges presented by a proxy-gated network was a welcome and useful project that I am glad to have completed. I hope that this has been useful and can provide inspiration or ideas to other professionals facing similar challenges.

About

A post-exploitation strategy for persistence and egress from networks utilizing authenticated web proxies

License:Apache License 2.0