T05 · Unauthorized Access and Privilege Escalation
- Location
scraper.py:11- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scraper.py, lines 11–40
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: HighVulnerable Code
python def scrape_links(url, selector="a"): """抓取页面中所有匹配CSS选择器的链接""" try: resp = requests.get(url, timeout=30, headers={'User-Agent': 'Mozilla/5.0'}) soup = BeautifulSoup(resp.text, 'html.parser') results = [] for el in soup.select(selector): text = el.get_text(strip=True) href = el.get('href') if href: href = urljoin(url, href) results.append({"text": text, "href": href}) return results except Exception as e: return [{"error": str(e)}] def scrape_table(url, table_selector="table"): """抓取网页表格数据""" try: resp = requests.get(url, timeout=30, headers={'User-Agent': 'Mozilla/5.0'}) soup = BeautifulSoup(resp.text, 'html.parser') table = soup.select_one(table_selector) if not table: return [] rows = [] for tr in table.select('tr'): cells = [td.get_text(strip=True) for td in tr.select('td, th')] if cells: rows.append(cells) return rows except Exception as e: return [{"error": str(e)}]Technical Analysis
Both scraping functions pass a user-controlled URL directly to
requests.get()without validating its scheme, hostname, port, resolved IP address, or redirect destination. Therequestslibrary follows redirects by default, so validating only the initial URL would also be insufficient.The application therefore permits requests to loopback, private, link-local, and other restricted network addresses reachable from the host. Potential targets include internal administration interfaces, private APIs, local services, and cloud instance metadata endpoints. Because ...[truncated 1456 chars]
- Remediation
View remediation
Remediation Suggestions
- Restrict accepted schemes to
httpandhttps. - Parse URLs with
urllib.parse.urlsplit()and reject malformed URLs, embedded credentials, unexpected ports, and ambiguous host representations. - Resolve the destination hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses using the
ipaddressmodule. - Block known metadata destinations, including link-local cloud metadata addresses and metadata hostnames.
- Disable automatic redirects or validate every redirect destination using the same scheme, hostname, and resolved-address controls.
- Protect against DNS rebinding by ensuring the validated address is the address actually used for the connection.
- Prefer an explicit allowlist of approved domains when the intended scraping scope is known.
- Apply outbound firewall or proxy rules so the process cannot reach internal networks or metadata services.
- Call
resp.raise_for_status()and impose response-size limits to reduce secondary availability risks.
- Restrict accepted schemes to
