这道题当时出了非预期,session两次base64就能getflag,但是这道题本身的考点是Golang SSTI
正好复盘学习一下
打开题目能看到经典计算器
点开flag在这里
发现只有短短一行提示
这里按照非预期接还是能够拿到flag
但是我们要看一下具体按照预期方法怎么能拿到flag
https://www.jianshu.com/p/e0ffb76ba7e9
这里我们通过{{.}}
查看一下作用域
整理一下,就能够看到整个calc的源码
这里有很多东西,我们可以进行一下删减整理(对我们getflag没什么用处),提取出我们想要的东西
注意下这里
这里是创建基于cookie的存储引擎,woW_you-g0t_sourcE_co6e
参数是用于加密的密钥
然后是这里
session.Get("FLAG")
这里是gin框架中的读取session,而他指定了FLAG
这个key(session是键值对格式数据,因此需要通过key查询数据),所以我们可以尝试本地起这个gin框架,修改一下代码,并且把题目中的session传入cookie,看看他最终会输出什么
exp:
结果如下
成功解密出flag
但是这里有个问题
笔者在写exp的时候,对String()
产生了疑惑(我的Golang水平停留在Hello world水平),如果exp这样写他会直接输出在界面上
出于好奇,我跟进了一下
这里给了注释,我蹩脚的翻译一下
跟进Render
这里就明了了,shit我根本不用改代码啊!!!直接让他渲染出来就好了!!
so,我们验证一下
结果如下
又是学到了新知识的一天!
flag
is
in
your session
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"
)
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))
}
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"
)
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"
))
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2022-4-24 10:31
被H3h3QAQ编辑
,原因: