Uncontrolled data used in network requestGO-S1010
Directly writing user input into an HTTP request without validating the input can aid different kinds of request forgery attacks, where the attacker essentially controls the request. If the vulnerable request is in server-side code, an attacker can bypass security mechanisms like external firewalls, etc. If the request is in client-side code, unsuspecting users can send malicious requests, potentially resulting in a DDOS attack.
It is recommended to guard against such request forgery attacks using the following ways:
- Avoid writing user input directly into network request; instead, sanitize it before using.
- Maintain a list of authorized request targets and allow only those who are allowed.
The following example shows an HTTP request parameter is used directly in a URL request without validating the input, which aids an SSRF attack. The request http.Get(...)
is vulnerable since attackers can choose a malicious value for the target.
Bad practice
func do(w http.ResponseWriter, req *http.Request) *http.Response {
target := req.FormValue("target")
// NOTE: `target` is controlled by the attacker and it is
// unsafe to use http.Get without santizing the `target`.
resp, err := http.Get("https://" + target + ".example.com/data/")
if err != nil {
fmt.Fprintln(os.Stderr, fmt.Errorf("error occurred: %v", err))
}
return resp
}
Recommended
func do(w http.ResponseWriter, req *http.Request) *http.Response {
// NOTE: On the basis of the user input, predefined subdomains
// are selected. There are multiple solution to this problem.
subdomain := ""
switch req.FormValue("target") {
case "US":
subdomain = "US"
case "EU":
subdomain = "EU"
default:
subdomain = "XX"
}
resp, err := http.Get("https://" + subdomain + ".example.com/data/")
if err != nil {
fmt.Fprintln(os.Stderr, fmt.Errorf("error occurred: %v", err))
}
return resp
}