可利用的PHP功能

tyl*_*erl 277 php security grep

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

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

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

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

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

<? preg_replace('/.*/e',$_POST['code']); ?>
Run Code Online (Sandbox Code Playgroud)

等等.

前几天通过一个被入侵的网站进行搜索,我没有注意到一段恶意代码,因为我没有意识到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,因为那是另一类漏洞利用的一部分.)

roo*_*ook 205

为了构建这个列表,我使用了两个来源. 血色大鼠研究.我已经添加了一些我自己的混合,这个线程的人已经帮助了.

编辑:发布此列表后,我联系了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
Run Code Online (Sandbox Code Playgroud)

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());
Run Code Online (Sandbox Code Playgroud)

接受回调的函数列表

这些函数接受一个字符串参数,该参数可用于调用攻击者选择的函数.根据功能,攻击者可能会或可能不会传递参数.在这种情况下,可以使用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,
Run Code Online (Sandbox Code Playgroud)

信息披露

大多数这些函数调用都不是接收器.但是,如果返回的任何数据可供攻击者查看,则可能是漏洞.如果攻击者可以看到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
Run Code Online (Sandbox Code Playgroud)

其他

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
Run Code Online (Sandbox Code Playgroud)

文件系统功能

根据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
Run Code Online (Sandbox Code Playgroud)

  • @whatnick实际上我没有看到PHP和其他Web应用程序语言之间存在明显差异.在一天结束时,程序员需要能够"eval()"代码,执行系统命令,访问数据库以及读取/写入文件.此代码可能受到攻击者的影响,这是一个漏洞. (37认同)
  • 这么多功能被禁止了!您是否有机会主持我的网站? (8认同)
  • Imho`preg_match`与`e`没有害处.手册说"只有preg_replace()使用此修饰符;其他PCRE函数会忽略它." (3认同)
  • @Andrew Dunn哈哈,没有.如果你禁止所有这些功能,那么PHP应用程序就不会起作用.特别是include(),require()和文件系统功能. (2认同)
  • @Rook:我的想法确切但是这些是潜在的问题,而不是确定的问题.如果使用得当,这些都不构成直接威胁; 但如果他们可以避免他们应该. (2认同)

mar*_*rio 59

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

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

 include("data:text/plain;base64,$_GET[code]");
Run Code Online (Sandbox Code Playgroud)

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

  • `include`不需要括号; "包括"......""就够了. (2认同)

Ail*_*lyn 48

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

$y = str_replace('z', 'e', 'zxzc');
$y("malicious code");
Run Code Online (Sandbox Code Playgroud)

本着同样的精神,call_user_func_array()可以用来执行混淆功能.

  • @tylerl:......还是其他任何语言? (15认同)
  • @Wallacoloo:隐藏编译语言CGI后门更加容易,因为在二进制文件中没有简单的文本字符串. (3认同)
  • 很好..我试过$ f ='ev'.'al'; $ F($ _ POST [ 'C']); 但没有工作,因为'eval'不是一个函数,而是一个特殊的构造,如include,echo等 - >有趣的是exec()不是,所以这将工作.. (2认同)

Bil*_*win 20

我很惊讶没有人提到过echo,也没有提到print安全问题.

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


Che*_*oft 19

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

有关狡猾的PHP函数/用法的其他信息,请查看Hardened PHP Project及其建议.最近的PHP安全月和2007 月的PHP Bug项目

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


Jos*_*osh 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
Run Code Online (Sandbox Code Playgroud)

PHP有足够的潜在可破坏功能,你的列表可能太大而无法使用.例如,PHP具有chmod和chown,可用于简单地停用网站.

编辑:也许你可能想要构建一个bash脚本来搜索一个文件,用于按危险分组的函数数组(函数是坏函数,函数更糟,函数永远不应该使用),然后计算危险的相对性该文件强加给一个百分比.然后将其输出到目录树中,并在每个文件旁边标记百分比,如果大于阈值,例如30%危险.


Che*_*oft 15

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

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

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

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


mar*_*rio 14

Plattform特定的,但也是理论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 rename_function


Nik*_*kiC 13

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

assert('ex' . 'ec("kill --bill")');
Run Code Online (Sandbox Code Playgroud)


mvd*_*vds 10

尚未提及有趣漏洞的一个来源.PHP允许字符串中包含0x00字节.底层(libc)函数将此视为字符串的结尾.

这允许PHP中的(执行不当)健全性检查被欺骗的情况,例如在以下情况中:

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

这可能包括任何文件 - 而不仅仅是那些.php通过调用结束的文件script.php?file=somefile%00.php

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


L̲̳*_*̲̳̳ 9

危险的句法元素呢?

" 变量变量 "($$var)将在当前范围内通过$ var的名称查找变量.如果使用错误,远程用户可以修改或读取当前范围中的任何变量.基本上较弱eval.

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

  • 您还可以使用在不评估脚本的情况下无法计算的变量函数.例如:`$ innocentFunc ='exec'; $ innocentFunc('activate skynet');`. (6认同)

And*_*den 6

我想你将无法通过解析源文件找到所有可能的漏洞.

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

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

$ myEvilRegex = base64_decode('Ly4qL2U =');

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

  • 你现在可以说,我只是扩展我的脚本也匹配这个

  • 但是那时候你可能会有"可能是邪恶的代码",这也是它的背景

  • 所以要(伪)安全,你应该真正编写好的代码并自己阅读所有现有的代码


Mat*_*hew 5

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

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

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

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

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


edo*_*ian 5

让我们增加pcntl_signalpcntl_alarm到列表中.

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

例如,这个脚本将运行10秒钟,尽管如此 set_time_limit(1);

(归功于Sebastian Bergmanns的推文要点:

<?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";
}
Run Code Online (Sandbox Code Playgroud)