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

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']); 

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

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

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

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

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

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

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

Просто чтобы назвать две странности:

  • Использование stripslashes после того, как mysql_real_escape_string удаляет слэши, которые были добавлены mysql_real_escape_string .
  • htmlentities заменяет символы символов < и > , которые используются в 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 имеет ссылки на символы типа &quot; . И не использование только одной из этих функций позволит разбить контекст.

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

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

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

Нет, это не слишком много, это уязвимость.

Этот код полностью уязвим для SQL Injection. Вы делаете 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 кодирует одиночные и двойные кавычки, убедитесь, что переменная, которую вы печатаете, также заключена в кавычки, что делает невозможным «вырваться» и выполнить код.

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

Я задаюсь вопросом о концепции санитарии. Вы сообщаете 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) Для коротких и прогнозируемых строк, которые должны соответствовать определенному стандарту (имя пользователя, адрес электронной почты, номер телефона и т. Д.), Вы можете: a) делать подготовленные заявления; или b) регулярное выражение или другое подтверждение данных.

4) Для строк, которые не будут соответствовать никакому реальному стандарту и которые могут иметь или не иметь предварительно или дважды сбежавший и исполняемый код повсюду (текст, заметки, разметка wiki, ссылки и т. Д.), Вы можете: a) сделать подготовленные заявления; или b) хранить и преобразовывать из формы binary / blob – преобразовывать каждый символ в двоичное, шестнадцатеричное или десятичное представление, прежде чем передавать значение в строку запроса и преобразовывать обратно при извлечении. Таким образом, вы можете больше сосредоточиться только на проверке html, когда вы вернете сохраненное значение обратно.