如何以更安全的方式检查PHP会话?

时间:2016-02-04 12:31:32

标签: php

我目前有一个PHP登录系统,通过验证用户输入的组织代码进行登录,因此查询的数据库会有所不同。

includes.php

<?php

mysql_connect("mysql.example.com", $dbconn, "MySecurePassword");
mysql_select_db($dbconn);

?>

login.php

// $org is the Organisation Code, will be set when user clicks Login

$dbconn = $org;
include "includes.php";

// Omitted the $userid & $pw variables, assume there is no error, and that MySQL Injection is prevented already

    $query = "SELECT * FROM `Login` WHERE `userid`=TRIM('$userid') AND `password`=TRIM('$pw' )";

    $result = mysql_query($query);

    if(mysql_num_rows($result)>0){

        session_start();
        $_SESSION['logged_in'] = $username;
        header("Location: loggedinpage.php");

    }

loggedinpage.php

<?php

session_start(); 

// As there is no fixed database, I've omitted the DB Connection

 define('DS',  TRUE); // used to protect includes
 define('USERNAME', $_SESSION['logged_in']);
 define('SELF',  $_SERVER['PHP_SELF'] );

// Checks if user is logged in
 if (!USERNAME) {
     header("Location: login.php");
}

?>

采取安全措施

  • 使用SHA-512对密码进行哈希处理,而不是以纯文本格式存储。

  • 使用mysql_real_escape_string()

  • 阻止MySQL注入

为了便于阅读,我省略了一些代码,请问这种检查用户是否登录的方式是否安全?如果没有,我该如何改进呢?

提前致谢!

  • 更新了问题以反映评论中的更新

2 个答案:

答案 0 :(得分:2)

假设您的查询按预期工作,并且仅在匹配完全正确时返回一行(例如,通过整理规则没有奇怪的模糊匹配,但纯bin比较),< em>身份验证部分非常好。

(你已经注意到SQL注入很多了,你自己也在那里。)

您的安全性归结为:

$_SESSION['logged_in'] = $username;

以及随后的:

define('USERNAME', $_SESSION['logged_in']);

if (!USERNAME) {
    header("Location: login.php");
}

我想你的问题是关于这部分的。
然后答案是:会话部分很好,阻止不是。

这就是会话的使用方式,是的,默认情况下它们是合理安全的;用户将无法以某种方式自行设置$_SESSION['logged_in']值,该值只能由您的服务器设置,并且可能只有在成功进行身份验证时才会这样做。请阅读有关会话劫持的内容,这是整个方案唯一真正的漏洞。

真正的问题是:

if (!USERNAME) {
    header("Location: login.php");
}

设置标题不会终止当前页面。如果您在此行之后输出敏感信息,发送到客户端!设置标题后,您需要明确exit

说完这一切之后,我们无法告诉您系统是否“安全”,因为您可能创建了许多我们没有看到的 facepalm 后门。一般来说,我会从以下几点开始:

  • 停止使用mysql,使用PDOmysqli
  • 绑定您的参数,不要mysql_real_escape_string他们;那里有安全隐患
  • 使用password_hash密码哈希,而不是SHA;特别是如果你只做一个SHA传递

答案 1 :(得分:1)

因为SQL注入:

如果您输入密码字段:

 ''='' 

密码的规则是正确的,因为密码= TRIM(&#39;&#39; =&#39;&#39;)为真。您必须控制密码的字符串:

  • 最短篇幅
  • 没有空格(感谢Trim功能)

你不必存储这样的密码,你必须输入密码