-1

所以我刚刚被告知(我的一个用户)我的登录不安全,会话很容易被劫持。

谁能告诉我为什么以及如何纠正这个问题?

这是我的用户类:

  class User
  {
    private $_db;
    private $_isLogged;

    public function __construct()
    {
      if (!session_id())
      {
        session_start();
      }
      $this->_db = Db::init();
      $this->_checkLogin();
    }

    public function isLogged() 
      {
          return $this->_isLogged;
      }

      public function login($username, $password)
      {
      $sth = $this->_db->prepare("SELECT * FROM users WHERE username = ?");
      $sth->execute(array($username));
      $result = $sth->fetch();

      if ($result)
      {
        if ($result['password'] == md5($password))
        {
          $this->_setLogin($result);
          return true;
        }
      }

      return false;
    }

    public function logout() 
    {
      session_destroy();
      setcookie ("simpleLogin", "", time() - 3600, '/');
    }

    public function fbLogin($fbId)
    {
      $sth = $this->_db->prepare("SELECT * FROM users WHERE facebook = ?");
      $sth->execute(array($fbId));
      $result = $sth->fetch();

      if ($result)
      {
        $this->_setLogin($result);
        return true;
      }
      return false;
    }

    private function _setLogin($userData)
    {
      $_SESSION['logged'] = true;
      $_SESSION['id'] = $userData['id'];
      $_SESSION['username'] = $userData['username'];
      $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];

      try {

        $sth = $this->_db->prepare("UPDATE users SET ip = ? WHERE id = ?");
        $sth->execute(array($_SERVER['REMOTE_ADDR'], $userData['id']));

        $forCookie = array(
          'id' => $userData['id'],
          'ip' => $_SERVER['REMOTE_ADDR'],
          'username' => $_SESSION['username']
        );

        setcookie('simpleLogin', serialize($forCookie), time()+60*60*24*30, '/');

      } catch (Exception $e) {
        die('Database error: ' . $e->getMessage());
      }
    }

      private function _checkLogin()
      {
      $this->_isLogged = false;

      if (isset($_SESSION['logged']) && $_SESSION['logged'])
          {
        $sth = $this->_db->query("SELECT * FROM users WHERE id = " . $_SESSION['id']);
        $result = $sth->fetch();

        if ($result['ip'] == $_SESSION['ip'])
        {
          $this->_isLogged = true;
        }
      }
      else if (isset($_COOKIE['simpleLogin']) && $_COOKIE['simpleLogin'])
      {
        $cookieData = unserialize(stripslashes($_COOKIE['simpleLogin']));

        $sth = $this->_db->query("SELECT * FROM users WHERE id = " . $cookieData['id']);
        $result = $sth->fetch();

        if ($result['ip'] == $cookieData['ip'])
        {
          $this->_isLogged = true;
          $this->_setLogin($result);
        }
      }
    }
  }
4

1 回答 1

0

通过改变这个来摆脱 SQL 注入漏洞:

$sth = $this->_db->query("SELECT * FROM users WHERE id = " . $cookieData['id']);

...对此:

$sth = $this->_db->prepare("SELECT * FROM users WHERE id = :ident");
$sth->execute([':ident' => $cookieData['id']]);

这假定DB::init()返回一个PDO实例。如果它是自定义类的实例,则需要在该类中实现参数绑定。

于 2013-09-14T19:11:14.797 回答