2019年9月29日星期日

结合攻防世界Web_php_include学习php伪协议

PHP伪协议

参考:

伪协议简介

php伪协议,事实上是其支持的协议与封装协议
支持的种类有这12种
  • 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:// — 处理交互式的流

先整理一下关于php://的用法

php://

PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的 过滤器

php://stdin, php://stdout 和 php://stderr

php://stdin、php://stdout 和 php://stderr 允许直接访问 PHP 进程相应的输入或者输出流。 数据流引用了复制的文件描述符,所以如果你打开php://stdin并在之后关了它, 仅是关闭了复制品,真正被引用的 STDIN 并不受影响。 推荐简单使用常量 STDIN、 STDOUT 和 STDERR 来代替手工打开这些封装器。
php://stdin是只读的,php://stdout 和 php://stderr 是只写的。

php://input

php://input 是个可以访问请求的原始数据的只读流。因为它不依赖于特定的 php.ini 指令。可以将想要执行的php代码放在post的数据中,不用以键值对的形式出现 注:enctype=”multipart/form-data” 的时候 php://input 是无效的。即php://input 不读取表单数据参数
结合一道题来看,源码为:
<!--
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];

if(isset($user)&&(file_get_contents($user,'r')==="the user is admin")){
    echo "hello admin!<br>";
    include($file); //class.php
}else{
    echo "you are not admin ! ";
}
 -->

php://output

php://output 是一个只写的数据流, 允许你以 print 和 echo 一样的方式 写入到输出缓冲区。

php://filter

可以说这是最常使用的一个伪协议,一般可以利用进行任意文件读取。 php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
php://filter 参数
名称 描述
resource=<要过滤的数据流> 它指定了你要筛选过滤的数据流。这个参数是必须的。
read=<读链的筛选列表>该参数可选。可以设定一个或多个过滤器名称,这采用一个|或以管道符 /分隔的多个过滤器名称
write=<写链的筛选列表>该参数可选。可以设定一个或多个过滤器名称,以管道符(_
<;两个链的筛选列表>任何没有以 read=write= 作前缀 的筛选器列表会视情况应用于读或写链。
还是结合上面那道题:
这里写图片描述

过滤器

过滤器有很多种,有字符串过滤器、转换过滤器、压缩过滤器、加密过滤器,这里只说一种转换过滤器中的一种
convert.base64-encode & convert.base64-decode
convert.base64-encode和convert.base64-decode使用这两个过滤器等同于分别用 base64_encode()和 base64_decode()函数处理所有的流数据。 convert.base64-encode支持以一个关联数组给出的参数。如果给出了line-length,base64 输出将被用 line-length个字符为长度而截成块。如果给出了* line-break-chars*,每块将被用给出的字符隔开。这些参数的效果和用 base64_encode()再加上 chunk_split()相同。
为什么要base64编码后再读取呢?
这涉及到include()的特性,如果include的文件不是txt格式会直接输出,如果包含<?php ?>这种格式在,则会执行相关代码。
综上,如果不加编码的话,引入的文件若符合php格式则会自动执行,将结果包含在流中,如果想要读取运行php文件的源码,就可以先base64编码,再传入include函数,这样就不会被认为是php文件,不会执行,会输出文件的base64编码,再解码即可。

file://

file://与php:filter类似,访问本地文件,但是只能传入绝对路径
img

data

data 与input 类似,都是用户可以控制传入的php代码,格式为:data: text/plain,<?php 执行内容 ?>
或者是:
data:text/plain;(注意是分号不是逗号,与前面不同)base64,编码后的php代码
img
有一点要注意的问题,base64编码后的加号和等号要手动的url编码,否则无法识别

http

include中也可以传入外部链接,采用http://,如图img

一道实例:

来自攻防世界 Web_php_include
访问URL,直接出现源码:
<?php
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
    $page=str_replace("php://", "", $page);
}
include($page);
?>
看到源码后,分析一下,过滤了php://有如下3种思路:
  1. data来代替php://
  2. 利用大小写绕过过滤Php://,直接php://input 代码执行

  3. 利用http://127.0.0.1/index.php?的方式来绕过过滤,这种方法比较巧妙,但是也比较巧合,需要该应用可直接在本地根目录去访问/index.php才能达到这个效果http://192.168.100.161:50281/?page=http://127.0.0.1/index.php/?hello=%3C?system(%22ls%22);?%3Eimg
今日分享:
高效的时间管理!!

嘿嘿,我自己说的,今天做的还不错,稍微表扬一下自己~

没有评论:

发表评论

XSS速查表

今天继续XSS的进一步学习,以下内容转载自Freebuf上的文章,原文章来自OWASP的xss备忘录 1.介绍 这篇文章的主要目的是给专业安全测试人员提供一份跨站脚本漏洞检测指南。文章的初始内容是由RSnake提供给 OWASP,内容基于他的XSS备忘录: http://...