FSQL User Guide for Security Analysts
What is FSQL?
Federated Search Query Language (FSQL) is Query's unified language for searching across multiple security data sources. It provides security analysts with a powerful yet approachable way to retrieve, filter, and analyze security data from various platforms through a single interface.
Getting Started with FSQL
Basic Query Structure
Every FSQL query follows this general pattern:
QUERY <fields to return>
WITH <filter conditions>
[BEFORE <end time>]
[AFTER <start time>]
[FROM <connector list>]
Example:
QUERY authentication.user.username, authentication.src_endpoint.ip
WITH authentication.status_id = FAILURE
BEFORE 24hrs AFTER 48hrs
FROM 'Active Directory', 'Okta'
This query returns failed authentication attempts from the past 24-48 hours, showing usernames and source IPs from both Active Directory and Okta.
Time Ranges
Time ranges are specified with BEFORE
and AFTER
keywords:
BEFORE 24hrs // Data from up to 24 hours ago
AFTER 48hrs // Data from at least 48 hours ago
Supported time units:
- Hours:
h
,hr
,hour
,hrs
- Days:
d
,day
,days
- Weeks:
w
,week
,weeks
- Months:
m
,month
,months
Data Sources
Specify data sources with the FROM
keyword followed by connector names in quotes:
FROM 'My S3 Bucket', 'Crowdstrike Falcon', 'AWS CloudTrail'
Security Analysis with FSQL
Finding Security Events
The simplest way to find security events is to query a specific event type:
QUERY authentication.*
WITH authentication.status_id = FAILURE
For a broader search across all network-related events:
QUERY #network.*
WITH #network.status_id = FAILURE
Tracking Entity Activity
To track activity associated with an IP address across all data sources:
QUERY #network.*
WITH %ip = '10.0.0.1'
To find all processes launched by a specific user:
QUERY process_activity.*
WITH process_activity.user.username = 'jsmith'
Identifying Suspicious Activity
For suspicious command-line activity:
QUERY process_activity.*
WITH process_activity.process.cmd_line CONTAINS 'mimikatz'
OR process_activity.process.cmd_line CONTAINS 'bypass'
For unusual outbound connections:
QUERY network_activity.*
WITH network_activity.dst_endpoint.port IN 4444, 8080, 6666
Field Selection Techniques
Basic Field Selection
To select specific fields:
QUERY authentication.time, authentication.user.username, authentication.src_endpoint.ip
Wildcards and Expansions
To select all fields from an event:
QUERY authentication.*
To select all fields except start and end time:
QUERY authentication.(* - (start_time | end_time))
Working with Multiple Event Types
To query across multiple specific event types:
QUERY (authentication | process_activity).user.username
To query all events in a category:
QUERY #network.*
Advanced Filtering
Comparison Operators
Operator | Description | Example |
---|---|---|
= | Equals | user.username = 'admin' |
== | Case-insensitive equals | user.username == 'ADMIN' |
!= | Not equals | status_id != SUCCESS |
CONTAINS or ~ | Contains substring | cmd_line CONTAINS 'powershell' |
ICONTAINS or ~~ | Case-insensitive contains | cmd_line ICONTAINS 'powershell' |
STARTSWITH or ^= | Starts with | filename STARTSWITH 'mal' |
ENDSWITH or $= | Ends with | filename ENDSWITH '.exe' |
IN | In list | status_id IN SUCCESS, FAILURE |
< , > , <= , >= | Numeric comparisons | count > 5 |
empty | Field is empty | user.email empty |
Combining Filters
Use parentheses with AND
and OR
operators to create complex filters:
QUERY process_activity.*
WITH (process_activity.process.name IN 'powershell.exe', 'cmd.exe')
AND (process_activity.process.cmd_line CONTAINS 'hidden'
OR process_activity.process.cmd_line CONTAINS 'encode')
List Filters with ANY and ALL
For array fields, use ANY
or ALL
quantifiers:
QUERY application.*
WITH ANY application.cloud.provider CONTAINS 'aws'
QUERY application.*
WITH ALL application.permissions.name IN 'admin', 'root'
Observable and Type Searches
Observable Searches
Use the %
symbol to search by observable type:
Observable | Usage | Description |
---|---|---|
%ip | WITH %ip = '10.0.0.1' | Finds IP across all applicable fields |
%domain | WITH %domain = 'evil.com' | Finds domain across all applicable fields |
%email | WITH %email = '[email protected]' | Finds email across all applicable fields |
%hash | WITH %hash = '44d88612fea8a8f36de82e1278abb02f' | Finds file hash across all applicable fields |
%username | WITH %username = 'admin' | Finds username across all applicable fields |
Type-Based Searches
Use the @
symbol to search by data type:
QUERY **:type(device)
WITH @ip = '10.0.0.1'
QUERY **:type(user)
WITH @email CONTAINS 'example.com'
Common Security Investigation Patterns
Investigation Pattern 1: Authentication Analysis
To find failed login attempts for a specific user:
QUERY authentication.*
WITH authentication.user.username = 'jsmith'
AND authentication.status_id = FAILURE
BEFORE 24hrs
Investigation Pattern 2: Lateral Movement Detection
To find potential lateral movement involving a compromised host:
QUERY #network.*
WITH #network.src_endpoint.hostname = 'WORKSTATION123'
AND #network.dst
Updated 2 days ago