Uncontrolled external site redirect - Go

Uncontrolled external site redirect - Go

Need

Controlled and secure external site redirects

Context

  • Usage of Go 1.16 for developing high-performance and concurrent applications
  • Usage of Gin for building web applications in Go

Description

Non compliant code

        package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()

    r.GET("/redirect", func(c *gin.Context) {
        destination := c.Query("url")
        c.Redirect(302, destination)
    })

    r.Run()
}
        
        

The code above is a simple Go application that uses the Gin framework. It sets up a GET endpoint at /redirect that takes a url parameter from the query string and then redirects the user to that URL.

However, the problem with this code is that it does not validate or control the url parameter. This means that an attacker could manipulate the url parameter to redirect users to a malicious website. This is known as an uncontrolled external site redirect vulnerability.

For example, an attacker could craft a link like http://yourwebsite.com/redirect?url=http://maliciouswebsite.com and trick users into clicking it. When the users click the link, they would be redirected to http://maliciouswebsite.com without realizing it. This could lead to various attacks such as phishing or stealing of user credentials.

Steps

  • Validate the input: Before redirecting the user to a destination, validate the input to ensure it is a trusted and safe URL.
  • Whitelist allowed domains: Maintain a whitelist of allowed domains that the application can redirect to. Only allow redirects to URLs within this whitelist.
  • Sanitize the input: Use a URL sanitizer to remove any potentially malicious characters or scripts from the input URL.
  • Implement a redirect validation mechanism: Instead of blindly redirecting the user, implement a validation mechanism to verify the authenticity and integrity of the redirect request.
  • Use a safe redirect method: Instead of using a 302 redirect, consider using a safer redirect method like 303 or 307, which do not allow the HTTP method to be changed upon redirection.
  • Implement a redirect confirmation page: Add an intermediate page that confirms the redirect to the user before actually redirecting them. This can help prevent phishing attacks.
  • Implement rate limiting: To prevent abuse and potential DoS attacks, implement rate limiting on the redirect endpoint to restrict the number of redirects a user can make within a certain time period.
  • Regularly update and patch dependencies: Keep all dependencies, including the Gin framework, up to date with the latest security patches to mitigate any known vulnerabilities.

Compliant code

        package main

import (
    "github.com/gin-gonic/gin"
    "net/url"
    "strings"
)

var trustedDomains = []string{
    "www.trusteddomain1.com",
    "www.trusteddomain2.com",
    // add more trusted domains here
}

func main() {
    r := gin.Default()

    r.GET("/redirect", func(c *gin.Context) {
        destination := c.Query("url")
        parsedUrl, err := url.Parse(destination)
        if err != nil {
            c.String(400, "Invalid URL")
            return
        }

        if !isTrustedDomain(parsedUrl.Host) {
            c.String(400, "Untrusted domain")
            return
        }

        c.Redirect(303, destination)
    })

    r.Run()
}

func isTrustedDomain(domain string) bool {
    for _, trustedDomain := range trustedDomains {
        if strings.EqualFold(domain, trustedDomain) {
            return true
        }
    }
    return false
}
        
        

The updated code includes several security measures to prevent uncontrolled external site redirects.

1. Input Validation: The URL provided in the query parameter is parsed using Go's url.Parse function. If the URL is not valid, the function will return an error, and the server will respond with a 400 status code and an "Invalid URL" message.

2. Whitelisting Trusted Domains: A list of trusted domains is maintained. When a redirect request is made, the host of the provided URL is checked against this list. If the host is not in the list of trusted domains, the server will respond with a 400 status code and an "Untrusted domain" message.

3. Safe Redirect Method: Instead of using a 302 redirect, a 303 redirect is used. This ensures that the HTTP method cannot be changed upon redirection.

Please note that this code does not include all the recommended security measures such as rate limiting, redirect confirmation page, and regular updates and patches for dependencies. These measures should also be implemented as part of a comprehensive security strategy.

References