[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)) }
第一遍看都没看明白,思路清晰了觉得好简单......