Retab changes for PR #2383
parent
0214501891
commit
de0d09886c
|
@ -8,173 +8,173 @@ require 'rexml/document'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Auxiliary
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
include Msf::Exploit::Remote::HttpClient
|
include Msf::Exploit::Remote::HttpClient
|
||||||
include Msf::Auxiliary::Scanner
|
include Msf::Auxiliary::Scanner
|
||||||
include Msf::Auxiliary::Report
|
include Msf::Auxiliary::Report
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Jenkins Vulnerability Scanner',
|
'Name' => 'Jenkins Vulnerability Scanner',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module scans a Jenkins installation for a few vulnerablities.
|
This module scans a Jenkins installation for a few vulnerablities.
|
||||||
},
|
},
|
||||||
'Author' => 'Jeff McCutchan',
|
'Author' => 'Jeff McCutchan',
|
||||||
'License' => MSF_LICENSE
|
'License' => MSF_LICENSE
|
||||||
))
|
))
|
||||||
|
|
||||||
register_options(
|
register_options(
|
||||||
[
|
[
|
||||||
OptString.new('TARGETURI', [ true, "Path to Jenkins instance", "/jenkins/"]),
|
OptString.new('TARGETURI', [ true, "Path to Jenkins instance", "/jenkins/"]),
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_host(ip)
|
def run_host(ip)
|
||||||
res = send_request_cgi(
|
res = send_request_cgi(
|
||||||
{
|
{
|
||||||
'uri' => target_uri.path,
|
'uri' => target_uri.path,
|
||||||
'method' => 'GET',
|
'method' => 'GET',
|
||||||
'ctype' => 'text/plain',
|
'ctype' => 'text/plain',
|
||||||
})
|
})
|
||||||
if res
|
if res
|
||||||
# check to see if we are dealing with a Jenkins installation
|
# check to see if we are dealing with a Jenkins installation
|
||||||
if not res.headers.include?('X-Jenkins')
|
if not res.headers.include?('X-Jenkins')
|
||||||
print_status("#{rhost}:#{rport} responded with #{res.code} but does not seem to be Jenkins") if res.code != 404
|
print_status("#{rhost}:#{rport} responded with #{res.code} but does not seem to be Jenkins") if res.code != 404
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
vprint_error("No reponse recieved from #{rhost}:#{rport}")
|
vprint_error("No reponse recieved from #{rhost}:#{rport}")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
version = res.headers['X-Jenkins']
|
version = res.headers['X-Jenkins']
|
||||||
vprint_status("#{rhost}:#{rport} Jenkins Version - #{version}")
|
vprint_status("#{rhost}:#{rport} Jenkins Version - #{version}")
|
||||||
# script - exploit module for this
|
# script - exploit module for this
|
||||||
# view/All/newJob - can be exploited manually
|
# view/All/newJob - can be exploited manually
|
||||||
# asynchPeople - Jenkins users
|
# asynchPeople - Jenkins users
|
||||||
# systemInfo - system information
|
# systemInfo - system information
|
||||||
apps = [ 'script',
|
apps = [ 'script',
|
||||||
'view/All/newJob',
|
'view/All/newJob',
|
||||||
'asynchPeople/',
|
'asynchPeople/',
|
||||||
'systemInfo',
|
'systemInfo',
|
||||||
]
|
]
|
||||||
apps.each do |app|
|
apps.each do |app|
|
||||||
check_app(app)
|
check_app(app)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_app(app)
|
def check_app(app)
|
||||||
uri_path = normalize_uri(target_uri.path, app)
|
uri_path = normalize_uri(target_uri.path, app)
|
||||||
res = send_request_cgi({
|
res = send_request_cgi({
|
||||||
'uri' => uri_path,
|
'uri' => uri_path,
|
||||||
'method' => 'GET',
|
'method' => 'GET',
|
||||||
'ctype' => 'text/plain',
|
'ctype' => 'text/plain',
|
||||||
})
|
})
|
||||||
if not res
|
if not res
|
||||||
vprint_error("Failed to connect to #{rhost}:#{rport}#{uri_path}")
|
vprint_error("Failed to connect to #{rhost}:#{rport}#{uri_path}")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
case res.code
|
case res.code
|
||||||
when 200
|
when 200
|
||||||
print_good("#{rhost}:#{rport}#{uri_path} does not require authentication (200)")
|
print_good("#{rhost}:#{rport}#{uri_path} does not require authentication (200)")
|
||||||
case app
|
case app
|
||||||
when "systemInfo"
|
when "systemInfo"
|
||||||
parse_system_info(res.body)
|
parse_system_info(res.body)
|
||||||
when "script"
|
when "script"
|
||||||
report_vuln(
|
report_vuln(
|
||||||
:host => rhost,
|
:host => rhost,
|
||||||
:port => rport,
|
:port => rport,
|
||||||
:proto => 'tcp',
|
:proto => 'tcp',
|
||||||
:sname => (ssl ? 'https' : 'http'),
|
:sname => (ssl ? 'https' : 'http'),
|
||||||
:name => self.name,
|
:name => self.name,
|
||||||
:info => "Module #{self.fullname} confirmed access to the Jenkins Script Console with no authentication"
|
:info => "Module #{self.fullname} confirmed access to the Jenkins Script Console with no authentication"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
when 403
|
when 403
|
||||||
vprint_status("#{rhost}:#{rport}#{uri_path} restricted (403)")
|
vprint_status("#{rhost}:#{rport}#{uri_path} restricted (403)")
|
||||||
when 401
|
when 401
|
||||||
vprint_status("#{rhost}:#{rport}#{uri_path} requires authentication (401): #{res.headers['WWW-Authenticate']}")
|
vprint_status("#{rhost}:#{rport}#{uri_path} requires authentication (401): #{res.headers['WWW-Authenticate']}")
|
||||||
when 404
|
when 404
|
||||||
vprint_status("#{rhost}:#{rport}#{uri_path} not found (404)")
|
vprint_status("#{rhost}:#{rport}#{uri_path} not found (404)")
|
||||||
when 301
|
when 301
|
||||||
vprint_status("#{rhost}:#{rport}#{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
|
vprint_status("#{rhost}:#{rport}#{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
|
||||||
when 302
|
when 302
|
||||||
vprint_status("#{rhost}:#{rport}#{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
|
vprint_status("#{rhost}:#{rport}#{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
|
||||||
else
|
else
|
||||||
vprint_status("#{rhost}:#{rport}#{uri_path} Don't know how to handle response code #{res.code}")
|
vprint_status("#{rhost}:#{rport}#{uri_path} Don't know how to handle response code #{res.code}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_system_info(body)
|
def parse_system_info(body)
|
||||||
vprint_status("#{rhost}:#{rport} getting useful information from systemInfo")
|
vprint_status("#{rhost}:#{rport} getting useful information from systemInfo")
|
||||||
infos = {
|
infos = {
|
||||||
"os.name" => nil,
|
"os.name" => nil,
|
||||||
"os.version" => nil,
|
"os.version" => nil,
|
||||||
"sun.os.patch.level" => nil,
|
"sun.os.patch.level" => nil,
|
||||||
"os.arch" => nil,
|
"os.arch" => nil,
|
||||||
"user.name" => nil,
|
"user.name" => nil,
|
||||||
"USERDOMAIN" => nil,
|
"USERDOMAIN" => nil,
|
||||||
"user.home" => nil,
|
"user.home" => nil,
|
||||||
"user.language" => nil,
|
"user.language" => nil,
|
||||||
"user.country" => nil,
|
"user.country" => nil,
|
||||||
"user.timezone" => nil,
|
"user.timezone" => nil,
|
||||||
"COMPUTERNAME" => nil,
|
"COMPUTERNAME" => nil,
|
||||||
"SystemDrive" => nil,
|
"SystemDrive" => nil,
|
||||||
"TEMP" => nil,
|
"TEMP" => nil,
|
||||||
"TMP" => nil,
|
"TMP" => nil,
|
||||||
"SHELL" => nil
|
"SHELL" => nil
|
||||||
}
|
}
|
||||||
# remove unclosed tags for REXML
|
# remove unclosed tags for REXML
|
||||||
body = body.gsub('<wbr>', '')
|
body = body.gsub('<wbr>', '')
|
||||||
body = body.gsub('<br>', '')
|
body = body.gsub('<br>', '')
|
||||||
doc = REXML::Document.new(body)
|
doc = REXML::Document.new(body)
|
||||||
tds = doc.get_elements("//td")
|
tds = doc.get_elements("//td")
|
||||||
tdcounter = 0
|
tdcounter = 0
|
||||||
tds.each do |td|
|
tds.each do |td|
|
||||||
td = td.get_text.to_s.strip
|
td = td.get_text.to_s.strip
|
||||||
infos.each do |k, v|
|
infos.each do |k, v|
|
||||||
if td == k
|
if td == k
|
||||||
infos[k] = tds[tdcounter +1].get_text.to_s.strip
|
infos[k] = tds[tdcounter +1].get_text.to_s.strip
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
tdcounter +=1
|
tdcounter +=1
|
||||||
end
|
end
|
||||||
|
|
||||||
# print out the goodies
|
# print out the goodies
|
||||||
infos.each do |k, v|
|
infos.each do |k, v|
|
||||||
next if v.nil?
|
next if v.nil?
|
||||||
case k
|
case k
|
||||||
when "os.name"
|
when "os.name"
|
||||||
print_line(" OS: #{v}")
|
print_line(" OS: #{v}")
|
||||||
when "os.version"
|
when "os.version"
|
||||||
print_line(" OS Version: #{v}")
|
print_line(" OS Version: #{v}")
|
||||||
when "sun.os.patch.level"
|
when "sun.os.patch.level"
|
||||||
print_line(" Patch Level: #{v}")
|
print_line(" Patch Level: #{v}")
|
||||||
when "os.arch"
|
when "os.arch"
|
||||||
print_line(" Arch: #{v}")
|
print_line(" Arch: #{v}")
|
||||||
when "user.name"
|
when "user.name"
|
||||||
print_line(" User: #{v}")
|
print_line(" User: #{v}")
|
||||||
when "USERDOMAIN"
|
when "USERDOMAIN"
|
||||||
print_line(" Domain: #{v}")
|
print_line(" Domain: #{v}")
|
||||||
when "COMPUTERNAME"
|
when "COMPUTERNAME"
|
||||||
print_line(" Computer Name: #{v}")
|
print_line(" Computer Name: #{v}")
|
||||||
when "SystemDrive"
|
when "SystemDrive"
|
||||||
vprint_line(" System Drive: #{v}")
|
vprint_line(" System Drive: #{v}")
|
||||||
when "SHELL"
|
when "SHELL"
|
||||||
print_line(" Shell: #{v}")
|
print_line(" Shell: #{v}")
|
||||||
when "TEMP"
|
when "TEMP"
|
||||||
print_line(" Temp Directory: #{v}")
|
print_line(" Temp Directory: #{v}")
|
||||||
when "TMP"
|
when "TMP"
|
||||||
print_line(" Temp Directory: #{v}") if infos["TEMP"].nil?
|
print_line(" Temp Directory: #{v}") if infos["TEMP"].nil?
|
||||||
when "user.home"
|
when "user.home"
|
||||||
vprint_line(" Home Directory: #{v}")
|
vprint_line(" Home Directory: #{v}")
|
||||||
when "user.language"
|
when "user.language"
|
||||||
vprint_line(" Language: #{v}")
|
vprint_line(" Language: #{v}")
|
||||||
when "user.country"
|
when "user.country"
|
||||||
vprint_line(" Country: #{v}")
|
vprint_line(" Country: #{v}")
|
||||||
when "user.timezone"
|
when "user.timezone"
|
||||||
vprint_line(" Timezone: #{v}")
|
vprint_line(" Timezone: #{v}")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
print_line('')
|
print_line('')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue