Привет, я делаю некоторые запросы к базе данных MySQL, которая включает в себя некоторые пользовательские ввода. И мне было интересно, как предотвратить инъекционные атаки, например, если кто-то должен был вводить
"; a-MySQL query here;"
Это будет выполнено, это позволит людям получить доступ к компрометации моей системы. Мне интересно, как я могу защитить от подобных вещей, возможно создать функцию, которая отфильтровывает запрос, ищущий плохие высказывания? или, возможно, не позволяя; персонаж?
Единственный способ – правильно удалить данные, предоставленные пользователем. Другие указали на некоторые способы сделать это.
Есть и другой способ: подготовленные заявления и заполнители. Подготовленные утверждения поддерживаются каждым современным интерфейсом базы данных PHP, включая mysqli и PDO .
Давайте используем PDO в качестве демонстрации. Предположим, мы хотели обновить бит данных в таблице foo
представленной пользователем.
$sql = 'UPDATE foo SET bar = ? WHERE user_id = ?'; $sh = $db->prepare($sql); $sh->execute(array( $_POST['bar'], $_SESSION['user_id'] ));
Переменные в массиве, переданные для execute
заменяют заполнители вопросительного знака в запросе. Когда это происходит, они автоматически экранируются и цитируются . Вам не нужно вручную удалять их, чтобы сделать их безопасными для размещения в базе данных!
С другой стороны, вам все равно придется отфильтровывать их для неожиданного контента, такого как HTML, Javascript, письма, в которых вы ожидаете номера, и т. Д. Обеспечение безопасности данных для вставки в базу данных – это только половина битвы .
Еще лучшим способом, чем вызов варианта mysql_escape_string
является использование связанных запросов в PDO, так что невозможно забыть или пропустить случай, поскольку PDO будет выполнять экранирование для вас, когда этого потребуют обстоятельства.
См. Подробнее: http://www.electrictoolbox.com/php-pdo-bound-placeholders/
Лучшим решением является запуск каждой части данных из дикой природы (пользователя) с помощью этой функции. PHP.net: MySQL Real Escape String. Это очистит большинство – если не все – проблемы с инъекцией, которые видны сегодня. Вам просто нужно сделать что-то вроде следующего:
$var = mysql_real_escape_string($_GET['var']); $query = "INSERT INTO foo (var) VALUES (\"$var\");
Это всегда хорошая практика, чтобы заставить литье типов переменных, которые, как вы знаете, должны быть типом. Например, числовой идентификатор:
$id = (INT)$_GET['id'];
или
$id = ( is_numeric($_GET['id']) ? (INT)$_GET['id'] : -1; // replace -1 with FALSE, or NULL, etc
Который заставит эту переменную быть Целочисленным, поэтому вы не получите $id
являющегося «foo» или другим нечисловым.