文章目录
命令执行漏洞简介
原因
应用未对用户输入做严格得检查过滤,导致用户输入得参数被当成命令来执行。
危害
- 继承Web服务程序的权限去执行系统命令或读写文件
- 反弹shell,获得目标服务器的权限
- 进一步内网渗透
远程代码执行
因为业务需求,在PHP中有时需要调用一些执行命令的函数,如: eval() 、 assert() 、
preg_replace() 、 create_function() 等,如果存在一个使用这些函数且未对可被用户控制
的参数进行检查过滤的页面,那么这个页面就可能存在远程代码执行漏洞。
PHP代码执行函数
Eval
eval ( string $code )
把字符串 code 作为PHP代码执行
<?php @eval($_POST['cmd']);?>
注意:eval() 函数传入的参数必须为PHP代码,即要以分号结尾;
函数eval()语言结构是非常危险的, 因为它允许执行任意 PHP 代码。
assert
assert ( mixed $assertion [, string $description ] )
如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。
<?php @assert($_POST['cmd'])?>
assert — 检查一个断言是否为
FALSE
注意:assert()函数是直接将传入的参数当成PHP代码执行,不需要以分号结尾
preg_replace
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [,
int $limit = -1 [, int &$count ]] )
执行一个正则表达式的搜索和替换,搜索 subject 中匹配 pattern 的部分, 以 replacement进行替换。
<?php
preg_replace("/test/e",$_POST["cmd"],"just test");
preg_replace('正则规则','替换字符','目标字符')
PCRE修饰符 e :preg_replace()在进行了对替换字符串的后向引用替换之后,
将替换后的字符串作为php代码评估执行(eval函数方式), 并使用执行结果作为实际参与替换
的字符串。
?>
等等这些…
系统命令执行
一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口,比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上,一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后后台会对该IP地址进行一次ping测试,并返回测试结果。而,如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交恶意命令,让后台进行执行,从而获得后台服务器权限。
利用PHP 的系统命令执行函数来调用系统命令并执行,这类函数有 system()、exec()、shell_exec()、passthru()、penti_exec()、popen()、proc_pen()等,此外还有反引号命令执行,这种方式实际上是调用 shell_exec()函数来执行。
PHP系统命令执行函数
system():执行外部程序,并且显示输出;
exec():执行一个外部程序
shell_exec():通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
passthru():执行unix系统命令并且显示原始输出
pcntl_exec():在当前进程空间执行指定程序
popen():打开进程文件指针
proc_open():执行一个命令,并且打开用来输入/输出的文件指针。
PHP提供4个专门的执行外部命令的函数:
exec()
system()
passthru()
shell_exec()
exec()
exec ( string $command [, array &$output [, int &$return_var ]] )
执行一个外部程序,exec() 执行 command 参数所指定的命令。
exec执行系统外部命令时不会输出结果,而是返回结果的最后一行。如果想得到结果,可以使用第二个参数,让其输出到指定的数组。此数组一个记录代表输出的一行。即如果输出结果有20行,则这个数组就有20条记录,所以如果需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组unset($output) ,以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0。
<?php
// 输出运行中的 php/httpd 进程的创建者用户名
// (在可以执行"whoami"命令的系统上)
// echo exec("whoami");
// exec('ls-la',$return);
// var_dump($return);
$cmd=$_POST['cmd'];
@exec($cmd,$return);
var_dump($return)
?>
使用eval函数时,可以使用 cmd=var_dump(exec(‘whoami’)); 获取信息
system
system ( string $command [, int &$return_var ] )
函数执行 command 参数所指定的命令, 并且输出执行结果。
system和exec的区别在于,system在执行系统外部命令时,直接将结果输出到浏览器,如果执行命令成功则返回true,否则返回false。第二个参数与exec第三个参数含义一样。
<?php
echo '<pre>';
// 输出 shell 命令 "ls" 的返回结果
// 并且将输出的最后一样内容返回到 $last_line
// 将命令返回值保存到 $retval
$last_line = system('ls',$retval);
//打印更多信息
echo'
</pre>
<hr />Last line of the output ' . $last_line .'
<hr />Return value:' . $retval;
?>
等等…
命令执行常用特殊字符
cmd1|cmd2:无论cmd1是否执行成功,cmd2将被执行
cmd1;cmd2:无论cmd1是否执行成功,cmd2将被执行
cmd1||cmd2:仅在cmd1执行失败时才能执行cmd2
cmd1&&cmd2:仅在cmd1执行成功后cmd2才执行
cmd2$(cmd) :echo $(whoami) 或者 $(touch test.sh; echo 'ls' > test.sh)
'cmd':用于执行特定命令,如 'whoami'
linux shell中绕过空格的方法
<、<>、$IFS$9、${IFS}、$IFS、$IFS[]、$IFS[@]等