Основы PHP
  Что такое PHP?
  Возможности PHP
  Преимущества PHP
  История развития
  Что нового в PHP5?
  «Движок» PHP
  Переход на PHP 5.3
New Переход на PHP 5.6
  Введение в PHP
  Изучение PHP
  Основы CGI
  Синтаксис PHP
  Типы данных PHP
  Переменные в PHP
  Константы PHP
  Выражения PHP
  Операторы PHP
  Конструкции PHP
  Ссылки в PHP
  PHP и ООП
  Безопасность
  Функции PHP
  Функции по категориям
  Функции по алфавиту
  Стандартные функции
  Пользовательские
  PHP и HTTP
  Работа с формами
  PHP и Upload
  PHP и Cookies
  PHP и базы данных
  PHP и MySQL
  Документация MySQL
  Учебники
  Учебники по PHP
  Учебники по MySQL
  Другие учебники
  Уроки PHP
  Введение
  Самые основы
  Управление
  Функции
  Документация
  Математика
  Файлы
  Основы SQL
  Дата и время
  CURL
  Изображения
  Стили
  Безопасность
  Установка
  Проектирование БД
  Регулярные выражения
  Подготовка к работе
  Быстрый старт
  Установка PHP
  Установка MySQL
  Конфигурация PHP
  Download / Скачать
  Скачать Apache
  Скачать PHP
  Скачать PECL
  Скачать PEAR
  Скачать MySQL
  Редакторы PHP
  Полезные утилиты
  Документация
  PHP скрипты
  Скачать скрипты
  Инструменты
  PHP в примерах
  Новости портала
 Главная   »  Сборник статей
 
 

Безопасность в PHP, Часть I

Автор: John Coggeshall
Автор перевода: Данил Миронов

Источник: detail.phpclub.net

В двух предыдущих моих статьях (Common Style Mistakes, part one и Common Style Mistakes, part two) я рассказал о некоторых распространённых ошибках, которых в PHP нужно избегать, ибо они затрудняют чтение кода и делают скрипт более "склонным" к багам. Так вот сегодня мы перейдём к главному блюду и поговорим о безопасности в PHP.

Насколько важно задумываться о безопасности

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

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

<?php
function write_text($filename, $text="") {
    static
$open_files = array();
    
    
// если filename равен null, то закрываем все открытые файлы
    
if ($filename == NULL) {
        foreach(
$open_files as $fr) {
            
fclose($fr);
        }
        return
true;
    }
    
$index = md5($filename);
    
    if(!isset(
$open_files[$index])) {
        
$open_files[$index] = fopen($filename, "a+");
        if(!
$open_files[$index]) return false;
    }
    
fputs($open_files[$index], $text);
    return
true;
}
?>

Эта функция по умолчанию принимает два параметра: имя файла и текст, который необходимо записать в только что указанный файл. Сначала функция проверяет, не был ли файл уже открыт ранее, и если файл открыт, будет использован старый указатель. В противном случае будет просто открыт указатель на файл. В любом случае далее последует запись текста. Если переданное в функцию имя файла равно NULL, то все открытые указатели на файлы будут закрыты. Ниже - пример использования.

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

<form action="<?=$_SERVER['PHP_SELF']?>" method="get">
Выберите тему высказывания:
<select name="quote" size="3">
<option value="funny">Юмор</option>
<option value="political">Политика</option>
<option value="love">О любви</option>
</select><br />
The quote: <input type="text" name="quote_text" size="30" />
<input type="submit" value="Save Quote" />
</form>
</body></html>

<?php
include_once('write_text.php');

$filename  = "/home/web/quotes/{$_GET['quote']}";
$quote_msg = $_GET['quote_text'];

if (
write_text($filename, $quote_msg)) {
    echo
"<center><hr><h2>Высказывание сохранено!</h2></center>";
} else {
    echo
"<center><hr><h2>Ошибка при записи высказывания</h2></center>";
}
write_text(NULL);
?>

Итак, как вы видите, разработчик использовал написанную функцию write_text() при создании системы, позволяющей пользователям отправлять их любимые высказывания, которые затем сохраняются в текстовые файлы. К сожалению, хотя разработчик об этом и не догадывается, этот скрипт может быть использован злоумышленником для обхода системы защиты на web-сервере.

Возможно, сейчас вы чешете в затылке и пытаетесь придумать, как такой маленький и вроде бы безобидный скрипт может представлять такую опасность. Ладно, вместо того, чтобы оставить вас париться и догадываться самим, предлагаю рассмотреть приведённый ниже URL (не забываем, что файл со скриптом называется quotes.php):

http://www.somewhere.com/fun/quotes.php?quote=different_file.dat"e_text=garbage+data

Что же будет, если сервер получит запрос с таким URL? Ну, несомненно, скрипт quotes.php будет выполнен; но вместо записи высказывания в один из трёх предусмотренных файлов создастся новый файл different_file.dat [другой_файл.dat], и в него будет произведена запись строки garbage data [всякий хлам]. Очевидно, не то, для чего писался скрипт. На самом деле, злоумышленник мог бы даже создать новую учётную запись, получив в Unix доступ к файлу с паролями, указав в параметре ../../../etc/passwd (хотя это возможно при условии, что сервер исполняет скрипты на правах суперпользователя; если это условие выполняется, то вам надо немедленно прекратить чтение и побыстрей исправить такое положение дел). Наверное, самый серьёзный вред, который можно нанести с помощью данного скрипта, - это запись и исполнение различных PHP-скриптов, если есть директория /home/web/quotes/ доступна через запрос к серверу. Фантазия злоумышленников бесконечна.

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

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

Типичные ошибки, связанные с безопасностью

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

Ошибка 1. Когда мы доверяем входящим данным

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

Ошибка 2. Когда мы храним уязвимые данные в дереве web-сервера

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

Ошибка 3. Когда мы игнорируем рекомендации по безопасности

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

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

Джон Коггсхол (John Coggeshall): специалист и один из создателей PHP. Недосыпания по причине PHP начались около пяти лет назад.

  Продолжение (Часть II) >   

 
 » Обсудить эту статью на форуме

 
 Сборник статей 
 Содержание раздела 
Есть еще вопросы или что-то непонятно - добро пожаловать на наш  форум портала PHP.SU 
 

 
Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS