可利用的PHP函数


277

我正在尝试建立可用于任意代码执行的功能列表。目的不是列出应列入黑名单或以其他方式不允许的功能。而是,当在受感染的服务器中搜索后门时,我希望有一个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](有关漏洞利用程序的详细信息,请参阅mario的答案

列出能够修改文件的功能可能也很有用,但是我想99%的利用代码中至少会包含上述功能之一。但是,如果您具有能够编辑或输出文件的所有功能的列表,请将其发布,并将在此处包括在内。(而且我不算mysql_execute,因为这是另一类漏洞利用的一部分。)


43
作为旁注,我希望看到该列表在不久的将来发布:)
yoda 2010年

16
@yoda:发表在哪里?我将在此处更新列表,因为SO是所有知识的来源。
tylerl

3
什么是/e修改怎么办?
Billy ONeal 2010年

6
@Billy:e修饰符使替换字符串被评估为PHP代码。
nikc.org 2010年

1
必须说:在regex中执行代码是Perl和Python可能要做的事情,而不是PHP独有的事情。不过,我不知道细节。
阿德里亚诺瓦里

Answers:


205

为了构建此列表,我使用了2个资源。 猩红RATS研究。我还添加了一些我自己的东西,这个线程上的人也提供了帮助。

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

这些函数调用大多数都归为接收器。将受污染的变量(如$ _REQUEST)传递给接收器函数时,您将遇到漏洞。像RATSRIPS之类的程序使用类似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

37
@whatnick实际上,我看不到PHP与其他Web应用程序语言之间的明显区别。最终,程序员需要具备eval()编码能力,执行系统命令,访问数据库以及读/写文件的能力。该代码可能会受到攻击者的影响,这是一个漏洞。
rook 2010年

8
禁止了这么多功能!您是我网站的托管人吗?
兰迪开发人员

2
@安德鲁·邓恩哈哈,不。如果禁止所有这些功能,那么没有PHP应用程序可以正常工作。特别是include(),require()和文件系统功能。
rook 2010年

2
@Rook:我的想法完全正确,但是这些是针对潜在问题的,而不是确切的。如果使用正确,这些都不会对立即构成威胁。但是如果可以避免的话,应该这样做。
Geekster 2010年

3
恕我直言,preg_matche没有危害。手册说:“只有preg_replace()使用此修饰符;其他PCRE函数将忽略它。”
NikiC

59

您必须扫描include($ tmp)和require(HTTP_REFERER)和* _once。如果漏洞利用脚本可以写入临时文件,则可以稍后将其包括在内。基本上分为两步。

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

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

另外,如果您的网络服务器已经受到威胁,您将不会总是看到未编码的恶意。漏洞利用外壳通常是gzip编码的。想想include("zlib:script2.png.gz");这里没有评估,还是一样的效果。


1
根据PHP的配置方式,include实际上可以包含来自任意URL的代码。诸如“ example.com/code.phps ”之类的东西;我看到了一个被入侵的网站,该网站已被分解为使用该功能和register_globals的组合。
BlackAura 2010年

@BlackAura regiser_globals如何适应攻击?是否可以通过使用$_GET[xyz]相反的方法轻松完成$xyz?还是有更深层次的东西?
tylerl 2010年

我不太确定为什么要这样做,但是该网站一直在做这样的事情:include($ prefix。'/filename.php'); 我认为,您可以通过在配置文件中设置$ prefix变量将核心代码移到Web根目录之外。如果攻击者将该值设置为“ example.com/code.phps?”之类的内容,PHP将改为包含该远程文件。据我所知,“机器人”实际上使用通用漏洞成功闯入。显然,许多旧的PHP代码都犯了这个错误。基本上,从不让任何用户提交的值包含在include语句附近。
BlackAura 2010年

我认为您可以将其概括为包括文件名中包含“:”的内容...,只是文件名可能是变量,因此很难做到grep。PHP-真是一场灾难。
tylerl

2
include不需要括号;include "…"足够了。
Gumbo 2010年

48

这本身不是一个答案,但是有一些有趣的东西:

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

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


1
而且也没有办法找到这个不执行的代码:(静态分析不会在这里帮助。
NikiC

15
@tylerl:...或其他任何语言?
汉尼拔·莱克特博士2010年

@dr Hannibal Lector:甚至是编译语言?
Ponkadoodle

3
@Wallacoloo:隐藏编译后的CGI后门甚至更容易,因为二进制文件中没有简单的grep文本字符串。
Iiridayn

2
很好..我尝试用$ f ='ev'。'al'; $ f($ _ POST ['c']); 但没有奏效,因为“EVAL”不是功能,而是一种特殊的结构像包括,回声等- >有趣的是,执行exec()不和所以这将工作..
redShadow

20

我很惊讶没有人提到echo,并print为安全开采点。

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


从技术上讲,这将是一个影响客户端而不是服务器的媒介。
damianb 2012年

@damianb:如果站点使用Ajax,并且我可以导致在任何用户的会话中对任意javascript进行评估,则可能在服务器上造成很多麻烦。
Bill Karwin 2012年

“在服务器上” ..至连接的客户端;它不会影响服务器后端。这属于客户端漏洞,例如游标劫持,CSRF,标头注入等。是的,这很危险,但是完全属于另一个分类。
damianb'3

19

我特别想将unserialize()添加到此列表。它具有各种漏洞的悠久历史,包括任意代码执行,拒绝服务和内存信息泄漏。切勿在用户提供的数据上调用它。在过去的露水年中,其中许多漏洞已被修复,但在撰写本文时,它仍保留了一些讨厌的漏洞。

有关狡猾的php函数/用法的其他信息,请查看Hardened PHP Project及其咨询。也是最近的PHP安全月和2007个月的PHP Bug项目

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


我有兴趣了解有关反序列化问题的更多信息。这仅仅是实现中的错误,还是设计中的缺陷(即无法修复)?您能否特别指出有关该问题的更多信息?
tylerl 2010年

有关任意代码执行和内存信息泄漏的信息,请参阅Stefan在php-security.org/2010/06/25/…上
Cheekysoft 2010年


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具有足够的潜在可破坏功能,您的列表可能太大而无法grep。例如,PHP具有chmod和chown,可用于简单地停用网站。

编辑:也许您可能想要构建一个bash脚本,该脚本在文件中搜索按危险分组的功能数组(不好的功能,糟糕的功能,永远不应该使用的功能),然后计算危险的相对性该文件的百分比。然后将其输出到目录树中,每个文件旁边都标有百分比,如果大于30%的危险阈值。


您可以在编译时设置“ --disable-posix”标志,并从disable_functions中删除所有这些posix函数。
Pixel Developer

15

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

这些会影响功能,例如trim(),rtrim(),ltrim(),explode(),strchr(),strstr(),substr(),chunk_split(),strtok(),addcslashes(),str_repeat()等。这在很大程度上但并非唯一地归因于该语言的呼叫时间传递引用功能已被弃用10年,但并未禁用。

富勒更多信息,请参阅斯特凡埃塞尔的在黑帽子美国2009年谈中断的脆弱性和其他低级别的PHP问题幻灯片

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


1
哎哟。好吧,在查看幻灯片之前,我真的认为PHP有​​点安全...
NikiC 2010年

14

特定于平台的,但也是理论的exec向量:

  • dotnet_load()
  • 新的COM(“ WScript.Shell”)
  • 新的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”)&& chmod(...)
  • PharData :: setDefaultStub-检查.phar文件中的代码的更多工作
  • runkit_function_rename(“ exec”,“ innocent_name”)或APD named_function

在第二个列表中也是call_user_func()
Cheekysoft

1
一个答案就足够了;)您只需将其添加到上一个答案即可。
贾斯汀·约翰逊

13

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

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

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字符串长度的函数都可能导致某些漏洞。


在5.4和最新的5.3版本中,将不再允许使用空文件路径。
StasM 2011年

@stasM这是我一段时间以来听说过的关于PHP的最好的事情之一。感谢分享。
威廉

9

危险的语法元素呢?

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

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


我明白您的意思,但这看起来像是另一类漏洞利用。有没有一种方法可以使用这种机制执行任意PHP代码(不使用上述任何函数)?还是只能滥用它来更改变量内容?如果我缺少什么,我想做对。
tylerl 2010年

6
您还可以使用变量函数,这些函数如果不评估脚本就无法解决。例如:$innocentFunc = 'exec'; $innocentFunc('activate skynet');
erisco 2010年

也要注意反射。
erisco 2010年

6

我想您将无法通过解析源文件来真正找到所有可能的利用。

  • 如果这里提供的列表确实很棒,那么您可能会错过一个可以被利用的功能

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

$ myEvilRegex = base64_decode('Ly4qL2U =');

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

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

  • 但随后您将拥有该mayn的“可能是邪恶的代码”,另外它不在上下文中

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


我已经看到base64_decode()在基于Wordpress的恶意软件中经常用于邪恶。很好的列表。
克里斯·艾伦·莱恩


5

我知道move_uploaded_file有人提到过,但是一般来说文件上传是非常危险的。只是存在$_FILES应该引起一些关注。

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

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

上传内容检查清单(非详尽清单):

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

5

让我们增加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";
}

4

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

PHP还允许通过在变量名的末尾添加()来调用变量函数,例如,$myvariable();将调用由变量指定的函数名。这是可利用的;例如,如果攻击者可以使变量包含单词“ eval”并可以控制参数,那么即使程序实际上不包含eval()函数,他也可以执行他想要的任何操作。


4

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

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

前两个可以耗尽所有可用的内存,而后者则使耗尽继续进行...


2

最近在security.stackexchange.com上对此进行了一些讨论

可用于任意代码执行的功能

嗯,这稍微减小了范围-但由于“打印”可用于注入javascript(并因此窃取会话等),因此仍然有些武断。

不是列出应列入黑名单或以其他方式不允许的功能。而是,我想有一个可重复的列表

这是一个明智的方法。

不过,请考虑考虑编写自己的解析器-很快您将发现一种基于grep的方法失去控制(awk会更好一些)。很快,您还将开始希望您也实施了白名单!

除了显而易见的建议之外,我建议您使用字符串字面量以外的其他参数标记包含在内的所有内容。还要注意__autoload()。


2

我担心我的回答可能有点否定,但是...

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

最好的办法是将跟踪从开始到结束的所有可能的用户或远程输入,开始$_SERVER$_GET$_POST$_FILE$_COOKIEinclude(some remote file)如果 allow_url_fopen是),其它所有功能/类处理远程文件,等你编程构建一个堆栈跟踪简介每个用户或远程提供的值。这可以通过编程来实现,方法是获取所使用的已分配变量和函数或方法的所有重复实例,然后递归编译这些函数/方法的所有出现的列表,依此类推。检查它以确保它首先经过相对于其接触的所有其他功能的正确过滤和验证功能。当然,这是手动检查,否则您的总数为case 开关等于PHP中函数和方法的数量(包括用户定义的数量)。

或者,仅处理用户输入,请在所有脚本的开头初始化静态控制器类,该类如下:1)根据允许的目的白名单验证并存储所有用户提供的输入值;2)擦除该输入源(即$_SERVER = null)。您会看到它在哪里有点Naziesque。


是的,当然,与许多编程语言一样,隐藏邪恶行为的方法是没有止境的。但是我认为这没有我要问的意图。这种情况是这样的:网站被黑客入侵后,您会被要求提供帮助。如果您可以在早晨之前保护其网站,则客户将支付额外的费用。该站点包含475个PHP文件,有用的取证细节已被破坏-您有一个巨大的干草堆和一个臭名昭著的小针头...您从哪里开始寻找?(简而言之,我的日常工作)
tylerl 2011年

1

这是我的提供者出于安全目的禁用的功能列表:

  • 执行
  • dl
  • show_source
  • apache_note
  • apache_setenv
  • 关闭日志
  • debugger_off
  • debugger_on
  • define_syslog_variables
  • Escapeshellarg
  • escapeshellcmd
  • ini_restore
  • 开放日志
  • 直通
  • 关闭
  • pcntl_exec
  • en
  • proc_close
  • proc_get_status
  • proc_nice
  • proc_open
  • proc_terminate
  • shell_exec
  • 系统日志
  • 系统
  • url_exec

1

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

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


0

使用解释文本的4位字符功能发现了几个缓冲区溢出。htmlentities()htmlspecialchars()

在顶部,一个好的防御方法是在解释之前使用mb_convert_encoding()转换为单一编码。


0

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


RIPS正在使用此页面上的列表。
rook 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.