(web3py), Server-Side Request Forgery (SSRF), (No CVE)

Listen to this Post

The vulnerability exists because web3.py enables CCIP Read (EIP-3668) by default globally (global_ccip_read_enabled = True). When a smart contract reverts with an `OffchainLookup` error, web3.py automatically fetches data from URLs provided in the revert payload. The code in `web3/utils/exception_handling.py` (sync) and `web3/utils/async_exception_handling.py` (async) takes these URLs, substitutes `{sender}` and `{data}` placeholders, and issues HTTP GET or POST requests via `requests` or `aiohttp` without any destination validation. No restriction to HTTPS, no blocklist for private IP ranges (127.0.0.0/8, 169.254.0.0/16, RFC1918 addresses), and no validation of redirects (both libraries follow 302/301 redirects by default). An attacker deploying a malicious contract can supply URLs pointing to internal services like http://169.254.169.254/latest/meta-data/` or loopbackhttp://127.0.0.1:8080/admin`. When any backend service calls `.call()` on that contract address, web3.py silently issues the HTTP request from the server’s network context, achieving blind SSRF. Additionally, POST requests can be forced when placeholders are missing, and redirects amplify the attack by bypassing superficial allowlists. The handler only checks response JSON for a `”data”` field, but the request itself already causes damage (metadata exfiltration, internal port scanning, side effects on internal APIs). EIP-3668’s own security considerations recommend client libraries provide override hooks and destination controls, but web3.py lacks them.

dailycve form:

Platform: web3.py
Version: All before patch
Vulnerability: SSRF via CCIP
Severity: High
date: 2025-04-05

Prediction: Patch within 30 days

What Undercode Say:

Check if CCIP Read is enabled (default)
python -c "from web3 import Web3; print(Web3.global_ccip_read_enabled)"
Disable globally as mitigation
python -c "from web3 import Web3; Web3.global_ccip_read_enabled = False"
Simulate malicious OffchainLookup payload
curl -X POST http://victim:8545 -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xmalicious","data":"0x..."},"latest"],"id":1}'
Test local listener for SSRF
python -m http.server 9999 &
python repro_ssrf.py from
Block private IPs via iptables (example)
sudo iptables -A OUTPUT -d 169.254.169.254 -j DROP

how Exploit:

Deploy malicious contract reverting with OffchainLookup supplying internal URLs (e.g., `http://169.254.169.254/latest/meta-data/`). Victim backend calls `.call()` on that contract. web3.py automatically GETs the metadata URL, leaking credentials. Redirects to internal endpoints also work.

Protection from this CVE:

Set `Web3.global_ccip_read_enabled = False` before any call. Use custom middleware to validate CCIP URLs (allow only HTTPS, block private IPs). Set `allow_redirects=False` in patched HTTP sessions. Upgrade to patched version when available.

Impact:

Blind SSRF: access cloud metadata, internal network probing, port scanning, POST-based state changes on internal APIs, redirect amplification. No direct response exfiltration but request alone compromises infrastructure.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top