Threat Hunting for AppData Installations

Threat Hunting for AppData Installations

Has it ever occurred to you when installing software why you didn't get prompted for administrator privileges? Many people live under a guise that to install software, they 'need' a privileged account. This isn't always the case. In fact, one of the worlds most popular browsers, Google Chrome (and therefore most of it's Chromium brothers) do not need any special privileges to install.

Why? User-based installations can install to a folder that every user in Windows has: AppData. Software vendors use this because it's a near-guaranteed place that a user will be able to write files to. Not needing any privileges makes it easier to install software, but can come at the cost of security. Adversaries can take advantage of this too.

I mentioned Google Chrome earlier for a specific reason. There is a rise in its derivative - Chromium - being used as a base for writing Potentially Unwanted Applications (PUA). These seem to come modified with extensions pre-installed and while I can't definitively tell you the end goal of these PUA's, I can estimate that tracking user web browsing is likely to be valuable data.

Sadly, it's not only ease of installation that makes the barrier of entry low either. In casual internet browsing, I was able to see Google Ads display one of these PUA's to me:


Article content
Sample PUA advert.

Hunting for AppData Installations

I ended up clicking on the above advert and installing the associated PUA. Due to its similarity with the Chromium code base, I was not surprised to find Defender allowed the install... a 2 click install I might add. However, the good news is that we now have valuable telemetry.

In the above example, the link prompted me to install a PUA named 'OneStart[.]ai'.

Start with assumptions

By assuming that something is going to get written to AppData for installation, we can start with some rough KQL:

DeviceFileEvents
| where ActionType == "FileCreated"
| where FolderPath contains "AppData" and FolderPath contains "OneStart"
| project FolderPath, FileName
| take 1        


Article content
Successfully seeing the file activity

Great, we now have a folder structure:

Users\<Username>\AppData\Local\<VendorName>\<SoftwareName>\....        

Readers of my blog will know I love using regular expressions (regex), so let's hop over to regex101.com to develop something that matches this pattern and extract useful information:


Article content
Testing our new regex

Above, we can see our capture groups:

  • Group 1: the username
  • Group 2: the vendor name
  • Group 3: the software/PUA name

We break down by software and vendor name because a vendor may write multiple pieces of software and therefore have subfolders within their root vendor folder.

Yes - we could use KQL string splitting with a combination of other conditions instead of regex; I prefer to see the visualisation in Regex101

Extrapolating useful regex groups into the KQL query:

| extend FolderInfomation=extract_all(@"\\Users\\(.+)\\AppData\\Local\\([^\\]+)\\([^\\]+)", FolderPath) // the regex
| where isnotempty(FolderInfomation)
| extend AppDataUser=tostring(FolderInfomation[0][0])
| extend AppDataVendor=tostring(FolderInfomation[0][1])
| extend AppDataSoftwareName=tostring(FolderInfomation[0][2])
| extend AppDataCombinedPath=strcat(AppDataVendor,":",AppDataSoftwareName)

        

  • A new field called 'FolderInformation' is created
  • If our new field is empty, we know the regex did not match, so we can remove these records
  • 'FolderInformation' is now an array, indexed by the group number, seen in regex101
  • For each valuable piece of information, we bring it into it's own column, starting with the phrase 'AppData'
  • The last line creates a new field. It combines 2 extracted fields and can be used to uniquely identify a piece of software. For example, 'Google:Chrome'. We will need this later

Building the detection for new AppData installations

Software installations are not commonly composed of one single file. They often need graphics, DLL's and configuration files to support their function. As such, it's possible for us to assume that multiple files are going to be written during an installation.

We can also say with a degree of confidence, that at least one of them will be a '.exe' file. To support our investigation, lets add a column for listing the file extension(s) being written:

| extend FileExtension=tostring(split(FileName, ".")[-1])        

Split the file by '.', take the last value and convert it to a string

Tie it all together

| summarize Extensions=make_set(FileExtension), FileWriteCount=count() by DeviceName, AppDataUser, AppDataKey,InitiatingProcessVersionInfoCompanyName, bin(Timestamp, 2m)
| where FileWriteCount > 10
        

'summarize' is really powerful, as it allows us to aggregate the activity seen. This KQL statement does the following:

  • We count AND make a list of file extensions

BY

  • The device
  • The user listed in the AppData Path
  • Our AppData software name (e.g. 'Google:Chrome')
  • The company name in the metadata of the process that wrote the files
  • Aggregate by a 2 minute window

The statement after summarize filters to where 10 files have been written within that 2 minute period. - may require fine tuning -

Success?

Our query results show that we've been able to catch potential PUA AppData installations! It also captures legitimate installations:


Article content
The PUA install (OneStart[.]ai) is detected, but so is legitimate software.

To tune this, we can focus on AppDataKey or the company name (InitiatingProcessVersionInfoCompanyName) writing the files. I opted for the latter and added the following to the end of my query:

| where InitiatingProcessVersionInfoCompanyName !in~ ('Microsoft Corporation', 'NVIDIA Corporation', 'Google LLC', 'Logitech, Inc.') // add as required        

Closing thoughts

The above results show there is a maintenance piece in identifying legitimate software installations, which may not make this KQL viable for a detection. This will be heavily influenced by complexities within an organisations software stack. The detection also relies upon software being installed using the 'assumed' folder structure that we look for within our regular expression.

Using this KQL should be done with the mindset that for as long as users can self-install to AppData, organisations will always have risk. Use this query to support implementing better security controls, such as AppLocker or folder restrictions!


Query:

DeviceFileEvents
| where ActionType == "FileCreated"
| extend FolderInfomation=extract_all(@"\\Users\\(.+)\\AppData\\Local\\([^\\]+)\\([^\\]+)", FolderPath)
| where isnotempty(FolderInfomation)
| extend AppDataUser=tostring(FolderInfomation[0][0])
| extend AppDataVendor=tostring(FolderInfomation[0][1])
| extend AppDataSoftwareName=tostring(FolderInfomation[0][2])
| extend AppDataKey=strcat(AppDataVendor,":",AppDataSoftwareName)
| extend FileExtension=tostring(split(FileName, ".")[-1])
// detection start
| summarize Extensions=make_set(FileExtension), FileWriteCount=count() by DeviceName, AppDataUser, AppDataKey,InitiatingProcessVersionInfoCompanyName, bin(Timestamp, 2m)
| where FileWriteCount > 10
// tuning
| where InitiatingProcessVersionInfoCompanyName !in~ ('Microsoft Corporation', 'NVIDIA Corporation', 'Google LLC', 'Logitech, Inc.')
        


To view or add a comment, sign in

Others also viewed

Explore content categories