Session Fixation
What does this mean ?
Authenticating a user or creating a new user session without invalidating any current session identifiers allows an attacker to steal authenticated sessions.
What can happen ?
Attackers can change the session identifier to a known value by directly constructing cookies from tainted data, allowing the attacker to share the session with the victim. If the session identification is not renewed after the victim authenticates, successful attacks may result in unauthorized access to sensitive information.
Recommendation
Before approving a new user session, invalidate any existing session IDs.
Sample Code
Vulnerable :
if (txtUsr.Text.Equals("james") && txtPwd.Text.Equals("pass1234"))
{
Session["LIn"] = txtU.Text.Trim();
Server.Transfer("index.aspx");
}
else
{
lblMessage.Text = "Wrong username or password";
}
Non Vulnerable :
protected void btnLogin_Handler(object sender, EventArgs e)
{
if (txtUsr.Text.Equals("james") && txtPwd.Text.Equals("pass1234"))
{
Session["LIn"] = txtU.Text.Trim();
string guid = Guid.NewGuid().ToString();
Session["AuthToken"] = guid;
// now create a new cookie with this guid value
Response.Cookies.Add(new HttpCookie("AuthToken", guid));
}
}
Vulnerable :
public class VulnerableServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Check if the user is already logged in
HttpSession session = request.getSession();
if (session.getAttribute("username") == null) {
// User is not logged in, check if a session ID was provided in the request
String sessionId = request.getParameter("sessionId");
if (sessionId != null) {
// A session ID was provided, fix the user's session to this ID
session.setId(sessionId);
}
// Redirect the user to the login page
response.sendRedirect("login.jsp");
} else {
// User is already logged in, display the protected content
response.getWriter().println("Protected content");
}
}
}
Non Vulnerable :
public class NonVulnerableServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Check if the user is already logged in
HttpSession session = request.getSession(true);
if (session.isNew()) {
// This is a new session, generate a new session ID
session.invalidate();
session = request.getSession(true);
}
if (session.getAttribute("username") == null) {
// User is not logged in, redirect to the login page
response.sendRedirect("login.jsp");
} else {
// User is already logged in, display the protected content
response.getWriter().println("Protected content");
}
}
}
Vulnerable :
session_start();
// Check if the user is already logged in
if (!isset($_SESSION['username'])) {
// User is not logged in, check if a session ID was provided in the request
if (isset($_GET['sessionId'])) {
// A session ID was provided, fix the user's session to this ID
session_id($_GET['sessionId']);
}
// Redirect the user to the login page
header('Location: login.php');
exit;
} else {
// User is already logged in, display the protected content
echo 'Protected content';
}
Non Vulnerable :
session_start();
// Check if the user is already logged in
if (!isset($_SESSION['username'])) {
// This is a new session, generate a new session ID
session_regenerate_id(true);
// Redirect the user to the login page
header('Location: login.php');
exit;
} else {
// User is already logged in, display the protected content
echo 'Protected content';
}
Vulnerable :
app.get('/login', function(req, res) {
// Check if the user is already logged in
if (req.session.username == null) {
// User is not logged in, check if a session ID was provided in the request
var sessionId = req.query.sessionId;
if (sessionId != null) {
// A session ID was provided, fix the user's session to this ID
req.session.id = sessionId;
}
// Redirect the user to the login page
res.redirect('/login.html');
} else {
// User is already logged in, display the protected content
res.send('Protected content');
}
});
Non Vulnerable :
app.get('/login', function(req, res) {
// Check if the user is already logged in
if (req.session.username == null) {
// This is a new session, generate a new session ID
req.session.regenerate(function(err) {
if (err) {
// An error occurred while regenerating the session
res.send('Error: ' + err);
} else {
// The session has been regenerated, redirect to the login page
res.redirect('/login.html');
}
});
} else {
// User is already logged in, display the protected content
res.send('Protected content');
}
});
Vulnerable :
func loginHandler(w http.ResponseWriter, r *http.Request) {
// Check if the user is already logged in
if r.Context().Value("username") == nil {
// User is not logged in, check if a session ID was provided in the request
sessionId := r.URL.Query().Get("sessionId")
if sessionId != "" {
// A session ID was provided, fix the user's session to this ID
http.SetCookie(w, &http.Cookie{
Name: "sid",
Value: sessionId,
})
}
// Redirect the user to the login page
http.Redirect(w, r, "/login", http.StatusFound)
} else {
// User is already logged in, display the protected content
fmt.Fprint(w, "Protected content")
}
}
Non Vulnerable :
func loginHandler(w http.ResponseWriter, r *http.Request) {
// Check if the user is already logged in
if r.Context().Value("username") == nil {
// This is a new session, generate a new session ID
session, _ := store.Get(r, "sid")
session.Options.MaxAge = -1 // delete session cookie
session.Save(r, w)
// Redirect the user to the login page
http.Redirect(w, r, "/login", http.StatusFound)
} else {
// User is already logged in, display the protected content
fmt.Fprint(w, "Protected content")
}
}
Vulnerable :
class VulnerableController < ApplicationController
def login
# Check if the user is already logged in
if session[:username].nil?
# User is not logged in, check if a session ID was provided in the request
if params[:session_id]
# A session ID was provided, fix the user's session to this ID
session[:session_id] = params[:session_id]
end
# Redirect the user to the login page
redirect_to '/login'
else
# User is already logged in, display the protected content
render plain: 'Protected content'
end
end
end
Non Vulnerable :
class NonVulnerableController < ApplicationController
def login
# Check if the user is already logged in
if session[:username].nil?
# This is a new session, generate a new session ID
reset_session
# Redirect the user to the login page
redirect_to '/login'
else
# User is already logged in, display the protected content
render plain: 'Protected content'
end
end
end