A condition is a boolean expression related to a single event that has been detected by Falco. You can use fields related to every supported event, but this document focuses on syscalls as they're currently the most common. The language supports boolean operators and parentheses as you'd expect. For example a condition like:
evt.type = execve and evt.dir = < and (proc.name = cat or proc.name = grep)
This will trigger for each execution of
grep. Below you can take a closer look at what is the meaning of those fields such as
evt.dir, how to discover the types of events available, and which fields are present with which event type.
Syscall event types, direction and args
Every syscall event will present the
evt field class. Each condition that you write for those events will normally start with a
evt.type expression or macro; this makes a lot of sense since security rules normally consider one syscall type at a time. For instance, you may want to consider
openat to catch suspicious activity when opening files,
execve to inspect spawned processes, and so forth. You don't have to guess the syscall name, as you can see the complete list of supported system calls events and understand which ones you can use.
Every syscall has an entry event and an exit event which is shown in the
evt.dir field, also known as the "direction" of the system call. A value of
> indicates entry, which fires when the syscall is invoked, while
< marks exit, meaning that the call has returned. In fact, by looking at the supported system call list you can see that our events have both entries. For example:
> setuid(UID uid)
< setuid(ERRNO res)
Most of the time the engine informs you about exit events as you want to understand what happened after the event execution is complete. You can see by using the events associated with opening files.
< open(FD fd, FSPATH name, FLAGS32 flags, UINT32 mode, UINT32 dev)
< openat(FD fd, FD dirfd, FSRELPATH name, FLAGS32 flags, UINT32 mode, UINT32 dev)
As you can see, each event has a list of arguments associated with it that you can access by using
evt.arg.<argname>. For example, to identify when a process opens a file to overwrite it, you need to check if the list of flags contains
O_TRUNC. You can use the
evt.arg.flags field of the
openat exit events shown above and the rule will then look like this:
evt.type in (open, openat) and evt.dir = < and evt.arg.flags contains O_TRUNC
Note that the arguments do not necessarily match the raw parameters that are used in the Linux kernel, but are parsed by Falco to make it easier to write rules. By using the
evt fields we can inspect many more aspects that are common across events.
Syscall event context and metadata
evt fields allow you to write pretty expressive conditions, arguments and common fields are usually not enough to write full security rules. Many times you want to add conditions based on the process context the event happens in, or whether or not something is happening inside a container or even correlate each event with the relevant Kubernetes metadata for the cluster, pods, and more. For this reason, Falco enriches many events with other field classes. Not all the classes are available for all the events and the list can grow. The documentation for each clarifies when those are expected to be available, but some are so common that you often rely on them.
proc field class gives you the context about the process and thread that is generating a specific syscall. This information is usually very important. The most basic piece of information you can get out of it is
proc.pid, but you can even traverse the process hierarchy by using
proc.apid[<n>]. Likewise, you may be interested in which user performs a specific action via the
user field class.
The documentation gives you an example of how to catch executions of
bash within containers:
if evt.type = execve and evt.dir = < and container.id != host and proc.name = bash
Note that you don't even have to look at the
execve args. That is because once
execve has returned the process context recorded by Falco is updated, meaning that the
proc. fields will already refer to all information, including the command line, executable, arguments, related to the new process that was just spawned.
You can use the following operators in conditions:
|Equality and inequality operators.
|Comparison operators for numeric values.
|For strings will evaluate to true if a string contains another, and
icontains is the case insensitive version. For flags it will evaluate to true if the flag is set. Examples:
proc.cmdline contains "-jar",
evt.arg.flags contains O_TRUNC.
|Check prefix or suffix of strings.
|Evaluate standard glob patterns. Example:
fd.name glob "/home/*/.ssh/*".
|Evaluate if the provided set (could have just one element) is completely contained in another set. Example:
(b,c,d) in (a,b,c) will evaluate
d is not contained in the compared set
|Evaluate if the provided set (could have just one element) has at least one element in common with another set. Example:
(b,c,d) intersects (a,b,c) will evaluate
TRUE since both sets contain
|Compare a file path against a set of file or directory prefixes. Example:
fd.name pmatch (/tmp/hello) will evaluate to true against
/tmp/hello/world but not
|Check if a field is set. Example:
|These operators work similarly to
startswith and allow performing byte matching against a raw string of bytes, accepting as input a hexadecimal string. Examples:
evt.buffer bcontains CAFEBABE,
evt.buffer bstartswith 012AB3CC.
Was this page helpful?
Let us know! You feedback will help us to improve the content and to stay in touch with our users.
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.