git protocol 是一个与 Git 一起打包的特殊守护进程;它侦听一个专用端口 (9418),该端口提供类似于 SSH 协议的服务,但绝对没有身份验证。
它是在 Git 最开始时介绍的,在 commit 2386d65 (July 2005, Git 0.99.1)
在“git 协议”连接逻辑处添加第一切。
对于从专用服务器上提取内容很有用。而不是连接
使用 ssh 或只是启动本地管道,我们通过 TCP 连接到
另一边试试看是否有git服务器在监听。
当然,因为我还没有写过 git 服务器,那永远不会
发生。但是服务器真的只需要监听一个端口,并且
当有人连接时执行“git-upload-pack”。
(它应该读取一个数据包行,应该是格式
"git-upload-pack directoryname\n"
最终我们可能会有服务器可能接受的其他命令。
该协议最初在next commit 9b011b2中描述
有两种 Pack 推拉协议。
-
upload-pack (S) | fetch/clone-pack (C) 协议:
-
send-pack | receive-pack协议
如今,Documentation/git-daemon.txt 中描述了 git 守护程序服务器的全部特征。
一个非常简单的 TCP Git 守护程序,通常侦听端口“DEFAULT_GIT_PORT”,即 9418。
它等待请求服务的连接,如果启用,它将为该服务提供服务。
请注意,即使 OSI 模型中没有列出,9418 仍然从一开始就被列为 IANA (Internet Assigned Numbers Authority)
见commit ba8a497 (Setp. 2005, Git 0.99.7a:
[PATCH] 添加有关 IANA 确认的注释
git 端口 (9418) 现已被 IANA 正式列出。
所以记录下来。
在 Git 2.31(2021 年第一季度)中,git:// URL 的主机和路径部分中的换行符现在被禁止。
参见Jeff King (peff) 的commit 6aed567、commit a02ea57(2021 年 1 月 7 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit c7b1aaf,2021 年 1 月 25 日)
报告人:Harold Kim
签字人:Jeff King
当我们连接到git:// 服务器时,我们会发送一个类似于以下内容的初始请求:
002dgit-upload-pack repo.git\0host=example.com
如果 repo 路径包含换行符,则按字面意思包含,我们得到:
002egit-upload-pack repo
.git\0host=example.com
如果您的存储库名称中确实有换行符,这很好用;服务器端使用 pktline 框架来解析字符串,而不是换行符。
但是,还有许多其他协议可以解析换行符,例如 HTTP。
因此,精心构建的git:// URL 实际上可以变成有效的 HTTP 请求。
例如:
git://localhost:1234/%0d%0a%0d%0aGET%20/%20HTTP/1.1 %0d%0aHost:localhost%0d%0a%0d%0a
变成:
0050git-upload-pack /
GET / HTTP/1.1
Host:localhost
host=localhost:1234
在电线上。
同样,这对于真正的 Git 服务器来说不是问题,但这确实意味着向 Git 提供恶意 URL(例如,通过子模块)可能会导致它发出意外的跨协议请求。
由于带有换行符的存储库名称可能非常少见(事实上,我们已经在 git-over-http 中禁止它们),让我们在此协议中禁止它们。
主机名同样可以注入换行符,但这在实践中不太可能成为问题;我们会尝试使用换行符解析主机名,但这是行不通的。
尽管如此,在这里谨慎行事并没有什么坏处,因为我们不希望它们一开始就起作用。
ssh 和本地代码路径不受此补丁的影响。
在这两种情况下,我们都尝试通过 shell 运行 upload-pack,并引用换行符以使其完整。
当然,攻击者可以将 ssh url 指向任意端口,但除非那里有一个实际的 ssh 服务器,否则我们永远无法发送我们的 shell 命令。
出于谨慎考虑,我们可以类似地限制这些协议中的换行符,但这样做似乎没有什么好处。
这里的新测试与 git-daemon(man) 测试一起运行,它们涵盖相同的协议,但它实际上根本不应该联系守护程序。
从理论上讲,我们可以通过设置一个包含换行符的实际存储库来使测试更加健壮(这样如果我们的新检查没有启动,我们的克隆就会成功)。
但是其中包含换行符的 repo 目录可能无法在所有文件系统中移植。
同样,我们可以检查 git-daemon 的日志,它根本没有被联系,但我们目前不记录日志(无论如何,它会使守护进程的日志写入测试变得激烈)。
我们将只检查客户端 stderr 以确保我们到达预期的代码路径。