Cryptomining Detection Using Falco
Cryptominers are programs that utilize computer resources to mine cryptocurrency. XMRig is an example of an open source cryptomining software designed for the sole purpose of mining cryptocurrencies, like Monero or Bitcoin. Cryptominers usually get rewarded with a token for every successful transaction mined, which makes cryptomining a profitable activity.
Whether the threat is from an external entity, or an insider, cybercriminals are most commonly abusing services such as Kubernetes and GitHub actions by infecting hosts and containers with cryptojackers and using the business resources to mine cryptocurrency on the attacker's behalf.
Detecting Mining Pools
Assuming the cybercriminal has already compromised your environment and installed the XMRig miner, they will need to communicate with a cryptocurrency mining pool to distribute the resources by miner, share the processing power over a network, and split the reward equally, according to the amount of work they contributed to the probability of finding a block.
Source: Compass Mining
The mining pool is a collection of miners that work together to augment their chances of mining a block, sharing rewards among each other in proportion to the computing power contributed in successfully mining a block. There are lots of pools to choose from. You can find a list at miningpoolstats.stream/monero.
Lists
By default, Falco creates a list of all common pool domains used for Monero mining. The below YAML file shows how the list defines all domains as list items.
- list: miner_domains
items: [
"asia1.ethpool.org","ca.minexmr.com",
"cn.stratum.slushpool.com","de.minexmr.com",
"eth-ar.dwarfpool.com","eth-asia.dwarfpool.com",
"eth-asia1.nanopool.org","eth-au.dwarfpool.com",
…
]
For the purpose of accuracy, we can define separate lists for HTTP domains as well as HTTPS domains.
- list: https_miner_domains
items: [
"ca.minexmr.com",
"cn.stratum.slushpool.com",
"de.minexmr.com",
"fr.minexmr.com",
…
]
- list: http_miner_domains
items: [
"ca.minexmr.com",
"de.minexmr.com",
"fr.minexmr.com",
"mine.moneropool.com",
…
]
Another list contains all port numbers that are commonly used by the cryptominer at the source.
There's no need for users to create the lists or macros. They are enabled by the default Falco rules.
- list: miner_ports
items: [
25, 3333, 3334, 3335, 3336, 3357, 4444,
5555, 5556, 5588, 5730, 6099, 6666, 7777,
7778, 8000, 8001, 8008, 8080, 8118, 8333,
8888, 8899, 9332, 9999, 14433, 14444,
45560, 45700
]
Macros
Similar to the lists mentioned above, the following macros are already created. The macros define the ports used to connect to the mining domains - whether HTTP (unsecure) domains or HTTP/s (secure) domain names. The HTTP/s domain connects over port 443. Unencrypted HTTP connections are made over port 80.
- macro: minerpool_https
condition: (fd.sport="443" and fd.sip.name in (https_miner_domains))
- macro: minerpool_http
condition: (fd.sport="80" and fd.sip.name in (http_miner_domains))
Falco assigns all commonly used miner ports to the miner domains via the minerpool_other
macro.
- macro: minerpool_other
condition: (fd.sport in (miner_ports) and fd.sip.name in (miner_domains))
The field fd.sport (File Descriptor - Port) could match any port listed in the miner_ports
macro, while the field fd.sip (File Description - IP name) would match any domain listed within the miner_domains
macro.
Falco Rule
The final rule will aim to detect anything matching the condition described by the net_miner_pool
macro, unless it's listed within the trusted_images_query_miner_domain_dns
macro. Both macros are specified within the condition
section of the completed Falco rule.
- rule: Detect outbound connections to common miner pool ports
desc: Miners typically connect to miner pools on common ports.
condition: >
net_miner_pool and not trusted_images_query_miner_domain_dns
enabled: false
output: >
Outbound connection to IP/Port flagged by https://cryptoioc.ch
(command=%proc.cmdline pid=%proc.pid port=%fd.rport ip=%fd.rip
container=%container.info image=%container.image.repository)
priority: CRITICAL
tags: [network, mitre_execution]
The rule is disabled by default. However, to enable this Falco rule you simply need to change the condition enabled: false
to enabled: true
.
Macro net_miner_pool
The following macro is looking at any event type such as connections made or message data sent to the macros: minerpool_http
, minerpool_https
, or minerpool_other
that were mentioned earlier in the blog.
- macro: net_miner_pool
condition: >
(evt.type in (sendto, sendmsg, connect) and evt.dir=< and
(fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses))
and ((minerpool_http) or (minerpool_https) or (minerpool_other)))
Macro trusted_images_query_miner_domain_dns
The below macro is created simply to exclude Falco images from detection. The rule will use it to exclude known Falco images from Docker registry or from the public Elastic Container Registry (ECR).
- macro: trusted_images_query_miner_domain_dns
condition: >
(container.image.repository in (docker.io/falcosecurity/falco,
falcosecurity/falco, public.ecr.aws/falcosecurity/falco))
Detecting Stratum Protocol
Miners typically specify the mining pool to connect with a URI that begins with stratum+tcp
. That's because Stratum is a line-based protocol using a plain TCP socket. The message payload is encoded as JSON-RPC. The protocol was designed specifically for mining operations. Therefore, it makes sense to detect scenarios where a client opens a TCP socket and writes requests using the Stratum protocol.
For more information on the new protocol designed for bitcoin mining, check out this link.
Falco Rule
The following rule quickly shows how to detect the Stratum protocol. There's no need for any complex macros this time around. The already existing macro spawned_process
watches for newly started processes, while the rest of the rule looks for a string on command, such as:
stratum+tcp
stratum2+tcp
stratum+ssl
stratum2+ssl
- rule: Detect crypto miners using the Stratum protocol
desc: >
Miners typically specify the mining pool to connect to
with a URI that begins with 'stratum+tcp'
condition: >
spawned_process and
(proc.cmdline contains "stratum+tcp" or
proc.cmdline contains "stratum2+tcp" or
proc.cmdline contains "stratum+ssl" or
proc.cmdline contains "stratum2+ssl")
output: Possible miner running (command=%proc.cmdline
pid=%proc.pid container=%container.info
image=%container.image.repository)
priority: CRITICAL
tags: [process, mitre_execution]
Macro
The spawned_process
macro is easy to understand. It's basically just looking for the event types execve
and/or execveat
in any event directory.
- macro: spawned_process
condition: (evt.type in (execve, execveat) and evt.dir=<)
Github Actions with Miners
Cryptomining detection shouldn't be limited to just your local endpoints, VMs, or EC2 hosts. GitHub Actions has unfortunately been actively abused in recent months to mine cryptocurrency on GitHub servers. Falco's GitHub plugin can detect potential miners abusing GitHub actions.
Falco Rule
The condition filters for webhook messages of type workflow_run
that point to the execution of miners. github.workflow.has_miners
is the main action to highlight. It fetches the workflow's definition file and scans it line by line, looking for patterns that identify the execution of one of the well-known miner binaries.
- rule: Github action with miners
desc: a github action containing crypto miners was executed
condition: >
github.type=workflow_run and
github.action=requested and
github.workflow.has_miners=true
output: >
a github action containing crypto miners was executed
(repository=%github.repo repo_owner=%github.owner
org=%github.org user=%github.user file=%github.workflow.filename)
priority: CRITICAL
source: github
Within github.workflow.miners.type
, we can specify one or more miners to be detected within the workflow definition file. This field contains the type of each detected miner as a comma separated list (e.g., XMRig, Stratum). Looking further into the miners.go
file, we can see the exact list of miner binaries checked:
var minersChecks = []string{
"xmrig",
"ccminer",
"t-rex",
"stratum",
"pool",
"hashrate",
"cryptonight",
"wallet",
… }
As you can see from the above list, it includes the strings for the crypto wallet, the crypto-mining pool, and the miners, such as xmrig and ccminer.
Set setuid
or setgid
bit
When the setuid or setgid bits are set for an application, this means that the application will run with the privileges of the owning user or group respectively. In the case of cryptojacking, the hacker will want to have root permissions over the running containerized workloads in order to install the XMRig binary. That's why it's important to detect setuid or setgid bits set via chmod.
Falco Rule
- rule: Set Setuid or Setgid bit
desc: >
When the setuid or setgid bits are set for an application,
This means that the application will run with the privileges
of the owning user or group respectively.
Detect setuid or setgid bits set via chmod
condition: >
chmod and (evt.arg.mode contains "S_ISUID" or
evt.arg.mode contains "S_ISGID")
and not proc.name in (user_known_chmod_applications)
and not exe_running_docker_save
and not user_known_set_setuid_or_setgid_bit_conditions
enabled: false
output: >
Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename
mode=%evt.arg.mode user=%user.name user_loginuid=%user.loginuid process=%proc.name
command=%proc.cmdline pid=%proc.pid container_id=%container.id
container_name=%container.name image=%container.image.repository:%container.image.tag)
priority:
NOTICE
tags: [process, mitre_persistence]
Similar to the mining pool example, the rule is disabled by default. To enable it within the rule engine, simply change the enabled
flag to enabled: true
.
In Linux systems, processes can receive a variety of signals, such as SIGINT or SIGKILL.
The SIGINT signal is sent to a process by its controlling terminal when a user wishes to interrupt the process. This is typically initiated by pressing Ctrl-C, but on some systems, the "delete" character or "break" key can be used. The SIGKILL signal is sent to a process to cause it to terminate immediately (kill). If XMRig is run as root, but the SIGINT
caller must also be running as root if the adversary plans on interrupting/pausing their operations to evade detection.
As a result, the adversary will need to give themselves root permissions by setting their User ID (SetUID) or Group User ID (SetGID) to root. Detecting changes to SetUID or SetGID bit is a clear indication of compromise, and we should look to prevent users (whether internal or adversarial) from giving themselves root permissions. Without root permissions, the adversary cannot operate XMRig effectively. The SetUID/SetGID Falco rule is in the rule engine, but disabled by default.
Container Drift Detection
As mentioned at the beginning of this blog, Kubernetes is an ideal target for cryptojacking - hijacking of legitimate running workloads/applications. To detect when an XMRig binary is installed, we can apply drift detection to containers at runtime.
Falco Rule
- rule: Container Drift Detected (open+create)
desc: New executable created in a container due to open+create
condition: >
evt.type in (open,openat,openat2,creat) and
evt.is_open_exec=true and
container and
not runc_writing_exec_fifo and
not runc_writing_var_lib_docker and
not user_known_container_drift_activities and
evt.rawres>=0
enabled: false
output: Drift detected (open+create), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type)
priority: ERROR
Generally speaking, attackers would look to install the XMRig miner in the /tmp directory. However, the above Falco rule will detect when executables are created in the container (regardless of the directory). From a forensics perspective, we will receive a Falco notification that tells us which executable was installed and to which directory.
Detect the XMRig Binary
We have provided multiple ways to detect the XMRig binary, whether that be through container drift when installing XMRig, outbound connections to mining pools coming from XMRig, or when file permissions are changed to root for XMRig.
The final rule, although not in the rules library by default, is to simply detect the XMRig binary outright - not based on behavior, just the binary name.
Custom Falco Rule
- rule: Malicious binary detected
desc: >-
Malicious script or binary detected in pod or host.
The rule was triggered by the execve syscall.
condition: >
spawned_process and (in_malicious_binaries or (proc.name in (shell_binaries)
and scripts_in_or and not proc.args startswith "-c"))
output: >-
Malicious binary or script executed in the pod or host.
proc.cmdline=%proc.cmdline evt.type=%evt.type evt.res=%evt.res
proc.pid=%proc.pid proc.cwd=%proc.cwd proc.ppid=%proc.ppid
proc.pcmdline=%proc.pcmdline proc.sid=%proc.sid proc.exepath=%proc.exepath
user.uid=%user.uid user.loginuid=%user.loginuid
user.loginname=%user.loginname user.name=%user.name group.gid=%group.gid
group.name=%group.name container.id=%container.id
container.name=%container.name %evt.args
priority: warning
source: syscall
The above Falco rule detects when a malicious script or binary is detected in a pod or host. The rule is triggered by the execve
syscall. The rule looks for any spawned process via the spawned_process
macro. As mentioned earlier, the spawned_process macro looks for the execve syscall.
Leveraging lists and macros again, to detect the XMRig binary, security teams can manually specify XMRig and other relevant binaries in a malicious_binaries
list, and place it within the in_malicious_binaries
macro.
Macro
- macro: in_malicious_binaries
condition: (proc.name in (malicious_binaries))
List
- list: malicious_binaries
items: [ "xmrig", ".x1mr", "kill_miner", "titcoind", "nanominer", "pwnrig", "ccminer" ]
The above list provides more binaries than just ‘XMRig.’ As new miners become available, users can add those binaries to their malicious_binaries
list.
Conclusion
The monetary gain of mining cryptocurrency is a motivation for threat actors to compromise the endpoints of unsuspecting users and use them for illegitimate mining activities.
The endpoints are usually part of a botnet that is being controlled by a Command and Control (C2) server. Aside from the rules listed above, Falco can also detect unwanted outbound connections to C2 servers, as well as other IoC's that could indicate a potential incident before the mining has begun.
The mode of initial access for threat actors may be through compromised SSH credentials or the exploitation of a vulnerability. Once the threat actor has gained remote access to the endpoints, the cryptomining software is executed on it. Being able to detect suspicious activity, such as Disallowed SSH connections on a Linux server, is critical for your incident response and forensics teams.
If you would like to find out more about Falco:
- Get started in falco.org.
- Read the official documentation.
- Check out the Falco project in GitHub.
- Get involved in the Falco community.
- Meet the maintainers on the Falco Slack.
- Follow @falco_org on Twitter.