• 文件包含漏洞与PHP伪协议


    PHP中支持的伪协议

    file:// — 访问本地文件系统
    http:// — 访问 HTTP(s) 网址
    ftp:// — 访问 FTP(s) URLs
    php:// — 访问各个输入/输出流(I/O streams)
    zlib:// — 压缩流
    data:// — 数据(RFC 2397)
    glob:// — 查找匹配的文件路径模式
    phar:// — PHP 归档
    ssh2:// — Secure Shell 2
    rar:// — RAR
    ogg:// — 音频流
    expect:// — 处理交互式的流
    

     file://协议

     PHP.ini:
    file:// 协议在双off的情况下也可以正常使用;
    allow_url_fopen :off/on
    allow_url_include:off/on

    file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
    filebh.php

    <?php
    if(isset($_GET['page']))
    {
        include $_GET['page'];
    }
    ?>
    

      file:// [文件的绝对路径和文件名]
     

    php://协议

    php://filter在双off的情况下也可以正常使用;
    条件:
    不需要开启allow_url_fopen,仅php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include。

    php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。

    php://filter

    php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。

    resource=<要过滤的数据流>     这个参数是必须的。它指定了你要筛选过滤的数据流。
    read=<读链的筛选列表>         该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
    write=<写链的筛选列表>    该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
    <;两个链的筛选列表>        任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。
    

    可以运用多种过滤器(字符串/转换/压缩/加密)
    例如平时我们用来任意文件读取的payload

    php://filter/read=convert.base64-encode/resource=upload.php
    这里读的过滤器为convert.base64-encode,就和字面上的意思一样,把输入流base64-encode。
    resource=upload.php,代表读取upload.php的内容
    

    这样就可以以base64编码的方式读取文件源代码

    过滤器

    过滤器有很多种,有字符串过滤器、转换过滤器、压缩过滤器、加密过滤器
    <字符串过滤器>
     

    string.rot13
    进行rot13转换
    string.toupper
    将字符全部大写
    string.tolower
    将字符全部小写
    string.strip_tags
    去除空字符、HTML 和 PHP 标记后的结果。
    功能类似于strip_tags()函数,若不想某些字符不被消除,后面跟上字符,可利用字符串或是数组两种方式
    

    举例  

    <?php
        $fp = fopen('php://output', 'w');
        stream_filter_append($fp, 'string.rot13');
        echo "rot13:";
        fwrite($fp, "This is a test.
    ");
        fclose($fp);
        echo "<br>";
    
        $fp = fopen('php://output', 'w');
        stream_filter_append($fp, 'string.toupper');
        echo "Upper:";
        fwrite($fp, "This is a test.
    ");
        fclose($fp);
        echo "<br>";
    
        $fp = fopen('php://output', 'w');
        stream_filter_append($fp, 'string.tolower');
        echo "Lower:";
        fwrite($fp, "This is a test.
    ");
        fclose($fp);
        echo "<br>";
    
        $fp = fopen('php://output', 'w');
        echo "Del1:";
        stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE);
        fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>
    ");
        fclose($fp);
        echo "<br>";
    
        $fp = fopen('php://output', 'w');
        echo "Del2:";
        stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, "<b>");
        fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>
    ");
        fclose($fp);
        echo "<br>";
    
        $fp = fopen('php://output', 'w');
        stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, array('b','h1'));
        echo "Del3:";
        fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>
    ");
        fclose($fp);
    ?>

    实例模拟

    <?php  
    $filename=$_GET["a"];  
    $data="test test";  
    file_put_contents($filename, $data);  
    ?>  
    

     PHP file_put_contents() 函数

    payload=http://127.0.0.1/xxx.php?a=php://filter/write=string.tolower/resource=test.php

     可以往服务器中写入一个文件内容全为小写且文件名为test.php的文件:

    xxx.php

    <?php  
    $filename=$_GET["a"];  
    echo file_get_contents($filename);  
    ?>  
    

     PHP file_get_contents() 函数

     ile_get_contents()的$filename参数不仅仅为文件路径,还可以是一个URL(伪协议)。

    payload=http://127.0.0.1/xxx.php?a=php://filter/convert.base64-encode/resource=test.php
    

      test.php的内容以base64编码的方式显示出来

     xxx.php

    <?php  
    $filename=$_GET['a'];
    $data="test test";
    include("$filename");
    ?>
    

     

    payload=http://127.0.0.1/xxx.php?a=php://filter/convert.base64-encode/resource=test.php
    

     

    同样可以把test.php的内容以base64编码的方式显示出来

    双引号包含的变量$filename会被当作正常变量执行,而单引号包含的变量则会被当作字符串执行。

    php://input

     php://input 是个可以访问请求的原始数据的只读流,可以读取到post没有解析的原始数据, 将post请求中的数据作为PHP代码执行。因为它不依赖于特定的 php.ini 指令。
    注:enctype=”multipart/form-data” 的时候 php://input 是无效的。

    allow_url_fopen :off/on
    allow_url_include:on
    

     xxx.php

    <?php  
    echo file_get_contents($_GET["a"]);  
    ?>  
    

     

     但是当PHP代码为:

    <?php  
    $test=$_GET['a'];
    include($test);
    ?>    
    

      

     并且当远程包含打开的时候(allow_url_include=on),就可以造成任意代码执行。
     

    zip://, bzip2://, zlib://协议

    zip://, bzip2://, zlib://协议

    PHP.ini:
    zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用;
    allow_url_fopen :off/on
    allow_url_include:off/on

    3个封装协议,都是直接打开压缩文件。
    compress.zlib://file.gz - 处理的是 '.gz' 后缀的压缩包
    compress.bzip2://file.bz2 - 处理的是 '.bz2' 后缀的压缩包
    zip://archive.zip#dir/file.txt - 处理的是 '.zip' 后缀的压缩包里的文件

    zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。

    zip://协议

    php 版本大于等于 php5.3.0
    使用方法:
    zip://archive.zip#dir/file.txt
    zip:// [压缩文件绝对路径]#[压缩文件内的子文件名]**
    要用绝对路径+url编码#

    测试:
    新建一个名为zip.txt的文件,内容为<?php phpinfo();?>,然后压缩为名为test.zip的zip文件。如果可以上传zip文件则上传zip文件,若不能则重命名为test.jpg后上传其他几种压缩格式也可以这样操

    作。

     更名为jpg
    payload:http://127.0.0.1/xxx.php?a=zip://C:UsersliuxianglaiDesktop est.jpg%23zip.txt

    小结:

  • 相关阅读:
    linux —— 学习笔记(汇总)
    linux —— ubuntu 初次安装问题
    更改CMD默认的初始路径
    深入浅出理解linux inode结构
    重拾简单的linux指令之info 【转】
    Python 中数据的序列化和反序列化(json处理)
    day07
    Python 的反射机制
    Python 的 __new__()方法与实例化
    Classes as objects
  • 原文地址:https://www.cnblogs.com/ls-pankong/p/9885035.html
Copyright © 2020-2023  润新知