Являются эти две функции излишеством для санитизации?

function sanitizeString($var)
{
    $var = stripslashes($var);
    $var = htmlentities($var);
    $var = strip_tags($var);
    return $var;
}

function sanitizeMySQL($var)
{
    $var = mysql_real_escape_string($var);
    $var = sanitizeString($var);
    return $var;
}

Я получил эти две функции из книги, и автор говорит, что при помощи этих двух, я могу быть дополнительным сейфом против XSS (первая функция) и внедрения SQL (2-й func). Все - необходимые?

Также для очистки, я использую подготовленные операторы для предотвращения внедрений SQL.

Я использовал бы его как это:

$variable = sanitizeString($_POST['user_input']);
$variable = sanitizeMySQL($_POST['user_input']);

Править: Избавьтесь от strip_tags для 1-й функции, потому что это ничего не делает. Был бы с помощью этих двух функций быть достаточно, чтобы предотвратить большинство нападений и быть хорошо для общедоступного сайта?

7
задан jpjp 30 May 2010 в 19:56
поделиться

7 ответов

Это правда, но такой уровень экранирования может не подходить для всех случаев. Что, если вы хотите сохранить HTML в базе данных?

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

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

Также обратите внимание, что strip_tags в вашей первой функции, скорее всего, не будет иметь никакого эффекта, если все < и > станут < и > .

5
ответ дан 6 December 2019 в 08:42
поделиться

Если вы используете подготовленные операторы и SQL-заместители и никогда не интерполируете пользовательский ввод непосредственно в ваши SQL-строки, вы можете полностью пропустить санирование SQL.

Когда вы используете заполнители, структура SQL-запроса (SELECT foo, bar, baz FROM my_table WHERE id = ?) отправляется в механизм базы данных отдельно от значений данных, которые (в конечном итоге) связаны с заполнителями. Это означает, что, за исключением серьезных ошибок в движке базы данных, нет абсолютно никакого способа для значений данных быть неправильно истолкованными как инструкции SQL, так что это обеспечивает полную защиту от атак SQL-инъекций без необходимости изменять данные для хранения.

2
ответ дан 6 December 2019 в 08:42
поделиться

Вы делаете htmlentities (который превращает все > в >), а затем вызываете strip_tags, который в данный момент ничего больше не сделает, поскольку тегов нет.

3
ответ дан 6 December 2019 в 08:42
поделиться

Ну, если вы не хотите изобретать колесо, вы можете использовать HTMLPurifier. Он позволяет точно определить, что вам нужно, а что нет, и предотвращает XSS-атаки и тому подобное

.
0
ответ дан 6 December 2019 в 08:42
поделиться

Нет, это не перебор, это уязвимость.

Этот код полностью уязвим для внедрения SQL. Вы выполняете mysql_real_escape_string (), а затем выполняете stripslashes (). Таким образом, " станет \" после mysql_real_escape_string (), а затем вернется к " после stripslashes (). Mysql_real_escape_string () лучше всего остановить sql инъекция.Библиотеки параметризованных запросов, такие как PDO и ADODB, используют его, а параметризованные запросы позволяют очень легко полностью остановить внедрение sql.

Продолжайте тестировать свой код:

$variable = sanitizeString($_POST['user_input']);
$variable = sanitizeMySQL($_POST['user_input']);
mysql_query("select * from mysql.user where Host='".$variable."'");

Что делать, если:

$_POST['user_input'] = 1' or 1=1 /*

Исправлено:

mysql_query("select * from mysql.user where Host='".mysql_real_escape_string($variable)."'");

Этот код также уязвим для некоторых типов XSS:

$variable = sanitizeString($_POST['user_input']);
$variable = sanitizeMySQL($_POST['user_input']);
print("<body background='http://localhost/image.php?".$variable."' >");

Что делать, если:

$_POST['user_input']="' onload=alert(/xss/)";

исправлено:

$variable=htmlspecialchars($variable,ENT_QUOTES);
print("<body background='http://localhost/image.php?".$variable."' >");

htmlspeicalchars кодирует одинарные и двойные кавычки, убедитесь, что печатаемая вами переменная также заключена в кавычки, это делает невозможным «прерывание» и выполнение кода.

2
ответ дан 6 December 2019 в 08:42
поделиться

Если честно, я думаю, что автор этой функции либо не имеет представления, что такое XSS и SQL-инъекции, либо что именно делает используемая функция.

Назовем две странности:

  • Использование stripslashes после mysql_real_escape_string удаляет косые черты, которые были добавлены mysql_real_escape_string .
  • htmlentities заменяет chatacters < и > , которые используются в strip_tags для идентификации тегов.

Более того: В общем, функции, которые защищают от XSS, не подходят для защиты от SQL-инъекций и наоборот. Потому что у каждого языка и контекста есть свои специальные символы, о которых нужно позаботиться.

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


Изменить Вот какой-то (возможно, странный) пример: представьте, что вы разрешаете своим пользователям вводить какое-то значение, которое должно использоваться в качестве сегмента пути в URI, который вы используете в некотором коде JavaScript в onclick ] значение атрибута. Итак, языковой контекст выглядит так:

  • Значение атрибута HTML
    • Строка JavaScript
      • Сегмент пути URI

И для большего удовольствия: вы сохраняете это входное значение в базе данных.

Теперь, чтобы правильно сохранить это входное значение в вашей базе данных, вам просто нужно использовать правильную кодировку для контекста, который вы собираетесь вставить в свой язык базы данных (например, SQL); остальное не имеет значения (пока). Поскольку вы хотите вставить его в объявление строки SQL, контекстные специальные символы - это символы, которые позволяют вам изменить этот контекст. Что касается объявлений строк, эти символы (особенно) - символы ", ' и \ , которые необходимо экранировать. Но, как уже говорилось, подготовленные операторы действительно все это работает на вас, поэтому используйте их.

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

  • Для контекста сегмента пути URI нам нужно экранировать (по крайней мере) все те символы, которые позволяют нам изменить это контекст; в этом случае / (оставить текущий сегмент пути), ? и # (оба выходят из контекста пути URI). Для этого мы можем использовать rawurlencode .
  • Для контекста строки JavaScript нам нужно позаботиться о ", ' и \ . ​​Мы можем использовать ] json_encode для этого (если доступно).
  • Для значения атрибута HTML нам нужно позаботиться о & , ", ] ' и <. Для этого мы можем использовать htmlspecialchars .

Теперь все вместе:

'… onclick="'.htmlspecialchars('window.open("http://example.com/'.json_encode(rawurlencode($row['user-input'])).'")').'" …'

Теперь, если $ row ['user-input'] равно «bar / baz» , вывод будет:

… onclick="window.open(&quot;http://example.com/&quot;%22bar%2Fbaz%22&quot;&quot;)" …

Но с использованием всего этого функция в этих контекстах не является излишним. Потому что, хотя в контекстах могут быть похожие специальные символы, они имеют разные escape-последовательности. URI имеет так называемое процентное кодирование, JavaScript имеет escape-последовательности, такие как \ ", а HTML имеет ссылки на символы, такие как " . А неиспользование только одной из этих функций позволит нарушить контекст.

10
ответ дан 6 December 2019 в 08:42
поделиться

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

В любом случае, вот еще несколько методов очистки ...

1) Для числовых значений всегда вручную приводите по крайней мере где-нибудь до или во время построения строки запроса: "SELECT field1 FROM tblTest WHERE (id =". (Int ) $ val. ")";

2) Для дат сначала преобразуйте переменную в метку времени unix. Затем используйте функцию Mysql FROM_UNIXTIME (), чтобы преобразовать ее обратно в дату. "SELECT field1 FROM tblTest WHERE (date_field> = FROM_UNIXTIME (". Strtotime ($ val). ")";. Иногда это действительно необходимо, чтобы иметь дело с тем, как Mysql интерпретирует и сохраняет даты, отличные от уровней скрипта или ОС.

3) Для коротких и предсказуемых строк, которые должны соответствовать определенному стандарту (имя пользователя, адрес электронной почты, номер телефона и т. Д.), Вы можете: а) выполнять подготовленные инструкции; или б) регулярное выражение или другая проверка данных.

4) Для строк, которые не соответствуют какому-либо реальному стандарту и которые могут иметь или не иметь пре- или двойное экранирование и исполняемый код повсюду (текст, заметки, разметка вики, ссылки и т. Д.), Вы можете а) делать подготовленные заявления; или б) сохранить и преобразовать из двоичной / блобовой формы - преобразование каждого символа в двоичное, шестнадцатеричное или десятичное представление даже до передачи значения в строку запроса и обратное преобразование при извлечении. Таким образом, вы можете больше сосредоточиться только на проверке HTML, когда вы выплевываете сохраненное значение обратно.

-1
ответ дан 6 December 2019 в 08:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: