Поэтому я немного опытный разработчик php и с тех пор «делал эту чертову»; Тем не менее, я все еще отношусь к n00bish, когда речь заходит о защите моих приложений. В том, что я действительно не знаю всего, что знаю, могу и должен.
Я взял Securing PHP Web Applications и читаю свой путь через это, проверяя вещи на этом пути. У меня есть некоторые вопросы для общей группы SO, которые относятся к запросу базы данных (в основном в mysql):
При создании приложений, которые помещают данные в базу данных, есть mysql_real_escape_string и общая проверка (is_numeric и т. Д.) На входных данных? Что касается других типов атак, отличных от SQL-инъекций.
Может ли кто-нибудь объяснить хранимые процедуры и подготовленные операторы немного больше информации, чем: вы делаете их и звоните им. Я хотел бы знать, как они работают, что валидация продолжается за кулисами.
Я работаю в среде, связанной с php4, и php5 пока не является опцией. Кто-нибудь еще был в этом положении раньше, что вы сделали, чтобы защитить свои приложения, в то время как все классные дети используют этот сладкий новый интерфейс mysqli?
Каковы некоторые общие примеры хорошей практики, которые люди считают выгодными, делая упор на создание инфраструктуры, способной выдерживать обновления и возможные миграции (например, перемещение php4 на php5).
Примечание. У нас не было ничего похожего на поиск, который попал в систему безопасности php-mysql.
Мои рекомендации:
Затем вы можете сделать что-то вроде:
$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', $dbusername, $dbpassword ); $sql = 'SELECT column FROM table WHERE condition=:condition'; $params = array( ':condition' => 1 ); $statement = $pdo_obj->prepare( $sql, array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) ); $statement->execute( $params ); $result = $statement->fetchAll( PDO::FETCH_ASSOC );
PROs:
Недостатки:
Ответ Хавьера, который имеет ссылку на овас, – хорошее начало.
Есть еще несколько вещей, которые вы можете сделать больше:
Что касается атак SQL-инъекций, вы можете написать функцию, которая будет удалять общие инструкции SQL из ввода типа «DROP» или «DELETE * WHERE», например:
* $ sqlarray = array ("DROP", "или 1 = 1", "union select", "SELECT * FROM", "select host", "create table", "FROM users", "users WHERE"); *
Затем напишите функцию, которая будет проверять ваш ввод против этого массива. Убедитесь, что какой-либо материал внутри $ sqlarray не будет распространяться среди ваших пользователей. (Не забудьте использовать strtolower на этом, спасибо lou).
Я не уверен, что memcache работает с PHP 4, но вы можете создать некоторую защиту от спама с помощью memcache, разрешив только определенный удаленный доступ к IP-адресу на странице process.php X раз в Y-период.
Привилегии важны. Если вам нужны только привилегии вставки (скажем, обработка заказов), вы должны войти в базу данных на странице процесса заказа с пользователем, который имеет только вставку и, возможно, выбор привилегий. Это означает, что даже если SQL-инъекция прошла, они могут выполнять только запросы INSERT / SELECT, а не удалять или реструктурировать.
Поместите важные файлы обработки php в каталог, например / include. Затем запретите доступ всех IP-адресов к этому каталогу / include.
Поместите соленое MD5 с помощью агента пользователя + remoteip + your salt в сеанс пользователя и убедитесь, что на каждой загрузке страницы проверяется, что правильный MD5 находится в их файле cookie.
Отключите определенные заголовки ( http://www.owasp.org/index.php/Testing_for_HTTP_Methods_and_XST ). Disallow PUT (Если вам не нужны файлы) / TRACE / CONNECT / DELETE заголовки.
Обычно я не работаю с PHP, поэтому я не могу предоставить рекомендации, специально предназначенные для ваших требований, но я предлагаю вам взглянуть на страницу OWASP, особенно в 10 самых популярных уязвимостей: http://www.owasp.org /index.php/Top_10_2007
На этой странице для каждой уязвимости вы получаете список вещей, которые вы можете сделать, чтобы избежать проблемы на разных платформах (.NET, Java, PHP и т. Д.).
Что касается подготовленных операторов, они работают, позволяя механизму базы данных знать, сколько параметров и каких типов ожидать в течение конкретного запроса, используя эту информацию, движок может понять, какие символы являются частью фактического параметра, а не то, что должно быть проанализировано как SQL как «апостроф» как часть данных вместо «как разделитель строк». Извините, я не могу предоставить больше информации, ориентированной на PHP, но надеюсь, что это поможет.
AFAIK, PHP / mySQL обычно не имеют параметризованных запросов.
Использование sprintf()
с mysql_real_escape_string()
должно работать очень хорошо. Если вы используете соответствующие строки форматирования для sprintf()
(например, «% d» для целых чисел), вы должны быть довольно безопасными.
Возможно, я ошибаюсь, но не должно быть достаточно использовать mysql_real_escape_string
для предоставленных пользователем данных?
если они не являются числами, и в этом случае вы должны убедиться, что они фактически являются числами, используя, например, ctype_digit
или is_numeric
или sprintf
(используя %d
или %u
для ввода ввода в число).
Кроме того, наличие serarate-пользователя mysql для ваших php-скриптов, которые могут только SELECT, INSERT, UPDATE и DELETE, вероятно, хорошая идея …
Пример из php.net
Пример №3 Запрос «Лучшая практика»
Использование mysql_real_escape_string () вокруг каждой переменной предотвращает SQL Injection. В этом примере демонстрируется метод «лучшей практики» для запроса базы данных, независимо от настройки «Волшебные кавычки».
Теперь запрос будет выполнен правильно, а атаки SQL Injection не будут работать.
<?php if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) { // Connect $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); if(!is_resource($link)) { echo "Failed to connect to the server\n"; // ... log the error properly } else { // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON. if(get_magic_quotes_gpc()) { $product_name = stripslashes($_POST['product_name']); $product_description = stripslashes($_POST['product_description']); } else { $product_name = $_POST['product_name']; $product_description = $_POST['product_description']; } // Make a safe query $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)", mysql_real_escape_string($product_name, $link), mysql_real_escape_string($product_description, $link), $_POST['user_id']); mysql_query($query, $link); if (mysql_affected_rows($link) > 0) { echo "Product inserted\n"; } } } else { echo "Fill the form properly\n"; }
Используйте хранимые процедуры для любой активности, которая включает в себя привязку к БД, и используйте параметры привязки для всех выборок.