T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/web-monitor.sh:30
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web-monitor.sh`, lines 30-47, 80-89, and 157-172 **Vulnerability Type**: Server-Side Request Forgery through user-controlled monitoring URLs **Risk Level**: High ### Complete Vulnerable Code ```bash fetch_page() { local url="$1" local output="$2" local ua="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" local http_code http_code=$(curl -s -L \ -H "User-Agent: $ua" \ -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \ -H "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8" \ -H "Connection: keep-alive" \ --max-time 30 \ -o "$output" \ -w "%{http_code}" \ "$url" 2>/dev/null) echo "$http_code" } ``` The URL is accepted directly from a command-line argument: ```bash cmd_add_task() { local url="" frequency="daily" selector="" threshold="5" notify="feishu" name="" while [[ $# -gt 0 ]]; do case "$1" in --url) url="$2"; shift 2 ;; --frequency) frequency="$2"; shift 2 ;; --selector) selector="$2"; shift 2 ;; --threshold) threshold="$2"; shift 2 ;; --notify) notify="$2"; shift 2 ;; --name) name="$2"; shift 2 ;; *) shift ;; esac done ``` The stored value is later fetched without destination validation: ```bash local url selector threshold url=$(echo "$task" | jq -r '.url') selector=$(echo "$task" | jq -r '.selector // ""') threshold=$(echo "$task" | jq -r '.threshold // "5"') log "INFO" "开始检查任务 $task_id: $url" # 抓取页面 local tmp_html tmp_html=$(mktemp /tmp/web-monitor-XXXXXX.html) local http_code http_code=$(fetch_page "$url" "$tmp_html") ``` ### Technical Analysis The monitoring URL is entirely user-controlled and is passed to `curl` without validation of: - The URL scheme. - The initial hostname or resolved IP address. - Loopback, private, link-local, multicast, and reserved address ranges. - ...[truncated 2512 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only explicitly supported schemes, preferably `https`, with `http` allowed only when required. 2. Parse URLs with a dedicated URL parser rather than regular expressions. 3. Resolve the hostname before making a request and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 4. Explicitly block cloud metadata destinations, including link-local metadata addresses. 5. Disable automatic redirect following, or process redirects manually and repeat the complete scheme, hostname, and resolved-address validation for every redirect hop. 6. Protect against DNS rebinding by ensuring the address validated is the address used for the connection. Consider pinning the validated address with `curl --resolve`. 7. Apply an explicit domain allowlist where the deployment has a known set of approved monitoring targets. 8. Restrict destination ports to expected web ports. 9. Run the monitor in a sandbox with outbound network controls that deny access to internal and metadata networks. 10. Limit response size, such as with `curl --max-filesize`, to reduce resource-exhaustion risk. 11. Record rejected requests without logging sensitive URL credentials or query-string secrets. 12. Add automated tests covering direct private addresses, IPv6 loopback, numeric and alternative IP representations, DNS rebinding scenarios, and public-to-private redirects. ]]>
