代码审计题
除了有点长以外 代码很简单
目录结构:

(此处强烈安利vscode的 project manager插件 再也不去找phpstorm的激活码了)
init初始化文件提供了包含了config.php和lib.php
config.php文件声明了tmp目录
lib.php提供了一些可以调用的函数
pages里面的页面是交给index.php入口包含调用的
而include的参数使用了pages的前缀 而且in_array使用了true参数 严格的白名单
任意文件包含这条路基本是堵死了
pages/flag.php的代码:

      <section>
        <h2>Get flag</h2>
        <p>
          <?php
          if (is_admin()) {
            echo "Congratulations! The flag is: <code>" . getenv('FLAG') . "</code>";
          } else {
            echo "You are not an admin :(";
          }
          ?>
        </p>
      </section>

使用了is_admin判断

function is_admin() {
  if (!isset($_SESSION['admin'])) {
    return false;
  }
  return $_SESSION['admin'] === true;
}

必须想办法将$_SESSION['admin']操作为true才能拿到flag
去找一下会操作session的代码
在lib.php里看了半天 没感觉哪里有可控的session操作
看看后面的逻辑吧
export.php中可以把我们add的文件导出成zip
而文件名是根据用户名生成的

$filename = get_user() . '-' . bin2hex(random_bytes(8)) . '.' . $type;
$filename = str_replace('..', '', $filename); // avoid path traversal
$path = TEMP_DIR . '/' . $filename;

(还特意把..置空帮我们构造空后缀 不得不说出题人挺贴心的)
当我们拥有一个可控一部分的用户名 我们可以干什么呢?
init中的

session_save_path(TEMP_DIR);

session_start();

就很值得怀疑了 这个文件和session文件保存在了同一路径下
而session文件的默认存储名称为sess_开头也就是说我们可以用sess作为username 伪造session文件
然后就是构造session数据了
在序列化中,布尔值的true会被转换为b:1
所以我们的session就是 admin|b:1;
当我们把他返回的文件下载下来时会发现在admin的前面还有一个0
这个0_会影响session数据的正常反序列化 所以要在前面加一个|b:1;,让0_成为前面的键。
这个题的流程:

  • 注册一个名为sess_的账号
  • 在add页面中加入tittle为|b:1;admin|b:1;的note
  • 在导出页面抓包 把type改为. 获取返回的文件名 然后使用session文件名去掉_sess前缀作为cookie访问flag路由,拿到flag
分类: 技术

0 条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注