可开发的PHP函数
我试图build立一个可以用于任意代码执行的函数列表。 目的不是列出应被列入黑名单或不允许的function。 相反,我希望在search受感染的服务器后门时,可以方便地使用可用的红旗标记关键字列表。
这个想法是,如果你想构build一个多用途的恶意PHP脚本 – 比如像c99或r57这样的“web shell”脚本,你将不得不使用一个或者多个相对较小的一组函数在文件某处为了让用户执行任意代码。 search这些函数可以帮助您更快地将数以万计的PHP文件的大堆缩小到需要仔细检查的相对较小的脚本集。
很明显,例如,以下任何一种都被认为是恶意的(或可怕的编码):
<? eval($_GET['cmd']); ?> <? system($_GET['cmd']); ?> <? preg_replace('/.*/e',$_POST['code']); ?>
等等。
有一天我search了一个受到攻击的网站,但是我没有注意到一个恶意代码,因为我没有意识到preg_replace
可能会被/e
标志使用( 这是严重的,为什么在那里 ? 。 还有其他的我错过了吗?
这是我的列表到目前为止:
shell执行
-
system
-
exec
-
popen
-
backtick operator
-
pcntl_exec
PHP执行
-
eval
-
preg_replace
(带/e
修饰符) -
create_function
-
include
[_once
] /require
[_once
]( 请参阅mario的漏洞利用细节的答案 )
有一个能够修改文件的函数列表也许是有用的,但我想99%的时间利用代码将至less包含上述function之一。 但是如果你有一个能够编辑或输出文件的所有function的列表,发布它,我会在这里包括它。 (而且我不计算mysql_execute
,因为这是另一类漏洞利用的一部分。)
为了build立这个清单,我使用了2个来源。 大猩猩与RATS研究 。 我也添加了一些我自己的组合,并在这个线程的人已经帮了大忙。
编辑:发布这个列表后,我联系了RIPS的创始人,截至目前,这个工具searchPHP代码,使用这个列表中的每个函数。
这些函数调用大部分被分类为宿。 当一个受污染的variables(如$ _REQUEST)被传递给一个接收函数时,那么你就有一个漏洞。 RATS和RIPS等程序使用类似grep的function来识别应用程序中的所有接收器。 这意味着程序员在使用这些函数的时候应该格外小心,但是如果它们全部被禁止的话,那么你就不能完成任务了。
“ 有了大权,责任重大。 ”
– 李静
命令执行
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
可以以本地文件包含和远程文件包含漏洞的forms用于远程代码执行。
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());
接受callback的函数列表
这些函数接受一个string参数,可以用来调用攻击者select的函数。 攻击者可能或可能不具备传递参数的function,具体取决于function。 在这种情况下,可以使用像phpinfo()
这样的Information Disclosure
function。
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
文件系统function
根据RATS在php中的所有文件系统function是讨厌的。 其中有些对攻击者来说似乎不是很有用。 其他人比你想象的更有用。 例如,如果allow_url_fopen=On
那么url可以用作文件path,所以调用copy($_GET['s'], $_GET['d']);
可以用来上传系统上任何位置的PHP脚本。 另外,如果一个站点容易受到通过GET发送的请求,那么这些文件系统的所有function都可能被滥用,从而通过您的服务器对其他主机进行通道和攻击。
// 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
你必须扫描include($ tmp),并且需要(HTTP_REFERER)和* _once。 如果一个漏洞利用脚本可以写入一个临时文件,那么以后就可以包含这个文件。 基本上是一个两步评估。
甚至可以隐藏远程代码,例如:
include("data:text/plain;base64,$_GET[code]");
另外,如果你的networking服务器已经被破坏,你不会总是看到未经编码的恶意。 攻击shell通常是gzip编码的。 想想include("zlib:script2.png.gz");
这里没有评价,效果还是一样的。
这本身并不是一个答案,但是这里有一些有趣的东西:
$y = str_replace('z', 'e', 'zxzc'); $y("malicious code");
同样的道理, call_user_func_array()
可以用来执行混淆函数。
我很惊讶没有人提到echo
和print
作为安全开发的要点。
跨站点脚本(XSS)是一个严重的安全漏洞,因为它比服务器端代码执行漏洞更为常见。
我特别想要添加unserialize()到这个列表。 它存在各种漏洞,包括任意代码执行,拒绝服务和内存信息泄漏等。 不应该在用户提供的数据上调用它。 许多这样的诉求已经在最近的露水年份里得到了解决,但是在写作的时候仍然保留着一些讨厌的诉讼。
有关狡猾PHPfunction/使用情况的其他信息,请查看Hardened PHP项目及其build议。 另外还有最近的PHP安全月和2007年的PHP Bugs项目月
另请注意,通过devise,反序列化对象将导致构造函数和析构函数执行; 另一个不用用户提供的数据来调用它的原因。
我的VPS设置为禁用以下function:
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,可以用来简单地停用一个网站。
编辑:也许你可能要build立一个bash脚本,search文件的危险分组函数(function是坏的,更糟糕的function,应该永远不会使用),然后计算相对危险该文件强加到一个百分比。 然后输出这个目录的树,每个文件旁边标记的百分比,如果大于说的阈值,30%的危险。
另外请注意,允许读取和写入任意内存位置的“中断漏洞”类别!
这些影响trim(),rtrim(),ltrim(),explode(),strchr(),strstr(),substr(),chunk_split(),strtok(),addcslashes(),str_repeat()等函数。 这在很大程度上,但不是唯一的,因为已经被使用了10年但没有被禁用的语言的通话时间传递参考function。
有关更多信息,请参阅Stefan Esser在BlackHat USA 2009上关于中断漏洞和其他较低级PHP问题的讨论。
本文/演示文稿还显示了如何使用dl()来执行任意系统代码。
Plattform特定的,但也是理论上的执行vector:
- 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
除了eval
语言结构之外,还有另外一个允许任意代码执行的函数: assert
assert('ex' . 'ec("kill --bill")');
没有提到有趣的攻击来源之一。 PHP允许string在其中有0x00
字节。 底层(libc)函数将此视为string的结尾。
这允许在PHP中可能愚弄实施(执行不佳)的理智检查的情况下,例如在以下情况下:
/// note: proof of principle code, don't use $include = $_GET['file']; if ( preg_match("/\\.php$/",$include) ) include($include);
这可能包括任何文件 – 不只是以.php
结尾的.php
– 通过调用script.php?file=somefile%00.php
所以任何不遵守PHPstring长度的函数都可能导致一些漏洞。
危险的语法元素呢?
“ variablesvariables ”( $$var
)将通过$ var的名称在当前范围中find一个variables。 如果使用错误,远程用户可以修改或读取当前范围内的任何variables。 基本上是一个较弱的eval
。
例如:你写了一些代码$$uservar = 1;
,那么远程用户将$uservar
设置$uservar
“admin”,导致$admin
在当前范围内被设置为1
。
我想你将无法通过parsing源文件来真正find所有可能的漏洞。
-
如果在这里提供了真正伟大的列表,你可能会错过一个可以被利用的function
-
仍然可能有这样的“隐藏”邪恶的代码
$ myEvilRegex = base64_decode('Ly4qL2U =');
preg_replace($ myEvilRegex,$ _POST ['code']);
-
你现在可以说,我只是扩展我的脚本,以配合这一点
-
但是那么你将会有那个可能的“可能是邪恶的代码”,而这些代码还不在其背景下
-
所以要(伪)安全的,你应该写出好的代码,并且自己读取所有的代码
反手操作员反向PHP手册
我知道move_uploaded_file
已经被提到,但是file upload通常是非常危险的。 只要$_FILES
的存在应该引起一些关注。
将PHP代码embedded到任何types的文件中是很有可能的。 图片可能特别容易受到文字评论的影响。 如果代码原样接受在$_FILES
数据中find的扩展,这个问题特别麻烦。
例如,用户可以将embedded的PHP代码的有效PNGfile upload为“foo.php”。 如果脚本特别幼稚,可能实际上将文件复制为“/uploads/foo.php”。 如果服务器configuration为允许在用户上传目录中执行脚本(通常是这种情况,还有一个可怕的疏忽),那么你可以立即运行任意的PHP代码。 (即使图像保存为.png,也可能通过其他安全漏洞获取代码)。
一个(非详尽的)要检查上传的东西列表:
- 确保分析内容,以确保上传是它声称的types
- 用一个永远不会执行的已知的,安全的文件扩展名保存文件
- 确保PHP(和任何其他代码执行)在用户上传目录中被禁用
让我们将pcntl_signal
和pcntl_alarm
添加到列表中。
在这些函数的帮助下,您可以解决在php.ini或脚本中创build的set_time_limit限制。
例如,这个脚本将运行10秒,尽pipeset_time_limit(1);
(信贷塞巴斯蒂安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"; }
有许多PHP漏洞可以通过PHP.ini文件中的设置来禁用。 很明显的例子是register_globals,但是根据设置,也可能通过HTTP包含或打开远程机器上的文件,如果程序使用include()或文件处理函数的variables文件名,可以利用这些文件。
PHP还允许通过在variables名称的末尾添加()来实现variables函数调用 – 例如$myvariable();
将调用variables指定的函数名称。 这是可以利用的; 例如,如果攻击者可以让variables包含单词“eval”,并且可以控制参数,那么即使程序实际上并不包含eval()函数,他也可以做任何他想做的事情。
这些function也可能有一些讨厌的影响。
-
str_repeat()
-
unserialize()
-
register_tick_function()
-
register_shutdown_function()
前两个可以耗尽所有可用的内存,后者保持耗尽…
最近有一些关于security.stackexchange.com的讨论
可以用于任意代码执行的函数
那么缩小范围有点 – 但因为“打印”可以用来注入JavaScript(因此窃取会话等),它仍然有点武断。
不是要列出应被列入黑名单或不允许的function。 相反,我想有一个可以清单的列表
这是一个明智的做法。
尽pipe考虑编写自己的parsing器 – 很快你会发现一个基于grep的方法失控(awk会好一点)。 很快,你也会开始希望你也实施了白名单!
除了显而易见的,除了string文字以外,我build议标记任何包含任何其他参数的东西。 小心__autoload()。
我担心我的答案可能有点过于消极,但是…
恕我直言,每一个function和方法都可以用于恶意目的。 把它看作是恶意的涓滴效应:variables被赋值给用户或远程input,variables用于函数中,函数返回值用于类属性,用于文件函数的类属性,等等。 请记住:伪造的IP地址或中间人攻击可能会利用您的整个网站。
最好的办法是从头到尾跟踪任何可能的用户或远程input,从$_SERVER
, $_GET
, $_POST
, $_FILE
, $_COOKIE
, include(some remote file)
( 如果 allow_url_fopen
打开),所有其他函数/处理远程文件的类等。您可以编程方式为每个用户或远程提供的值构build一个堆栈跟踪configuration文件。 这可以通过编程方式完成指定variables的所有重复实例以及所使用的函数或方法的重复实例,然后recursion编译这些函数/方法的所有出现的列表等等。 检查它,以确保它首先通过适当的筛选和validationfunction相对于其所触及的所有其他function。 这当然是一个手动检查,否则你将有大量的case
开关等于PHP中函数和方法的数量(包括用户定义的)。
或者仅处理用户input,在所有脚本的开始处都有一个静态控制器类,它们被初始化:1)validation所有用户提供的input值并将其存储在允许用途的白名单中; 2)input源的抹布(即$_SERVER = null
)。 你可以看到这里有点纳粹式的。
以下是我的提供程序出于安全目的禁用的function列表:
- 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
代码中的大多数攻击都使用多个访问源,或多个步骤来执行自己。 我不仅要search代码或具有恶意代码的方法,还要search执行或调用它的所有方法。 最好的安全性还包括编码和validation表单数据进出。
同时注意定义系统variables,之后可以从代码中的任何函数或方法调用它们。
使用4位字符函数来解释文本,发现了几个缓冲区溢出。 htmlentities()htmlspecialchars()
在顶端,一个很好的防御就是在解释之前使用mb_convert_encoding()转换为单一编码。
您可以在RIPS /config/sinks.php中find一个不断更新的敏感接收器列表(可利用的php函数)及其参数,这是PHP应用程序中的漏洞的静态源代码分析器,它也检测PHP后门程序。