uberAgent ESA, our endpoint security analytics product, comes with a powerful Activity Monitoring Engine (AME). AME makes use of rules to describe unwanted/risky/dangerous behavior that should be flagged. An AME rule consists of multiple components, the most important of which is a query that defines which activities the rule should match. This post introduces uAQL, uberAgent’s query language.
uberAgent’s Activity Monitoring is best understood with an example. Take a look at the following rule:
[ActivityMonitoringRule] RuleName = Detect Microsoft Office download operations (LOLBAS) EventType = Process.Start Tag = proc-start-lolbas-download Query = ParentIsMsOffice and regex_match(Process.CommandLine, r"(http|https)")
AME rules are configured through
[ActivityMonitoringRule] stanzas (rule syntax documentation).
RuleName element is purely for the rule author’s sake. It should be descriptive and include a reference to the rule’s origin (in this case, the LOLBAS project).
EventType defines which types of activity should trigger evaluation of the rule’s query. In the example above, we’re interested in process start events. Whenever a new process is started, we want uberAgent to check if the rule’s query matches the properties of the newly created process.
AME supports a broad range of event types in addition to process starts. See the event types documentation for details.
uberAgent ESA generates an activity monitoring event whenever an AME rule matches activity on a monitored endpoint. The event is sent to the agent’s configured backend(s), typically a SIEM. The event captures many properties of the process that initiated the activity (see Activity Monitoring Metrics). Additionally, a tag and a risk score can be defined in the rule. The tag (a text string) makes it possible to easily differentiate between different types of events in the SIEM. The risk score allows for filtering by severity or criticality.
Query acts as a kind of filter. We don’t want the rule in the example above match all process starts. We only want it to match newly started processes where the parent process is a Microsoft Office application and where the command line contains either
When we designed uberAgent ESA, we realized that we needed a query language that is powerful in its capabilities while being easy to read and write. We also wanted to be able to evolve the language as we would add new features to uberAgent ESA. The result is uAQL.
As developers, we have worked with many different programming languages. For each language feature we wanted to add to uAQL, we first examined how the existing languages in our repertoire implemented it. We then took the best approaches and combined them into a practical, hands-on query language designed to be easy to work with for non-developers.
Circling back to the example above, I have to admit that I cheated a little. uberAgent does not magically know how to identify parent processes that are part of the MS Office suite. Instead,
ParentIsMsOffice refers to a uAQL expression that looks like this:
[AddActivityMonitoringExpression name=ParentIsMsOffice] Query = istartswith(Parent.Company, "Microsoft") and Parent.Name in ["excel.exe", "msaccess.exe", "onenote.exe", "outlook.exe", "powerpnt.exe", "winword.exe"]
By itself, a uAQL expression does not do anything. But it provides a convenient way to define reusable rule parts that can later be pasted into multiple different rules.
The example above also illustrates the use of functions.
regex_match is a built-in function that matches a given string against a regular expression.
regex_match code also shows that properties of the monitored event can be used (almost) anywhere. In the example above,
Process.CommandLine is substituted with the actual command line when the rule is evaluated.
Now that you know what an AME rule looks like let’s examine a different example:
[ActivityMonitoringRule] RuleName = Detect child processes of Adobe Acrobat Reader # Source: https://www.microsoft.com/security/blog/2019/02/22/recommendations-for-deploying-the-latest-attack-surface-reduction-rules-for-maximum-impact/ EventType = Process.Start Tag = proc-start-adobereader-child Query = Parent.Name == "acrord32.exe" and Process.Name not in ["RdrCEF.exe", "acrord32.exe", "AdobeARM.exe"]
As you can see, this second example is somewhat similar to the first MS Office rule, but there are notable differences.
First of all, this second rule targets Adobe Acrobat Reader. The query does not reference an expression but specifies the name of the parent executable directly since there is only one (
Parent.Name == "acrord32.exe").
In the second half of the query, we’re making sure that the newly started process is not one of the legitimate Acrobat Reader processes (
Process.Name not in ["RdrCEF.exe", "acrord32.exe", "AdobeARM.exe"]).
If the rule matches an activity on one of your monitored endpoints, uberAgent ESA generates a SIEM event with the tag
proc-start-adobereader-child and the default risk score of 50.
This concludes our foray into uAQL land. As you have seen, the rule syntax is simple, intuitive, yet powerful. While we highly encourage anyone to become familiar with uAQL, there is no need to start from scratch. uberAgent ESA ships with hundreds of preconfigured rules for use cases such as monitoring applications, network activity, permissions, certificates, and many more. Take a look at the documentation!