Session Fixation

از Secure Coding

آسیب پذیری session fixation باعث دسترسی به session کاربر بدون هیچگونه محدودیتی می شود.

Session fixation.jpg

برای مثال در تصویر بالا مهاجم پس از ورود به سیستم، cookie مختص خود را دریافت می کند. سپس درخواست ورود به سامانه را به همراه cookie خود به قربانی می دهد.

قربانی پس از ارسال درخواست با cookie مهاجم به احراز هویت می شود. وب سرور به دلیل موجود بودن session با cookie مهاجم، cookie جدیدی ایجاد نمی کند و فقط کاربر این cookie را بروز می کند. حال مهاجم با استفاده از این آسیب پذیری می تواند به هر کاربر دسترسی پیدا کند.


روش های جلوگیری

روش های جلوگیری در php

مثال 1)

<?php
// https://gist.github.com/markjames/516977
// Demo for session fixation
// 
// Attacker creates a session by visiting the page: http://famfamfam.com/sessionfixation.php
// Attacker gets their session ID out of the cookie (or in this case from the page)
// Attacker creates a URL such as http://famfamfam.com/sessionfixation.php?PHPSESSID=attackerssessionid and sends it to victim
// Victim clicks the URL (now both the attacker and victim are using the same session)
// Victim logs in
// Now the attacker is logged in to the victim's account too (same session!)

session_start();

if( isset($_GET['password']) && $_GET['password'] == 'blissfulignorance' ) {
	$_SESSION['logged_in'] = true;
	$_SESSION['logged_in_as'] = 'Mark J.';
	
}

if( isset($_SESSION['logged_in']) && $_SESSION['logged_in'] ) {

	echo "You are logged in as ", htmlentities($_SESSION['logged_in_as'],ENT_QUOTES,'UTF-8');

} else {
	echo "You are not logged in";

}

echo "<br>", "Your session ID is " . session_id(); 

?>

راه حل 1)

<?php
//https://gist.github.com/markjames/516977
// Demo for session fixation
// 
// Attacker creates a session by visiting the page: http://famfamfam.com/sessionfixation.php
// Attacker gets their session ID out of the cookie (or in this case from the page)
// Attacker creates a URL such as http://famfamfam.com/sessionfixation.php?PHPSESSID=attackerssessionid and sends it to victim
// Victim clicks the URL (now both the attacker and victim are using the same session)
// Victim logs in
// Now the attacker is logged in to the victim's account too (same session!)

session_start();

if( isset($_GET['password']) && $_GET['password'] == 'blissfulignorance' ) {
	$_SESSION['logged_in'] = true;
	$_SESSION['logged_in_as'] = 'Mark J.';
	
	session_regenerate_id()
}

if( isset($_SESSION['logged_in']) && $_SESSION['logged_in'] ) {

	echo "You are logged in as ", htmlentities($_SESSION['logged_in_as'],ENT_QUOTES,'UTF-8');

} else {

	echo "You are not logged in";

}

echo "<br>", "Your session ID is " . session_id(); 

?>

روش های جلوگیری در ASP.NET

مثال 1)

/*
* https://www.codeproject.com/Articles/210993/Session-Fixation-vulnerability-in-ASP-NET
*/
protected void Page_Load(object sender, EventArgs e)
{
    if (Session["LoggedIn"] != null)
    {
        lblMessage.Text = "Congratulations !, you are logged in.";
        lblMessage.ForeColor = System.Drawing.Color.Green;
        btnLogout.Visible = true;
    }
    else
    {
        lblMessage.Text = "You are not logged in.";
        lblMessage.ForeColor = System.Drawing.Color.Red;
    }
}

protected void LoginMe(object sender, EventArgs e)
{
    // Check for Username and password (hard coded for this demo)
    if (txtU.Text.Trim().Equals("u") && txtP.Text.Trim().Equals("p"))
    {
        Session["LoggedIn"] = txtU.Text.Trim();
    }
    else
    {
        lblMessage.Text = "Wrong username or password";
    }
}

protected void LogoutMe(object sender, EventArgs e)
{
    Session.Clear();
    Session.Abandon();
    Session.RemoveAll();
}

راه حل 1)

/*
* https://www.codeproject.com/Articles/210993/Session-Fixation-vulnerability-in-ASP-NET
*/
protected void Page_Load(object sender, EventArgs e)
{
    //NOTE: Keep this Session and Auth Cookie check
    //condition in your Master Page Page_Load event
    if (Session["LoggedIn"] != null && Session["AuthToken"] != null 
           && Request.Cookies["AuthToken"] != null)
    {
        if (!Session["AuthToken"].ToString().Equals(
                   Request.Cookies["AuthToken"].Value))
        {
            // redirect to the login page in real application
            lblMessage.Text = "You are not logged in.";
        }
        else
        {
            lblMessage.Text = "Congratulations !, you are logged in.";
            lblMessage.ForeColor = System.Drawing.Color.Green;
            btnLogout.Visible = true;
        }
    }
    else
    {
        lblMessage.Text = "You are not logged in.";
        lblMessage.ForeColor = System.Drawing.Color.Red;
    }
}

protected void LoginMe(object sender, EventArgs e)
{
    // Check for Username and password (hard coded for this demo)
    if (txtU.Text.Trim().Equals("u") && 
                  txtP.Text.Trim().Equals("p"))
    {
        Session["LoggedIn"] = txtU.Text.Trim();
        // createa a new GUID and save into the session
        string guid = Guid.NewGuid().ToString();
        Session["AuthToken"] = guid;
        // now create a new cookie with this guid value
        Response.Cookies.Add(new HttpCookie("AuthToken", guid));

    }
    else
    {
        lblMessage.Text = "Wrong username or password";
    }
}

protected void LogoutMe(object sender, EventArgs e)
{
    Session.Clear();
    Session.Abandon();
    Session.RemoveAll();

    if (Request.Cookies["ASP.NET_SessionId"] != null)
    {
        Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
        Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
    }

    if (Request.Cookies["AuthToken"] != null)
    {
        Response.Cookies["AuthToken"].Value = string.Empty;
        Response.Cookies["AuthToken"].Expires = DateTime.Now.AddMonths(-20);
    }
}

روش های جلوگیری در JAVA

مثال 1)

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> </title>
</head>
<body>
<%
	String user = request.getParameter("user");
	String pass = request.getParameter("pass");
	Class.forName("com.mysql.jdbc.Driver");
	Connection con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root" , "");
	PreparedStatement ps=(PreparedStatement) con.prepareStatement("select * from users where username=? and password=? limit 0,1");
	ps.setString(1,user);
	ps.setString(2,pass);
	ResultSet rs=ps.executeQuery();
	if(rs.next())
	{
		session.setAttribute("useracc", rs.getString("user"));
		out.println("Login success");
	}
	else
	{
		out.println("Login failed");
	}
%>
</body>
</html>

راه حل 1)

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title> </title>
</head>
<body>
<%
	String user = request.getParameter("user");
	String pass = request.getParameter("pass");
	Class.forName("com.mysql.jdbc.Driver");
	Connection con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/userdb", "root" , "");
	PreparedStatement ps=(PreparedStatement) con.prepareStatement("select * from users where username=? and password=? limit 0,1");
	ps.setString(1,user);
	ps.setString(2,pass);
	ResultSet rs=ps.executeQuery();
	if(rs.next())
	{
		session.invalidate();
		request.getSession(true);
		session.setAttribute("useracc", rs.getString("user"));
		out.println("Login success");
	}
	else
	{
		out.println("Login failed");
	}
%>
</body>
</html>