Use of an insecure channel - HTTP - Go

Use of an insecure channel - HTTP - Go

Need

Secure transmission of client information

Context

  • Usage of Go 1.16 for building high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go

Description

Non compliant code

        package main

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

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

    router.GET("/login", func(c *gin.Context) {
        username := c.Query("username")
        password := c.Query("password")

        // ... authentication process ...

    })

    router.Run(":80")
}
        
        

This Go code uses the Gin framework to create a simple HTTP server that listens on port 80. It includes a route, /login, that accepts GET requests. The server retrieves the username and password from the query parameters of the request.

The vulnerability lies in the fact that the server is using HTTP, not HTTPS. HTTP is a plaintext protocol, meaning that all data sent between the client and server is unencrypted. This includes the username and password query parameters in the /login route.

If an attacker can intercept the network traffic between the client and server (for example, if the client is using an unsecured Wi-Fi network), they can easily read the username and password in plain text. This is known as a "man-in-the-middle" attack.

Furthermore, it's a bad practice to send sensitive data like passwords as query parameters, even over HTTPS, because they can be stored in server logs or browser history.

The server should instead be configured to use HTTPS, which encrypts all data sent between the client and server. In addition, sensitive data should be sent in the body of a POST request, not as query parameters.

Steps

  • Step 1: Switch from using HTTP to HTTPS for secure communication.
  • Step 2: Obtain an SSL/TLS certificate for your domain to enable HTTPS.
  • Step 3: Configure your Go backend application to use HTTPS instead of HTTP.
  • Step 4: Update the router.Run() function to listen on the appropriate HTTPS port (e.g., :443).
  • Step 5: Implement proper authentication mechanisms to protect sensitive information.
  • Step 6: Use secure protocols and encryption algorithms for transmitting sensitive data.
  • Step 7: Regularly update and patch your server and dependencies to ensure security.
  • Step 8: Implement secure coding practices to prevent other vulnerabilities.

Compliant code

        package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
    "log"
    "crypto/tls"
)

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

    router.GET("/login", func(c *gin.Context) {
        username := c.Query("username")
        password := c.Query("password")

        // ... authentication process ...

    })

    // Configure HTTPS with the SSL/TLS certificate and key
    server := &http.Server{
        Addr: ":443",
        Handler: router,
        TLSConfig: &tls.Config{
            // Use modern TLS configurations
            MinVersion: tls.VersionTLS13,
        },
    }

    log.Fatal(server.ListenAndServeTLS("server.crt", "server.key"))
}
        
        

The updated code now uses HTTPS for secure communication. The router.Run(":80") function has been replaced with a http.Server struct that is configured to use HTTPS on port 443. The ListenAndServeTLS function is used to start the server with the provided SSL/TLS certificate and key.

The TLSConfig struct is used to specify the minimum version of TLS to use. In this case, it is set to tls.VersionTLS13, which is the latest version of TLS and offers improved security over previous versions.

The ListenAndServeTLS function requires the paths to the SSL/TLS certificate and key as arguments. These files should be obtained from a trusted Certificate Authority and stored securely on the server.

The log.Fatal function is used to log any errors that occur when starting the server. If the server fails to start, the application will exit with a non-zero status code.

Remember to replace "server.crt" and "server.key" with the actual paths to your SSL/TLS certificate and key.

The username and password are still being retrieved from the query parameters in the /login route. This is not a secure way to transmit sensitive information, even over HTTPS. Consider implementing a secure authentication mechanism, such as JWT or OAuth.

Regularly update and patch your server and dependencies to ensure security. Implement secure coding practices to prevent other vulnerabilities.

References