Server-Side Request Forgery (SSRF)
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
By providing URLs to unexpected hosts or ports, attackers can make it appear that the server is sending the request, possibly bypassing access controls such as firewalls.
Jak naprawić tę podatność
Strategie zapobiegania dla Server-Side Request Forgery oparte na 4 regułach detekcji Shoulder.
Parse URL and validate host against domain allowlist
package main import ( "io" - "net/http" - ) - - func handler(w http.ResponseWriter, r *http.Request) { - targetURL := r.URL.Query().Get("url") - // Vulnerable: user-controlled URL - resp, err := http.Get(targetURL) - if err != nil { - http.Error(w, err.Error(), 500) - return - } + "net" + "net/http" + "net/url" + ) + + var allowedDomains = map[string]bool{ + "api.example.com": true, + "cdn.example.com": true, + } + + func isPrivateIP(ip net.IP) bool { + private := []string{ + "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", + "169.254.0.0/16", "127.0.0.0/8", + } + for _, cidr := range private { + _, network, _ := net.ParseCIDR(cidr) + if network.Contains(ip) { + return true + } + } + return false + } + + func handler(w http.ResponseWriter, r *http.Request) { + targetURL := r.URL.Query().Get("url") + + parsed, err := url.Parse(targetURL) + if err != nil { + http.Error(w, "Invalid URL", 400) + return + } + + // Validate scheme + if parsed.Scheme != "https" { + http.Error(w, "HTTPS required", 400) + return + } + + // Validate domain + if !allowedDomains[parsed.Host] { + http.Error(w, "Domain not allowed", 403) + return + } + + // Block private IPs (DNS rebinding protection) + ips, _ := net.LookupIP(parsed.Hostname()) + for _, ip := range ips { + if isPrivateIP(ip) { + http.Error(w, "Private IP not allowed", 403) + return + } + } + + resp, _ := http.Get(targetURL) defer resp.Body.Close() io.Copy(w, resp.Body) }
Validate URLs against an allowlist of permitted domains before fetching
'use server' - - export async function fetchData(url: string) { - const response = await fetch(url); - return await response.json(); + const ALLOWED_DOMAINS = ['api.example.com', 'cdn.example.com']; + + export async function fetchData(url: string) { + const parsed = new URL(url); + if (!ALLOWED_DOMAINS.includes(parsed.hostname)) { + throw new Error('URL not allowed'); + } + return await fetch(url).then(r => r.json()); }
Validate URLs against domain allowlist before making requests
const http = require('http'); - - function fetchUrl(url) { - // Vulnerable: no URL validation - return new Promise((resolve, reject) => { - http.get(url, (res) => { + const https = require('https'); + + const ALLOWED_DOMAINS = ['api.example.com', 'cdn.example.com']; + + function fetchUrl(url) { + const parsed = new URL(url); + + // Validate protocol + if (!['http:', 'https:'].includes(parsed.protocol)) { + throw new Error('Invalid protocol'); + } + + // Validate against allowlist + if (!ALLOWED_DOMAINS.includes(parsed.hostname)) { + throw new Error('Domain not allowed'); + } + + // Block private/internal IPs + if (isPrivateIP(parsed.hostname)) { + throw new Error('Private IP not allowed'); + } + + const client = parsed.protocol === 'https:' ? https : http; + return new Promise((resolve, reject) => { + client.get(url, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }).on('error', reject); }); }
Znajdz podatnosci w swoim kodzie
Uzyj Shoulder do skanowania kodu w poszukiwaniu wzorcow Server-Side Request Forgery (SSRF). 4 reguly.
# Scan with Shoulder CLI npx @shoulderdev/cli trust --cwe=918 # Or scan entire project npx @shoulderdev/cli trust .
Reguly Wykrywania (4)
Na co zwracac uwage podczas przegladu kodu
Te wzorce wskazuja na potencjalne podatnosci Server-Side Request Forgery (SSRF). Szukaj ich podczas przegladow kodu i audytow bezpieczenstwa.
Przeskanuj swój kod w poszukiwaniu Server-Side Request Forgery (SSRF)
Shoulder CLI znajduje podatne wzorce w całym Twoim kodzie.