2010-03-01 3 views
55

mysql_real_escape_string достаточно для очистки ввода пользователя в большинстве ситуаций?PHP: Является ли mysql_real_escape_string достаточным для очистки ввода пользователя?

:: EDIT ::

Я имею в виду главным образом с точки зрения предотвращения инъекции SQL, но я в конечном счете хочу знать, могу ли я доверять пользовательские данные после того, как я применяю mysql_real_escape_string или, если я должен принять дополнительные меры по очистке перед тем, как передать его в приложение и базы данных.

Я вижу, что очистка HTML-символов важна, но я бы не счел нужным доверять пользователю.

T

+3

XSS является огромной проблемой, если вы игнорируете это вы просите проблемы равной величины. Вы должны проверить на своем пути, но если вы не снимаете javascript при отображении пользовательского контента, это действительно тривиально, чтобы делать такие вещи, как Session Hijacking и XSS-атаки, что, откровенно говоря, проще, чем SQL-инъекция, но немного но люди так и не поняли. –

+1

'mysql_real_escape_string' предназначен только для защиты от SQL-инъекций. Для других уязвимостей вам нужны другие инструменты. – Gumbo

+1

@Gumbo mysql_real_we_really_mean_it_this_time_escape_string будет охватывать эти случаи. Когда он будет добавлен в ближайшее время. – David

ответ

33

mysql_real_escape_string не хватает во всех ситуациях, но это, безусловно, очень хороший друг.лучше решение использует Prepared Statements

//example from http://php.net/manual/en/pdo.prepared-statements.php 

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)"); 
$stmt->bindParam(1, $name); 
$stmt->bindParam(2, $value); 

// insert one row 
$name = 'one'; 
$value = 1; 
$stmt->execute(); 

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

...........

Edit: Основываясь на комментариях ниже, мне нужно отправить эту ссылку (я должен был сделать, прежде чем жаль создание путаницы)

mysql_real_escape_string() versus Prepared Statements

Цитирование:

mysql_real_escape_string() подвержен тем же самым проблемам, что касается addslashes().

Крис Шифлетт (Security Expert)

+3

Приведите пример того, где этого недостаточно, но где указаны подготовленные утверждения. – Marius

+0

@Marius: Особенно в ситуациях, когда символы кодируются с помощью UTF8, hex и т. Д. Если вы исследуете в Интернете, вы обнаружите, что большинство разработчиков предлагают, если это возможно, использовать подготовленные операторы над mysql_real_escape_string. К сожалению, я не могу вспомнить ссылку. Надеюсь, что прояснит, извините за плохой английский :( – Sarfraz

+0

Хотя я согласен с тем, что подготовленные заявления превосходят, мне также было бы очень интересно узнать, когда mysql_real_escape_string() недостаточно для экранирования данных, используемых в запросе. – jasonbar

0

Лучший путь будет использовать Prepared Statements

+0

Неработающая ссылка .... – Damien

+2

2 года назад, тонны других ответов в этой теме - это действительно имеет значение? –

5

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

Вы также должны рассмотреть валидацию ввода против того, что вы ожидаете от этого.

Считаете ли вы использование prepared statements? PHP предлагает множество способов взаимодействия с вашей базой данных. Большинство из них лучше, чем функции mysql_ *.

PDO, MDB2 и MySQL Improved должно начаться.

+0

«К базе данных» - так что тогда будет выводиться. Не вводится. – symcbean

4

В каких ситуациях?

Для SQL-запросов это замечательно. (Подготовленные утверждения лучше - я проголосовал за PDO за это, но функция отлично справляется.) Для HTML и т. П. Это не инструмент для работы - попробуйте общий htmlspecialchars или более точный инструмент, например HTML Purifier.

Чтобы обратиться к редактированию: Единственный другой слой, который вы могли бы добавить, это валидация данных, например. подтвердите, что если вы помещаете целое число в базу данных и ожидаете положительного целого числа, вы возвращаете пользователю ошибку при попытке ввести отрицательное целое число. Что касается целостности данных, то mysql_real_escape_string - лучшее, что у вас есть для экранирования (хотя, опять же, подготовленные операторы - это более чистая система, которая позволяет избежать полного экранирования).

+0

Опять же, ответ почти прав - но вопрос был о вводе - не вывод – symcbean

+0

Иногда ввод идет прямо на выход, например. ' '. – Matchu

1

Существует два способа: использовать подготовленные операторы (как указано в других ответах), но это замедлит ваше приложение, потому что теперь вам нужно отправить два запроса в базу данных, а не в одну. Если вы можете жить с пониженной производительностью, то идите на это; Подготовленные заявления делают ваш код более красивым и понятным.

Если вы решили использовать mysql_real_escape_string, убедитесь, что вы избегаете всех ненадежных строк. Скрытая строка (mysql_real_escape_string) - это SQL Injection secure. Если вы не избежите всех строк, тогда вы не защищены. Вы действительно должны объединить mysql_real_escape_string с проверкой ввода; проверяя, что переменная, которую вы ожидаете провести на самом деле, представляет собой число и в пределах ожидаемого диапазона. Помните, никогда не доверяйте пользователю.

2

mysql_real_escape_string() полезно для предотвращения только инжекция SQL атак. Это не поможет вам предотвратить атаки на сценарии межсайтового сценария. Для этого вы должны использовать htmlspecialchars() непосредственно перед выводом данных, которые были первоначально собраны с пользовательского ввода.

+1

SQL-инъекция настолько проста в понимании, что XSS сейчас является огромной проблемой. Спасибо, что вызвали это. –

1

Существуют различные типы «чистки».

mysql_real_escape_string достаточно для данных базы данных, но все равно будет оцениваться браузером при отображении, если это HTML.

Чтобы удалить HTML с пользовательского ввода, вы можете использовать strip_tags.

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

10

Ответ на ваш вопрос: Нет. Mysql_real_escape_string() не подходит для всех пользовательских ввода, а mysql_real_escape_string() не останавливает все SQL-инъекции. addslashes() - еще одна популярная функция, используемая в php, и имеет ту же проблему.

уязвимый код:

mysql_query("select * from user where id=".mysql_real_escape_string($_GET[id])); 

PoC эксплуатируют:

http://localhost/sql_test.php?id=1 or sleep(500) 

Патч использовать кавычки вокруг ID:

mysql_query("select * from user where id='".mysql_real_escape_string($_GET[id])."'"); 

Действительно лучший подход заключается в использовании параметризованных запросов о чем указывал ряд людей. Pdo работает хорошо, adodb - еще одна популярная библиотека для php.

Если вы используете mysql_real_escape_string, его следует использовать только для SQL-инъекции и ничего больше.Уязвимости сильно зависят от того, как используются данные. Следует применять меры безопасности по функции по функциям. И да, XSS - это ОЧЕНЬ СЕРЬЕЗНАЯ ПРОБЛЕМА. Не фильтровать для html - это серьезная ошибка, которую хакер будет использовать для pw3n. Пожалуйста, прочитайте xss faq.

+2

Что это связано с способностью mysql_real_escape_string() предотвращать инъекцию? Правильно цитируйте или передайте свое значение как целое число. – jasonbar

+0

@jasonbar Вы можете бросить его, вы также можете забыть бросить его. Если вы используете параметризованные запросы, чтобы вы знали, что это всегда безопасно, даже если у вас есть 15 пьяных обезьян, работающих над проектом. – rook

+2

Правильно, но это не делает 'mysql_real_escape_string()' непригодным для * escaping * строк для SQL. Изменить: Да, подготовленные заявления лучше. – jasonbar

0

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

Вот manual entry, а также blog post [от Matt Butcher] о том, почему они великолепны.

+0

помните, что это не поможет вам в отношении SQL-инъекций, но против XSS! – Alfred

1

Вы можете попробовать оба, как и в

function clean_input($instr) { 

    // Note that PHP performs addslashes() on GET/POST data. 
    // Avoid double escaping by checking the setting before doing this. 
    if(get_magic_quotes_gpc()) { 
     $str = stripslashes($instr); 
    } 
    return mysql_real_escape_string(strip_tags(trim($instr))); 
} 
+0

Я использовал эту технику. Спасибо @crafter. –