From 244e291b779972ee39f5daeb35e59b2f350f62c6 Mon Sep 17 00:00:00 2001 From: Drew Bednar Date: Sun, 2 Feb 2025 08:44:15 -0500 Subject: [PATCH] Adding session manager package --- README.md | 67 ++++++++++++++++++++++++++++++++- go.mod | 5 ++- go.sum | 2 + migrations/20_sessions.down.sql | 1 + migrations/20_sessions.up.sql | 7 ++++ 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 migrations/20_sessions.down.sql create mode 100644 migrations/20_sessions.up.sql diff --git a/README.md b/README.md index d6ad50f..26b9db8 100644 --- a/README.md +++ b/README.md @@ -181,4 +181,69 @@ The [official template docs](https://pkg.go.dev/text/template#hdr-Functions) can ## Form Validation -- https://www.alexedwards.net/blog/validation-snippets-for-go: Covers snippets for common form validation logic. \ No newline at end of file +- https://www.alexedwards.net/blog/validation-snippets-for-go: Covers snippets for common form validation logic. + +## Session Managment + +- https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html +- https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html +- https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html + +Session management used here: `go get github.com/alexedwards/scs/v2@v2` + +Session ids should be meaningless. The server side stored information can typically include: +- the client IP address +- User-Agent +- e-mail +- username +- user ID +- role +- privilege level +- access rights +- language preferences +- account ID +- current state +- last login +- session timeouts +- and other internal session details. + +The preferred session ID exchange mechanism should allow defining advanced token properties, such as the token expiration date and time, or granular usage constraints. + - Cookies foot the bill which is why they are used. + +- the Secure cookie attribute must be used to ensure the session ID is only exchanged through an encrypted channel. + +- Do not switch a given session from HTTP to HTTPS, or vice-versa, as this will disclose the session ID in the clear through the network. + - When redirecting to HTTPS, ensure that the cookie is set or regenerated after the redirect has occurred. + +- Do not mix encrypted and unencrypted contents (HTML pages, images, CSS, JavaScript files, etc) in the same page, or from the same domain. +- HTTP Strict Transport Security (also named HSTS) can be used to enforce HTTPS connections. Can also https://www.leviathansecurity.com/blog/the-double-edged-sword-of-hsts-persistence-and-privacy result in user tracking even without cookies. + +- It is important to emphasize that TLS does not protect against session ID prediction, brute force, client-side tampering or fixation; however, it does provide effective protection against an attacker intercepting or stealing session IDs through a man in the middle attack. + +### Cookies +- `Secure`attribute instructs web browsers to only send the cookie through an encrypted HTTPS (SSL/TLS) connection. + - protects against man in the middle +- The `HttpOnly` cookie attribute instructs web browsers not to allow scripts (e.g. JavaScript or VBscript) an ability to access the cookies via the DOM document.cookie object. + - This session ID protection is mandatory to prevent session ID stealing through XSS attacks. + - XSS + CSRF though could still leak the session id. +- `SameSite` defines a cookie attribute preventing browsers from sending a SameSite flagged cookie with cross-site requests +- The `Domain` cookie attribute instructs web browsers to only send the cookie to the specified domain and all subdomains. + - THE DOMAIN ATTRIBUTE SHOULD NOT BE SET, which will restrict the cookie to the origin server. + - You don't want to mess with cross subdomain cookies. That can just be a mess. +- The `Path` cookie attribute instructs web browsers to only send the cookie to the specified directory or subdirectories (or paths or resources) within the web application + - `Path` attribute should be set as restrictive as possible to the web application path that makes use of the session ID. +- Session management mechanisms based on cookies can make use of two types of cookies, non-persistent (or session) cookies, and persistent cookies. If a cookie presents the `Max-Age` (that has preference over `Expires`) or `Expires` attributes, it will be considered a persistent cookie and will be stored on disk by the web browser based until the expiration time. + - Typically, session management capabilities to track users after authentication make use of non-persistent cookies. This forces the session to disappear from the client if the current web browser instance is closed. + - Therefore, it is highly recommended to use non-persistent cookies for session management purposes, so that the session ID does not remain on the web client cache for long periods of time, from where an attacker can obtain it. + - Depends on what the application does. An RSS reader doesn't need a short lived session. + +If we look at reddit cookies we can find one called `token_v2`. + +It has: + +- Domain: .reddit.com +- Path: / +- Expires/ Max-Age for roughly 3 days +- httpOnly: true +- Secure: true +- SameSite: None \ No newline at end of file diff --git a/go.mod b/go.mod index 63341a0..db9f173 100644 --- a/go.mod +++ b/go.mod @@ -4,4 +4,7 @@ go 1.23.3 require github.com/mattn/go-sqlite3 v1.14.24 -require github.com/go-playground/form/v4 v4.2.1 // indirect +require ( + github.com/alexedwards/scs/v2 v2.8.0 // indirect + github.com/go-playground/form/v4 v4.2.1 // indirect +) diff --git a/go.sum b/go.sum index 25129c1..52a0516 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw= +github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/form/v4 v4.2.1 h1:HjdRDKO0fftVMU5epjPW2SOREcZ6/wLUzEobqUGJuPw= github.com/go-playground/form/v4 v4.2.1/go.mod h1:q1a2BY+AQUUzhl6xA/6hBetay6dEIhMHjgvJiGo6K7U= diff --git a/migrations/20_sessions.down.sql b/migrations/20_sessions.down.sql new file mode 100644 index 0000000..3b15188 --- /dev/null +++ b/migrations/20_sessions.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS sessions; \ No newline at end of file diff --git a/migrations/20_sessions.up.sql b/migrations/20_sessions.up.sql new file mode 100644 index 0000000..bf67e0e --- /dev/null +++ b/migrations/20_sessions.up.sql @@ -0,0 +1,7 @@ +CREATE TABLE sessions ( + token TEXT PRIMARY KEY, + data BLOB NOT NULL, + expiry REAL NOT NULL +); + +CREATE INDEX sessions_expiry_idx ON sessions(expiry); \ No newline at end of file