命令执行是web攻击中常用的手法之一,在PHP中,可调用以下函数来实现命令执行,如
exec函数用的较少,主要是因为该函数默认返回值是执行结果的最后一行,并不会有全部的执行结果。如果要打印执行结果,需遍历打印output数组,
string exec ( string command, array &output, int &return_var) //command参数是要执行的命令 //output数组是保存输出结果 //return_var整形用来保存命令执行后的状态码,0代表执行成功,1代表执行失败
<?php $command = 'ls /'; $ret=exec($command,$output,$a); #默认只返回第一行结果 echo "第一行结果:".$ret,PHP_EOL,PHP_EOL; #打印出执行状态码 echo "Status: ",$a,PHP_EOL,PHP_EOL; #数组的长度 $length=count($output); for($i=0;$i<$length;$i++){ echo $output[$i]; echo PHP_EOL; } ?>
可得如下结果,
shell_exec可以字符串的形式,返回所有结果,使用方便,较为常见
shell_exec(string $cmd): string // cmd 要执行的命令 // 返回结果string
<?php $cmd = "ls /"; $output = passthru($cmd); echo $output,PHP_EOL; ?>
返回结果如下,
system 和exec 类似,返回执行的结果的最后一行,且将执行结果回显到标准输出中
system(string command , int & return_var) //command参数是要执行的命令, //return_var参数存放返回的值,可不写该参数
<?php $cmd = 'ls /'; $output = system($cmd,$resCode); echo $resCode == 0 ? '执行成功!':'执行失败',PHP_EOL,PHP_EOL; echo $output; ?>
返回结果如下,
4、`$command`
php 执行运算符,也就是数字键1前面的反引号,可见PHP官方文档,PHP 支持一个执行运算符:反引号(``)。注意这不是单引号!PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符“`”的效果与函数 shell_exec() 相同。
<?php $cmd = "ls /"; echo `$cmd`,PHP_EOL; ?>
同 exec() 函数类似, passthru() 函数 也是用来执行外部命令(command
)的。 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数。 常用来执行诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置 Content-type 为 image/gif
, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚本中直接输出图像到浏览器。
passthru(string $command, int &$return_var = ?): void // command 为执行的命令 // 状态码
同system、exec 类似,将输入输出到了标准输出
popen ( string command, string mode ) //打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。 //返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写 //)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。
<?php $command='ls /'; $fd = popen($command, 'r'); while($s=fgets($fd)){ print_r($s); } ?>
proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力。
proc_open( mixed $cmd, array $descriptorspec, array &$pipes, string $cwd = null, array $env = null, array $other_options = null ): resource
proc_open 用法稍显复杂,通常其他函数被过滤时,可以考虑使用此函数
<?php $command = 'ls /'; $descriptorspec=array( 0=>array('pipe','r'), 1=>array('pipe','w'), 2=>array('pipe','w') ); $handle=proc_open($command,$descriptorspec,$pipes,NULL); if(!is_resource($handle)){ die('proc_open failed'); } while($s=fgets($pipes[1])){ print_r($s); } while($s=fgets($pipes[2])){ print_r($s); } fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($handle); ?>