首页 > 其他分享 >[GFCTF 2021]web部分题解(更新中ing)

[GFCTF 2021]web部分题解(更新中ing)

时间:2024-01-18 20:11:08浏览次数:31  
标签:function web 题解 GFCTF param 2e params template var

[GFCTF 2021]Baby_Web

拿源码环节:

打开环境(◡ᴗ◡✿)

乍一看什么都没有,F12下没看到js文件,但是看到了出题师傅的提示:“源码藏在上层目录xxx.php.txt里面,但你怎么才能看到它呢?”

这时候在思考文件在上层目录中,既然是目录下那就试一下dirsearch扫描先看看后台都有什么(这里就直接展示一下扫描结果,收到了一部分新师傅的私信说之前的题解虽然讲了在那些题目下Kali,bp的使用方法但是没说具体的,后边会单独出教程的T-T这里就不多说了)

这里出现了几个很重要的关键词“cgi-bin”“.%2e”想到了之前偶然间看到的两篇博客:“CVE-2021-41773--Jay 17”“Apache httpd CVE-2021-41773 漏洞分析”简单来说就是:在 Apache HTTP Server 2.4.49 版本中,在对用户发送的请求中的路径参数进行规范化时, ap_normalize_path()函数会对路径参数先进行 url 解码,然后判断是否存在 ../路径穿越符。结果就是如果路径中存在 %2e./形式,程序就会检测到路径穿越符。然而,当出现 .%2e 或 %2e%2e/ 形式,程序就不会将其检测为路径穿越符。那么就可以活用到这道题目。

打开BP,本地环境修改以后刷新网页进行抓包(ρ_・).。:

在发包界面点击Repeater,进入可修改发包界面,在url栏修改代码然后发包:

GET /icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.1

代码形式参考kali扫描结果!^_~

修改成下图:

GET /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.1

可以看到已经可以有目录了,那么开始想既然当前目录是/var/www/html,那上层就是/var/www/想起来刚才说源码在xxx.php.txt那应该有最原始的index吧?O.o,先做尝试?

GET /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/var/www/index.php.txt HTTP/1.1

有了!ヾ(^▽^*))) index.php长这样!

<?php
error_reporting(0);
define("main","main");
include "Class.php";
$temp = new Temp($_POST);
$temp->display($_GET['filename']);

?>

看了一下源码!Class.php?好啊,看来同目录下还有个这个那直接找一下,刚才的文件叫“xxx.php.txt”这个也一样喽?

GET /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/var/www/Class.php.txt HTTP/1.1

Class.php长这样!

<?php
defined('main') or die("no!!");
Class Temp{
    private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];
    private $template;
    public function __construct($data){

        $this->date = array_merge($this->date,$data);
    }
    public function getTempName($template,$dir){
        if($dir === 'admin'){
            $this->template = str_replace('..','','./template/admin/'.$template);
            if(!is_file($this->template)){
                die("no!!");
            }
        }
        else{
            $this->template = './template/index.html';
        }
    }
    public function display($template,$space=''){

        extract($this->date);
        $this->getTempName($template,$space);
        include($this->template);
    }
    public function listdata($_params){
        $system = [
            'db' => '',
            'app' => '',
            'num' => '',
            'sum' => '',
            'form' => '',
            'page' => '',
            'site' => '',
            'flag' => '',
            'not_flag' => '',
            'show_flag' => '',
            'more' => '',
            'catid' => '',
            'field' => '',
            'order' => '',
            'space' => '',
            'table' => '',
            'table_site' => '',
            'total' => '',
            'join' => '',
            'on' => '',
            'action' => '',
            'return' => '',
            'sbpage' => '',
            'module' => '',
            'urlrule' => '',
            'pagesize' => '',
            'pagefile' => '',
        ];

        $param = $where = [];

        $_params = trim($_params);

        $params = explode(' ', $_params);
        if (in_array($params[0], ['list','function'])) {
            $params[0] = 'action='.$params[0];
        }
        foreach ($params as $t) {
            $var = substr($t, 0, strpos($t, '='));
            $val = substr($t, strpos($t, '=') + 1);
            if (!$var) {
                continue;
            }
            if (isset($system[$var])) { 
                $system[$var] = $val;
            } else {
                $param[$var] = $val; 
            }
        }
        // action
        switch ($system['action']) {

            case 'function':

                if (!isset($param['name'])) {
                    return  'hacker!!';
                } elseif (!function_exists($param['name'])) {
                    return 'hacker!!';
                }

                $force = $param['force'];
                if (!$force) {
                    $p = [];
                    foreach ($param as $var => $t) {
                        if (strpos($var, 'param') === 0) {
                            $n = intval(substr($var, 5));
                            $p[$n] = $t;
                        }
                    }
                    if ($p) {

                        $rt = call_user_func_array($param['name'], $p);
                    } else {
                        $rt = call_user_func($param['name']);
                    }
                    return $rt;
                }else{
                    return null;
                }
            case 'list':
                return json_encode($this->date);
        }
        return null;
    }
}

我了个豆T.T,这么长啊打开Vscode建在一个工程下

开始审计代码。。。┭┮﹏┭┮

index.php

先分析一下

首先,这里调用了Temp作为类,并构造方式传参,传参方式是POST。然后调用了Temp中Display作为方式传,Get形式提交filename

代码放这里对照看一下

Class.php

1.先看一下“temp”类吧:

private $date=['version'=>'1.0','img'=>'https://www.apache.org/img/asf-estd-1999-logo.jpg'];
    private $template;
    public function __construct($data){

        $this->date = array_merge($this->date,$data);

可以看到用了array_merge()函数,简单介绍一下吧:array_merge()出现时,则合并一个或多个数组.合并后参数2数组的内容附加在参数1之后。同时如果参数1、2数组中有相同的字符串键名则合并后为参数2数组中对应键的值,发生了覆盖。(造成变量覆)盖然而,如果数组包含数字键名,后面的值将不会覆盖原来的值,而是附加到后面。如果只给了一个数组并且该数组是数字索引的,则键名会以连续方式重新索引。

这里附上php手册上的例子:

2.往下分析display:

    public function display($template,$space=''){

        extract($this->date);
        $this->getTempName($template,$space);
        include($this->template);

可以看出来有两个魔术方法分别是“extract()”以及“include()”那么直接查手册得到这两个方法含义:

extract():从数组中将变量导入到当前的符号表。

include():包含一个文件。

3.再看getTempName():

    public function getTempName($template,$dir){
        if($dir === 'admin'){
            $this->template = str_replace('..','','./template/admin/'.$template);
            if(!is_file($this->template)){
                die("no!!");
            }
        }
        else{
            $this->template = './template/index.html';
        }
    }
    
    

可以看到句子意思是:如果传入getTempName()中形参dir是admin,那么就对template的属性:

$this->template

进行一个拼接,拼接过程为属性,同时进行替换过滤。过滤内容为:

'..','','./template/admin/'

其中

is_file()用于检查是否是文件。

4.最后检查一下listdata():

    public function listdata($_params){
        $system = [
            'db' => '',
            'app' => '',
            'num' => '',
            'sum' => '',
            'form' => '',
            'page' => '',
            'site' => '',
            'flag' => '',
            'not_flag' => '',
            'show_flag' => '',
            'more' => '',
            'catid' => '',
            'field' => '',
            'order' => '',
            'space' => '',
            'table' => '',
            'table_site' => '',
            'total' => '',
            'join' => '',
            'on' => '',
            'action' => '',
            'return' => '',
            'sbpage' => '',
            'module' => '',
            'urlrule' => '',
            'pagesize' => '',
            'pagefile' => '',
        ];

        $param = $where = [];

        $_params = trim($_params);

        $params = explode(' ', $_params);
        if (in_array($params[0], ['list','function'])) {
            $params[0] = 'action='.$params[0];
        }
        foreach ($params as $t) {
            $var = substr($t, 0, strpos($t, '='));
            $val = substr($t, strpos($t, '=') + 1);
            if (!$var) {
                continue;
            }
            if (isset($system[$var])) { 
                $system[$var] = $val;
            } else {
                $param[$var] = $val; 
            }
        }
        // action
        switch ($system['action']) {

            case 'function':

                if (!isset($param['name'])) {
                    return  'hacker!!';
                } elseif (!function_exists($param['name'])) {
                    return 'hacker!!';
                }

                $force = $param['force'];
                if (!$force) {
                    $p = [];
                    foreach ($param as $var => $t) {
                        if (strpos($var, 'param') === 0) {
                            $n = intval(substr($var, 5));
                            $p[$n] = $t;
                        }
                    }
                    if ($p) {

                        $rt = call_user_func_array($param['name'], $p);
                    } else {
                        $rt = call_user_func($param['name']);
                    }
                    return $rt;
                }else{
                    return null;
                }
            case 'list':
                return json_encode($this->date);
        }
        return null;
    }
}

trim():去除字符串首尾处的空白字符。
in_array():检查数组中是否存在某个值。

foreach():遍历给定的数组。

strpos():查找字符串首次出现的位置

function_exists():如果给定的函数已经被定义就返回“ture”

intval():获取变量的整数值

call_user_func_array():call_user_func_array:调用回调函数,并把一个数组参数作为回调函数的参数

call_user_func():第一个参数是被调用的回调函数,其余参数是回调函数的参数。

json_encode():进行json格式的加密

explode():根据指定的分隔符将一个字符串拆分为一个数组的子字符串。比如说原来$ _ params=“1 2 3 E”,explode处理后为$params=[“1”,“2”,“3”,“E”]

标签:function,web,题解,GFCTF,param,2e,params,template,var
From: https://www.cnblogs.com/TagLmtCtf/p/17969708

相关文章

  • Go Web项目分层 对比看下portal server 转载
    这样我们Controller中的入口函数就变成了下面这样:funcCreateOrder(ctxcontext.Context,req*CreateOrderStruct)(   *CreateOrderRespStruct,error,){   //...}CreateOrder有两个参数,ctx用来传入trace_id一类的需要串联请求的全局参数,req里存储了我们创......
  • Dojoup 安装问题解决
    Dojoup安装问题解决InstallDojouphttps://book.dojoengine.org/getting-started/quick-start.htmlcurl-Lhttps://install.dojoengine.org|bash安装失败dojoup═══════════════════════════════════════════════......
  • Oozie重试任务不生效问题解决
    1、oozie默认为不重试规则,想要重试需在action中配置重试规则,示例如下:retry-max="3"retry-interval="1"发现增加以上配置后,任务失败并未生效;2、在~/oozie/conf/oozie-site.xml中增加以下配置:<property><name>oozie.service.LiteWorkflowStoreService.user.retry.error.cod......
  • [AGC044E] Random Pawn题解
    [AGC044E]RandomPawn题解题目链接AtCoder原题链接Step1.拆环原问题是在环上的问题,考虑将环拆开变成链来处理。因此,我们需要找到一个点,使得操作越过这个点一定不优。令使\(a\)的值最大的位置的下标为\(maxp\)。容易发现,如果现在正处在\(maxp\)上,那么继续操作一定不可......
  • 题解 CF741E Arpa’s abnormal DNA and Mehrdad’s deep interest
    CF741EArpa’sabnormalDNAandMehrdad’sdeepinterest记\(R_{i}\)表示把\(T\)插入在\(S\)的第\(i\)位后组成的字符串。有\(q\)组询问,给定\((x,y,l,r)\),求\(\min_{i}R_{i},({i\in[l,r],i\%k\in[x,y]})\)。一个暴力的想法是先把\(R_{i}\)的排名求出来,这显......
  • 使用jmeter对websockt和protobuf进行压力测试
     这是基于JmeterWebsocketSampler的插件,支持对基于websocket和protobuf的服务器进行测试。 想要应用到具体业务中,还需要进行代码改造,可参考demo代码。 工程结构 两个子工程组成: 1. jmeter-websocketprotobuf-front工程。基于maciejzaleski/JMeter-WebSocketSampler(htt......
  • NSS Round#16 web
    RCE但是没有完全RCE<?phperror_reporting(0);highlight_file(__file__);include('level2.php');if(isset($_GET['md5_1'])&&isset($_GET['md5_2'])){if((string)$_GET['md5_1']!==(string)$_GET['md5_2&......
  • Web前端新手入门系列:案例1 招商银行页面的制作
    一次比较复杂的网页设计(对初学者而言)效果图代码可能不太符合规范,但效果差不多(HTML部分<!DOCTYPEhtml><htmllang="en"xmlns="http://www.w3.org/1999/xhtml"><head><metacharset="utf-8"/><title>招商银行</title>&......
  • C# WebApi传参及Postman调试
    概述欢迎来到本文,本篇文章将会探讨C#WebApi中传递参数的方法。在WebApi中,参数传递是一个非常重要的概念,因为它使得我们能够从客户端获取数据,并将数据传递到服务器端进行处理。WebApi是一种使用HTTP协议进行通信的RESTful服务,它可以通过各种方式传递参数。在本文中,我们只会针对Ge......
  • CF1921 F Sum of Progression 题解
    QuestionCF1921FSumofProgression给定一个序列\(\{a\}\),有\(q\)组询问,对于每组询问\(s,d,k\),求\[a_s+a_{s+d}\cdot2+\cdots+a_{s+d(k-1)}\cdotk\]Solution\(s,d,k\)其实就是在描述一个等差数列考虑到\(d\timesk\len\)如果\(d\)很大,那么就意味着\(k\)很......