漏洞原理
命令注入(Command Injection),对一些函数的参数没有做过滤或过滤不严导致的,可以执行系统或者应用指令(CMD命令或者 bash 命令)的一种注入攻击手段。
PHP常见的执行系统命令的函数
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
system()
string system ( string $command [, int &$return_var ] )
$command为执行的命令,&return_var可选,用来存放命令执行后的状态码。
system()函数执行有回显,将执行结果输出到页面上。
passthru()
void passthru ( string $command [, int &$return_var ] )
和system函数类似,$command为执行的命令,&return_var可选,用来存放命令执行后的状态码。
执行有回显,将执行结果输出到页面上。
exec()
string exec ( string $command [, array &$output [, int &$return_var ]] )
$command是要执行的命令,$output是获得执行命令输出的每一行字符串,$return_var用来保存命令执行的状态码(检测成功或失败)。
exec()函数执行无回显,默认返回最后一行结果。
shell_exec()
string shell_exec( string &command)
&command是要执行的命令,shell_exec()函数默认无回显,通过 echo 可将执行结果输出到页面。
反引号`
shell_exec() 函数实际上仅是反撇号 (`) 操作符的变体,当禁用shell_exec时,` 也不可执行。
在php中称之为执行运算符,PHP将尝试将反引号中的内容作为shell命令来执行,并将其输出信息返回。
popen()
resource popen ( string $command , string $mode )
函数需要两个参数,一个是执行的命令command,另外一个是指针文件的连接模式mode,有r和w代表读和写。
函数不会直接返回执行结果,而是返回一个文件指针,但是命令已经执行。
popen()打开一个指向进程的管道,该进程由派生给定的command命令执行而产生。
返回一个和fopen()所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用pclose()来关闭。
此指针可以用于fgets(),fgetss()和 fwrite()。
> c:/1.txt', 'r' ); ?>
proc_open()
resource proc_open (
string $cmd ,
array $descriptorspec ,
array &$pipes [, string $cwd [, array $env [, array $other_options ]]]
)
与Popen函数类似,但是可以提供双向管道。
pcntl_exec()
void pcntl_exec ( string $path [, array $args [, array $envs ]] )
path是可执行二进制文件路径或一个在文件第一行指定了 一个可执行文件路径标头的脚本;
args是一个要传递给程序的参数的字符串数组;
pcntl是linux下的一个扩展,需要额外安装,可以支持 php 的多线程操作;
pcntl_exec函数的作用是在当前进程空间执行指定程序,版本要求:PHP>4.2.0。
对这些危险函数,可以在php.ini中禁用,进行安全加固
漏洞判断方法
1.判断是否执行系统命令
2.判断函数或函数的参数是否可
3.判断是否拼接注入命令
命令拼接运算符
windows和unix都可以使用
command 1 && command 2 #先执行命令1,成功后再执行命令2
command 1 & command 2 #先执行命令1,不论成功都执行命令2
command 1 | command 2 #先执行命令1,将1的结果作为2的输入,只打印2的结果
command 1 || command 2 #先执行命令1,1执行失败再执行命令2,直到有命令执行成功
仅unix可以使用
;#如果每个命令都被一个分号(;)所分隔,那么命令会连续地执行下去
Newline (0x0a or \n)
在基于Unix的系统上,您还可以使用反引号或美元字符在原始命令中内嵌执行注入命令:
` injected command ` #反引号
$( injected command ) #美元符号
有时,您控制的输入会出现在原始命令的引号中。在这种情况下,需要先使用引号终止上下文(使用“或”),然后再使用适当的外壳元字符来插入新命令.
漏洞防御
不要从应用程序层代码中调用OS命令,使用更安全的平台API来实现所需功能的替代方法。
如果认为无法通过用户提供的输入调出OS命令,则必须执行强大的输入验证,有效验证的一些示例包括:
1.根据允许值的白名单进行验证。
2.验证输入是否为数字。
3.验证输入仅包含字母数字字符,不包含其他语法或空格。
参考链接
https://www.cnblogs.com/hiccup/p/5423976.html
https://zhuanlan.zhihu.com/p/161165318
https://blog.csdn.net/Auuuuuuuu/article/details/88778852
https://blog.csdn.net/Auuuuuuuu/article/details/88778852
2020-8-12 第四周