Как обезопасить проект от взломов и атак? - PullRequest
3 голосов
/ 22 ноября 2011

Я начал заниматься веб-разработкой не так давно. Сейчас я кое-что знаю, но я действительно обеспокоен проблемами безопасности, которые могут возникнуть. Я знаю простые решения для обеспечения безопасности, такие как preg_replace, но я не уверен в этом.

Поэтому я хотел бы попросить вас рассказать о каких-либо «универсальных» стандартах безопасности, которые могут применяться в следующих случаях. Как я уже говорил, я не профессионал, поэтому было бы здорово, если бы вы могли начать с чего-то простого, но полезного. Если возможно, не могли бы вы привести примеры, пожалуйста?

Я посмотрел руководство по php, хотя хотел бы узнать дополнительную информацию от человека.

Вот несколько типичных вещей MySQL / PHP, которые я использую в своих проектах. Не могли бы вы предложить какие-либо улучшения, чтобы сделать их более безопасными?

$sql = mysql_query("SELECT * FROM stories WHERE showing = 1 ORDER BY cr_date DESC LIMIT 5") or die (mysql_error("There was an error in connection"));
        while($row = mysql_fetch_assoc($sql)){
            $story_id = $row["id"];
            // etc...
        }

$username = $_POST['username'];
$sql = mysql_query("INSERT INTO myMembers (username, //etc... ) 
VALUES('$username' //etc.. ")or die (mysql_error());

$username = $_GET['username']; 
//gets username from url like http://myweb.com/profile.php?username=blabla

Ответы [ 4 ]

6 голосов
/ 22 ноября 2011

Прежде всего, спасибо за заботу о веб-безопасности. Многие разработчики PHP ничего об этом не знают и не хотят учиться. Именно они раскрывают наши пароли и банковские счета хакерам. Будь частью решения! : -)

1. Относитесь к расширению mysql как к устаревшему.

Используйте взамен PDO или mysqli . Простое расширение mysql не поддерживает подготовленные операторы и некоторые другие функции, такие как управление транзакциями. Никто не должен использовать mysql, если у них есть PDO_mysql или mysqli для них.

2. Не интерполируйте внешние данные в SQL.

Каждый раз, когда вы получаете значение из $ _GET или $ _POST, вы должны считать его небезопасным для использования в любом операторе SQL, или в shell_exec (), или в другом экземпляре, где вы выполняете строку в качестве некоторого кода.

3. Используйте подготовленные параметры запроса вместо интерполяции.

Это действительно легко. На самом деле проще использовать параметры запроса, чем интерполировать переменные в строки SQL. Вам не нужно беспокоиться об экранировании или длительной сложной конкатенации строк.

См. Пример кода здесь: http://us.php.net/manual/en/pdo.prepare.php

4. Для угловых случаев используйте тщательную фильтрацию.

Параметр запроса занимает место для одного литерального значения в выражении SQL. Не имена таблиц, не имена столбцов, не ключевые слова SQL, не списки значений или полные выражения. Для этого вам нужно использовать интерполяцию строк, но посмотрите мою презентацию Мифы и ошибки SQL-инъекций , где приведены примеры того, как вы можете использовать «белые» значения для интерполяции.

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


Глядя на ваши примеры, запрос SELECT не имеет динамических значений, интерполированных из внешних источников, таких как $ _GET. Так что это безопасно.

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

Также учтите, что SQL-инъекция является одной из двух наиболее распространенных проблем безопасности в PHP. Другой - межсайтовый скриптинг (XSS). Это не имеет прямого отношения к SQL, но вы должны также узнать об этом.

Вот хороший ресурс для получения дополнительной информации о безопасности веб-программирования: Шпаргалки OWASP.org .

2 голосов
/ 22 ноября 2011

Многие фреймворки уже имеют хороший набор мер безопасности, которые помогут предотвратить такие вещи, как инъекции SQL. Yii, CakePhP, CodeIgnitre могут быть полезны.

1 голос
/ 22 ноября 2011

Хотя победить Билла практически невозможно, я чувствую, что должен уточнить ответы, в которых говорится, что «вы не должны доверять никакому вводу пользователя».

На самом деле, совсем наоборот - защита с помощью SQL-инъекций пойдет на пользу только в том случае, если она будет полностью неосведомлена об источнике данных. И будет рассматривать ВСЕ данные как потенциально вредоносные. И обработайте его соответственно.

Итак, подведем итог всем советам:

Подготовленные заявления - это хороший подход , но не полный .
У него блестящая идея использовать некоторый заполнитель , прокси для представления фактического значения в запросе. Таким образом, это значение может быть должным образом обработано.
Но эти заполнители, как сказал Билл, ограничены только строками и числами. Так что было бы неплохо добавить еще один собственный заполнитель - для идентификаторов. Но вы все равно должны следить за синтаксисом ключевых слов SQL вручную.

Таким образом, вместо «Не интерполируйте внешние данные в SQL». утверждение один должен использовать

"2. Не интерполировать значения в запрос напрямую, а только через некоторый прокси-сервер, выполняя необходимые меры предосторожности"

0 голосов
/ 22 ноября 2011

Самая важная вещь, которую следует запомнить: никогда не доверяйте ничему из внешнего источника (например, ввод пользователя, ответы от других веб-служб и т. Д.). Всегда очищайте все входные данные и, по возможности, используйте для этого код вашего поставщика базы данных.

В случае MySQL параметризация всех запросов необходима, поэтому используйте подготовленный оператор, например,

$statement = $db->prepare('SELECT * FROM stories WHERE title = :title');
$statement->execute(array(':title' => $title));
$rows = $statement->fetchAll();

Ваш текущий оператор вставки уязвим для атаки SQL-инъекцией , измените его так, чтобы он был ближе к:

$username = $_POST['username'];
$statement = $db.prepare("INSERT INTO myMembers (username) VALUES(':username');
$statement->execute(array(':username' => $username));

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

Это всего лишь несколько способов сделать ваше приложение более безопасным, я настоятельно рекомендую прочитать 10 самых уязвимых мест OWASP и исследовать их по отдельности, поскольку каждый из них сам по себе является довольно большой темой!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...