可利用的PHP功能

时间:2010-06-25 04:34:36

标签: php security grep

我正在尝试构建一个可用于任意代码执行的函数列表。目的不是列出应列入黑名单或以其他方式禁止的功能。相反,我希望在搜索受感染的后台服务器时,有一个grep能够列出的 red-flag 关键字。

这个想法是,如果你想构建一个多用途的恶意PHP脚本 - 比如像c99或r57这样的“web shell”脚本 - 你将不得不使用一个或多个相对较小的文件中某处的函数集,以允许用户执行任意代码。搜索这些功能可以帮助您更快地将数万个PHP文件的大海捞变到相对较小的脚本集中,这些脚本需要仔细检查。

显然,例如,以下任何一种都会被视为恶意(或可怕的编码):

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

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

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

等等。

前几天在一个被入侵的网站上搜索,我没有注意到一段恶意代码,因为我没有意识到使用preg_replace标志可能会使/e变得危险{(1}} em>哪个,认真?为什么即使那样?)。还有其他我错过的吗?

到目前为止,这是我的清单:

Shell执行

  • system
  • exec
  • popen
  • backtick operator
  • pcntl_exec

PHP执行

  • eval
  • preg_replace(使用/e修饰符)
  • create_function
  • include [_once] / require [_once](请参阅马里奥的回答了解漏洞利用详情)

拥有一个能够修改文件的函数列表可能也很有用,但我想99%的时间漏洞利用代码将包含至少一个上述函数。但是如果你有一个能够编辑或输出文件的所有功能的列表,请发布它,我会在这里包含它。 (我不算mysql_execute,因为那是另一类利用的一部分。)

23 个答案:

答案 0 :(得分:205)

要构建此列表,我使用了2个来源。 A Study In ScarletRATS。我还添加了一些我自己的东西,这个帖子的人都帮了忙。

编辑:在发布此列表后,我联系了RIPS的创始人,截至目前,此工具会搜索PHP代码,以便使用此列表中的每个功能。

大多数这些函数调用都归类为接收器。当一个受污染的变量(如$ _REQUEST)传递给接收器函数时,您就有了一个漏洞。像RATSRIPS这样的程序使用类似grep的功能来识别应用程序中的所有接收器。这意味着程序员在使用这些功能时应该格外小心,但如果他们全部被禁止,那么你将无法完成任务。

强大的力量带来了巨大的责任。

- Stan Lee

命令执行

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和{{3}的形式用于远程执行代码漏洞。

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 Disclosurephpinfo()函数。

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中的所有Remote File Include都很讨厌。其中一些对攻击者来说似乎没什么用处。其他人比你想象的更有用。例如,如果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

答案 1 :(得分:59)

您必须扫描包含($ tmp)和require(HTTP_REFERER)和* _once。如果漏洞利用脚本可以写入临时文件,则可以稍后再包含该文件。基本上是一个两步的评估。

甚至可以使用以下方法隐藏远程代码:

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

此外,如果您的网络服务器已被盗用,您将不会总是看到未编码的邪恶。漏洞利用shell通常是gzip编码的。想想include("zlib:script2.png.gz");此处没有评价,效果仍然相同。

答案 2 :(得分:48)

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

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

本着同样的精神,call_user_func_array()可用于执行混淆函数。

答案 3 :(得分:20)

我很惊讶没有人提到echoprint作为安全漏洞。

Cross-Site Scripting (XSS)是一种严重的安全漏洞,因为它比服务器端代码执行漏洞更常见。

答案 4 :(得分:19)

我特别想在这个列表中添加unserialize()。它有各种各样的漏洞,包括任意代码执行,拒绝服务和内存信息泄漏。永远不应该在用户提供的数据上调用它。这些vuls中的许多已经在最后一个露水年份被修复,但在目前的写作时它仍然保留了几个令人讨厌的vuls。

有关狡猾的php函数/用法的其他信息请查看Hardened PHP Project及其建议。还有最近的Month of PHP Security和2007年的Month of PHP Bugs项目

另请注意,通过设计,反序列化对象将导致构造函数和析构函数执行;另一个原因是不在用户提供的数据上调用它。

答案 5 :(得分:17)

我的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%危险。

答案 6 :(得分:15)

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

这些影响函数,如trim(),rtrim(),ltrim(),explode(),strchr(),strstr(),substr(),chunk_split(),strtok(),addcslashes(),str_repeat( ) 和更多。这主要是(但不是唯一的)由于语言的调用时间传递参考功能已被弃用了10年但未被禁用。

更多信息,请参阅Stefan Esser关于BlackHat USA 2009中断漏洞和其他低级PHP问题的讨论Slides Paper

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

答案 7 :(得分:14)

Plattform特定的,但也是理论上的exec载体:

  • dotnet_load()
  • 新COM(“WScript.Shell”)
  • new Java(“java.lang.Runtime”)
  • event_new() - 最终

还有更多的伪装方法:

  • proc_open是popen的别名
  • call_user_func_array(“exE”.chr(99),array(“/ usr / bin / damage”,“ - all”));
  • file_put_contents(“/ cgi-bin / nextinvocation.cgi”)&amp;&amp; CHMOD(...)
  • PharData :: setDefaultStub - 检查.phar文件中的代码还有一些工作
  • runkit_function_rename(“exec”,“innocent_name”)或APD rename_function

答案 8 :(得分:13)

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

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

答案 9 :(得分:10)

尚未提及有趣漏洞的一个来源。 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字符串长度的函数都可能导致某些漏洞。

答案 10 :(得分:9)

危险的句法元素呢?

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

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

答案 11 :(得分:6)

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

  • 如果这里提供了很棒的列表,你可以错过一个可以利用的功能

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

  

$ myEvilRegex = base64_decode('Ly4qL2U =');

     

preg_replace($ myEvilRegex,$ _POST ['code']);

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

  • 但是那时候你可能会有“可能是邪恶的代码”,而这个代码也不在其背景之中

  • 为了(伪)安全,您应该编写好的代码自己阅读所有现有代码

答案 12 :(得分:5)

我知道move_uploaded_file已被提及,但文件上传一般非常危险。 $_FILES的存在应引起一些关注。

很有可能将PHP代码嵌入到任何类型的文件中。图像可能特别容易受到文本注释的影响。如果代码按原样接受在$_FILES数据中找到的扩展名,则问题尤其麻烦。

例如,用户可以将嵌入了PHP代码的有效PNG文件上传为“foo.php”。如果脚本特别天真,它实际上可能将文件复制为“/uploads/foo.php”。如果服务器配置为允许在用户上载目录中执行脚本(通常是这种情况,以及可怕的疏忽),那么您可以立即运行任意PHP代码。 (即使图像保存为.png,也可能通过其他安全漏洞获取代码。)

要检查上传内容的(非详尽的)列表:

  • 确保分析内容以确保上传是其声称的类型
  • 使用无法执行的已知安全文件扩展名保存文件
  • 确保在用户上传目录中禁用PHP(和任何其他代码执行)

答案 13 :(得分:5)

反击操作符Backtick on php manual

答案 14 :(得分:5)

我们将pcntl_signalpcntl_alarm添加到列表中。

借助这些功能,您可以解决在php.ini或脚本中创建的任何set_time_limit限制。

例如,尽管set_time_limit(1);

,此脚本仍将运行10秒

(归功于Sebastian Bergmanns tweetgist

<?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";
}

答案 15 :(得分:4)

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

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

答案 16 :(得分:4)

这些功能也会产生一些令人讨厌的效果。

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

前两个可以耗尽所有可用的内存,而后者则会耗尽......

答案 17 :(得分:2)

最近在security.stackexchange.com

上对此进行了一些讨论
  

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

这样可以缩小范围 - 但是由于'print'可以用于注入javascript(因此窃取会话等),它仍然有点武断。

  

不列出应列入黑名单或以其他方式禁止的功能。相反,我想有一个grep-able列表

这是一种明智的做法。

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

除了明显的那些之外,我建议标记除了字符串文字之外的任何包含参数的东西。注意__autoload()。

答案 18 :(得分:2)

我担心我的回答可能有点过于消极,但是......

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

您最好的选择是从开始到结束跟踪任何可能的用户或远程输入,从$_SERVER$_GET$_POST$_FILE,{{1}开始},$_COOKIE如果 include(some remote file)打开),所有其他函数/类处理远程文件等。您以编程方式构建每个用户的堆栈跟踪配置文件 - 或远程供应的价值。这可以通过获取所分配的变量的所有重复实例以及它所使用的函数或方法以编程方式完成,然后递归地编译这些函数/方法的所有实例的列表,依此类推。检查它以确保它首先通过适当的过滤和验证功能相对于它接触的所有其他功能。这当然是手动检查,否则您将有allow_url_fopen个开关的总数等于PHP中的函数和方法的数量(包括用户定义的)。

或者仅用于处理用户输入,在所有脚本的开头初始化一个静态控制器类,1)验证所有用户提供的输入值并将其存储在允许目的的白名单中; 2)擦除输入源(即case)。你可以看到这里有一点Naziesque。

答案 19 :(得分:1)

以下是我的提供商出于安全目的禁用的功能列表:

  • EXEC
  • DL
  • 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

答案 20 :(得分:1)

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

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

答案 21 :(得分:0)

使用4位发现了几个缓冲区溢出 解释文本的字符函数。 ヶ辆() 用htmlspecialchars()

处于最顶端,一个很好的防守就是使用 mb_convert_encoding()转换为单个 解释前的编码。

答案 22 :(得分:0)

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