Должен ли я mysql_real_escape_string все куки, которые я получаю от пользователя, чтобы избежать внедрения MySQL в php? - PullRequest
2 голосов
/ 18 сентября 2008

Когда пользователь заходит на мой сайт, мой скрипт проверяет наличие 2 файлов cookie, в которых хранится идентификатор пользователя + часть пароля, для автоматического входа в систему.

Можно редактировать содержимое файлов cookie с помощью редактора файлов cookie, поэтому я полагаю, что возможно добавить некоторый вредоносный контент в записанный файл cookie?

Должен ли я добавить mysql_real_escape_string (или что-то еще) ко всем моим вызовам cookie или есть какая-то встроенная процедура, которая не позволяет этому произойти?

Ответы [ 9 ]

8 голосов
/ 18 сентября 2008

Что вам действительно нужно , так это не отправлять эти значения файлов cookie, которые можно взломать. Вместо этого, почему бы не хэшировать имя пользователя и пароль и (секретную) соль и установить это в качестве значения cookie? i.e.:

define('COOKIE_SALT', 'secretblahblahlkdsfklj');
$cookie_value = sha1($username.$password.COOKIE_SALT);

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

if ($user_cookie_value == sha1($username_from_db.$password_drom_db.COOKIE_SALT)) {
  # valid
} else {
  #not valid
}

mysql_real_escape_string делает дополнительный удар по базе данных, кстати (многие люди не понимают, что требуется соединение с БД и запрашивает MySQL).

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

3 голосов
/ 18 сентября 2008

Смысл mysql_real_escape_string не в том, чтобы защищать от инъекционных атак, а в том, чтобы гарантировать, что ваши данные точно хранятся в базе данных. Таким образом, он должен вызываться для ЛЮБОЙ строки, поступающей в базу данных, независимо от ее источника.

Однако вы должны также использовать параметризованные запросы (через mysqli или PDO), чтобы защитить себя от внедрения SQL. В противном случае вы рискуете оказаться как школа маленьких столиков Бобби .

1 голос
/ 18 сентября 2008

Подготовленные операторы и привязка параметров - это всегда хороший путь.

PEAR :: MDB2 поддерживает подготовленные операторы, например:

$db = MDB2::factory( $dsn );

$types = array( 'integer', 'text' );
$sth = $db->prepare( "INSERT INTO table (ID,Text) (?,?)", $types );
if( PEAR::isError( $sth ) ) die( $sth->getMessage() );

$data = array( 5, 'some text' );
$result = $sth->execute( $data );
$sth->free();
if( PEAR::isError( $result ) ) die( $result->getMessage() );

Это позволит только правильным данным и предварительно заданному количеству переменных попадать в базу данных.

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

1 голос
/ 18 сентября 2008

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

Когда кто-то пишет апостроф, он продолжает добавлять косые черты, разрушающие страницы блога.

Значение переменной само по себе не опасно: только когда вы помещаете ее в строку или что-то подобное, вы начинаете отклоняться в опасные воды.

Конечно, никогда не доверяйте ничему, что исходит со стороны клиента.

0 голосов
/ 18 сентября 2008

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

(с головы на свободном php - трактуйте как псевдокод):

$usernameFromPostDbsafe = LimitToAlphaNumUnderscore($usernameFromPost);
$result = Query("SELECT hash FROM userTable WHERE username='$usernameFromPostDbsafe' LIMIT 1;");
$hashFromDb = $result['hash'];
if( (sha1($usernameFromPost.$passwordFromPost.SALT)) == $hashFromDb ){
    //Auth Success
}else{
   //Auth Failure
}

После успешной аутентификации вы можете сохранить хеш в $ _SESSION или в таблице базы данных с зашифрованными аутентифицированными именем пользователя / хешами. Затем отправьте хэш обратно в браузер (например, в файл cookie), чтобы при последующих загрузках страницы хеш отправлялся обратно на сервер для сравнения с хешем, хранящимся в выбранном вами хранилище сеанса.

0 голосов
/ 18 сентября 2008

Я бы порекомендовал использовать htmlentities ($ input, ENT_QUOTES) вместо mysql_real_escape_string, так как это также предотвратит случайный вывод действительного HTML-кода. Конечно, вы можете использовать mysql_real_escape_string и htmlentities, но зачем вам это?

0 голосов
/ 18 сентября 2008

mysql_real_escape_string настолько устарела ... В наши дни вы должны действительно вместо этого использовать привязку параметров.

Я уточню, упомянув, что я имел в виду подготовленные высказывания и предоставлю ссылку на статью, демонстрирующую, что иногда mysl_real_escape_string недостаточно: http://www.webappsec.org/projects/articles/091007.txt

0 голосов
/ 18 сентября 2008

Я согласен с вами. Можно изменить файлы cookie и отправить вредоносные данные.

Я считаю, что хорошей практикой является фильтрация значений, которые вы получаете из файлов cookie, перед их использованием. Как правило, я фильтрую любые другие входные данные, которые могут быть изменены.

0 голосов
/ 18 сентября 2008

Вы должны mysql_real_escape_string что-нибудь , которое может быть потенциально вредным. Никогда не доверяйте никаким типам ввода, которые могут быть изменены пользователем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...