Эксплуатируемые функции PHP
Я пытаюсь создать список функций, которые можно использовать для выполнения произвольного кода. Цель не состоит в том, чтобы перечислить функции, которые должны быть помещены в черный список или иначе запрещены. Скорее, я хотел бы иметь grep
-able список ключевых слов с красным флагом, удобный при поиске взломанного сервера для бэкдора.
Идея состоит в том, что если вы хотите создать многоцелевой вредоносный PHP-скрипт, такой как скрипт "веб-оболочки", такой как c99 или r57, вам придется использовать одну или несколько из относительно небольшого набора функций. где-то в файле, чтобы позволить пользователю выполнить произвольный код. Поиск этих функций поможет вам быстрее сузить стог из десятков тысяч PHP-файлов до относительно небольшого набора сценариев, которые требуют более тщательного изучения.
Ясно, например, что любое из следующего будет считаться вредоносным (или ужасным кодированием):
<? eval($_GET['cmd']); ?>
<? system($_GET['cmd']); ?>
<? preg_replace('/.*/e',$_POST['code']); ?>
и так далее.
Просматривая взломанный веб-сайт на днях, я не заметил части вредоносного кода, потому что не осознавал preg_replace
может стать опасным при использовании /e
флаг (который, серьезно? Почему это даже там?). Есть ли другие, которые я пропустил?
Вот мой список пока:
Shell Execute
system
exec
popen
backtick operator
pcntl_exec
PHP Выполнить
eval
preg_replace
(с/e
модификатор)create_function
include
[_once
] /require
[_once
] (см. ответ Марио для деталей об эксплойтах)
Также может быть полезно иметь список функций, которые могут изменять файлы, но я думаю, что в 99% случаев код эксплойта будет содержать хотя бы одну из указанных выше функций. Но если у вас есть список всех функций, способных редактировать или выводить файлы, опубликуйте его, и я включу его здесь. (И я не считаю mysql_execute
, так как это часть другого класса эксплойтов.)
23 ответа
Для построения этого списка я использовал 2 источника. Этюд в Скарлет и РАТС. Я также добавил некоторые свои собственные в микс, и люди в этой теме помогли.
Изменить: После публикации этого списка я связался с основателем RIPS, и на данный момент этот инструмент ищет PHP-код для использования каждой функции в этом списке.
Большинство из этих вызовов функций классифицируются как Sinks. Когда испорченная переменная (например, $_REQUEST) передается в функцию приемника, вы получаете уязвимость. Такие программы, как RATS и RIPS, используют функцию, подобную grep, для идентификации всех приемников в приложении. Это означает, что программисты должны проявлять особую осторожность при использовании этих функций, но если они будут заблокированы, вы не сможете сделать многое.
" С большой силой приходит большая ответственность ".
- Стэн Ли
Выполнение команды
exec - Returns last line of commands output
passthru - Passes commands output directly to the browser
system - Passes commands output directly to the browser and returns last line
shell_exec - Returns commands output
`` (backticks) - Same as shell_exec()
popen - Opens read or write pipe to process of a command
proc_open - Similar to popen() but greater degree of control
pcntl_exec - Executes a program
Выполнение кода PHP
Помимо eval
Есть и другие способы выполнения кода PHP: include
/ require
может использоваться для удаленного выполнения кода в виде уязвимостей Local File Include и Remote File Include.
eval()
assert() - identical to eval()
preg_replace('/.*/e',...) - /e does an eval() on the match
create_function()
include()
include_once()
require()
require_once()
$_GET['func_name']($_GET['argument']);
$func = new ReflectionFunction($_GET['func_name']); $func->invoke(); or $func->invokeArgs(array());
Список функций, которые принимают обратные вызовы
Эти функции принимают строковый параметр, который можно использовать для вызова функции по выбору злоумышленника. В зависимости от функции атакующий может иметь или не иметь возможность передавать параметр. В этом случае Information Disclosure
функционировать как phpinfo()
может быть использован.
Function => Position of callback arguments
'ob_start' => 0,
'array_diff_uassoc' => -1,
'array_diff_ukey' => -1,
'array_filter' => 1,
'array_intersect_uassoc' => -1,
'array_intersect_ukey' => -1,
'array_map' => 0,
'array_reduce' => 1,
'array_udiff_assoc' => -1,
'array_udiff_uassoc' => array(-1, -2),
'array_udiff' => -1,
'array_uintersect_assoc' => -1,
'array_uintersect_uassoc' => array(-1, -2),
'array_uintersect' => -1,
'array_walk_recursive' => 1,
'array_walk' => 1,
'assert_options' => 1,
'uasort' => 1,
'uksort' => 1,
'usort' => 1,
'preg_replace_callback' => 1,
'spl_autoload_register' => 0,
'iterator_apply' => 1,
'call_user_func' => 0,
'call_user_func_array' => 0,
'register_shutdown_function' => 0,
'register_tick_function' => 0,
'set_error_handler' => 0,
'set_exception_handler' => 0,
'session_set_save_handler' => array(0, 1, 2, 3, 4, 5),
'sqlite_create_aggregate' => array(2, 3),
'sqlite_create_function' => 2,
Раскрытие информации
Большинство из этих вызовов функций не являются приемниками. Но скорее это может быть уязвимость, если какие-либо из возвращенных данных будут доступны для просмотра злоумышленнику. Если злоумышленник может видеть phpinfo()
это определенно уязвимость.
phpinfo
posix_mkfifo
posix_getlogin
posix_ttyname
getenv
get_current_user
proc_get_status
get_cfg_var
disk_free_space
disk_total_space
diskfreespace
getcwd
getlastmo
getmygid
getmyinode
getmypid
getmyuid
Другой
extract - Opens the door for register_globals attacks (see study in scarlet).
parse_str - works like extract if only one argument is given.
putenv
ini_set
mail - has CRLF injection in the 3rd parameter, opens the door for spam.
header - on old systems CRLF injection could be used for xss or other purposes, now it is still a problem if they do a header("location: ..."); and they do not die();. The script keeps executing after a call to header(), and will still print output normally. This is nasty if you are trying to protect an administrative area.
proc_nice
proc_terminate
proc_close
pfsockopen
fsockopen
apache_child_terminate
posix_kill
posix_mkfifo
posix_setpgid
posix_setsid
posix_setuid
Функции файловой системы
Согласно RATS все функции файловой системы в php противны. Некоторые из них кажутся злоумышленнику не очень полезными. Другие полезнее, чем вы думаете. Например, если allow_url_fopen=On
тогда URL можно использовать как путь к файлу, поэтому вызов copy($_GET['s'], $_GET['d']);
может быть использован для загрузки сценария PHP в любом месте системы. Также, если сайт уязвим для запроса, отправляемого через GET, каждая из этих функций файловой системы может быть использована для направления и атаки на другой хост через ваш сервер.
// open filesystem handler
fopen
tmpfile
bzopen
gzopen
SplFileObject->__construct
// write to filesystem (partially in combination with reading)
chgrp
chmod
chown
copy
file_put_contents
lchgrp
lchown
link
mkdir
move_uploaded_file
rename
rmdir
symlink
tempnam
touch
unlink
imagepng - 2nd parameter is a path.
imagewbmp - 2nd parameter is a path.
image2wbmp - 2nd parameter is a path.
imagejpeg - 2nd parameter is a path.
imagexbm - 2nd parameter is a path.
imagegif - 2nd parameter is a path.
imagegd - 2nd parameter is a path.
imagegd2 - 2nd parameter is a path.
iptcembed
ftp_get
ftp_nb_get
// read from filesystem
file_exists
file_get_contents
file
fileatime
filectime
filegroup
fileinode
filemtime
fileowner
fileperms
filesize
filetype
glob
is_dir
is_executable
is_file
is_link
is_readable
is_uploaded_file
is_writable
is_writeable
linkinfo
lstat
parse_ini_file
pathinfo
readfile
readlink
realpath
stat
gzfile
readgzfile
getimagesize
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
ftp_put
ftp_nb_put
exif_read_data
read_exif_data
exif_thumbnail
exif_imagetype
hash_file
hash_hmac_file
hash_update_file
md5_file
sha1_file
highlight_file
show_source
php_strip_whitespace
get_meta_tags
Вам нужно будет отсканировать include($tmp), а также require(HTTP_REFERER) и *_once. Если скрипт эксплойта может записать во временный файл, он может просто включить это позже. В основном двухступенчатый eval.
И даже можно скрыть удаленный код с помощью обходных путей, таких как:
include("data:text/plain;base64,$_GET[code]");
Кроме того, если ваш веб-сервер уже был взломан, вы не всегда увидите незакодированное зло. Часто оболочка эксплойта кодируется в gzip. Думать о include("zlib:script2.png.gz");
Эвала здесь нет, все тот же эффект.
Это не ответ сам по себе, но вот кое-что интересное:
$y = str_replace('z', 'e', 'zxzc');
$y("malicious code");
В том же духе, call_user_func_array()
может использоваться для выполнения запутанных функций.
Я удивлен, что никто не упомянул echo
а также print
как точки безопасности эксплуатации.
Межсайтовый скриптинг (XSS) - это серьезный эксплойт безопасности, потому что он даже более распространен, чем эксплойты на стороне сервера.
Я бы особенно хотел добавить unserialize() в этот список. У него долгая история различных уязвимостей, включая выполнение произвольного кода, отказ в обслуживании и утечка информации в памяти. Он никогда не должен вызываться на предоставленных пользователем данных. Многие из этих выпусков были исправлены в выпусках за последние годы росы, но в настоящее время в них сохраняется пара неприятных выпусков.
Для получения дополнительной информации о хитроумных функциях / использовании php посмотрите проект Hardened PHP Project и его рекомендации. Также последний Месяц безопасности PHP и Месяц ошибок PHP 2007 года.
Также обратите внимание, что при проектировании несериализация объекта вызовет выполнение функций конструктора и деструктора; Еще одна причина, чтобы не вызывать его на предоставленных пользователем данных.
Мой VPS настроен на отключение следующих функций:
root@vps [~]# grep disable_functions /usr/local/lib/php.ini
disable_functions = dl, exec, shell_exec, system, passthru, popen, pclose, proc_open, proc_nice, proc_terminate, proc_get_status, proc_close, pfsockopen, leak, apache_child_terminate, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid
В PHP достаточно потенциально разрушаемых функций, поэтому ваш список может быть слишком большим для поиска. Например, в PHP есть chmod и chown, которые можно использовать для простой деактивации сайта.
РЕДАКТИРОВАТЬ: Возможно, вы захотите создать сценарий bash, который ищет файл для массива функций, сгруппированных по опасности (плохие функции, худшие функции, функции, которые никогда не должны использоваться), а затем рассчитывает относительную опасность что файл накладывается в процентах. Затем выведите это в дерево каталога с процентами, помеченными рядом с каждым файлом, если они превышают порог, скажем, 30% опасности.
Также имейте в виду класс "уязвимостей прерывания", которые позволяют произвольным ячейкам памяти считываться и записываться!
Они влияют на такие функции, как trim(), rtrim(), ltrim(), explode(), strchr(), strstr(), substr(), chunk_split(), strtok(), addcslashes(), str_repeat() и другие., Это во многом, но не исключительно, из-за функции передачи по ссылке во время разговора языка, который устарел в течение 10 лет, но не отключен.
Для получения дополнительной информации см. Доклад Стефана Эссера об уязвимостях прерывания и других низкоуровневых проблемах PHP на бумаге для слайдов BlackHat USA 2009
Эта статья / презентация также показывает, как dl () может использоваться для выполнения произвольного системного кода.
Специфичные для платформы, но и теоретические векторы исполнения:
- dotnet_load ()
- новый COM("WScript.Shell")
- новая Java ("java.lang.Runtime")
- event_new () - очень рано
И есть еще много способов маскировки:
- proc_open - псевдоним для popen
- call_user_func_array ("exE".chr (99), массив ("/usr/bin/mage", "--all"));
- file_put_contents ("/ cgi-bin / nextinvocation.cgi") && chmod (...)
- PharData:: setDefaultStub - еще немного работы для изучения кода в файлах.phar
- runkit_function_rename ("exec", "innocent_name") или APD rename_function
Отдельно от eval
В языковой конструкции есть еще одна функция, которая позволяет выполнять произвольный код: assert
assert('ex' . 'ec("kill --bill")');
Один источник интересных подвигов не был упомянут. PHP позволяет иметь строки 0x00
байтов в них. Базовые (libc) функции обрабатывают это как конец строки.
Это учитывает ситуации, когда (плохо реализованная) проверка работоспособности в PHP может быть одурачена, например, в такой ситуации:
/// note: proof of principle code, don't use
$include = $_GET['file'];
if ( preg_match("/\\.php$/",$include) ) include($include);
Это может включать любой файл - не только те, которые заканчиваются на .php
- по телефону script.php?file=somefile%00.php
Поэтому любая функция, которая не подчиняется длине строки PHP, может привести к некоторой уязвимости.
Как насчет опасных синтаксических элементов?
" Переменная переменная" ($$var
) найдет переменную в текущей области с именем $var. Если используется неправильно, удаленный пользователь может изменить или прочитать любую переменную в текущей области. В основном слабее eval
,
Пример: вы пишете код $$uservar = 1;
затем удаленный пользователь устанавливает $uservar
в "админ", вызывая $admin
быть установленным на 1
в текущем объеме.
Я думаю, вы не сможете действительно найти все возможные эксплойты, анализируя ваши исходные файлы.
также, если здесь есть действительно хорошие списки, вы можете пропустить функцию, которая может быть использована
там еще может быть "скрытый" злой код, как этот
$ myEvilRegex = base64_decode ('Ly4qL2U =');
preg_replace ($ myEvilRegex, $ _POST ['code']);
Теперь вы можете сказать, я просто расширяю свой сценарий, чтобы соответствовать этому
но тогда у вас будет этот "возможно злой код", который, кроме того, находится вне контекста
так что, чтобы быть (псевдо) безопасным, вы должны действительно написать хороший код и прочитать весь существующий код самостоятельно
Я знаю move_uploaded_file
было упомянуто, но загрузка файлов в целом очень опасна. Просто наличие $_FILES
должен вызвать некоторое беспокойство.
Вполне возможно встроить код PHP в любой тип файла. Изображения могут быть особенно уязвимы с текстовыми комментариями. Проблема особенно проблематична, если код принимает расширение, найденное в $_FILES
данные как есть.
Например, пользователь может загрузить действительный файл PNG со встроенным кодом PHP как "foo.php". Если скрипт особенно наивный, он может скопировать файл как "/uploads/foo.php". Если сервер сконфигурирован так, чтобы разрешать выполнение скриптов в пользовательских каталогах загрузки (часто это бывает, и ужасный недосмотр), тогда вы можете мгновенно запустить любой произвольный код PHP. (Даже если изображение сохранено в формате.png, возможно, можно будет выполнить код с помощью других недостатков безопасности.)
(Неисчерпывающий) список вещей, которые нужно проверить при загрузке:
- Обязательно проанализируйте содержимое, чтобы убедиться, что выгрузка соответствует типу
- Сохраните файл с известным безопасным расширением, которое никогда не будет выполнено
- Убедитесь, что PHP (и любое другое выполнение кода) отключено в пользовательских каталогах загрузки
Давайте добавим pcntl_signal
а также pcntl_alarm
к списку.
С помощью этих функций вы можете обойти любое ограничение set_time_limit, созданное в php.ini или в скрипте.
Этот скрипт, например, будет работать в течение 10 секунд, несмотря на set_time_limit(1);
(Благодарность идет Себастьяну Бергманну, твит и суть:
<?php
declare(ticks = 1);
set_time_limit(1);
function foo() {
for (;;) {}
}
class Invoker_TimeoutException extends RuntimeException {}
class Invoker
{
public function invoke($callable, $timeout)
{
pcntl_signal(SIGALRM, function() { throw new Invoker_TimeoutException; }, TRUE);
pcntl_alarm($timeout);
call_user_func($callable);
}
}
try {
$invoker = new Invoker;
$invoker->invoke('foo', 1);
} catch (Exception $e) {
sleep(10);
echo "Still running despite of the timelimit";
}
Существует множество эксплойтов PHP, которые можно отключить с помощью настроек в файле PHP.ini. Очевидным примером является register_globals, но в зависимости от настроек также может быть возможно включать или открывать файлы с удаленных машин через HTTP, что можно использовать, если программа использует переменные имена файлов для любой из своих функций include() или обработки файлов.
PHP также позволяет вызывать функцию переменной, добавляя () в конец имени переменной - например, $myvariable();
вызовет имя функции, указанное в переменной. Это пригодно для использования; например, если злоумышленник может заставить переменную содержать слово "eval" и может управлять параметром, он может делать все, что захочет, даже если программа фактически не содержит функцию eval().
Эти функции также могут иметь некоторые неприятные последствия.
str_repeat()
unserialize()
register_tick_function()
register_shutdown_function()
Первые два могут исчерпать всю доступную память, а последние поддерживают истощение памяти...
Об этом недавно говорилось на security.stackexchange.com.
функции, которые можно использовать для выполнения произвольного кода
Что ж, это немного уменьшает область видимости - но так как "print" может использоваться для внедрения javascript (и, следовательно, кражи сессий и т. Д.), Он все еще несколько произвольный.
не перечислять функции, которые должны быть в черном списке или иным образом запрещены. Скорее, я хотел бы иметь grep-способный список
Это разумный подход.
Однако подумайте над написанием собственного парсера - очень скоро вы обнаружите, что подход на основе grep выходит из-под контроля (awk будет немного лучше). Довольно скоро вы также захотите начать реализовывать белый список!
В дополнение к очевидным, я бы рекомендовал отмечать все, что включает, аргументом чего-либо, кроме строкового литерала. Остерегайтесь __autoload() тоже.
Боюсь, мой ответ может быть слишком негативным, но...
ИМХО, каждая функция и метод там могут быть использованы в гнусных целях. Думайте об этом как о эффекте ручеек гнусности: переменная присваивается пользователю или удаленному вводу, переменная используется в функции, возвращаемое значение функции используется в свойстве класса, свойство класса используется в файловой функции, и так далее. Помните: поддельный IP-адрес или атака "человек посередине" могут использовать весь ваш сайт.
Лучше всего отслеживать от начала до конца любой возможный пользовательский или удаленный ввод, начиная с $_SERVER
, $_GET
, $_POST
, $_FILE
, $_COOKIE
, include(some remote file)
(если allow_url_fopen
все остальные функции / классы, связанные с удаленными файлами и т. д. Вы программно строите профиль трассировки стека для каждого значения, предоставленного пользователем или удаленно. Это можно сделать программным путем, получив все повторяющиеся экземпляры назначенной переменной и функций или методов, в которых она используется, затем рекурсивно составив список всех вхождений этих функций / методов и т. Д. Изучите его, чтобы убедиться, что он сначала проходит через надлежащие функции фильтрации и проверки относительно всех других функций, к которым он прикасается. Это, конечно, ручной экзамен, иначе у вас будет общее количество case
переключатели, равные количеству функций и методов в PHP (включая определяемые пользователем).
В качестве альтернативы для обработки только пользовательского ввода имейте статический класс контроллера, инициализированный в начале всех сценариев, который 1) проверяет и сохраняет все предоставленные пользователем входные значения в соответствии с белым списком разрешенных целей; 2) стирает этот источник ввода (т.е. $_SERVER = null
). Вы можете видеть, где это становится немного нацистским.
Вот список функций, которые мой провайдер отключает в целях безопасности:
- Exec
- дл
- show_source
- apache_note
- apache_setenv
- closelog
- debugger_off
- debugger_on
- define_syslog_variables
- escapeshellarg
- EscapeShellCmd
- ini_restore
- openlog
- пройти
- pclose
- pcntl_exec
- POPEN
- proc_close
- proc_get_status
- proc_nice
- proc_open
- proc_terminate
- shell_exec
- системный журнал
- система
- url_exec
Большинство атак в коде используют несколько источников доступа или несколько шагов для выполнения самих себя. Я бы искал не только код или метод, имеющий вредоносный код, но и все методы, выполняющие функции или вызывающие его. Наилучшая защита также будет включать в себя кодирование и проверку данных формы по мере их поступления.
Также следите за определением системных переменных, они могут впоследствии вызываться из любой функции или метода в коде.
Вы можете найти постоянно обновляемый список чувствительных приемников (эксплуатируемых функций php) и их параметров в RIPS /config/sinks.php, статическом анализаторе исходного кода на наличие уязвимостей в приложениях PHP, который также обнаруживает бэкдоры PHP.
Было обнаружено несколько переполнений буфера с использованием функций 4-битных символов, которые интерпретируют текст. htmlentities() htmlspecialchars()
на вершине, хорошая защита - использовать mb_convert_encoding() для преобразования в одну кодировку перед интерпретацией.