Skip to main content

Lack of data validation - Session Cookie

Need

Implementation of secure data validation for session cookies

Context

  • Usage of Go 1.15 for developing high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go
  • Usage of net/http for creating a server and handling HTTP requests in a Node.js application

Description

Non compliant code

package main

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

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

r.GET("/set_cookie", func(c *gin.Context) {
cookie, _ := c.Cookie("session_id")
c.SetCookie("session_id", cookie, 3600, "/", "localhost", false, true)
c.String(http.StatusOK, "session_id: %s", cookie)
})

r.Run()
}

The above code is a simple Go server using the Gin framework that sets a session cookie based on the value received from the client.

Here is a detailed breakdown of the vulnerable part:

cookie, _ := c.Cookie("session_id")
c.SetCookie("session_id", cookie, 3600, "/", "localhost", false, true)

In the first line, the server retrieves the session_id cookie value from the client's request. In the second line, it sets a new session_id cookie with the value it just received from the client.

The vulnerability here is that there is no validation or sanitization of the session_id cookie value received from the client. This means an attacker can set any value for the session_id cookie, which can lead to session fixation attacks, session hijacking, or other types of attacks based on manipulating session cookies.

The server should not trust any data received from the client. It should always validate and sanitize this data before using it. In this case, the server should generate a new, secure session id for the session cookie, rather than using the value received from the client.

Steps

  • Implement server-side session management
  • Validate the session cookie value on the server-side
  • Use a secure method to generate the session cookie
  • Set the 'Secure' flag on the session cookie to ensure it is only sent over HTTPS
  • Set the 'HttpOnly' flag on the session cookie to prevent client-side access
  • Set the 'SameSite' attribute on the session cookie to restrict cross-site requests

Compliant code

package main

import (
"crypto/rand"
"encoding/base64"
"github.com/gin-gonic/gin"
"net/http"
)

func generateSessionID() string {
b := make([]byte, 32)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(b)
}

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

r.GET("/set_cookie", func(c *gin.Context) {
sessionID := generateSessionID()
c.SetCookie("session_id", sessionID, 3600, "/", "localhost", true, true)
c.String(http.StatusOK, "session_id: %s", sessionID)
})

r.Run()
}

The updated code now includes a function generateSessionID() that generates a secure random session ID using the crypto/rand package. This session ID is then base64 encoded to ensure it is safe to use as a cookie value.

In the main function, we now call generateSessionID() to generate a new session ID each time the "/set_cookie" endpoint is accessed. This session ID is then set as the value of the "session_id" cookie.

The SetCookie function has been updated to include the 'Secure' and 'HttpOnly' flags. The 'Secure' flag ensures that the cookie is only sent over HTTPS, while the 'HttpOnly' flag prevents client-side JavaScript from accessing the cookie. This helps to mitigate the risk of cross-site scripting (XSS) attacks.

Please note that the 'SameSite' attribute is not directly supported by the SetCookie function in the gin framework. To set this attribute, you would need to manually construct the 'Set-Cookie' header. This is not shown in the provided code.

This updated code helps to mitigate the risk of session hijacking by ensuring that session cookies are securely generated and handled.

References