T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- bin/fetch_url.py:10
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Locations**: - `bin/fetch_url.py:10-17` - `bin/extract_main_text.py:9-14` - `bin/crawl_site.py:11-24` - `bin/render_url.py:8-19` - `bin/chrome_dump_dom.sh:7-8` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code `bin/fetch_url.py:10-17`: ```python parser = argparse.ArgumentParser() parser.add_argument('url') parser.add_argument('--timeout', type=int, default=20) args = parser.parse_args() headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36' } resp = requests.get(args.url, headers=headers, timeout=args.timeout) ``` `bin/extract_main_text.py:9-14`: ```python parser = argparse.ArgumentParser() parser.add_argument('url') parser.add_argument('--timeout', type=int, default=20) args = parser.parse_args() headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36' } resp = requests.get(args.url, headers=headers, timeout=args.timeout) ``` `bin/crawl_site.py:11-24`: ```python parser = argparse.ArgumentParser() parser.add_argument('url') parser.add_argument('--limit', type=int, default=10) parser.add_argument('--timeout', type=int, default=15) args = parser.parse_args() start = args.url start_host = urlparse(start).netloc headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36'} seen = set() queue = collections.deque([start]) results = [] while queue and len(results) < args.limit: url = queue.popleft() if url in seen: continue seen.add(url) try: resp = requests.get(url, headers=headers, timeout=args.timeout) ``` `bin/render_url.py:8-19`: ```python url = sys.argv[1] cmd = [ "/usr/bin/google-chrome-stable", "--headless=new", "--disable-gpu", "--no-sandbox", "--virtual-time-budget=15000", "--dump-do ...[truncated 2075 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only explicitly supported `http` and `https` URLs. 2. Resolve the destination hostname before connecting and reject every address in loopback, private, link-local, multicast, reserved, unspecified, and other non-public ranges for both IPv4 and IPv6. 3. Disable automatic redirects or implement a redirect handler that validates every destination before following it. 4. Protect against DNS rebinding by connecting to a previously validated address while preserving correct TLS hostname verification, or route traffic through a hardened outbound proxy. 5. Consider an explicit domain allowlist where the research task permits it. 6. Reject URLs containing embedded credentials and restrict destination ports. 7. Apply equivalent controls to browser rendering, not only the Python `requests` clients. 8. Enforce outbound firewall rules so application-level validation is not the sole control. ]]>
