Initialize MSTICPy

Configure msticpy settings if needed

At minimum you should configure settings for:

See MSTICPy Getting Started

Be sure to save your msticpyconfig.yaml using the Save Settings button

If saved to the current directory, it will be found automatically.

If you put it somewhere else you will need to specify the location in the MSTICPYCONFIG environment variable.

Connecting to a data provider

Depending on your provider the initialization sequence will look a little different.

The connect function may require authentication parameters if you have not configured them in your msticpyconfig.yaml


Part 1 - Account Attacks


1. Identify the attack period

Query for hourly logons for 30 days

Alternatively, load data from demo file

Perform time series decomposition

Visualize the Timeseries results

Extract anomaly periods and create time range

2. Identify Adversary logon attempts

Query Logon details for selected period

Alternatively, load data from demo file

Query for a baseline

We need a comparison data set to compare the attack period data with. We need to ensure that:

We can re-use the time_range widget value but offset it to 2 weeks prior.

Alternatively, load data from demo file

Identify repeating with pandas value_counts function

Identify repeating features

Password sprays often repeat values in the logon request. We can use pandas value_counts function to find frequently repeating values.

Here are some examples using the location country, appId and useragent for both the baseline and attack period.

Graphical comparison

We can make a graphical comparison of all properties for the two periods.

Show different re-use of logon parameter values

Anywhere orange bars show indicates that the top 10 repeated values for the
column were more frequent in the attack period than our baseline period.

Where blue shows (for location and clientapp used), it means that
the attack period had greater variation in these property values.

E.g. with location country, the attacker used more country origins than the organization typically shows.

Note you might see this latter pattern more frequently with
more sophisticated attacks where properties are randomized
for each logon request. However, detecting that requires
more sophisticated analysis than we are doing here.

Manually selecting properties

Often you can manually select a few specific columns that are likely to be repeated in a password spray.

E.g. User name, target application, User agent, location.

Use MSTICPy Matrix plot to show patterns of IP vs Location country

The Y axis is IPAddress and is too crammed to see individual addresses.

However, this is not so important here - what we are looking for is different distribution patterns between the normal baseline period and the suspected attack period.

In the first chart you can see a few larger circles indicating that the same IP address was having repeated logon failures. But in most cases the logon failures are widely dispersed across different IP addresses in each region.

This isn't uncommon in a large organization, due to things like applications or systems using accounts with expired passwords.

Contrast with attack period

This shows two significant differences:

  1. Lots of IP addresses with repeated failures
  2. Lots of activity from regions that weren't even in the "baseline" data set.

Matrix plots of re-used usernames

In the baseline, the largest repeating username had 96 failed attempts across two regions. This could be suspicious and probably should be investigated.

Contrast with attack period is significant.

Create a Map of normal vs. suspect period locations

Utility function to create IpAddress entities from data

Isolate attacker events

Select the most commonly repeated User Agent and AppID

We'll pick two common repeating properties to try to isolate the attacker events.

Sanity check - what does the data look like without the isolated logons?

It looks pretty normal

Use a Threat Intel provider to check the IP Addresses

Look up a sample using a Threat Intelligence provider

This lookup is using AlienVault OTX. For this to work you will need

See MSTICPy Threat Intelligence providers for details on how to do this.

You can also use any of the other available providers:

Was the attacker successful?

Use properties of the the isolated attack events to search for successful operations with the same properties.

or load from pickle file

Next steps

Investigate and remediate


Part 2 - Powershell scripted attack


How do we find suspicious events?

Query host process events

or read in from Pickle file

Simple methods often work

Plot histogram of command line length

Look at those events.

At least one seems suspicious

Searching for scripting executables is often not helpful

These are commonly used for system tasks and produce too much noise

Try to find any encoded command lines

Powershell attack scripts are often (nearly always) encode

using MSTICPy's mp_b64.extract pandas function

Note: this function is moving and will be access with this syntax

data_frame.mp.b64extract(column=col_name, utf16=True)

Match the decoded command lines back with the Process events in our data

Filter out uninteresting items

In this case the processes in the system session (SubjectLogonId = '0x3e7') seem uninterested. Filter them out to get a list of remaining sessions

View the processes in a process tree

We want to view, not just the encoded commands but also other processes running in the same suspect sessions

Interpreting the process tree

It is pretty easy to spot the powershell processes with long, encoded command lines. Notice:

  1. It is run from the shell (explorer) via windows scripting host
  2. One of its child processes is 'whoami.exe', which is unusual.

Examine the PowerShell script

Find the process that we're interested in We read the following values from the process tree view:

And its encoded command line

(first 2000 characters)

Look at the raw decoded command - not very readable!

Using a simple reformatter from MSTICPy we can see the code more clearly

We can use the code_view module to add intelligent highlighting.

This uses the pygments Python package to parse and highlight the code.

Note iex == InvokeExpression (i.e. run the data as powershell script)

Do a web search for a section of the code

$ref=[ref].assembly.gettype('system.management.automation.amsiutils')

https://github.com/S3cur3Th1s****/Amsi-Bypass-Powershell


Part 3 - Scheduled Tasks


Search periods of unusual activity

Number of distinct event types in 5 min windows

Using MSTICPy .mp_plot.timeline() makes it easier to see more detail

Search for process events using schtasks.exe on the commandline

We only have one in this case.

Reformat the commandline for easier reading

IEX == Invoke-Expression

From schtasks help

    /TR   taskrun      Specifies the path and file name of the program to be 
                       run at the scheduled time.
                       Example: C:\windows\system32\calc.exe

Windows Scheduled task events

The Registered Task event (ID 106) doesn't give a lot of info

Tells you that a task was created but not what the parameters were.

You may need to search in process create and powershell logs

Windows event 4698 has the detail in the TaskContent field

(However it's in encoded XML)

Interpretation

IEX ([Text.Encoding]::UNICODE.GetString([Convert]::FromBase64String((gp HKCU:\Software\Microsoft\Windows\CurrentVersion debug).debug)

Execute whatever comes next

IEX (...)

Read a string

[Text.Encoding]::UNICODE.GetString(...)

Decode from base64

[Convert]::FromBase64String(...)

Get property (debug value from HKCU...CurrentVersion\debug key)

gp HKCU:\Software\Microsoft\Windows\CurrentVersion debug).debug

Find the script that the task is executing

What is in the HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion debug key?

Task command line

/TR "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 
    -NonI 
    -W hidden 
    -c \"IEX ([Text.Encoding]::UNICODE.GetString([Convert]::FromBase64String((gp HKCU:\Software\Microsoft\Windows\CurrentVersion debug).debug)))\""

gp == Get-ItemProperty

We could look at the Task config on the host but we want to work from logs

Let's check if any registry events in the PowerShell pipeline logs

// Example query
EventsTable
| where EventReceivedTime <= datetime(2020-09-21 03:18:00)
| where EventReceivedTime >= datetime(2020-09-21 03:15:00)
| where EventID == 800

Search (EventID 800) for registry events

Decode any B64 encoded text in the DataFrame

Format and prettify the decoded code

Note - there was more Base64 encoded text in body of decoded PowerShell

... getstring([convert]::frombase64string('aAB0AHQAcAA6AC8ALwAxADAALgAxADAALgAxADAALgA1AA==')))

The encoded string in the de-obfuscted code above won't decode because we've made everything lowercase in the de-obfuscation.


When MSTICPy sees nested encodings it returns each item as a separate row in the results. The decoded value of the nested string is in the next row in our decoded results Dataframe.

You can also use the %%b64 MSTICPy magic to decode inline

References

OTRF Security Datasets https://securitydatasets.com/

Sysmon event ID 13 https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventid=90013

Event ID 4698 https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventid=4698

Powershell 800 pipeline event https://www.myeventlog.com/search/show/975

Powershell de-obfuscator https://github.com/thewhiteninja/deobshell