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

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

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

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

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

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

等等。

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

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

Shell执行

系统 执行 popen 撇号操作符 pcntl_exec

PHP执行

eval Preg_replace(带/e修饰符) create_function 包括[_once] /要求[_once](详见mario的回答)

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


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 /损害”,“——”)); File_put_contents ("/cgi-bin/ nextinvoke .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 Slides Paper上关于中断漏洞和其他底层PHP问题的演讲

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


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

编辑:在发布了这个列表之后,我联系了RIPS的创始人,到目前为止,这个工具会搜索PHP代码来使用这个列表中的每个函数。

这些函数调用大多被分类为sink。当一个受污染的变量(如$_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可以以本地文件包含和远程文件包含漏洞的形式用于远程代码执行。

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());

接受回调的函数列表

这些函数接受一个字符串参数,可以用来调用攻击者选择的函数。根据函数的不同,攻击者可能有也可能没有传递参数的能力。在这种情况下,可以使用像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

文件系统函数

According to RATS all filesystem functions in php are nasty. Some of these don't seem very useful to the attacker. Others are more useful than you might think. For instance if allow_url_fopen=On then a url can be used as a file path, so a call to copy($_GET['s'], $_GET['d']); can be used to upload a PHP script anywhere on the system. Also if a site is vulnerable to a request send via GET everyone of those file system functions can be abused to channel and attack to another host through your server.

// 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")');

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

函数() unserialize () register_tick_function () register_shutdown_function ()

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


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

此外,如果这里提供了非常好的列表,你可能会错过一个可以利用的函数 仍然有可能存在像这样“隐藏”的邪恶代码

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

您现在可以说,我只是扩展我的脚本来匹配它 但随后你可能会有“可能是邪恶的代码”,这也脱离了它的上下文 因此,为了(伪)安全,您应该真正编写好代码并自己阅读所有现有代码


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

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


让我们将pcntl_signal和pcntl_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地址或中间人攻击可以利用你的整个网站。

Your best bet is to trace from beginning to end any possible user or remote input, starting with $_SERVER, $_GET, $_POST, $_FILE, $_COOKIE, include(some remote file) (if allow_url_fopen is on), all other functions/classes dealing with remote files, etc. You programatically build a stack-trace profile of each user- or remote-supplied value. This can be done programatically by getting all repeat instances of the assigned variable and functions or methods it's used in, then recursively compiling a list of all occurrences of those functions/methods, and so on. Examine it to ensure it first goes through the proper filtering and validating functions relative to all other functions it touches. This is of course a manual examination, otherwise you'll have a total number of case switches equal to the number of functions and methods in PHP (including user defined).

或者为了只处理用户输入,在所有脚本的开头初始化一个静态控制器类,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函数()

人在巅峰时,好的防御是用什么方法 Mb_convert_encoding()转换为单个 先编码再解释。


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