可利用的PHP函数

我试图构建一个可以用于任意代码执行的函数列表。其目的不是列出应该列入黑名单或以其他方式禁止的函数。更确切地说,我想有一个grep-able的红旗关键字列表方便搜索一个受影响的服务器后门。

其思想是,如果您想构建一个多用途的恶意PHP脚本——例如c99或r57这样的“web shell”脚本——您将不得不在文件中的某个位置使用一个或多个相对较小的函数集,以便允许用户执行任意代码。搜索这些函数可以帮助您更快地将数万个PHP文件缩小到需要仔细检查的相对较小的脚本集。

显然,例如,以下任何一种代码都被认为是恶意的(或糟糕的编码):

<? eval($_GET['cmd']); ?>


<? system($_GET['cmd']); ?>


<? preg_replace('/.*/e',$_POST['code']); ?>

等等。

前几天在搜索一个受感染的网站时,我没有注意到一段恶意代码,因为我没有意识到preg_replace可以通过使用/e标志(这严重吗?为什么会在那里?)而变得危险。还有其他我错过的吗?

以下是我目前列出的清单:

Shell执行

  • system
  • exec
  • popen
  • backtick operator
  • pcntl_exec

PHP执行

  • eval
  • preg_replace(带有/e修饰符)
  • create_function
  • include[_once] / require[_once] (请看马里奥的回答用于漏洞利用细节)

有一个能够修改文件的函数列表可能也很有用,但我想99%的情况下,利用代码将至少包含上述函数之一。但是如果你有一个所有能够编辑或输出文件的函数的列表,把它贴出来,我会把它包括在这里。(我没有计算mysql_execute,因为这是另一类利用的一部分。)

149775 次浏览

反勾运算符返回php手册

你必须扫描include($tmp)和require(HTTP_REFERER)以及*_once。如果一个利用脚本可以写入一个临时文件,它可以在以后包含它。基本上是两步计算。

甚至可以隐藏远程代码,比如:

 include("data:text/plain;base64,$_GET[code]");

此外,如果你的网络服务器已经被入侵,你不会总是看到未编码的邪恶。利用shell通常是gzip编码的。想想include("zlib:script2.png.gz");这里没有eval,还是一样的效果。

危险的语法元素怎么办?

"变量的变量" ($$var)将在当前作用域中找到一个名为$var的变量。如果使用错误,远程用户可以修改或读取当前作用域中的任何变量。基本上是一个较弱的eval

例如:你写一些代码$$uservar = 1;,然后远程用户将$uservar设置为“admin”,导致$admin在当前范围内被设置为1

我特别想将unserialize()添加到这个列表中。长期以来,它一直存在各种漏洞,包括任意代码执行、拒绝服务和内存信息泄漏。永远不应该对用户提供的数据调用它。这些vuls中的许多已经在过去的露水年的发布中被修复,但它仍然保留了一对讨厌的vuls,在目前的写作时间。

有关狡猾php函数/用法的其他信息,请参阅加固PHP项目及其警告。还有最近的PHP安全月和2007的PHP bug之月项目

还要注意,按照设计,反序列化对象将导致执行构造函数和析构函数;另一个不调用用户提供的数据的原因。

平台特定的,但也是理论的执行向量:

  • dotnet_load ()
  • 新的COM(“WScript.Shell”)
  • 新的Java(“java.lang.Runtime”)
  • Event_new()—非常最终

而且还有更多的伪装方法:

  • Proc_open是popen的别名
  • 中的call_user_func_array (exE .chr(99),数组(“/ usr / bin /损害”,“——”));
  • 写入“/目录/ nextinvocation.cgi”),,chmod(…)
  • setDefaultStub -检查.phar文件中的代码
  • runkit_function_rename("exec", "innocent_name")或APD rename_function

我的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有足够多的潜在可破坏函数,您的列表可能太大,grep无法处理。例如,PHP有chmod和chown,它们可以用来简单地禁用一个网站。

EDIT:也许您希望构建一个bash脚本,在一个文件中搜索按危险(坏的函数、更坏的函数、永远不应该使用的函数)分组的函数数组,然后计算该文件所造成的危险的相对百分比。然后将其输出到目录树中,并在每个文件旁边标记百分比,如果超过阈值,例如30%的危险。

还要注意允许任意内存位置被读写的“中断漏洞”类!

这些影响函数,如trim(), rtrim(), ltrim(),爆炸(),strchr(), strstr(), substr(), chunk_split(), strtok(), addcslashes(), str_repeat()等。这主要(但不完全)是由于该语言的调用时引用传递特性,该特性已经被弃用了10年,但并没有被禁用。

欲了解更多信息,请参阅Stefan Esser在BlackHat USA 2009 幻灯片 上关于中断漏洞和其他底层PHP问题的讨论

本文还展示了如何使用dl()来执行任意系统代码。

为了构建这个列表,我使用了两个来源。红字的研究老鼠。我也加入了一些我自己的想法,在这条线上的人也提供了帮助。

在发布这个列表后,我联系了撕裂的创始人,到目前为止,这个工具搜索PHP代码,以使用这个列表中的每个函数。

这些函数调用大多被分类为sink。当一个受污染的变量(如$_REQUEST)被传递给接收器函数时,就有一个漏洞。像老鼠撕裂这样的程序使用类似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可以以本地文件包含远程文件包含漏洞的形式用于远程代码执行。

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

我知道move_uploaded_file已经被提到了,但是文件上传通常是非常危险的。仅仅是$_FILES的存在就应该引起一些关注。

可以将PHP代码嵌入到任何类型的文件中。带有文本注释的图像尤其容易受到攻击。如果代码按原样接受在$_FILES数据中找到的扩展,那么这个问题就特别麻烦。

例如,用户可以上传一个有效的带有嵌入式PHP代码的PNG文件作为“foo.php”。如果脚本特别简单,它实际上可能会将文件复制为“/uploads/foo.php”。如果服务器被配置为允许在用户上传目录中执行脚本(通常情况下,这是一个严重的疏忽),那么您可以立即运行任何PHP代码。(即使图像保存为。png格式,也有可能通过其他安全漏洞让代码执行。)

一份(非详尽的)上传检查清单:

  • 一定要分析内容,以确保上传的内容是它所声称的类型
  • 将文件保存为一个已知的、安全的文件扩展名,该扩展名永远不会被执行
  • 确保在用户上传目录中禁用PHP(以及任何其他代码执行)

有很多PHP漏洞可以通过PHP.ini文件中的设置来禁用。最明显的例子是register_globals,但是根据设置,也可以通过HTTP从远程机器包含或打开文件,如果程序对其include()或文件处理函数使用变量文件名,则可以利用这一点。

PHP还允许通过在变量名后面添加()来调用变量函数——例如$myvariable();将调用变量指定的函数名。这是可利用的;例如,如果攻击者可以让变量包含“eval”这个词,并且可以控制参数,那么他可以做任何他想做的事情,即使程序实际上不包含eval()函数。

这本身并不是一个答案,但这里有一些有趣的事情:

$y = str_replace('z', 'e', 'zxzc');
$y("malicious code");

同样,call_user_func_array()也可以用来执行模糊函数。

除了eval语言结构之外,还有另一个允许任意代码执行的函数:assert

assert('ex' . 'ec("kill --bill")');

这些函数也会产生一些不好的影响。

  • str_repeat()
  • unserialize()
  • register_tick_function()
  • register_shutdown_function()

前两种方法会耗尽所有可用内存,而后者会继续耗尽内存……

我猜,通过解析源文件,您无法真正找到所有可能的漏洞。

  • 此外,如果这里提供了非常好的列表,你可能会错过一个可以利用的函数

  • 仍然有可能存在像这样“隐藏”的邪恶代码

$myEvilRegex = base64_decode('Ly4qL2U=');

preg_replace (myEvilRegex美元$ _POST['代码']);

  • 您现在可以说,我只是扩展我的脚本来匹配它

  • 但随后你可能会有“可能是邪恶的代码”,这也脱离了它的上下文

  • 因此,为了(伪)安全,您应该真正编写良好的代码读取所有现有代码自己

我很惊讶没有人提到echoprint作为安全利用点。

跨站脚本(XSS)是一个严重的安全漏洞,因为它甚至比服务器端代码执行漏洞更常见。

让我们将pcntl_signalpcntl_alarm添加到列表中。

在这些函数的帮助下,您可以绕过php.ini或脚本中创建的任何set_time_limit限制。

例如,该脚本将运行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";
}

最近在security.stackexchange.com上有一些关于这个的讨论

可用于任意代码执行的函数

好吧,这缩小了一点范围-但由于'print'可以用来注入javascript(因此窃取会话等),它仍然有点随意。

不是列出应该被列入黑名单或不允许的函数。相反,我想要一个grep-able列表

这是一个明智的方法。

不过,一定要考虑编写自己的解析器——很快你就会发现基于grep的方法会失控(awk会更好一点)。很快你就会开始希望你也实现了一个白名单!

除了那些显而易见的,我建议标记任何包含了字符串字面量以外的参数的东西。还要注意__autoload()。

这里没有提到一个有趣的漏洞来源。PHP允许字符串中包含0x00字节。底层(libc)函数将此作为字符串的结束。

这允许在某些情况下(糟糕的实现)在PHP中的健康检查可以被愚弄,例如在如下情况下:

/// note: proof of principle code, don't use
$include = $_GET['file'];
if ( preg_match("/\\.php$/",$include) ) include($include);

通过调用script.php?file=somefile%00.php,这可以包括任何文件——不仅仅是以.php结尾的文件

因此,任何不遵守PHP字符串长度的函数都可能导致一些漏洞。

我担心我的回答可能有点太消极了,但是……

恕我直言,每一个单独的函数和方法都可以用于邪恶的目的。可以将其视为邪恶的涓滴效应:变量被分配给用户或远程输入,变量被用于函数,函数返回值被用于类属性,类属性被用于文件函数,等等。记住:一个伪造的IP地址或中间人攻击可以利用你的整个网站。

最好的方法是从头到尾跟踪任何可能的用户或远程输入,从$_SERVER$_GET$_POST$_FILE$_COOKIEinclude(some remote file) (如果 allow_url_fopen是打开的)开始,所有其他处理远程文件的函数/类,等等。您可以通过编程方式为每个用户或远程提供的值构建堆栈跟踪概要文件。这可以通过编程方式完成,方法是获取所分配变量和函数或方法的所有重复实例,然后递归地编译这些函数/方法的所有重复列表,等等。检查它以确保它首先通过了相对于它所涉及的所有其他函数的适当过滤和验证函数。这当然是一个手动检查,否则你会有case开关的总数等于PHP中的函数和方法的数量(包括用户定义的)。

或者为了只处理用户输入,在所有脚本的开头初始化一个静态控制器类,它1)根据允许的目的白名单验证和存储所有用户提供的输入值;2)擦除输入源(即$_SERVER = null)。你可以看出这有一点纳粹主义。

下面是我的提供商出于安全考虑禁用的函数列表:

  • 执行
  • 戴斯。莱纳姆:
  • 中将
  • apache_note
  • apache_setenv
  • closelog
  • debugger_off
  • debugger_on
  • define_syslog_variables
  • escapeshellarg
  • escapeshellcmd
  • ini_restore
  • openlog
  • passthru
  • pclose
  • pcntl_exec
  • popen
  • proc_close
  • proc_get_status
  • proc_nice
  • proc_open
  • proc_terminate
  • shell_exec
  • syslog
  • 系统
  • url_exec

代码中的大多数攻击使用多个访问源或多个步骤来执行自己。我不仅会搜索含有恶意代码的代码或方法,还会搜索所有执行或调用它的方法、函数。最好的安全性还包括对输入和输出的表单数据进行编码和验证。

在定义系统变量时也要注意,它们之后可以从代码中的任何函数或方法调用。

使用4bit发现了几个缓冲区溢出 字符解释文本的函数。 htmlentities () htmlspecialchars函数()< / p >

都在顶端,好的防御是要用的 Mb_convert_encoding()转换为单个

你可以在撕裂 /config/sink .php中找到持续更新的敏感接收器(可利用的php函数)及其参数列表,这是一个用于php应用程序漏洞的静态源代码分析器,也可以检测php后门。