# [鹤城杯 2021]EasyP
# [鹤城杯 2021]EasyP
```php
```
先看第一部分代码:
```php
// 检查是否设置了 POST 请求中的 'guess' 参数
if (isset($_POST['guess'])) {
// 将 'guess' 参数转换为字符串
$guess = (string) $_POST['guess'];
// 检查是 $guess 否等于 $secret 变量
if ($guess === $secret) {
$message = 'Congratulations! The flag is: ' . $flag;
} else {
$message = 'Wrong. Try Again';
}
}
```
这部分代码让你去猜 secret 变量的内容,显然是个干扰项
再看第二部分代码:
```php
// 检查当前 PHP 文件的路径是否以 'utils.php' 结尾,防止直接访问 utils.php 文件
if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("hacker :)");
}
// 检查请求 URI 是否包含 'show_source',防止直接访问 show_source 相关的页面
if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
exit("hacker :)");
}
// 检查是否设置了 GET 请求中的 'show_source' 参数
if (isset($_GET['show_source'])) {
// 如果设置了 'show_source' 参数,高亮显示当前文件的源代码并退出
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
} else {
// 如果未设置 'show_source' 参数,显示当前文件的源代码并退出
show_source(__FILE__);
}
```
- 正则表达式 `/utils\.php\/*$/i` 检查 `$_SERVER['PHP_SELF']` 是否以 `utils.php` 结尾
- `$`:这是锚定字符,表示匹配的模式必须出现在字符串的末尾
- 正则表达式 `/show_source/` 匹配包含 "show_source" 字符串的文本
- `$_SERVER['PHP_SELF']`:包含当前执行脚本的文件名,是相对于网站根目录的路径
- `$_SERVER['REQUEST_URI']`:包含当前请求的完整 URI(包括传参内容)
- `basename()`:返回路径中的文件名部分,即去掉路径后的部分,只保留文件名
> 关于 `$_SERVER['PHP_SELF']`、`$_SERVER['REQUEST_URI']` 和 `basename()` :
>
> 假设有以下 PHP 文件:`index.php`
>
> ```php
> // 获取当前脚本文件的相对路径
> $phpSelf = $_SERVER['PHP_SELF'];
>
> // 获取当前请求的 URI
> $requestUri = $_SERVER['REQUEST_URI'];
>
> // 获取当前脚本文件的基本文件名
> $baseName = basename($_SERVER['PHP_SELF']);
>
> echo "PHP_SELF: $phpSelf
";
> echo "REQUEST_URI: $requestUri
";
> echo "basename: $baseName
";
> ?>
> ```
>
>现在,如果通过浏览器访问 `http://example.com/index.php?page=1`,则输出将是:
>
>```
> PHP_SELF: /index.php
> REQUEST_URI: /index.php?page=1
> basename: index.php
> ```
> 关于`basename()`:
>
>```PHP
> echo "1) ".basename("/etc/sudoers.d").PHP_EOL;
> echo "2) ".basename("/etc/passwd").PHP_EOL;
> echo "3) ".basename("/etc/").PHP_EOL;
> echo "4) ".basename(".").PHP_EOL;
> echo "5) ".basename("/");
> ?>
> ```
>
>以上例程会输出:
>
>```
> 1) sudoers.d
> 2) passwd
> 3) etc
> 4) .
> 5)
> ```
获得 flag 需满足 :
1. 参数 show_source 得到传值
2. URI ($_SERVER['REQUEST_URI'])不能包含:show_source
3. `basename($_SERVER['PHP_SELF'])` 的结果是:utils.php
4. 当前 PHP 文件的路径($_SERVER['PHP_SELF'])不能以:utils.php/ 结尾
同时满足1、2:用 `[` `.` `(空格)` 来代替 `_` ,即 `show[source` `show source` `show.source`
同时满足3、4:在 `utils.php/` 后加一个非 ASCII 编码,例如:`%88`、`%ff`等
payload:`index.php/utils.php/%88?show[source=1`
![[鹤城杯 2021]EasyP-1](https://pic.imgdb.cn/item/6552dee9c458853aefda4ebe.jpg)
> **相关实验**
>
> 网页代码:
>
> ```php
> echo "\$_SERVER['REQUEST_URI']的值:".$_SERVER['REQUEST_URI'];
> echo "
";
> echo "\$_SERVER['PHP_SELF']的值:".$_SERVER['PHP_SELF'];
> echo "
";
> echo "basename(\$_SERVER['PHP_SELF'])的值:".basename($_SERVER['PHP_SELF']);
> echo "
";
>
> if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) {
> echo("匹配到正则:/utils\.php\/*$/i");
> echo "
";
> }else{
> echo("绕过正则:/utils\.php\/*$/i");
> echo "
";
> }
> if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
> echo("匹配到正则:/show_source/");
> echo "
";
> }else{
> echo("绕过正则:/show_source/");
> echo "
";
> }
> if (isset($_GET['show_source'])) {
> echo("参数 show_source 得到传值");
> echo "
";
> }
> ?>
> ```
>
> ![[鹤城杯 2021]EasyP-2](https://pic.imgdb.cn/item/65521cf1c458853aef0aacaa.jpg)