本文最后更新于:2019 , 八月 19日 星期一, 8:51 晚上
简介
PHP中,我们可以对输入进行注入攻击,命令注入也称命令执行注入
:通过利用无验证码变量构造特殊语句对服务器进行渗透
命令执行:可以执行系统或应用指令的漏洞(例如:CMD命令或bash命令)
而该漏洞的产生主要是基于一些函数的过滤不严导致
执行函数
system()
执行外部程序,并且显示输出
system($command[,int &$return_ar]); /* command:要执行的命令 return_var:外部命令执行后的返回状态会设置到此变量中 */
执行系统外部命令时,直接将结果输出到浏览器
执行成功:true,失败:false
exec()
主要用于执行外部程序
exec($command [, array &$output [, int &$return_var ]] ); /* command:要执行的命令 output:命令执行的输出填充此数组,每行没输出填充数组的一个元素 数组中的数据不包含行尾的空白字符 Ps:如果数组中已经包含部分元素,会在数组末尾追加内容 如果你不想在数组末尾进行追加,在使用之前对数组进行重置(unset) return_var:命令执行后的返回状态会被写入到此变量 */ # 例子 $command = "ls"; exec($command,$array); print_r($array); // Linux中执行:php ./exec.php
shell_exec()
通过shell环境执行命令,并且将完整的输出以字符串的方式返回
shell_exec($cmd); // 如果执行过程中发生错误或者进程不产生输出,则返回NULL
passthru()
执行外部程序并且显示原始输出
passthru($command[,int &$return_var]); /* command:要执行的命令 return_var:返回状态会被写入到此变量 */
当所执行的Unix命令输出二进制数据,并且需要直接传输到浏览器时,就需要用到此函数
pcntl_exec()
在当前进程空间执行指定程序
pcntl_exec($path[,$args[,$envs]]); /* path:必须是可执行程序路径 或 一个在文件第一行指定一个可执行文件路径标头的脚本 例如第一行:#!/usr/local/bin/perl args(array):要传递给程序的参数的字符串数组 envs(array):要传递给程序作为环境变量的字符串数组 数组格式:key=>value key:传递的环境变量的名称 value:环境变量值 */
popen()
打开进程文件指针
popen(command,mode); /* command:要执行的命令 mode:连接模式 r:只读 w:只写(打开并清空或创建一个新文件) */ # 例子 popen('whoami >> D:/2.txt','r');
proc_open()
执行一个命令,并且打开用来输入/输出的文件指针
proc_open($cmd, array $descriptorspec,array &$pipes[,string $cwd[,array $env [,array $other_options]]]); /* cmd:要执行的命令 descriptorspec:一个索引数组 数组的键表示描述符 数组元素值表示PHP如何将这些描述传至子进程 0 标准输入 1 标准输出 2 标准错误 pipes:将被置为索引数组,其中的元素是被执行程序创建的管道对应到PHP这一端的文件指针 cwd:要执行命令的初始工作目录,必须是绝对路径,设置为NULL表示使用默认值(当前目录) env:要执行的命令所使用的环境变量 other_options:指定一些附加选项 suppress_errors(winds平台):True,抑制本函数产生的错误 bypass_shell(win平台):True,绕过cmd.xex shell */
另外反引号(`)也是可以执行命令,不过实际上这种方式也是调用的shell_exec()函数
echo `whoami`; // 在后面调用shell_exec()函数实现的
简易复现
这是自己手写的超级难看的靶场了吧
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>命令执行</title>
</head>
<body>
<form action="cmd.php" method="POST">
Ping:<input type="text" name="cmd">
<input type="submit" value="执行" name="run">
</form>
</body>
</html>
<?php
if(isset($_POST['run'])){
$cmd = $_POST['cmd'];
if(trim($cmd)){
$run = 'ping ' . $cmd;
echo "<pre>".iconv('GB2312','UTF-8',shell_exec($run))."</pre>";
}else{
echo "IP Error";
}
}
?>
本意:这只是用来检测网址的连通情况
然而,发现我们可以使用一些其他符号进行绕过,执行其他的命令
例如:|
这里是因为没有对我们输入的字符进行过滤,导致了用户可以通过其他字符进行绕过
达到执行任意命令的效果
防御
- 自定义函数过滤或使用正则
- escapeshellarg()
- escapeshellcmd()