Secure60 Platform has a simple and flexible query language that is used in various parts of the platform. The query syntax allows selection of specific fields, matching of partial text, regex and vairous comparison operators. The syntax also allows grouping of conditions to achieve sophisticated matching rules.
Query sytax is used in the following key system components:
condition statement that is a query in the Secure60 query syntaxSecure60 supports flexible open search functionality that allows you to search for terms across multiple fields without specifying individual field names. This provides a quick and intuitive way to find relevant events.
Single Term Search:
error - Searches for “error” across all default fieldsMultiple Terms (AND logic):
error timeout - Searches for events containing both “error” AND “timeout” across all default fieldsExact Phrase Search:
"disk full" - Searches for the exact phrase “disk full” across all default fieldsCombining with Field Queries:
error AND user_name = 'admin' - Combines open search with specific field queries(login failed) OR ip_src_address = '192.168.1.100' - Uses grouping with open searchBy default, open search queries are executed across the following fields for optimal performance:
message_text - Log message contenthost_name - Source hostnameip_src_address - Source IP addressip_dst_address - Destination IP addressuser_name - Username associated with the eventOn-premise and custom deployments have additional configuration options available:
Contact your system administrator for information about available configuration options in your deployment.
Secure60 supports two main query types:
A basic traditional field query looks like: fieldname operator value
ip_src_address = '43.53.63.62'Multiple basic query elements can be joined together with a keyword
ip_src_address = '43.53.63.62' AND host_name = 'testserver4.example.com'Query component evaluation can be controlled by using grouping
(ip_src_address = '43.53.63.62' AND host_name = 'testserver4.example.com') OR (ip_src_address = '8.8.8.8')Query element using regex and searching in a case insensitive manner
ip_geo_city_name ~ '(?i)melbourne'fieldnameoperator= Exact match!= Not match: Contains - Partial text match, case insensitive
A plain value is a substring search on its own: app_name : 'sshd' matches anywhere in the field. You do not need to surround it with %.
Case is ignored, so app_name : 'SSHD' and app_name : 'sshd' return the same rows.
(Polling Rules Only) Expression can contain normal characters and the following metasymbols:
% indicates an arbitrary number of arbitrary characters (including zero characters)._ indicates a single arbitrary character.\ is for escaping literals %, _ and \ — see Quoting and escaping a valueSupplying your own % at the start or end anchors the match instead of adding to it:
| Written | Matches |
|---|---|
field : 'value' |
anywhere in the field (the default) |
field : 'value%' |
field starts with value |
field : '%value' |
field ends with value |
field : '%value%' |
anywhere in the field (same as the plain form) |
(Streaming Rules) Expression matches text provided exactly (no wildcards). Never use % in a streaming rule — it is matched as a literal percent sign.
!: Not Contains - Partial text not match, case insensitive. Follows the same anchoring rules as :.< or <= Less than or Less than equal to> or >= Greater than or Greater than equal to~ Regex search (Not available in Streaming Rules)
value=) text only, and the comparison is case sensitive:) the value is matched anywhere in the field and case is ignored. Add a % at the start or end only when you want to anchor the match to the end or the start of the field~) then can include re regex syntaxA value is written between single quotes ('…') or double quotes ("…"), and \ is the escape character inside both.
| Written | Means |
|---|---|
\% |
a literal percent sign, not a wildcard |
\_ |
a literal underscore, not a wildcard |
\\ |
a literal backslash |
\' |
a literal single quote |
\" |
a literal double quote |
Two consequences are worth stating outright, because Windows paths run into both:
\\. process_image : '%C:\Windows\\' is correct; '%C:\Windows\' reads the final \' as an escaped quote, leaves the literal unterminated, and is rejected with Unterminated string literal in query.'%\rundll32.exe' needs no escaping at all. Escaping it anyway ('%\\rundll32.exe') matches the same rows.The other quote character is available whenever escaping would be noisier than switching: user_name = "O'Brien" and user_name = 'O\'Brien' are the same query.
Streaming rules resolve the same escapes, so one rule means one thing in both engines — but they match the resulting text exactly, with no wildcards, so a % that survives escaping is matched as a percent sign.
Instead of a fieldname we make a number of functions available to enhance query feature set
Usage of a function is to state the function, if data evaluates to true then results from this function will be included
Function List (Not available in Streaming Rules):
isField('fieldname') - Used to look for the presence of a specific field (with any value)
fieldname - Any valid Secure60 fieldname!isField('fieldname') - Used to exclude a specific field (with any value)isIPAddressInRange('fieldname', 'prefix')
fieldname - Any valid Secure60 fieldnameprefix - String IP address with subnet (Eg. 127.0.0.0/24)!isIPAddressInRange('fieldname', 'prefix') - Used to exclude an IP address from matchingisInList('list_id', 'fieldname') - Applies filtering logic to the query to only return results that have a match between the fieldname provided and a List Item in the list_id provided.
fieldname - Any valid Secure60 fieldnamelist_id - Any valid List ID!isInList('list_id', 'fieldname') - Applies filtering logic to the query to exclude results that have a match between the fieldname provided and a List Item in the list_id provided.
fieldname - Any valid Secure60 fieldnamelist_id - Any valid List IDisEntity('entity_name') - Returns all activity belonging to a registered entity, matched across every identifier recorded against it.
entity_name - The entity’s name, exactly as shown on the Entities page (e.g. Host 2)isEntityGroup('group_name') - Returns all activity belonging to any member of an entity group.
group_name - The group’s name, exactly as shown on the Entities page!isEntity('entity_name') / !isEntityGroup('group_name') - Exclude all activity belonging to that entity or group.isOlderThanDays('days') - Returns records whose timestamp is at least days old.
days - A whole number of daysisNewerThanDays('days') - Returns records whose timestamp is less than days old.!isOlderThanDays('days') / !isNewerThanDays('days') - The inverse of each.isBusinessHours('start_hour', 'end_hour', 'timezone') - Returns records that fall on a weekday between the two hours, in the timezone given.
start_hour, end_hour - Whole hours, 0 to 23. The start hour is inclusive and the end hour is exclusive, so ('08', '18', ...) covers 08:00:00 until 17:59:59 and treats 18:00:00 as outside business hours.timezone - An IANA timezone name, for example Australia/Sydney. Log timestamps are stored in UTC, so the timezone is what makes the result mean anything locally.!isBusinessHours('start_hour', 'end_hour', 'timezone') - Returns records outside those hours: any weekend, or any weekday before the start hour or at and after the end hour. This is the form to use for after-hours detections.isWeekend('timezone') - Returns records that fall on a Saturday or Sunday in the timezone given.!isWeekend('timezone') - Returns records that fall Monday to Friday.isHourBetween('from_hour', 'to_hour', 'timezone') - Returns records that fall within an hour window on any day, in the timezone given. The window may cross midnight: ('22', '02', ...) covers 22:00 to 02:59.!isHourBetween('from_hour', 'to_hour', 'timezone') - Returns records outside that window.Notes on the time functions:
NOT keyword in the query language, so each function is registered with its own ! form. !isBusinessHours(...) is a true complement of isBusinessHours(...) over the same arguments: every record matches exactly one of the two.Notes on isEntity:
The value is the entity’s name, not one of its identifiers. isEntity('Host 2') is correct; isEntity('192.1.2.44') will not match, even if that IP is one of its identifiers.
The point of the function is that you do not need to know how an entity happens to be recorded in each log. A host registered with a hostname and an IP is matched by both host_name='web-01' events and ip_src_address='10.1.2.3' events from a single isEntity('Web 01').
Matching is done against the identifiers you register on the entity, compared against these log fields:
| Entity type | Fields matched |
|---|---|
| Host | host_name, ip_src_address |
| User | user_name |
| Application | app_name |
An identifier only matches if its value appears in one of those fields. Registering a MAC address or an FQDN identifier, for example, will only match where that value is present in host_name.
Entity names are not required to be unique. If two entities share a name, activity for both is returned.
Newly created entities, and new identifiers added to an existing entity, take up to a minute to become searchable.
Notes:
isInList can also be applied via the parameters list_allow_field and list_allow_id for example. See:
Use Open Search when:
Use Traditional Field Queries when:
Open Search Examples:
failed login - Find any events mentioning failed logins"connection timeout" - Find exact phrase across all fieldsmalware AND ip_src_address = '10.0.0.1' - Combine approachesTraditional Field Query Examples:
user_name = 'admin' - Exact user matchevent_count > 100 - Numeric comparisonip_src_address : '192.168.%' - IP subnet search with wildcards~) are the one exception to the escaping table above: they are passed to the regex engine with their backslashes still to be resolved, so a backslash the pattern needs has to be written twice over.
process_target_image ~ '\lsass.exe$'process_target_image ~ '\\\lsass.exe$'