4
\$\begingroup\$

I'm implementing a login script and I want it to be more secure:

function sec_session_start() {
        $session_name = 'sec_session_id';   // Set a custom session name
        $secure = SECURE;
        // This stops JavaScript being able to access the session id.
        $httponly = true;
        // Forces sessions to only use cookies.
        if (ini_set('session.use_only_cookies', 1) === FALSE) {
            //header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
            exit();
        }
        // Gets current cookies params.
        $cookieParams = session_get_cookie_params();
        session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly);
        // Sets the session name to the one set above.
        session_name($session_name);
        session_start();            // Start the PHP session 
        session_regenerate_id();    // regenerated the session, delete the old one. 
    }

    function  checkIp($mysqli) {
        if(isset($_SESSION['user_id'])){
            $user_id = $_SESSION['user_id'];
            $user_ip = $_SERVER['REMOTE_ADDR'];
            $user_browser = $_SERVER['HTTP_USER_AGENT'];

            if($stmt === $mysqli->prepare("SELECT UserIP, BrowserInfo FROM users WHERE UserID = ? LIMIT 1")){
                $stmt->bind_param('i', $user_id);
                $stmt->execute();
                $stmt->store_result();

                if($stmt->num_rows == 1){
                    $stmt->bind_result($db_ip,$db_browser);
                    $stmt->fetch();

                    if($user_ip == $db_ip && $user_browser == $db_browser){
                        return true;
                    }else{
                        return false;
                    }
                }else{
                    return false;
                }
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

Are these functions secure enough to prevent session hijacking? If they are not, what can I do to make them secure enough?

\$\endgroup\$
  • \$\begingroup\$ If i can get physical access to your machine as an attacker i can grab your session. The rest of his script can be found here: wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQL \$\endgroup\$ – CodeX Jun 29 '14 at 7:17
  • \$\begingroup\$ You can't prevent physical access as web service. Maybe you should have timeout for inactivity (one minute (refresh via ajax), 20 minutes), like some bank institutions have. \$\endgroup\$ – Tomasz Jun 29 '14 at 10:20
4
\$\begingroup\$

Checking an "constant" IP address is an bad idea because of ISP with load balancing. IP address should change to less busy proxy.

In most of cases IP address belongs to the same block. It is called CIDR matching:

function cidr_match($ip, $range)
{
    list ($subnet, $bits) = explode('/', $range);
    $ip = ip2long($ip);
    $subnet = ip2long($subnet);
    $mask = -1 << (32 - $bits);
    $subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
    return ($ip & $mask) == $subnet;
}

usage:

if(!empty($_SESSION['ip'])){
  //192.168.001.xxx = 192.168.001.000/24
  if(!cidr_match($_SERVER['REMOTE_ADDR'],$_SESSION['ip'].'/24')){
     session_destroy();
  }
} else {
  $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
}

http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing

Personally, i recommend to you to check IP address range and some client data (but data may be fake).

PS: do not store session data in MySQL, you should store them just in session.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.