Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.

Commit 663df1e

Browse files
authored
Merge pull request #179 from microsoft/mjmelone-patch-29
Create Episode 1 - KQL Fundamentals.csl
2 parents f51205c + 7399d32 commit 663df1e

File tree

1 file changed

+353
-0
lines changed

1 file changed

+353
-0
lines changed
Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
print Series = 'Tracking the Adversary with MTP Advanced Hunting', EpisodeNumber = 1, Topic = 'KQL Fundamentals', Presenter = 'Michael Melone, Tali Ash', Company = 'Microsoft'
2+
3+
// Language Reference: https://docs.microsoft.com/en-us/azure/kusto/query/
4+
// Advanced Hunting Reference: https://docs.microsoft.com/en-us/microsoft-365/security/mtp/advanced-hunting-schema-tables?view=o365-worldwide
5+
6+
// ---------------
7+
8+
// What is KQL \ Azure Data Explorer?
9+
// - Write Once, Read Many (WORM) dataset
10+
// - Used in a variety of Microsoft products including
11+
// + Defender ATP Advanced Hunting
12+
// + Microsoft Threat Protection Advanced Hunting
13+
// + Azure Sentinel
14+
// + Azure Data Explorer
15+
// - Tuned to work best with log data
16+
// - Case sensitive
17+
// - Automatically expires records based on a specified interval (up to 10 years)
18+
19+
// ---------------
20+
21+
// When using Kusto datasources
22+
// - If the data source is log-based, try to reduce the timeframe
23+
// - More current data is likely to be in hot storage and will return more quickly
24+
// - Try to reduce data earlier in the query before joining or manipulating it
25+
26+
// ---------------
27+
28+
// Getting Started: Query Format
29+
//
30+
// DataSource
31+
// | filters \ modifiers \ limiters
32+
33+
DeviceProcessEvents
34+
| take 100
35+
36+
// DeviceProcessEvents
37+
// ref: https://docs.microsoft.com/en-us/microsoft-365/security/mtp/advanced-hunting-deviceprocessevents-table?view=o365-worldwide
38+
// Process creation and related events
39+
// - The newly-launched process
40+
// - The process which initiated the process
41+
// + The device the process
42+
// + The identity the process was launched as
43+
44+
// take
45+
// Returns rows up to a pre-set count. Good for testing out your query at a small scale before use.
46+
47+
// Note: There is no order or consistency when using take without sorting!
48+
49+
// SQL Equivalent: SELECT TOP 15 * FROM DeviceProcessEvents
50+
51+
// ---------------
52+
53+
// Data sources can be tables, functions, variables
54+
55+
let foo = "bar";
56+
print foo
57+
58+
// let
59+
// Declares a variable which can be used later in the query.
60+
// - Values can be:
61+
// + Scalar (single value)
62+
// + Tabular (a 2-dimensional table)
63+
// + A function
64+
// + Dynamic (a JSON-formatted object that can be addressed using dotted notation (this.that))
65+
// - A semicolon must exist after every let statement!
66+
67+
// print
68+
// Outputs a scalar value
69+
70+
// ---------------
71+
72+
DeviceLogonEvents
73+
| count
74+
75+
// DeviceLogonEvents
76+
// A table containing a row for each logon a device enrolled in Defender ATP
77+
// Contains
78+
// - Account information associated with the logon
79+
// - The device which the account logged onto
80+
// - The process which performed the logon
81+
// - Network information (for network logons)
82+
// - Timestamp
83+
84+
// count
85+
// Returns the row count for a tablular dataset
86+
87+
// ---------------
88+
89+
AppFileEvents
90+
| take 100
91+
| sort by Timestamp desc
92+
93+
94+
// AppFileEvents
95+
// ref: https://docs.microsoft.com/en-us/microsoft-365/security/mtp/advanced-hunting-appfileevents-table?view=o365-worldwide
96+
// Information regarding activity relating to files stored in cloud services
97+
// monitored by Microsoft Cloud App Security (MCAS), including
98+
// - The cloud application name
99+
// - The type of action performed
100+
// - The item the action was performed on
101+
// - The identity which performed the action
102+
// - The IP address and geolocation
103+
104+
// sort
105+
// Orders the dataset based on the specified column
106+
107+
// SQL Equivalent: SELECT TOP 100 * FROM DeviceFileEvents ORDER BY Timestamp desc
108+
109+
// ---------------
110+
111+
DeviceRegistryEvents
112+
| top 100 by Timestamp desc
113+
114+
// DeviceRegistryEvents
115+
// Registry changes which occurred on a Windows device monitored by Defender ATP
116+
// Contains
117+
// - Registry information (Key, Value, Data)
118+
// - Device information
119+
// - The process which performed the operation
120+
// - Timestamp
121+
122+
// top
123+
// Returns an ordered list of rows based on the column specified
124+
125+
// SQL Equivalent: SELECT TOP 100 * FROM DeviceRegistryEvents ORDER BY Timestamp desc
126+
127+
// ---------------
128+
129+
DeviceNetworkEvents
130+
| take 1000
131+
| distinct RemoteIP, RemoteUrl
132+
133+
// DeviceNetworkEvents
134+
// Table containing inbound and outbound network connections and attempts from a device monitored by Defender ATP
135+
// Contains
136+
// - Networking information (source and destination IP and port, URL, protocol)
137+
// - Device information
138+
// - The process which made or received the connection
139+
// - Timestamp
140+
141+
// distinct
142+
// Returns a table of unique results based on the column(s) specified
143+
144+
// SQL Equivalent: SELECT DISTINCT RemoteIP, RemoteUrl FROM DeviceNetworkEvents
145+
146+
// ---------------
147+
148+
DeviceInfo
149+
| take 100
150+
| project DeviceId, DeviceName, OSPlatform
151+
152+
// DeviceInfo
153+
// Operating information about a device monitored by Defender ATP
154+
// Contains
155+
// - Device name, ID
156+
// - Operating system information
157+
// - Public IP address
158+
// - Logged on user
159+
// - Machine group
160+
161+
// project
162+
// Can be used to
163+
// - Reduce columns returned from a dataset
164+
// - Rename columns in a dataset
165+
// - Create calculated columns
166+
167+
// DataSource
168+
// | project Column1, Column2, Column3 = Column1 + Column2
169+
170+
// SQL Equivalent: The column list in a query statement
171+
// SELECT [this is the project statement] FROM DataSource
172+
173+
DeviceInfo
174+
| project Timestamp, DeviceName, Four = 2 + 2
175+
| take 100
176+
177+
// --------------
178+
179+
DeviceNetworkInfo
180+
| take 100
181+
| project-away Timestamp
182+
183+
// DeviceNetworkInfo
184+
// Local network configurations for a device monitored by Defender ATP
185+
186+
// Other useful project commands:
187+
188+
// project-away
189+
// Removes columns from the dataset
190+
191+
// project-rename
192+
// Renames a column
193+
194+
// project-reorder
195+
// Changes the order of columns in the results making the specified columns first
196+
// No real change to the data, just how its represented
197+
198+
// ---------------
199+
200+
DeviceImageLoadEvents
201+
| take 100
202+
| extend DomainAndUser = strcat(InitiatingProcessAccountDomain, '\\', InitiatingProcessAccountName)
203+
| project-reorder DomainAndUser, InitiatingProcessAccountDomain, InitiatingProcessAccountName
204+
205+
// DeviceImageLoadEvents
206+
// Identifies any DLLs loaded by a process. Useful for tracking DLL sideloading attacks.
207+
// Contains
208+
// - The process that loaded the library
209+
// - The module loaded by the process
210+
// - The device where the load occurred
211+
// - Timestamp
212+
213+
// extend
214+
// Adds a column to the current dataset
215+
216+
// strcat()
217+
// Concatenates two or more strings
218+
219+
// ---------------
220+
221+
AppFileEvents
222+
| where Timestamp > ago(3d)
223+
224+
// where
225+
// Used to filter a tables results based on a Boolean expression
226+
227+
// DataSource
228+
// | where Column == "value"
229+
230+
// SQL Equivalent
231+
// SELECT * FROM SecurityEvent WHERE EventID = 4624
232+
233+
// ago()
234+
// Function used to identify a timespan relative to the current date and time
235+
// Used with one of the following quantifiers:
236+
// d: days
237+
// h: hours
238+
// m: minutes
239+
// s: seconds
240+
// ms: milliseconds
241+
// microsecond: microseconds
242+
// tick: ticks (100 nanosecond intervals)
243+
244+
// Important note: The most effective way to improve query performance in KQL
245+
// is filtering based on time.
246+
247+
// ----------------------------------
248+
249+
// Note that Kusto is a case sensitive language and
250+
// many of the operators are case sensitive.
251+
252+
print IsItEqual = 'TEST' == 'test'
253+
254+
// For a case insensitive string search, use =~
255+
256+
print IsItEqual = 'TEST' =~ 'test'
257+
258+
// Common Operators and their case insensitive counterparts
259+
// __________________________________________________________________
260+
// | Case Sensitive | Case Insensitive | Operation |
261+
// --------------------------------------------------------------------
262+
// | == | =~ | Equality |
263+
// | != | !~ | Inequality |
264+
// | has_cs | has | Term comparison (whole word) |
265+
// | !has_cs | !has | Term comparison (whole word) |
266+
// | hasprefix_cs | hasprefix | Term prefix comparison (any) |
267+
// | !hasprefix_cs | !hasprefix | Term prefix comparison (any) |
268+
// | hassuffix_cs | hassuffix | Term suffix comparison (any) |
269+
// | !hassuffix_cs | !hassuffix | Term suffix comaprison (any) |
270+
// | contains_cs | contains | Substring |
271+
// | !contains_cs | !contains | Substring |
272+
// | startswith_cs | startswith | String prefix |
273+
// | !startswith_cs | !startswith | String prefix |
274+
// | endswith_cs | endswith | String suffix |
275+
// | !endswith_cs | !endswith | String suffix |
276+
// | in | in~ | Array element match |
277+
// | !in | !in~ | Array element match |
278+
// | | has_any | Term array match |
279+
// | matches regex | | Regular expression match |
280+
// --------------------------------------------------------------------
281+
282+
print IsItEqual = "quick" in ("The", "Quick", "Brown", "Fox")
283+
284+
print IsItEqual = pack_array("lorem","ipsum","dolor") has "Dolor"
285+
286+
print IsItEqual = "Microsoft" contains_cs "ICR"
287+
288+
// For a list of all string operators: https://docs.microsoft.com/en-us/azure/kusto/query/datatypes-string-operators
289+
290+
// ---------------
291+
292+
// Special characters \ escaping
293+
294+
// In KQL, the '\' character is the escape character. If you want to use a '\'
295+
// in your query you will need to either escape it by using '\\', or you can
296+
// make it a string literal by prepending '@' before the string
297+
298+
print '\\ This \\ example \\ uses \\ the \\ escape \\ method \\'
299+
300+
// Now using the string literal method
301+
print @'\ This \ example \ uses \ the \ string \ literal \ method \'
302+
303+
// ---------------
304+
305+
// Checking for null or blank values
306+
307+
// isnull(Column) / isnotnull(Column)
308+
// - Checks for null values
309+
310+
// SQL Equivalent: SELECT TimeGenerated, EventData FROM SecurityEvent WHERE EventData IS NOT NULL
311+
312+
print isnull("")
313+
314+
// isempty(Column) / isnotempty(Column)
315+
// - Checks for null values or empty strings
316+
317+
// SQL Equivalent: SELECT TimeGenerated, EventData FROM SecurityEvent WHERE EventData LIKE '%'
318+
319+
IdentityQueryEvents
320+
| where isnotempty(AccountSid)
321+
| take 100
322+
323+
// IdentityQueryEvents
324+
// - contains query activities performed against Active Directory objects, such as users, groups, devices, and domains monitored by Azure ATP
325+
// - Includes SAMR, DNS and LDAP requests
326+
327+
// ---------------
328+
329+
search 'microsoft.com'
330+
| take 10
331+
| project-reorder RemoteUrl
332+
333+
// search
334+
// Searches the entire dataset for a given value
335+
// Can be used to search the entire database (all tables and columns) all at once.
336+
// Columns will be an aggregate of every table that brought back 1+ results, with
337+
// columns having the same name merged together
338+
339+
// No true SQL equivalent (aside from indexing every table and searching the index, or unioning every table and column and searching that... yuck)
340+
341+
IdentityInfo
342+
| search "administrator"
343+
| take 100
344+
| project-reorder AccountUpn, AccountName, AccountDisplayName, Surname, EmailAddress, JobTitle
345+
346+
// IdentityInfo
347+
// - Contains information about users in Azure Active Directory
348+
349+
// Can be used with string equality comparisons. Comparison is row-based
350+
351+
search "administrator" and "cmd"
352+
| take 100
353+
| project-reorder ProcessCommandLine, FileName, AccountName, FolderPath, AccountDisplayName, Surname, EmailAddress, JobTitle, AccountUpn

0 commit comments

Comments
 (0)