Custom Sandfly Options
The options area of a custom sandfly is where the parameters for scanning are passed to the associated agentless forensic engines.
See Option Data for the complete Options JSON structure. Options that must be present on every sandfly are:
- engines - This is an array that must contain a single string entry naming the scanning engine this sandfly will use.
- explanation - When a sandfly alerts, this string will be displayed to the user to explain what was found. You may include values from the result data structure by placing expr expressions inside of curly braces (
{ ...}
). For example, if using the file engine you can report on the found file name by including{file.name}
in the explanation. - rule_op - This may be the string
and
oror
. When there are multiple rules in the rules array, they will be combined with eitherand
oror
logic. - rules - This array of strings contains the expr rules to determine if the rule alerts. Since at least one rule is required, if a sandfly should trigger on all candidate results that an engine considers, you may include a simple
"true"
rule to always alert. For details on writing these rules, please see Rule Construction.
Optional options include:
- always_pass - This boolean, when true, will cause the rule to always have a "pass" status, but include the detailed forensic data gathered by the engine. This is used, for example, in the recon sandflies where you want to gather data but not trigger alerts.
- inverse_result - This means that Sandfly should consider it an alert when the sandfly does not find anything matching the rules. This may be used to alert on the absence of expected data on the target system.
- explanation_not_found - On inverse_result rules, this explanation is used for the alert explanation. Because there is no result data (since nothing was found), you may not use the
{}
interpolation variables like the regular explanation field. - os_exclude - If this rule is true, will cause the sandfly to be skipped on the target system. The "os" data will be available for use in the rules.
- JSON example of the response struct:
-
"os_exclude": { "rule_op": "or", "rules": [ "os.info.os_release.id == 'alpine'", "os.info.os_release.id == 'gentoo'" ] }
- response - For "process" results only, the sandfly has the option to suspend or kill found processes.
- This section is optional in the sense that it does not have to have anything inside of it, but the top level key itself must exist for all "process" sandflies.
- JSON example of the response struct:
-
"response": { "process": { "kill": false, "suspend": false } }
In addition to the above universal sandfly options, some engines have options to control their scanning behavior.
atjob:
- follow_links - Apply search that follows symbolic links.
- search_paths - Search path for directory.
- search_paths_patterns - Search pattern inside directory.
- search_paths_patterns_ignore - Search patterns to ignore.
cron:
- follow_links - Apply search that follows symbolic links.
- search_paths - Search path for directory.
- search_paths_patterns - Search pattern inside directory.
- search_paths_patterns_ignore - Search patterns to ignore.
- search_paths_individual - Individual filename search.
directory:
- follow_links - Apply search that follows symbolic links.
- home_dir_scan - Apply search paths to all user home directories.
- search_paths - Search path for directory.
- search_paths_recurse - Recursively travel through sub-directories.
- search_paths_patterns - Search pattern inside directory.
- search_paths_patterns_ignore - Search patterns to ignore.
- search_paths_individual - Individual directory search.
file:
- executables_only - Apply search only to files that are executable.
- follow_links - Apply search that follows symbolic links.
- home_dir_scan - Apply search paths to all user home directories.
- search_paths - Search path for directory.
- search_paths_recurse - Recursively travel through sub-directories.
- search_paths_patterns - Search pattern inside directory.
- search_paths_patterns_ignore - Search patterns to ignore.
- search_paths_individual - Individual directory search.
- search_pattern_text - File content search.
- search_pattern_depth_bytes - Limits the number of bytes in a file that we will search for the search_pattern_text in. E.g. if you might have 100MB files but you want to limit the search to the first 1MB of each file, you would set a value of 1048576. Protects you from runaway performance problems searching for file content in directory trees with potentially large files.
- match_paths - Paths to look for files with the same hash.
- match_paths_recurse - Recursively index files for match_paths by traveling through sub-directories.
- match_paths_individual - Individual paths to look for files with the same hash.
- max_size - When >0, files over this size will not be considered for a match regardless of other rules and criteria. This can be used as an early escape valve based on file size for sandflies that may perform hash/entropy/etc checks on directories with extremely large files.
kernel_module :
- taint_inconsistency - Match if the kernel's tainted state is inconsistent with the currently-loaded modules that we are able to find.
process:
- redact_environment - Allow the sandfly agent process to be scanned.
- scan_self - Do not include process environment variables in the result.
- masquerade_binary_check - List of binaries to compare this process against.
user:
- username - Search patterns for usernames to check.
- username_ignore - Search patterns for usernames to ignore.
- password_auditor:
- password_is_username - Check if the user's password is the same as the username.
- password_list - List of passwords to attempt against each user.
- max_random_users_to_attempt - If >0, the max number of users to try to crack this run.
- password_auditor:
Character Escaping
When writing sandfly JSON, proper character escaping (especially for things like quotes and backslashes) at all levels must be considered. For example, to look for a process name that starts with "a", ends with ".b", and has one or more digits in the middle, you can use a regular expression with the "matches" operator in expr.
The regular expression would be:
^a[0-9]+\.b$
Since periods (.) normally match any character in regular expressions, we need to escape them with a backslash to make them literal periods.
The full expr rule to match process name against that regular expression would be:
process.name matches '^a[0-9]+\\.b$'
Because we are putting the regular expression inside of a string, we need to escape the backslash in the original regular expression, since a single backslash is the escape character inside of strings.
Finally, we put that expr rule into the rules array in the sandfly JSON:
"rules": [
"process.name matches '^a[0-9]+\\\\.b$'"
]
Because the expr rule is being placed inside of a string in JSON, we must escape the string contents as necessary. In this case, each backslash in our "bare" expr rule must be escaped, so each "" turns into "\", leaving us with four total backslashes to ultimately get a single literal backslash in regular expression.
Literal String Syntax
Expr now supports the same literal string syntax Go does, that is you can put strings in backticks and then you do not need to escape anything in the string. This alternative method can remove one level of escaping we need to consider in strings in expr rules -- we would only need to escape for JSON, not for JSON + expr.
For example, instead of a rule that is:
"process.cmdline matches '(toptal\\\\.com/developers/hastebin|tor2web|zerobin\\\\.i2p)'"
It can alternatively be written as:
"process.cmdline matches `(toptal\\.com/developers/hastebin|tor2web|zerobin\\.i2p)`"
In this version the single quote marks were changed to backticks and the inner level of escaping of the backslash has been removed.
Updated 4 months ago