mwf攻防。

用了git,所以怀疑源码泄露。

下载文件,用的这个工具。

这东西被注释了,所以伪协议不一定能读取。
读源码

接收传入的page,拼接后,如果里面带有文件跳跃的..给你输出这个页面

如果没匹配到,就输出另外一个页面
这里的flag明显存在。
在PHP的语法中,单引号和双引号本身不能“互相替代”,但可以合法嵌套使用——只要引号的“配对关系”正确,就能被PHP正常解析,这也是之前注入场景中能同时用单、双引号的原因。
1. 先明确PHP单/双引号的基础规则
- 单引号:包裹的是“纯字符串”,不会解析其中的变量、特殊转义(仅支持 \' 转义自身单引号);
- 双引号:包裹的字符串会解析其中的变量(如 "$var" )、特殊转义(如 \n )。
2. 单/双引号的“合法嵌套”是关键
PHP允许单引号包裹的字符串里包含未转义的双引号,也允许双引号包裹的字符串里包含未转义的单引号——只要引号的“开闭配对”正确即可:
- 例1(单引号里嵌套双引号):
php
echo 'hello "world"'; // 输出:hello "world"(双引号是普通字符)
- 例2(双引号里嵌套单引号):
php
echo "hello 'world'"; // 输出:hello 'world'(单引号是普通字符)
3. 回到之前的注入场景:为什么单/双引号能一起用?
在注入的 $page 参数( ' . system("cat templates/flag.php") . ' )中:
- 外层的单引号:是用来闭合原代码中 assert 语句里包裹 $file 的单引号(原代码是 strpos('$file', '..') ,这里的单引号是成对的);
- 内层的双引号:是 system() 函数的参数包裹符——因为它处于“单引号包裹的字符串”内部,双引号会被PHP当作普通字符处理,不影响外层单引号的配对。
最终,PHP会将这段代码解析为合法的语法:
php
strpos('templates/'. system("cat templates/flag.php") . '.php', '..') === false
这里的单、双引号是“嵌套配对”的关系,而非“兼容替代”,所以能被正常执行。

$file = "templates/' . system("cat templates/flag.php") . '.php";
strpos('templates/'. system("cat templates/flag.php") . '.php', '..') === false
可以直接执行。
这个代码里的命令拼接执行,是通过 assert() 的代码执行特性 + 用户可控的 $page 参数拼接实现的,具体对应代码中的这两个核心环节:
1. $file 的拼接逻辑:
代码中 $file = "templates/" . $page . ".php"; 里的 $page 是用户通过 GET 参数可控的——这是“拼接命令执行代码”的输入入口。
2. assert() 的代码执行能力:
代码里的 assert("strpos('$file', '..') === false") 会把字符串参数当作PHP代码执行。当用户构造恶意 $page (比如 ' . system("cat templates/flag.php") . ' )时, $file 会被拼接成包含 system() (命令执行函数)的内容,最终让 assert 执行的代码里拼接了命令执行逻辑,从而实现系统命令的执行。
简言之:这个代码本身没有直接写命令执行函数,但通过“用户可控参数拼接 $file + assert 执行代码”的组合,实现了命令的拼接与执行。
