T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/utils/validator.js:3
- Finding
- Arbitrary URL Fetching Enables SSRF and External Exfiltration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/validator.js:3-8`, `scripts/video2text/index.js:104-105`, `scripts/video2text/index.js:140-145`, `scripts/utils/download.js:479-492` **Vulnerability Type**: Server-Side Request Forgery (SSRF) with external upload **Risk Level**: High ### Vulnerable Code ```js // scripts/utils/validator.js:3-8 function isUrl(url) { try { const parsedUrl = new URL(url); return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:"; } catch (_) { return false; } } ``` ```js // scripts/video2text/index.js:104-105 if (validator.isUrl(file)) { const filepath = utils.downloadPath(); ``` ```js // scripts/video2text/index.js:140-145 const presignedUrl = await video.getPresignedUrl(tokenValue, file); if (!presignedUrl || !presignedUrl?.url || presignedUrl.url === "") { throw new Error("获取预签名URL失败,请反馈给开发者"); } utils.printInfo("上传文件到安全空间..."); await upload.uploadFileToOSS(file, presignedUrl.url, presignedUrl.headers); ``` ```js // scripts/utils/download.js:479-492 this.__redirectCount++; if (this.__redirectCount > this.__opts.maxRedirects) { const err = new Error("Too many redirects"); this.__setState(this.__states.FAILED); this.emit("error", err); return reject(err); } const redirectedURL = /^https?:\/\//.test(response.headers.location) ? response.headers.location : new URL(response.headers.location, this.url).href; this.__isRedirected = true; this.__initProtocol(redirectedURL); this.emit("redirected", redirectedURL, this.url); return this.__start(); ``` ### Technical Analysis URL validation checks only whether the scheme is HTTP or HTTPS. It does not reject: - Loopback destinations such as `127.0.0.1` or `[::1]` - RFC1918 private networks - Link-local addresses, including cloud metadata services - Reserved or multicast address ranges - Hostnames that resolve to private addresses - Public URLs that redirect to private destinations - DNS rebinding between validation an ...[truncated 1831 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Resolve the hostname before every connection and reject any address in loopback, private, link-local, carrier-grade NAT, multicast, documentation, or other reserved IPv4 and IPv6 ranges. 2. Reapply the complete validation policy after every redirect. 3. Reject IP-literal URLs unless explicitly required. 4. Where practical, use an allowlist of supported public video platforms and approved content-delivery domains. 5. Protect against DNS rebinding by connecting only to the validated resolved address while preserving the expected TLS hostname. 6. Disable redirects by default or limit them to validated destinations using HTTPS. 7. Apply outbound network controls at the operating-system or container level so the process cannot reach internal and metadata networks. 8. Validate that the downloaded response is an expected media type before writing or uploading it. 9. Do not upload content if URL validation, address validation, or media validation fails. ]]>
