北京三个程序员信息技术有限公司
PHP安全编码——书写安全的代码
5、命令注入攻击
2024-01-30
提问
问题1:什么是命令注入攻击?
问题2:php哪些函数可能引起命令注入攻击?
问题3:如何防范命令注入攻击?
课程单元
1. 什么是命令注入攻击
2. 涉及注入攻击的主要PHP函数说明
3. 命令注入攻击举例
4. 如何防范命令注入攻击
1、什么是命令注入攻击
命令注入攻击指的是,由于Web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至PHP程序中,并且执行外部程序或系统命令实施攻击,非法获取数据或者网络资源等。命令注入攻击漏洞是PHP应用程序中常见的漏洞之一,很多著名的开源PHP程序都曾经存在过该类型漏洞。
2、涉及注入攻击的主要PHP函数说明
(1)system
system函数可以用来执行一个外部的应用程序并将相应的执行结果输出
函数的用法为:
string system(string command, int &return_var)
其中,command是要执行的命令,return_var存放执行命令的执行后的状态值。
(2)exec
exec函数可以用来执行一个外部的应用程序
函数的用法为:
string exec (string command, array &output, int &return_var)
其中,command是要执行的命令,output是获得执行命令输出的每一行字符串,return_var存放执行命令后的状态值。
(3)passthru
passthru函数可以用来执行一个系统命令并显示原始的输出,特别是可以用来显示二进制输出
函数的用法为:
void passthru (string command, int &return_var)
其中,command是要执行的命令,return_var存放执行命令后的状态值。
(4)shell_exec
shell_exec函数可以用来执行shell命令并返回输出的字符串
函数的用法为:
string shell_exec (string command)
其中,command是要执行的命令。
(5)``运算符
``与shell_exec功能相同,执行shell命令并返回输出的字符串
用法为:
`$command`
其中,command是要执行的命令。
(6)eval
eval函数会将参数字符串作为PHP程序代码来执行,用户可以将PHP代码保存成字符串的形式,然后传递给eval函数执行
函数的用法为:
mixed eval(string $code_str)
其中,code_str是PHP代码字符串,为要执行的PHP代码。
(7)preg_replace
preg_replace函数执行一个正则表达式的搜索和替换
函数的用法为:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject)
其中,pattern为要搜索的模式,e模式可能会引起命令注入攻击。
(8)str_replace
str_replace函数可以执行字符串替换功能
函数的用法为:
mixed str_replace ( mixed $search , mixed $replace , mixed $subject)
其中,search为查找的目标值,replace为替换值,subject为执行替换的数组或者字符串。
(9)call_user_func
call_user_func函数可以把第一个参数作为回调函数来调用
函数的用法为:
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
其中,callback为将被调用的回调函数。
3、命令注入攻击举例
3.1、system、exec、passthru、shell_exec、``等可以直接执行系统命令的函数举例
这几种方法参数里都有command,都可以直接执行系统命令,因此,实施攻击的方法都是类似的。
例如:
用户传入目录名字,显示目录下的文件:
<?php
$dir = $_GET[“dir”]; //用户传入的目录名字
system(“dir ” . $dir);
?>
当$dir用户传入|cat /etc/passwd时,实际执行的命令就成了:
system(“dir |cat /etc/passwd”),这样就把不该被泄漏出来的/etc/passwd文件的内容泄漏出来了。
3.2、eval、preg_replace、str_replace、call_user_func等可以直接执行PHP语句的函数举例
这几种方法都可以直接执行PHP语句,因此实施攻击的方法是类似的。
例如:
执行用户传入的php语句:
<?php
$cmd = $_GET[“cmd”]; //用户传入的php语句
eval($cmd);
?>
当$cmd用户传入phpinfo()时,实际执行的语句就成了:
eval(phpinfo()),这样就把不该被泄漏出来的很多phpinfo的系统信息都泄漏出来了。
例如:这是某知名开源CMS中的一行:
@eval(file_get_contents('php://input'));
php://input是一个输入流,可以通过POST方式获取相应的原始数据内容,也就是说eval函数执行的内容可以通过构造POST数据包的方式进行控制,那么,我们在post中传入phpinfo(),就直接执行了phpinfo()函数。
4、如何防范命令注入攻击
1、尽量不要执行外部的应用程序或命令,在需要用到相关功能时,尽量使用自定义函数或函数库来实现。例如,尽量不要用shell(“rm 1.txt”)的方式,而是用unlink(“1.txt”)的方式来执行。
2、在必须执行外部应用程序或者命令时,在执行之前,传入的参数需要检查确认清楚具体是什么,不要直接执行$_GET、$_POST等用户传入的内容,以免给黑客可乘之机。
例如:
<?php
$cmd = $_GET[“cmd”]; //用户传入的php命令
eval($cmd);
?>
对于这个例子,我们可以在eval($cmd)之前,判断一下是否是我们允许执行的命令,如果是,才允许执行。
<?php
$cmd = $_GET[“cmd”]; //用户传入的php命令
$allow_cmds = array(“getdate”); //允许执行的命令列表
if(in_array($cmd, $allow_cmds)){ //只有在这个列表中的命令,才允许执行
eval($cmd);
}
?>
3、在必须用$_GET、$_POST等用户传入的内容时,需要使用escapeshellarg函数处理相关参数。escapeshellarg 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,并且还是确保安全的。例如:
<?php
$dir = $_GET[“dir”]; //用户传入的目录名字
system(escapeshellarg(“dir ” . $dir));
?>
当|cat /etc/passwd时,实际执行的命令就成了:
system(escapeshellarg(“dir |cat /etc/passwd”)),这时,php会做好相应的处理,不会导致/etc/passwd文件内容泄漏。
4、使用safe_mode_exec_dir执行可执行的文件路径。将php.ini文件中的safe_mode设置为On,然后将允许执行的文件放入一个目录中,并使用safe_mode_exec_dir指定这个可执行的文件路径。这样,在需要执行相应的外部程序时,程序必须在safe_mode_exec_dir指定的目录中才会允许执行,否则执行将失败。但是,这样的方式只能防治执行指定的目录之外的文件,并不能防止文件参数中带有其他不该有的内容。
关注我们,获取更多资讯