Attack Detection Fundamentals 2021: Windows - Lab #4

By Alfie Champion and Riccardo Ancarani on 7 April, 2021

Alfie Champion and Riccardo Ancarani

 7 April, 2021

In the first part of WithSecure Consulting's Attack Detection Fundamentals workshop series for 2021, we covered advanced defense evasion and credential access techniques targeting Windows endpoints. This included the offensive and defensive use of API hooking, as well as the theft of cookies to enable 'session hijacking'.

 A recording of the first workshop can be found here and the slides are available here

In our last lab, we turned our focus to some post exploitation; using API hooking to grab some plaintext credentials as our target user authenticated to a remote host with RDP. 

In this lab, we'll keep with the post exploitation theme. We are going to steal browser cookies from a target user who has authenticated to a web service of interest (in our case we'll use GitHub). We'll make use of Rich Warren's Chlonium project to extract the master key used by Chrome to encrypt the cookies, then copy the cookie database onto our attacking host. With both of these components - the master key and the cookie database - we can import the cookies into our attacker instance of Chrome and hijack the target user's session; accessing GitHub as them!

By configuring SACLs on our sensitive Chrome files, we'll explore how we might detect suspected hijacking.

Finally, we'll look at another feature of Chlonium that enables us to extract saved passwords from our target user's Chrome browser, decrypting these to reveal them in plaintext.

References

DISCLAMER: Set up of the tools and the testing environment is not covered comprehensively within this lab. We will assume basic familiarity with Windows command line and the ability of the reader to build the necessary tools.

Required Tools

  • 2x Windows VMs (both with Google Chrome installed - tested with version 89.0.4389.82)
  • A compiled version of Chlonium (UI and command-line tool). We've provided a pre-compiled version modified for Chrome 89.0.4389.82 here

Walkthrough

Setup

Firstly on our target host, we'll need to authenticate as a legitimate user to our web service of choice (so we have a session to steal!). For our purposes, we'll use GitHub, but you might want to experiment with other services.

To keep things simple for our lab, we're going to use Chlonium from our target host as a simple executable, so make sure that is present on the host (the chlonium.exe binary only, we'll need the chloniumUI.exe on our attacker host later). It's worth nothing that, as a .NET assembly, there are many ways in which Chlonium could be used in a more life-like offensive scenario. As an example, it could be run entirely in-memory, as supported by many popular C2 frameworks, e.g. using Cobalt Strike's 'execute-assembly' function. We'll also touch on an alternative means of executing this attack later on.

As we saw in the workshop, there are two files of particular interest for our attack technique.

  • %USERPROFILE%\AppData\Local\Google\Chrome\User Data\Local State
  • %USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Cookies

The first of these contains our master key, and the second, our cookie database. We need both elements to decrypt the cookies, before they can be re-imported on our attacker host. As such, we'll use the following script (run as admin) to place a SACL on both files, producing a log entry when either file is read (script adapted from Dane Stuckey's great post here).

# SACL Primitive for File Reads / Directory Traversals / Ownership Changes
$AuditUser = "Everyone"
$AuditRules = "ReadData, TakeOwnership"
$InheritType = "None"
$PropagationFlags = "None"
$AuditType = "Success"
$FileReadSuccessAudit = New-Object System.Security.AccessControl.FileSystemAuditRule($AuditUser,$AuditRules,$InheritType, $PropagationFlags,$AuditType)
$FilePaths = @(
"$ENV:USERPROFILE\AppData\Local\Google\Chrome\User Data\Local State",
"$ENV:USERPROFILE\AppData\Local\Google\Chrome\User Data\Default\Cookies"
)

ForEach-Object -InputObject $FilePaths -Process {
# Get the ACL with Audit ACEs
$Acl = Get-Acl $_ -Audit

# Set the ACE
$Acl.SetAuditRule($FileReadSuccessAudit)

# Apply the ACL
$Acl | Set-Acl | Out-Null
}

For our Object Read events (ID 4663) to surface in the Windows Event Log, we'll need to enable the Object Access logging. As we're just applying this to our target lab host (as opposed to say, a full corporate environment), we can apply this with local Group Policy, navigating to the following location:

Computer Configuration -> Windows Settings -> Security Settings -> Advanced Audit Policy Configuration -> System Audit Policies - Local Group Policy Object -> Object Access -> Audit File

For our purposes, we'll enable both successful and failed access attempts.

With our SACL set on the 'Cookies' and 'Local State' files, and our File System Audit settings enabled, we can open 'Event Viewer' and hopefully view our Event ID 4663s in the 'Security' log!

Retrieving Session Material from Target Host

Firstly, let's retrieve the master key from the 'Local State' file. For our Google Chrome browser, we can use the default settings of Chlonium and just run it as below. As discussed in the workshop, Chrome makes use of DPAPI to protect the credential material stored in the Local State file. As we're running under the context of our target user, we can simply run Chlonium to transparently decrypt this key and exfiltrate it from the host.

Then we can copy the 'Cookies' database from the target host. In our case, we're just saving it to a shared drive between our attacker and target VMs, but in a real-life scenario, this would likely be downloaded through an existing C2 channel.

Importing Session Material on Attacker Host

On our attacker host, we can use Chlonium's UI component to import the cookies into our attacker Chrome session. We provide the master key we retrieved, and the 'Cookies' database.

Clicking the 'Import' button, if all goes well, we should receive a message box confirming successful import.

Now with our cookies imported, browsing to GitHub with Chrome on our attacker host, we should be taken straight to our compromised user's GitHub account!

Retrieving Saved Passwords from Chrome

Chlonium can also be used to decrypt the passwords that have been saved in Chrome. Conveniently, these passwords are encrypted with the same master key we've already retrieved, and the only additional material we need from the victim host is the following file.

  • %USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Login Data

For our lab, confirm that the target web service credentials are saved in Chrome.

Now, we can retrieve the 'Login Data' file and, as before, we'll simply save it to a shared drive.

With our master key from before, we can provide the 'Login Data' file to the Chlonium UI, in lieu of our previous 'Cookies' file. Rather than import these saved credentials into our attacker Chrome browser, we'll just export them to a text file to view them in plaintext.

Clicking the 'Export to Text File' option and saving to a suitable location, we should hopefully be presented with an 'Exported!' message box confirming the successfully decryption of our saved passwords!

Viewing the exported text file, we can see our plaintext password!

Alternative Implementations

As outlined in Harmj0y's blog, there are several options for abusing DPAPI for extracting our Chrome cookies.

Benjamin Delpy's Mimikatz includes functionality for extracting cookies and master keys, as well as (as we well know) many other things. It is left as an exercise to the reader to experiment with Cookie theft using Mimikatz and how the detection opportunities we've explored in this lab might differ.

Detecting the Attack

Viewing our ID 4663 events in the 'Security' log in Event Viewer, we can see entries for both our 'Local State' file (containing the master key we retrieved using 'Chlonium.exe'), and our 'Cookies' file.

Note the information presented in these log entries - we can see the user that initiated the file read, the file that was accessed, and the process used.

This presents us a good opportunity to detect cookie theft through identifying anomalous processes accessing sensitive files. One thing to bear in mind, both as an operator and as a defender, is the limitations of this specific SACL-centric detection. Should an attacker inject malicious code into the Chrome process to retrieve the sensitive material, the activity could pass without scrutiny, in the event that the Chrome process is filtered out of any developed detection.

As an exercise for the reader, can you apply a SACL to the 'Login Data' file and detect processes attempting to retrieve saved passwords from our target Chrome instance?

One other detection opportunity that might be worth considering here is from the target web service's perspective. If a user were to access a given service from their IP address, compromising their cookie database and master key, we might start making similar requests to the web service from a different, attacker-controlled IP address.

With the necessary telemetry provided from the web service, we could potentially map back a given authenticated user session to its source IP addresses, investigating instances of 'impossible travel', for example. This of course has varying degrees of feasibility based on the log source quality for the web service in question.

Conclusion

Having compromised a user's endpoint, session hijacking presents a potent technique for attackers seeking to access their web services; particularly those otherwise protected with Multi-Factor Authentication (MFA).

As we've seen, System Access Control Lists (SACLs) provide us with the opportunity to log attempted access to the sensitive files needed to perform a session hijack (at least in the manner we've seen in this lab). As you can probably imagine, the utility of SACLs extends far beyond our lab example, and could be applied to all manner of sensitive files (and registry keys!) to detect suspicious activity. This could include:

  • Canary files (i.e. files placed specifically to be picked up by an attacker's initial host-based reconnaissance activities).
  • Password vaults.
  • SSH keys.
  • Cloud Provider Access Keys.

Invariably, the volume of telemetry that a given SACL produces is dictated by the object we apply it to, as well as the type of behaviour we choose to log. We applied an 'object read' SACL in our example; in another scenario, we might want to use an 'object write' SACL instead, ensuring telemetry is only produced when changes are made to the file.

And there we have it, that's a wrap on the first workshop of our 2021 Attack Detection Fundamentals series. See you for the next one!