知识点
php://filter
php://filter是一种元封装器,是PHP中特有的协议流,设计用于数据流打开时的筛选过滤应用,作用是作为一个“中间流”来处理其他流。
php://filter目标使用以下的参数作为它路径的一部分。复合过滤链能够在一个路径上指定。
名称 | 描述 | 备注 |
---|---|---|
resource=<要过滤的数据流> 指定了你要筛选过滤的数据流。 | 必选 | |
read=<读链的筛选列表> | 可以设定一个或多个过滤器名称,以管道符(|)分隔。 | 可选 |
write=<写链的筛选列表> | 可以设定一个或多个过滤器名称,以管道符(|)分隔。 | 可选 |
<;两个链的筛选列表> | 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。 |
PHP file_put_contents()
file_put_contents() 函数把一个字符串写入文件中。
file_put_contents(file,data,mode,context)
file 必需。规定要写入数据的文件。如果文件不存在,则创建一个新文件。
data 可选。规定要写入文件的数据。可以是字符串、数组或数据流。
实例介绍
eee.php
<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);
?>
当用户通过POST方式提交一个数据时,会和exit拼接,从而造成提交的数据不能被执行。
txt=aPD9waHAgcGhwaW5mbygpOyA/Pg==&filename=php://filter/write=convert.base64-decode/resource=b.png
向b.png写入,解码后的$content拼接上txt的内容
base64编码中只包含64个可打印字符,当PHP遇到不可解码的字符时,会选择性的跳过,这个时候base64就相当于以下的过程:
<?php
$_GET['txt'] = preg_replace('|[^a-z0-9A-Z+/]|s', '', $_GET['txt']);
base64_decode($_GET['txt']);
所以,当$content 包含 <?php exit; ?>时,解码decode过程会先去除识别不了的字符,都将被去除,于是剩下的字符就只有phpexit以及我们传入的字符了。由于base64是4个byte一组,再添加一个字符例如添加字符’a’后,将’phpexita’当做两组base64进行解码,也就绕过这个死亡exit了。
phpexitaPD9waHAgcGhwaW5mbygpOyA/Pg==
phpe xita aPD9 waHA ... ...
phae xita 解码失败
后面分组正常能继续正常解码
此处参考:从一题CTF学习php://filter伪协议