Рубрики
Нестандартные мысли

Написание безопасных PHP-скриптов — часть 1

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

Содержимое

Защита ваших переменных

В большинстве версий PHP вы можете получить доступ к значению переменной до ее инициализации. Рассмотрим этот простой пример:

если ($ пароль == $ the_password) { $logged_in = 1; } если ($ logged_in == 1) { // безопасный материал }

Все, что нужно сделать посетителю, это добавить ?logged_in=1 в конец URL-адреса, и он получит доступ. Хотя это может показаться очевидным, это чрезвычайно распространенная проблема со сценариями PHP.

Лучший способ предотвратить это — всегда убедиться, что переменные объявлены до их использования. Для этого примера вы можете просто добавить следующую строку вверху файла:

$logged_in = 0;

Теперь переменная не может быть сброшена пользователем, так как она объявляется перед использованием.

Еще одна рекомендация — включить отчеты об ошибках. При правильной настройке ваши сценарии будут генерировать ошибку, если переменная используется до ее определения. Хотя это может показаться утомительным, это может быть весьма полезно для обеспечения безопасности, поскольку оно сообщит вам о любых переменных, которые вы пропустили.

Вы можете включить это для всего вашего сервера с помощью строки в php.ini:

error_reporting = E_ALL

Чтобы включить это для определенного PHP-скрипта, просто добавьте это в начало файла:

отчет об ошибках (E_ALL);

Если вы включили отчеты об ошибках в вашем php.ini, но вам нужно обойти его для определенного скрипта, вы можете использовать это в своем файле:

отчет об ошибках (0);

Переменные, переданные скрипту

На большинстве серверов посетитель может указать переменную в URL-адресе, который затем будет преобразован в переменную в скрипте. Будет много раз, когда вам понадобится информация, переданная сценарию таким образом, но только если вы запрашиваете ее. Вот тут-то и появляются суперглобалы.

Есть две суперглобальные переменные, которые вы будете использовать большую часть времени. $_GET и $_POST . $_GET используется для получения переменных, переданных в URL-адресе. $_POST используется для получения значений из html-форм. В прошлом у вас также были $HTTP_POST и $GET_VARS , но они устарели и не должны использоваться. Вот пример:

$the_name = $_GET[‘имя’];

Имейте в виду, однако, что вам нужно убедиться, что значение существует в суперглобальном массиве, прежде чем использовать его, иначе вы можете получить ошибку. Попробуй это:

если (isset($_GET[‘имя’])) { $the_name = $_GET[‘имя’]; } еще { $the_name = “”; }

Теперь, когда вы знаете, как правильно получать ввод от пользователя, все еще остается вопрос, может ли кто-то передать случайные переменные в ваш сценарий. Это легко исправить с помощью параметра PHP register_globals .

В вашем файле php.ini добавьте эту строку:

register_globals = Выкл.

Или в файле .htaccess:

php_flag register_globals выключен

Опять же, если вам нужно снова включить register_globals для определенного сценария, вы можете сделать это с помощью альтернативного файла .htaccess.

Если функция register_globals отключена, вы сможете принимать пользовательский ввод только с помощью superglobals. Параметры, передаваемые скрипту, больше не будут автоматически превращаться в переменные.

Никогда не доверяйте пользователю

Независимо от того, какой ввод вы ожидаете или для чего он будет использоваться, всегда проверяйте его!

Даже если у вас есть текстовое поле формы с максимальной длиной 10 символов, вам все равно нужно убедиться, что ввод имеет правильный размер, потому что можно легко обойти самые основные ограничения html-форм. Можно даже легко отправить многострочный ввод в однострочное текстовое поле, если вы знаете, что делаете.

Если вы отображаете пользовательский ввод на странице, вы должны преобразовать символы html в их безопасные для браузера версии, чтобы пользователь не вызывал выполнение кода на вашем сервере.

Если вы вводите пользовательский ввод в запрос MySql, вы должны использовать регулярные выражения, чтобы убедиться, что данные находятся в нужном вам формате, а затем экранировать их с помощью mysql_real_escape_string . В противном случае кто-то может очень легко ввести строку символов, которая может очень плохо повлиять на вашу базу данных.

Вот простая функция, которая принимает пользовательский ввод и делает его безопасным для отображения на странице. Во-первых, он заменяет любые специальные символы html их кодами безопасных символов. Затем он проверяет магические кавычки (чтобы увидеть, были ли автоматически добавлены косые черты при вводе) и удаляет их, если это необходимо.

функция fix_for_page($value){ $value = htmlspecialchars(trim($value)); если (get_magic_quotes_gpc()) $значение = полоски($значение); вернуть $значение; }

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

Следующая функция принимает пользовательский ввод и делает его безопасным для использования в запросе MySql. Он делает это, удаляя косые черты (при необходимости), а затем используя функцию mysql_real_escape_string .

функция fix_for_mysql ($ значение) { если (get_magic_quotes_gpc()) $значение = полоски($значение); $значение = mysql_real_escape_string($значение); вернуть $значение; }

Распространено мнение, что независимо от того, отображаете ли вы пользовательский ввод на экране или используете его в запросе, символы, которые вам нужно экранировать, одни и те же, но это не так. Вот почему существуют отдельные функции. Если вы передаете данные на запрос, который только что был проверен с использованием стандартного спецсимвола и escape-функций, все еще есть шанс на эксплойт. Всегда используйте надлежащие средства защиты.

Другое использование пользовательского ввода

Каждый раз, когда вы включаете файл в свой сценарий, и имя файла было дано пользователем, вы должны быть очень осторожны. Представьте, что это на вашей странице:

Раздел 1 Раздел 2 Раздел 3

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

Если вы работаете с небольшим количеством файлов, вы всегда можете просто убедиться, что ввод точно соответствует одному из параметров, например:

$pages = массив(‘section1.php’, ‘section2.php’, ‘section3.php’); если (in_array($the_file, $pages)) { включить ($ the_file); } еще { die(“Неверный файл!”); }

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

Еще одно решение — создать каталог, содержащий файлы, и позволить сценарию открывать файлы только в этом каталоге. Во-первых, обязательно удалите все лишние косые черты в пользовательском вводе, чтобы имя файла не могло ссылаться на другой каталог. Затем жестко закодируйте путь следующим образом:

$ имя_файла = “/данные/” . $the_file;

Это очень простой пример, но вы поняли идею. Если вы не проверите наличие лишних косых черт, кто-то может попытаться открыть что-то вроде « ../../../config.php ».

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

почтовые программы на PHP

Наиболее часто используемым PHP-скриптом является, пожалуй, почтовая программа. Очень редко можно найти тот, у которого нет дыр в безопасности. Многие думают, что, поскольку имя получателя жестко закодировано в скрипте, его нельзя использовать для отправки почты другим людям. Это совершенно неверно!

Наиболее распространенный способ использования почтовых программ форм — внедрение альтернативных заголовков электронной почты. Вот очень простой пример. Представьте, что кто-то вводит это в поле темы письма:

Купить мои материалы!\\nСкрытая копия: Someone_getting_spammed@domain.com

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

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

$from = $_POST[“отправитель”]; if (eregi(“\\r”,$from) || eregi(“\\n”,$from)) { die(“Неверный ввод!”); }

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

Вам действительно нужно беспокоиться об этом только в полях «Имя», «Электронная почта», «Тема» и т. Д. Само сообщение не так важно (при условии, что вы правильно используете функцию почты), так как оно помещается не в заголовки, а под ними.

Одним из вариантов было бы иметь поле для сообщения и все. Тогда никакие заголовки не могут быть введены. Или у вас все еще могут быть поля, но вместо того, чтобы помещать пользовательский ввод в заголовки, он может просто поместить его в само сообщение.

Можно еще многое сказать о сценариях рассылок форм, но это все, что я расскажу здесь. Скоро я напишу статью, полностью посвященную почтовым программам PHP, которая будет включать в себя мой личный скрипт.

Вывод

На этом первая часть этой статьи заканчивается. Вопросы и/или комментарии приветствуются!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *