[VNCTF2022]gocalc0刷题笔记

gin模版注入

{{.}} => 获取当前作用域对象

拿到源码

package main

import (
    _ "embed"
    "fmt"
    "os"
    "reflect"
    "strings"
    "text/template"

    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
    "github.com/maja42/goval"
)

//go:embed template/index.html
var tpl string

//go:embed main.go
var source string

type Eval struct {
    E string `json:"e" form:"e" binding:"required"`
}

func (e Eval) Result() (string, error) {
    eval := goval.NewEvaluator()
    result, err := eval.Evaluate(e.E, nil, nil)
    if err != nil {
        return "", err
    }
    t := reflect.ValueOf(result).Type().Kind()

    if t == reflect.Int {
        return fmt.Sprintf("%d", result.(int)), nil
    } else if t == reflect.String {
        return result.(string), nil
    } else {
        return "", fmt.Errorf("not valid type")
    }
}

func (e Eval) String() string {
    res, err := e.Result()
    if err != nil {
        fmt.Println(err)
        res = "invalid"
    }
    return fmt.Sprintf("%s = %s", e.E, res)
}

func render(c *gin.Context) {
    session := sessions.Default(c)

    var his string

    if session.Get("history") == nil {
        his = ""
    } else {
        his = session.Get("history").(string)
    }

    fmt.Println(strings.ReplaceAll(tpl, "{{result}}", his))
    t, err := template.New("index").Parse(strings.ReplaceAll(tpl, "{{result}}", his))
    if err != nil {
        fmt.Println(err)
        c.String(500, "internal error")
        return
    }
    if err := t.Execute(c.Writer, map[string]string{
        "s0uR3e": source,
    }); err != nil {
        fmt.Println(err)
    }
}

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    r := gin.Default()
    store := cookie.NewStore([]byte("woW_you-g0t_sourcE_co6e"))
    r.Use(sessions.Sessions("session", store))

    r.GET("/", func(c *gin.Context) {
        render(c)
    })

    r.GET("/flag", func(c *gin.Context) {
        session := sessions.Default(c)
        session.Set("FLAG", os.Getenv("FLAG"))
        session.Save()
        c.String(200, "flag is in your session")
    })

    r.POST("/", func(c *gin.Context) {
        session := sessions.Default(c)

        var his string

        if session.Get("history") == nil {
            his = ""
        } else {
            his = session.Get("history").(string)
        }

        eval := Eval{}
        if err := c.ShouldBind(&eval); err == nil {
            his = his + eval.String() + "<br/>"
        }
        session.Set("history", his)
        session.Save()
        render(c)
    })

    r.Run(fmt.Sprintf(":%s", port))
}

思路:在flag路由里将环境变量flag值设入cookie的FLAG中,但是cookie中的内容经过加密无法直接拿到,在本地搭建一样的环境,从相同cookie中拿到FLAG对应的值,找地方输出即可

package main

import (
    _ "embed"
    "fmt"
    "os"

    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8888"
    }
    r := gin.Default()
    store := cookie.NewStore([]byte("woW_you-g0t_sourcE_co6e"))
    r.Use(sessions.Sessions("session", store))
    r.GET("/flag", func(c *gin.Context) {
        session := sessions.Default(c)
        c.String(200, session.Get("FLAG").(string))
    })
    r.Run(fmt.Sprintf(":%s", port))
}

第一遍看都没看明白,思路清晰了觉得好简单......

posted @ 2022-02-16 09:38  Yu_so1dier0n  阅读(178)  评论(0编辑  收藏  举报