PHP URL Защитный вопрос - PullRequest
       11

PHP URL Защитный вопрос

0 голосов
/ 01 апреля 2010

Я хочу, чтобы пользователи хранили URL в моей базе данных. Я использую php mysql и htmlpurifier. Мне было интересно, был ли следующий код хорошим способом отфильтровать плохие данные перед тем, как сохранить их в базе данных?

Вот частичный код PHP.

$url = mysqli_real_escape_string($mysqli, $purifier->purify(htmlspecialchars(strip_tags($_POST['url'])));

Ответы [ 6 ]

4 голосов
/ 01 апреля 2010

Вам не нужно вызывать htmlspecialchars() и HTMLPurifier для данных - у вас действительно есть только одна проблема, и это гарантирует, что URL не содержит SQL-инъекцию - mysqli_real_escape_string() будет сортировать что.

В качестве альтернативы, если вы выводите данные на страницу / HTML (вместо того, чтобы использовать их в качестве заголовков перенаправления HTTP), вам нужно будет использовать htmlentities() для защиты от XSS-данных, КОГДА ВЫ ВЫХОДИТЕ. Золотое правило - понимание контекста:

Кодировка сущности HTML подходит для ненадежные данные, которые вы положили в тело документа HTML, например внутри тега. Это даже своего рода работает для ненадежных данных, которые идут в атрибуты, особенно если вы религиозны об использовании цитат вокруг ваших атрибутов. Но HTML кодирование объектов не работает, если вы положить ненадежные данные внутри помечать где угодно или событие атрибут обработчика, например onmouseover, или внутри CSS или в URL. Так что даже если вы используете метод кодирования сущности HTML повсюду ты еще скорее всего уязвимы для XSS. Вы ДОЛЖНЫ использовать экранировать синтаксис для части HTML документ, который вы помещаете ненадежные данные в.

Подробную информацию о предотвращении XSS можно найти в OWASP .

Всегда лучше кодировать данные (против соответствующей атаки) непосредственно перед их использованием (т. Е. Escape-строки MySQL для ввода в базу данных, чтобы предотвратить SQLi, escape-строки HTML для вывода на экран, чтобы предотвратить XSS, а не оба одновременно). ). Это позволяет вам отслеживать поток данных через ваше приложение, и вы знаете, что все данные в базе данных готовы для любых целей. Если вы кодируете эти данные в формате HTML перед тем, как поместить их в БД, вам придется дешифровать их, например, перед использованием в качестве заголовка HTTP.

Если вам необходимо закодировать данные до того, как они попадут в базу данных, убедитесь, что имя столбца отражает это для будущих разработчиков / сопровождающих!

EDIT:

Согласно комментарию VolkerK, лучший способ предотвратить XSS при выводе URL-адреса - проверить протокол - если он не соответствует вашим разрешенным протоколам (возможно, http / https), отклоните его:

$url = 'http://hostname/path?arg=value#anchor';

$parsedUrl = parse_url( $url );

if( $parsedUrl['scheme'] != 'http' ) {
    // reject URL
} else {
    $url = mysqli_real_escape_string( $mysqli, $url );
    $sql = "INSERT INTO table (url) VALUES ('$url')";
    // insert query
}

Это имеет преимущество в предотвращении javascript:alert('xss') атак в <a href="$url"> ситуациях. Запуск htmlentities() на javascript:alert('xss') не влияет (поскольку ограниченное подмножество символов, таких как <>, не должно быть экранированного), поэтому злонамеренный пользователь сможет запустить JS в вашем домене.

1 голос
/ 01 апреля 2010

Только mysqli_real_escape_string() необходимо, прежде чем вы поместите значение в базу данных.

Для защиты от XSS, htmlspecialchars() следует вызывать для всех отображаемых вами данных , когда они отображаются (в HTML), а не до того, как они будут сохранены.

Представьте себе, что однажды вам может понадобиться вывести данные в формате, отличном от HTML; тогда вы пожалеете, что позвонили htmlspecialchars() на все, прежде чем оно было сохранено в вашей базе данных.

Я не знаю, почему вы используете purifier и strip_tags(), возможно, у вас есть особая причина, но это выглядит как излишнее по принципу «чем больше слоев очистки данных я использую, тем лучше» , htmlspecialchars() сделает любой HTML безвредным в любом случае.

0 голосов
/ 01 апреля 2010

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

Перенос данных из суперглобальных массивов в переменные приложения с использованием расширения фильтра и соответствующих фильтров.

После этого вам может потребоваться очистить $ _POST, чтобы избежать повторного использования нефильтрованных данных.

Тогда вы массируете его в нужную вам форму.

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

Escape с mysqli_real_escape_string для хранения в БД MySQL. Если вы используете другую СУБД, вам следует использовать другую функцию.

Еще лучше, используйте подготовленные операторы и заполнители для пользовательских данных.

При выводе в формате HTML htmlentities может быть мудрым. При условии, что вы не хотите иметь какой-либо HTML-код в данных. Если вы это сделаете, используйте доверенную библиотеку, такую ​​как HTMLPurifier.

Я рекомендую вам не пытаться делать все в одной строке кода, как в вашем примере. Это труднее читать и труднее поддерживать.

Для URL-адресов htmlentities - это хороший способ избежать символов без символов и. Конечно, они должны быть & Это также гарантирует, что вы не используете кавычки, так как вы, конечно, используете флаг, чтобы те тоже были в кавычках - верно?

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

Фильтр ввода - выход выхода! (Цитирует Криса Шиффлетта)

0 голосов
/ 01 апреля 2010

Я храню URL в моем БД, и он очищается только в формате xss, но автоматически экранируется ормом. По сути это сводится к:

mysqli_real_escape_string(strip_tags($var));

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

На этом пути, однако, вы бы потянули его, а затем в своем шаблоне использовали htmlentities () на случай, если в нем есть что-то, что может помешать html.

Тебе не нужно слишком сильно проектировать что-то подобное.

PS. если вы работаете с POST, вы можете сделать:

$fixed = $_POST;
$fixed = array_map('strip_tags', $fixed);
$fixed = array_map('mysqli_real_escape_string', $fixed);

Затем работайте с массивом $ fixed.

0 голосов
/ 01 апреля 2010

Если вам нужно только сохранить URL-адреса в базе данных и получить их обратно, достаточно просто пропустить строку через mysqli_real_escape_string один раз. Больше ничего не нужно. Вам нужно будет использовать htmlspecialchars только тогда, когда вы хотите вывести его обратно пользователю на HTML-странице.

HTMLPurifier здесь вообще не принадлежит, поскольку он очищает HTML, а не URL-адреса.

0 голосов
/ 01 апреля 2010

Если вы беспокоитесь о внедрении SQL, это очистит его и предотвратит это. В противном случае, не уверен точно, что ты спрашиваешь.

...