命令执行
1、挖掘经验
命令执行漏洞最多出现在包含环境包的应用里,类似于eyou(亿邮)这类产品,直接在系统安装即可启动自带的Web服务和数据库服务,一般这类的产品会有一些额外的小脚本来协助处理日志以及数据库等,Web应用会有比较多的点之间使用system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open()等函数执行系统命令来调用这些脚本,用得多了难免就会出现纰漏导致漏洞,这类应用可以直接在代码里搜这几个函数,收获应该会不少。除了这类应用,还有像discuz等应用也有调用外部程序的功能,如数据库导出功能,曾经就出现过命令执行漏洞,因为特征比较明显,所以可以直接搜函数名即可进行漏洞挖掘。
2、函数介绍
system()、exec()、shell_exec()、passthru()以及反引号()是可以直接传入命令并且函数会返回执行结果,比较简单和好理解,其中system()函数会直接回显结果打印输出,不需要echo也可以popen()、proc_open()函数不会直接返回执行结果,而是返回一个文件指针,但命令是已经执行了<br />**system** ( string$command[, int&$return_var] ) : string<br />• 同 C 版本的 **system()** 函数一样, 本函数执行command参数所指定的命令, 并且输出执行结果。如果 PHP 运行在服务器模块中, **system()** 函数还会尝试在每行输出完毕之后, 自动刷新 web 服务器的输出缓存。<br />**passthru** ( string$command[, int&$return_var] ) : void<br />• 同 exec() 函数类似, **passthru()** 函数 也是用来执行外部命令(command)的。<br />**exec** ( string$command[, array&$output[, int&$return_var]] ) : string<br />• **exec()** 执行command参数所指定的命令。<br />**shell_exec** ( string$cmd) : string<br />• PHP 将尝试将$cmd作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。与反引号运算符“”的效果相同。
popen ( string $command , string $mode ) : resource
• 打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。
<?php//system函数if($_GET['cmd']){$cmd = $_GET['cmd'];system($cmd);}else{echo "fail!";}//passthru()函数if($_GET['cmd']){$cmd = $_GET['cmd'];passthru($cmd);}else{echo "fail!";}//exec,没有回显,只返回一行$cmd = $_GET['cmd'];echo exec($cmd);//shell_exec,没有回显,反引号也可以调用此函数if($_GET['cmd']){$cmd = $_GET['cmd'];echo shell_exec($cmd);}else{echo "fail!";}if($_GET['cmd']){$cmd = $_GET['cmd'];echo `$cmd`;}else{echo "fail!";}//popenpopen ('whoami >>D;/2.txt','r')
3、过滤函数
• Escapeshellcmd()—-过滤整条命令
• Escapeshellarg()—-过滤整个参数
4、修复方案
• 尽量少用执行命令的函数或者直接禁用参数值尽量使用引号包括
• 在使用动态函数之前,确保使用的函数是指定的函数之一
• 在进入执行命令的函数/方法之前,对参数进行过滤,对敏感字符进行转义
• 尽量少用执行命令的函数
• 对于可控点是程序参数的情况下,使用escapeshellcmd函数进行过滤;对于可控点是程序参数值的情况下,使用escapeshellarg函数进行过滤
• 参数的值尽量使用引号包裹,并在拼接前调用addslashes进行转义
• 而针对由特定第三方组件引发的漏洞,我们要做的就是及时打补丁,修改安装时的默认配置。
