Anomaly rules engine
General
The Anomaly Rules Engine is a powerful tool CAST AI provides as part of our Kubernetes runtime security feature set. It allows you to define custom rules to detect and classify events as anomalies based on specific criteria. This enables proactive monitoring and alerting for potential security threats or unusual behavior within your Kubernetes cluster.
Rule types
The Anomaly Rules Engine supports two types of rules:
- Built-In Rules: These rules are pre-defined by CAST AI and cover common security scenarios. They are readily available for use and can be quickly enabled or disabled as needed.
- User-Defined CEL Rules: These rules are custom-defined by you using the Common Expression Language (CEL). CEL provides a flexible and expressive way to define complex matching criteria based on event properties and resource attributes.
Each rule consists of two main components:
- Resource Selectors: Used to filter and select the relevant resources to which the rule should be applied.
- Event Matching: Defines the conditions and criteria for identifying anomalous events.
Note
Only the resource selectors can be modified for Built-In rules, while the event-matching logic is pre-defined by CAST AI. For User-Defined CEL rules, you have full control over both the resource selectors and event-matching logic.
Resource selectors
Resource selectors allow you to filter events based on specific resource attributes before applying the rule. This helps narrow down the scope of events to be analyzed.
Resource selectors are defined using CEL expressions. The CEL program has access to two variables:
cluster
of typetypes.Cluster
: Represents the Kubernetes cluster.resource
of typetypes.KubernetesObject
: Represents the Kubernetes resource associated with the event.
These variables expose various properties that can be used in the CEL expressions to select the desired resources. Refer to the corresponding sections below for more details on the available properties.
Resource selectors examples
Include only some clusters and namespaces:
cluster.name in ["dev", "testing"] && resource.namespace == "apps"
Exclude pods with prefixes:
resource.namespace == "castai-agent" && resource.pod.startsWith("castai-imgscan")
User-defined CEL rules
User-defined CEL rules provide the flexibility to define custom anomaly detection logic based on your specific requirements. You can write CEL expressions to match events and trigger anomalies based on various conditions.
CEL rules Examples
Detect OOM:
event.type == event_process_oom_killed
Detect that container dropped new executed binary and process started with the name nginx
:
event.type == event_magic_write && event.process.name.startsWith("nginx")
Detect TCP connection to non-standard ports for public IP:
event.type == event_tcp_connect &&
event.tcp.destination.ip.public() &&
!(event.tcp.destination.port in [80, 443])
Detect exec arguments matches:
cel.bind(bad_args, ["tigervnc", "novnc", "--vnc", "rfbport"],
event.type == event_exec &&
bad_args.exists_one(bad_arg,
event.exec.args.exists_one(arg, arg.lowerAscii().contains(bad_arg))
))
Exclude dropped binary hashes:
event.type == event_exec && event.exec.is_upper_layer &&
!(hex(event.exec.sha256) in [
"9f64a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a",
])
Exposed variables
In a User-defined CEL rule, the program has access to the event through the event
variable of type types.Event
. This variable represents the current event being evaluated and provides access to its properties.
Refer to the sections below for more information on the available exposed properties.
Helper Functions
The Anomaly Rules Engine provides several helper functions that can be used in CEL expressions to perform common operations:
Function | Description |
---|---|
IP(string) -> IP | Parses the given string into an IP address. If the string is not a valid IP address, it will fail with an error. Example: IP("10.0.0.1") != IP("2345:425:2CA1:0000:0000:567:5673:23b5") |
CIDR(string) -> types.CIDR | Parses the given string formatted in prefix notation to a CIDR. Example: CIDR("10.0.0.0/8") != CIDR("2001:1111:2222:3333::/64") |
hex(bytes) -> string | Encodes the given bytes as a hexadecimal string. The resulting string will be lowercase. Example: hex(event.exec.sha256) |
fromHex(string) -> bytes | Inverse of hex(bytes) that takes a hex-encoded string and turns it into bytes. It will fail with an error if the given string is an invalid hex.Example: fromHex('CAFE') |
UUID(string) -> bytes | Parses the given string as a UUID and returns the underlying bytes. Example: event.cluster.id == UUID('ecb5cb1b-7e7f-4dad-b504-6d13b69ce62e') |
Standard library functions | https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions |
Other custom string functions | https://github.com/google/cel-go/blob/b66ac6c0896350d105d71bf1960eece62ebb0c3c/ext/strings.go#L41 |
These functions can be used in your CEL expressions to parse and manipulate data related to events and resources. They provide convenient ways to work with IP addresses, CIDR notations, hexadecimal representations, and UUIDs.
Common Types
The Anomaly Rules Engine uses various types to represent events, resources, and their associated properties. These types expose properties that can be accessed and used in CEL expressions to define resource selectors and event-matching logic. Here are the commonly used types.
types.Event
The types.Event
type represents an event observed in the Kubernetes cluster. It contains information about the event type, timestamp, associated cluster, resource, and other event-specific details.
Property | Type | Description |
---|---|---|
type | types.EventType | Type of the event. See the types.EventType table below for available types. |
timestamp | Timestamp (RFC3339 string) | Timestamp when the event was observed. |
cluster | types.Cluster | Cluster in which the event was observed. |
resource | types.KubernetesObject | Kubernetes resource the event was observed for. |
process | types.Process | Process details. |
dns | types.DNSPayload | Additional information about the observed DNS request if the event is of type event_dns . |
exec | types.ExecPayload | Additional information about the observed command execution if the event is of type event_exec . |
file | types.FilePayload | Additional information about the file if the event is of type event_magic_write . |
socks5 | types.SOCKS5Payload | Additional information about the observed SOCKS5 actions if the event is of type event_socks5 . |
stdio_via_socket | types.StdioViaSocketPayload | Additional information regarding the potential reverse shell if the event is of type event_stdio_via_socket . |
tcp | types.TCPPayload | Additional information about the observed TCP actions if the event is any of the event_tcp_\* types. |
payload_digest | uint64 | Field used to group related events together. |
types.EventType
The types.EventType
type represents the different types of events that can be observed by the Anomaly Rules Engine. Each event type corresponds to a specific action or occurrence in the Kubernetes cluster.
Name | Description |
---|---|
event_exec | Triggered when the execution of a binary is observed. |
event_dns | Triggered when a DNS-related request is observed. |
event_tcp_connect | Triggered when a new TCP connection is observed. |
event_tcp_listen | Triggered when a new TCP socket starts listening. |
event_process_oom_killed | Triggered when a process is observed to have been killed due to an out-of-memory (OOM) condition. |
event_magic_write | Triggered when a write operation on an ELF binary is observed at runtime. |
event_stdio_via_socket | Triggered when the binding of any standard input/output (STDIO) file descriptors to a network socket is observed, which might indicate a reverse shell. |
event_tty_detected | Triggered when the allocation of a new pseudo-terminal (PTTY) device is detected. |
event_socks5_detected | Triggered when SOCKS5-related network traffic is observed. |
types.Cluster
The types.Cluster
type represents a Kubernetes cluster and contains information about the cluster's identity and organization.
Property | Type | Description |
---|---|---|
id | UUID | Unique identifier of the cluster. |
name | string | Name of the cluster. |
organization_id | UUID | Identifier of the organization to which the cluster belongs. |
types.KubernetesObject
The types.KubernetesObject
type represents a Kubernetes resource associated with an event. It provides details about the container, pod, namespace, and workload related to the event.
Property | Type | Description |
---|---|---|
container | string | Container the event was observed for. |
namespace | string | Namespace in which the container is running. |
pod | string | Pod the event was observed for. |
pod_annotations | map[string]string | Annotations set on the Pod that the event was observed for. |
pod_labels | map[string]string | Labels set on the Pod that the event was observed for. |
workload_id | UUID | ID of the workload related to the event. |
workload_kind | string | Kind of workload the Pod belongs to (e.g., Deployment, StatefulSet). |
workload_name | string | Name of the workload to which the Pod belongs. |
types.Process
Property | Type | Description |
---|---|---|
name | string | Process name. |
host_pid | int | Process ID as seen on the host. |
types.DNSAnswer
The types.DNSAnswer
type represents the answer received for a DNS query. It contains information about the type of the answer and the associated data.
Property | Type | Description |
---|---|---|
type | types.DNSAnswerType | Type of the DNS answer, indicating whether it is a public IP, private IP, or CNAME. |
cname | string | Domain name returned if the DNS answer type is dns_cname . |
ip | IP | IP address returned if the DNS answer type is either dns_public_ip or dns_private_ip . |
types.DNSAnswerType
The types.DNSAnswerType
type represents the different types of DNS answers that can be received.
Name | Description |
---|---|
dns_unknown | DNS type could not be determined. |
dns_public_ip | DNS answer was classified as a public IP address. |
dns_private_ip | DNS answer was classified as a private IP address. |
dns_cname | DNS answer was classified as CNAME. |
types.ExecPayload
The types.ExecPayload
type contains additional information about an observed command execution event.
Property | Type | Description |
---|---|---|
args | []string | List of arguments observed in the execute command. |
file_details | types.FileDetails | Additional information about the executed file. |
path | string | Path to the executed file. |
sha256 | types.SHA256Hash | SHA256 hash of the executed file. |
is_upper_layer | bool | Execution from upperdir writable layer. Works only for overlays. |
is_memfd | bool | Execution of a binary in memfd . |
is_tmpfs | bool | Execution of a binary in tmpfs . |
is_dropped_binary | bool | Execution of a binary that was observed to be dropped (this should also have triggered a MAGIC_WRITE event). |
types.FilePayload
The types.FilePayload
type represents additional information about a file related to the event.
Property | Type | Description |
---|---|---|
path | string | Path to the file related to the event. |
types.TCPPayload
The types.TCPPayload
type contains additional information about observed TCP actions
Property | Type | Description |
---|---|---|
destination | types.AddrPort | Destination of the TCP-related packets. |
network_details | types.NetworkDetails | Additional information about the destination based on IP set data. |
ip_details | types.IPDetails | Additional information about the destination IP from third-party services (like AbuseIPDB). |
types.StdioViaSocketPayload
The types.StdioViaSocketPayload
type represents additional information about a potential reverse shell event.
Property | Type | Description |
---|---|---|
destination | types.AddrPort | The destination of the socket to which the standard input/output (STDIO) file descriptor is bound. |
fd | uint32 | The file descriptor bound to the socket (0 = STDIN, 1 = STDOUT, 2 = STDERR). |
types.AddrPort
The types.AddrPort
type represents an IP address and port combination.
Property | Type | Description |
---|---|---|
ip | IP | IP address related to the observed event (depends on the event type). |
port | uint16 | Port number related to the observed event (depends on the event type). |
types.NetworkDetails
The types.NetworkDetails
type contains additional information about a network.
Property | Type | Description |
---|---|---|
Category | types.Category | The category under which the network has been classified. |
types.FlowDirection
The types.FlowDirection
type represents the direction of network flow.
Name | Description |
---|---|
flow_unknown | Network flow direction is unknown. |
flow_ingress | Network was classified as incoming. |
flow_egress | Network was classified as outgoing. |
types.Category
The types.Category
type represents different categories to which events can be classified.
Name | Description |
---|---|
category_malware | Event was classified as being related to malware. |
category_crypto | Event was classified as being related to cryptocurrency. |
types.FileDetails
The types.FileDetails
type contains additional details about a file.
Property | Type | Description |
---|---|---|
category | types.Category | Category to which the file has been classified. |
malware_name | string | Name of the malware identified, if the file is related to malware. |
malware_version | string | Version of the malware detected, if the file is related to malware. |
types.IPDetails
The types.IPDetails
type represents additional information about an IP address.
Property | Type | Description |
---|---|---|
abuse_confidence_score | int | A score from 0-100 indicating the confidence level of classifying the IP address as malicious. |
country_code | string | Country code from which the IP address originates. In ISO 3166-1 alpha-2 format. |
domain | string | Domain name related to the IP address. |
hostnames | []string | Host names associated with the IP address. |
ip_address | string | IP address of the event as a string. |
ip_version | int | Version of the IP address (4 = IPv4, 6 = IPv6). |
is_tor | bool | Flag indicating whether the IP address is related to the Tor network. |
isp | string | Name of the Internet Service Provider (ISP) to which the IP belongs. |
types.SOCKS5Payload
The types.SOCKS5Payload
type contains additional information about observed SOCKS5 actions.
Property | Type | Description |
---|---|---|
destination | types.AddrPort | Destination details of the SOCKS5 communication. If the address type is socks5_address_domain_name , only the port field is populated. |
flow_direction | types.FlowDirection | Direction of the observed SOCKS5 communication. |
address_type | types.SOCKS5AddressType | Address type used in the SOCKS5 command. If the command or reply does not contain an address type, this field might be set to unknown. |
command_or_reply | uint8 | Command or reply identifier as specified by RFC1928. |
destination_domain | string | Destination domain if the address_type is set to socks5_address_domain_name . |
role | types.SOCKS5Role | Role of the observed process in the SOCKS5 communication. |
types.SOCKS5CmdOrReply
The types.SOCKS5CmdOrReply
type represents the different address types used in SOCKS5 commands or replies.
Name | Description |
---|---|
socks5_address_domain_name | A domain name was observed to be used. |
socks5_address_ipv6 | An IPv6 address was observed to be used. |
socks5_address_unknown | The address type could not be determined. |
socks5_address_ipv4 | An IPv4 address was observed to be used. |
types.SOCKS5Role
The types.SOCKS5Role
type represents the role of the observed process in SOCKS5 communication.
Name | Description |
---|---|
socks5_role_unknown | Role could not be identified. |
socks5_role_client | Event was triggered by a SOCKS5 client. |
socks5_role_server | Event was triggered by a SOCKS5 server. |
Updated about 19 hours ago