Prevention of session hijacking
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/login", func(c *gin.Context) {
username := c.Query("username")
password := c.Query("password")
// This is just a dummy check. Replace this with your actual user authentication logic
if username == "admin" && password == "password" {
c.SetCookie("session_id", "123456", 3600, "/", "localhost", false, true)
c.JSON(200, gin.H{
"message": "Logged in successfully",
})
} else {
c.JSON(401, gin.H{
"message": "Invalid credentials",
})
}
})
r.Run()
}
In the above code, when a user logs in with the correct username and password, a session cookie (
session_id
) is set with a static value (
123456
). This cookie is used to maintain the user's session.
However, the issue here is that the session cookie's value does not change even after a successful login. This means that if an attacker knows the session cookie's value (
123456
in this case), they can hijack the user's session by setting their own browser's cookie to this value.
This is a classic example of a Session Fixation vulnerability, where the attacker fixes the user's session ID before the user even logs in, and then uses that session ID to impersonate the user once they've logged in.
In a real-world scenario, the attacker would somehow have to make the victim use a session ID known to the attacker. After the user logs in, the attacker can use that session ID to impersonate the user.
This vulnerability can lead to unauthorized access to the user's account, and potentially, to sensitive data and functionality.
package main
import (
"crypto/rand"
"encoding/base64"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
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("/login", func(c *gin.Context) {
username := c.Query("username")
password := c.Query("password")
// This is just a dummy check. Replace this with your actual user authentication logic
if username == "admin" && password == "password" {
sessionID := generateSessionID()
c.SetCookie("session_id", sessionID, 3600, "/", "localhost", false, true)
c.JSON(200, gin.H{
"message": "Logged in successfully",
})
} else {
c.JSON(401, gin.H{
"message": "Invalid credentials",
})
}
})
r.Run()
}
The updated code now generates a new session ID for each successful login, which helps to prevent session fixation attacks. The
generateSessionID
function uses the
crypto/rand
package to generate a random 32-byte value, which is then base64-encoded to create a session ID.
The session ID is stored in a secure cookie with the 'Secure' and 'HttpOnly' flags set to
false
and
true
respectively. The 'Secure' flag is set to
false
because the application is running on localhost, but in a production environment, this should be set to
true
to ensure that the cookie is only sent over HTTPS. The 'HttpOnly' flag is set to
true
to prevent the cookie from being accessed by client-side scripts, which helps to mitigate the risk of cross-site scripting (XSS) attacks.
The cookie also has an expiration time of 1 hour (3600 seconds), after which the user will be automatically logged out. This helps to limit the potential damage if an attacker is able to hijack a user's session.
Finally, the code includes a dummy user authentication check. In a real application, this should be replaced with a robust user authentication and authorization mechanism to prevent unauthorized access.