0%

php中的basename绕过

本次记录是通过【[Zer0pts2020]Can you guess it?】所学习到的。

basename 定义 及利用点

定义

1
string basename ( string $path [, string $suffix ] )

给出一个包含有指向一个文件的全路径的字符串,本函数返回基本的文件名。
如:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$path = "/testweb/home.php/";

//显示带有文件扩展名的文件名
echo basename($path);

//显示不带有文件扩展名的文件名
echo basename($path,".php");
?>
———————————————————————————
home.php
home

利用点

我们需要注意的是他会忽略一些奇怪的字符如: %80 ~ %ff

CTF题解

【题目链接】

  1. 打开题目,我们可以看到源码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?php
    include 'config.php'; // FLAG is defined in config.php

    if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
    exit("I don't know what you are thinking, but I won't let you read it :)");
    }

    if (isset($_GET['source'])) {
    highlight_file(basename($_SERVER['PHP_SELF']));
    exit();
    }

    $secret = bin2hex(random_bytes(64));
    if (isset($_POST['guess'])) {
    $guess = (string) $_POST['guess'];
    if (hash_equals($secret, $guess)) {
    $message = 'Congratulations! The flag is: ' . FLAG;
    } else {
    $message = 'Wrong.';
    }
    }
    ?>
  2. 虽然下面猜对了也可以出flag,但似乎没有漏洞点。其实利用点在:
    1
    2
    3
    4
    if (isset($_GET['source'])) {
    highlight_file(basename($_SERVER['PHP_SELF']));
    exit();
    }
    但是前面还有过滤:
    1
    2
    3
    if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
    exit("I don't know what you are thinking, but I won't let you read it :)");
    }
  3. 其中$_SERVER['PHP_SELF']我们知道它的值是url相对路径。也就是说我们输入/index.php/config.php?source 会返回/index.php/config.php
  4. 我们知道preg_match 是需要完全匹配才会返回true的,也就是说我们输入/index.php/config.php/a就可以绕过,但是basename的结果会是a显然会报错,因为没这个文件。此时我们想到了basename会忽略一些奇怪的字符%80 ~ %ff
  5. 所以我们输入/index.php/comfig.php/%ff 就可以进行显示comfig.php文件,这里所有的操作都是在index.php下进行的(我们看到的代码都是index.php的代码)。当然我们不要忘记传get的变量source。
  6. payload:/index.php/config.php/%81?source

-------------本文结束感谢您的阅读-------------