Обработка надежно защищенный паролем приложение


У меня есть некоторые небольшие приложения, которые я хочу защитить. Я использую следующие настройки, которые я думаю, довольно безопасная, однако я никогда не был в состоянии установить мой разум в покое, что он на самом деле. Не могли бы вы дать мне некоторые комментарии о безопасности? Для этого не нужна супер-безопасности, такие как данные кредитной карты, но я предполагаю, что безопасно безопасно.

Сессий на основе файлов cookie. Таблица пользователей:

  • Поле "Имя пользователя" (открытый текст)
  • Случайный/уникальный соленое поле (созданного с mt_rand() при регистрации
  • Поле Пароль (хэш SHA256)
  • (среди других вещей)

Login метод принимает имя пользователя, ищет строки БД, получает соли, добавляет его в конец выложил пароль, предположения на SHA256 хэш этой строки, и сравнивает, что в поле пароля в БД.

auth.php включают в начале приложения

<?php
session_start();
if(!isset($_GET['logout']) && isset($_SESSION['user']) && $_SESSION['ipadd'] == $_SERVER['REMOTE_ADDR']) {
    // currently logged in
        // setup data 
    require_once('lib/functions.php');
    $db = new ezSQL_sqlite('./','main.db');
    $user = new user($db,$_SESSION['user']);
    return;

}


// build login form

$head = '<html><head><title>Please login</title>
<style type="text/css">h2 { margin-top: 75px; margin-left: 100px; }</style>
</head><body>';

$form = '<form method="post" action="'.$_SERVER['PHP_SELF'].'" id="userLogin">
    <table><tr>
    <td>UserName:</td><td><input type="text" name="username" value="'.$_POST['username'].'"></td>
    </tr><tr>
    <td>Password:</td><td><input type="password" name="pass" /></td>
    </tr><tr>
    <td>Remember me on this computer</td>
    <td><input type="checkbox" name="remember" value="1" /></td>
    </tr><tr>
    <td>&nbsp;</td>
    <td><input type="hidden" name="loggingin" value="true" />
    <input type="submit" value="login" />
    </td></tr></table>
    </form></body></html>';

$msg[1] = '<h2>You\'ve logged out.</h2>';
$msg[3] = '<h2>That username and password didn\'t match anything on record.</h2>';
$msg[4] = '<h2>You must login to use this application</h2>';


// used logout button
if($_GET['logout'] == 'true') {
    setcookie('SaveMe','',time()-3600);
    session_unset();
    die($head.$msg[1].$form);


// trying to login from form or returning with 'save me' cookie
} elseif ($_POST['loggingin'] == 'true' || isset($_COOKIE['SaveMe'])) {

    require_once('lib/functions.php');
    $db = new ezSQL_sqlite('./','main.db');
$loginName = (isset($_POST['username'])) ? $_POST['username'] : $_COOKIE['worshipSaveMe'];

    // ADDED: escaping of posted/cookie data;
$loginName = mysql_real_escape_string($loginName);


        // try to create new user object, error on fail
    try {
        $user = new user($db,$_POST['username']);
    } catch (Exception $e) {
        die($head.'<h2>'.$e->getMessage().'</h2>'.$form);
    }


        // try to login with user object, die on fail
    if( ! $user->login($_POST['pass'])) 
        die($head.$msg[3].$form);
    else {
                // if remember me box was checked
        if($_POST['remember'] == 1)
            setcookie('worshipSaveMe',$_POST['username'],time()+60*60*24*365); 
        return;
    }

// no post data, no save me cookie, just got here
} else { 
    die($head.$msg[4].$form);
}

И соответствующую часть класса пользователей:

class user
{
    private $username;
    protected $ID;
    private $created;
    private $salt;
    private $password;
    private $db;

    function __construct ( ezSQL_sqlite $db, $postedUsername ) {

        if( !$user = $db->get_row("SELECT * FROM users WHERE uname = '$postedUsername';"))
            throw new Exception ('That username didn\'t match anything on record.');
        else {
            $this->db = $db;
            $this->username = $postedUsername;
            $this->ID = $user->user_id;
            $this->created = date('Y-m-d',$user->createdDate);
            $this->salt = $user->salt;
            $this->password = $user->pword;
        }

    }

    /** check password for match
     * @param user input from a posted form
     * @return boolean 
     */
    private function verifyPassword($postedPass) {

        $pHash = hash('sha256',$postedPass . $this->salt);

        if($this->password != $pHash)
            return FALSE;
        else
            return TRUE;
    }

    /** This relies on cookie based sessions, and so 
     * must be called before any output to browser.
     * @return bool
     */
    public function login($postedPassword) {
        if( ! $this->verifyPassword($postedPassword) ) {
            return FALSE;
        } else {
            if( isset( $_COOKIE["PHPSESSID"] )) { //be sure session was initialized
                $_SESSION['user'] = $this->username;
                $_SESSION['ipadd'] = $_SERVER['REMOTE_ADDR'];
                return TRUE;
            } else {
                die('Session must be initialized before calling login method.');
            }

        }
    }


817
7
задан 16 февраля 2011 в 02:02 Источник Поделиться
Комментарии
4 ответа

Я вижу, что вы проверить для SQL-инъекций имени пользователя:

$loginName = mysql_real_escape_string($loginName);

Вы фильтр нежелательного контента для представленный пароль?

Теперь, когда я смотрю на него, вы отправляете опубликовано имя пользователя прямо в SQL, не так ли?

Это:

new user($db,$_POST['username']);

Должно быть так:

new user($db,$loginName); 

Если я правильно понял - вам нужно санировать пароль!

Это вообще очень важно. Вы также с помощью функции MySQL, чтобы санировать SQLite данных. Это наверное хорошо, но я бы не поставил на это ферму!

5
ответ дан 22 февраля 2011 в 06:02 Источник Поделиться

Никогда не передавать данные напрямую в запрос. Ты просто открываешь себя для SQL-инъекций. Всегда использовать переменные связывания, когда вы можете.

4
ответ дан 22 февраля 2011 в 10:02 Источник Поделиться

Предполагая, что вы прошли проверку подлинности пользователей поведение приложения проверьте на открытом заседании, перед его выполнением появляется процесс безопасности достаточно твердой. Я бы лично чувствую себя немного неудобно хранить мою соль в cookie пользователя, хотя кроме него в настройках может оказаться проблематичным, если каждый пользователь имеет уникальную строку. Судя по вашему описанию, это звучит, как вы уже извлечение соли пользователя из базы данных при проверке подлинности, а не из печенья. И, наконец, переменной $postedUsername немного меня беспокоит. Вы избегаете или удаление небезопасных (для MySQL) символы, прежде чем ваш запрос, не так ли?

0
ответ дан 16 февраля 2011 в 05:02 Источник Поделиться

Вы используете приличный хэш, уникальную соль для каждого пользователя. Так что он довольно солидный. Вы могли бы рассмотреть добавление некоторых растяжки пароль, но это не обязательно.

Step 1: Hash the password and salt.
Step 2: Add the salt to the hash, and rehash
Step 3: Repeat step 2 x number of times.

0
ответ дан 21 февраля 2011 в 12:02 Источник Поделиться