Критическая уязвимость в PHP

Компьютерная группа реагирования на чрезвычайные ситуации (CERT) опубликовала уведомление об утечке информации о критической уязвимости в PHP, которая позволяет запустить произвольный код на сервере или просмотреть исходный код любого PHP-скрипта, выполняемого в CGI-режиме (используется некоторыми хостинг-провайдерами). Cкрипты, выполняемые с использованием mod_php и FastCGI (например, связки nginx с php-fpm), не подвержены проблеме.

Опасность уязвимости усугубляет тот факт, что несмотря на то, что разработчики PHP были уведомлены о проблеме ещё 17 января, а 23 февраля был отправлен дополнительный запрос от имени CERT, уязвимость остаётся неисправленной. Проблема вызвана ошибкой, допущенной в 2004 году. Интересно также то, что утечка информации возникла из-за оплошности разработчиков PHP, поместивших информацию о проблеме в публичный трекер ошибок, до момента выхода исправления с устранением уязвимости.

via Opennet.ru

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

Уязвимость позволяет проводить сразу несколько видов атак:

Читать остальную часть заметки »

Теги: , , , , , ,

Скрытие кода, метод 9

Этот метод популярен у ботоводов (т.е. распространителей perl-ботов), зашифрованный код передается непосредственно процессу Perl, запускаемому функцией popen():

error_reporting( 1 );
global $HTTP_SERVER_VARS;
if (@is_resource( $f = @popen( 'perl - E54POCH', "w" ) )) {
	@fwrite( $f, 'eval( pack( "H*", "6368...7d20" ) );eval( pack( "H*", "7573...353b"));' );
	@fflush( $f );
	sleep( 1 );
	@pclose( $f );
	echo "RUN OK";
} else {
	echo "RUN FALSE";
};
Читать остальную часть заметки »

Теги: , , , , , , , ,

Скрытие кода, метод 8

<?php # Web Shell by oRb
$auth_pass = "63a9f0ea7bb98050796b649e85481845";
$color = "#df5";
$default_action = 'FilesMan';
$default_use_ajax = true;
$default_charset = 'Windows-1251';
preg_replace("/.*/e","\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66
\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F
\x64\x65\x28'5b1pdx...Kn6fwE='\x29\x29\x29\x3B",".");?>

Чертовски гениально!) preg_replace ничего не заменяет, а просто выполняет роль eval(), выполняя весь код из второго аргумента!

pattern

Искомый шаблон. Может быть как строкой, так и массивом строк.

Также доступны некоторые модификаторы PCRE, включая ‘e‘ (PREG_REPLACE_EVAL), специфичный только для этой функции.

Раскодировать символы вида “\x65” можно двумя способами:

Читать остальную часть заметки »

Теги: , , , , , , ,

Скрытие кода, метод 7

Следующих код был взят из двух файлов, залитых на взломанный сайт. В каждом из файлов код состоял из трех блоков. Первый блок был почти одинаковым, массив функций, закодированный в base64:

$GLOBALS['_482181972_'] = Array(
    base64_decode( 'Z' .'mlsZ' .'V9' .'nZ' .'XRfY29u' .'dGV' .'udHM' .'=' ),
// file_get_contents
    base64_decode( 'c3Ry' .'c' .'G' .'9z' ), // strpos
    base64_decode( 'ZmlsZW10' .'a' .'W' .'1l' ), // filemtime
    base64_decode( 'Zm9wZW4=' ), // fopen
    base64_decode( 'Z' .'ndyaXRl' ), // fwrite
    base64_decode( '' .'ZmN' .'sb3Nl' ), // fclose
    base64_decode( 'dG91Y2g=' ) // touch
);

Различие было в том, что в каждой закодированной строке случайным образом было вставлено “’ .’”. Это исключает поиск в файлах по строке – функции, закодированной в base64.

Читать остальную часть заметки »

Теги: , , , , , , ,

Function hijaking

Перехват функций – архиполезная штука. Если нет возможности изобрести пяттиколесный велосопед, поймать опасную функцию (системную команду) за хвост можно с помощью модуля Baxtep (спасибо Андрею).

Baxtep – PHP security extension to intercept execution of system commands.

Для сборки модуля понадобятся пара прямых рук и такие команды:

# скачиваем с репозитория
svn checkout http://baxtep.googlecode.com/svn/trunk/ baxtep

# переходим в каталог
cd baxtep

# собираем:
phpize
# если у вас PHP в нестандартном каталоге, укажите полный путь:
# /usr/local/php5-fcgi/bin/phpize
./configure
make

# закиньте модуль в папку с модулями:
cp .libs/baxtep.so /usr/local/php5-fcgi/lib/php/extensions/no-debug-non-zts-20060613/baxtep.so

# каталог с модулями можно определить командой
php -i | grep extension_
# или по полному пути:
# /usr/local/php53-fcgi/bin/php -i | grep extension_

# php.ini можно найти тоже через php -i, добавьте туда:
baxtep.logfile = "/tmp/baxtep_messages"
# или укажите другой путь, куда удобнее. я добавил строчку перед
# [Zend]

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

2012-02-25 19:35:39 BAXTEP: proc_open CMDLINE: `php` FILE: /path/to/file/1.php on line 11 URI: /1.php
2012-02-25 19:35:39 BAXTEP: shell_exec CMDLINE: `date` FILE: - on line 1 URI: (null)

Среди опасных, есть еще функция proc_open, чтобы ее перехватывать, нужно добавить в файл baxtep.c строчку:

php_baxtep_substitute_function("proc_open" TSRMLS_CC);

и пересобрать/переподгрузить модуль.

Список функций, которые я блокирую, если в них нет острой необходимости (php.ini):

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec

Теги: , , , , , ,

Скрытие кода, метод 5

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

var s = '';
  try { new asd[0]
}
catch (q) {
  if (q) r = 1;
  c = String;
}
if (r && document.createTextNode) t = 2;
e = eval;
m = [4.5*t,18/t,52.5*t,204/t,16*t,80/t,...,4.5*t,18/t,62.5*t]; // здесь очень длинная строка
mm = c['fro'+'mCharCode'];
for (i = 0; i != m.length; i++) s += mm( e( "m" + "[" + "i" + ']' ) );
try {
  document.appendChild( null )
}
catch (q) {
  e( s );
}

На первый взгляд все крайне запутано и сложно, java-скрипты я пишу/читаю редко, поэтому сразу слегка даже растерялся. В причесанном коде выделил понятные места и довел все до понимания.

mm = c['fro'+'mCharCode'];

c – обозначает строку (String), т.е. переменной mm будет присвоена строка fromCharCode и mm будет выполнять роль этой функции.

mm( e( "m" + "[" + "i" + ']') );
// равносильно
String.fromCharCode( eval( "m[i]" ) );

это значит, что все арифметические выражения в массиве m будут подсчитаны, затем коды переведены в символы функцией fromCharCode и посимвольно в цикле внесены в строку s.

Результирующий код для расшифровки:

Читать остальную часть заметки »

Теги: , , , , , , , ,

Скрытие кода, метод 4

Взято из демо-версии DLE:

<?php $_F=__FILE__;$_X='STRING=';$_D=strrev('edoced_46esab');eval($_D('STRING2=='));?>

В коде бросаются в глаза две длиннющие строки в base64, раскодировать “в лоб” можно только вторую, там содержится кусок кода для дешифрации первой строки (STRING=). Причесанный вид файла:

$_F = __FILE__;
$_X = 'STRING=';
$_D = strrev( 'edoced_46esab' );
eval( $_D( 'STRING2==' ) );

edoced_46esab – это всего лишь перевертыш base64_decode. Вторая строка (STRING2==) после раскодировки и причесывания:

$_X = base64_decode( $_X );
$_X = strtr( $_X, 'STR1', 'STR2' );
$_R = str_replace( '__FILE__', "'".$_F."'", $_X );
eval( $_R );
$_R = 0;
$_X = 0;

Опять eval, от которого нужно избавиться. Собственно, интерес представляют только 2 и 3 строки. Дальше, общая раскодировка выглядит так:

$_F = __FILE__;
$_X = 'STRING=';
$_X = base64_decode( $_X );
$_Y = 'STRING2==';
$_Y = base64_decode( $_Y );
$_P = array(); // массив строк, которые будут вырезаны
$_P[0] = '$_X=base64_decode($_X);';
$_P[1] = 'eval($_R);$_R=0;$_X=0;';
$_Y = str_replace($_P, '', $_Y);
eval($_Y);
echo $_X;

Теги: , , , , , , ,