Skip to content

Commit 61c7a0b

Browse files
authored
Fix CVE-2023-48795 in moby-compose by patching vendor packages (#9232)
1 parent a6e6339 commit 61c7a0b

2 files changed

Lines changed: 237 additions & 1 deletion

File tree

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
2+
index 653dc4d..e7d4545 100644
3+
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
4+
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
5+
@@ -34,6 +34,16 @@ type keyingTransport interface {
6+
// direction will be effected if a msgNewKeys message is sent
7+
// or received.
8+
prepareKeyChange(*algorithms, *kexResult) error
9+
+
10+
+ // setStrictMode sets the strict KEX mode, notably triggering
11+
+ // sequence number resets on sending or receiving msgNewKeys.
12+
+ // If the sequence number is already > 1 when setStrictMode
13+
+ // is called, an error is returned.
14+
+ setStrictMode() error
15+
+
16+
+ // setInitialKEXDone indicates to the transport that the initial key exchange
17+
+ // was completed
18+
+ setInitialKEXDone()
19+
}
20+
21+
// handshakeTransport implements rekeying on top of a keyingTransport
22+
@@ -94,6 +104,10 @@ type handshakeTransport struct {
23+
24+
// The session ID or nil if first kex did not complete yet.
25+
sessionID []byte
26+
+
27+
+ // strictMode indicates if the other side of the handshake indicated
28+
+ // that we should be following the strict KEX protocol restrictions.
29+
+ strictMode bool
30+
}
31+
32+
type pendingKex struct {
33+
@@ -201,7 +215,10 @@ func (t *handshakeTransport) readLoop() {
34+
close(t.incoming)
35+
break
36+
}
37+
- if p[0] == msgIgnore || p[0] == msgDebug {
38+
+ // If this is the first kex, and strict KEX mode is enabled,
39+
+ // we don't ignore any messages, as they may be used to manipulate
40+
+ // the packet sequence numbers.
41+
+ if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) {
42+
continue
43+
}
44+
t.incoming <- p
45+
@@ -432,6 +449,11 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
46+
return successPacket, nil
47+
}
48+
49+
+const (
50+
+ kexStrictClient = "kex-strict-c-v00@openssh.com"
51+
+ kexStrictServer = "kex-strict-s-v00@openssh.com"
52+
+)
53+
+
54+
// sendKexInit sends a key change message.
55+
func (t *handshakeTransport) sendKexInit() error {
56+
t.mu.Lock()
57+
@@ -445,7 +467,6 @@ func (t *handshakeTransport) sendKexInit() error {
58+
}
59+
60+
msg := &kexInitMsg{
61+
- KexAlgos: t.config.KeyExchanges,
62+
CiphersClientServer: t.config.Ciphers,
63+
CiphersServerClient: t.config.Ciphers,
64+
MACsClientServer: t.config.MACs,
65+
@@ -455,6 +476,13 @@ func (t *handshakeTransport) sendKexInit() error {
66+
}
67+
io.ReadFull(rand.Reader, msg.Cookie[:])
68+
69+
+ // We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm,
70+
+ // and possibly to add the ext-info extension algorithm. Since the slice may be the
71+
+ // user owned KeyExchanges, we create our own slice in order to avoid using user
72+
+ // owned memory by mistake.
73+
+ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info
74+
+ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
75+
+
76+
isServer := len(t.hostKeys) > 0
77+
if isServer {
78+
for _, k := range t.hostKeys {
79+
@@ -474,17 +502,24 @@ func (t *handshakeTransport) sendKexInit() error {
80+
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
81+
}
82+
}
83+
+
84+
+ if t.sessionID == nil {
85+
+ msg.KexAlgos = append(msg.KexAlgos, kexStrictServer)
86+
+ }
87+
} else {
88+
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
89+
90+
// As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
91+
// algorithms the server supports for public key authentication. See RFC
92+
// 8308, Section 2.1.
93+
+ //
94+
+ // We also send the strict KEX mode extension algorithm, in order to opt
95+
+ // into the strict KEX mode.
96+
if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
97+
- msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1)
98+
- msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
99+
msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
100+
+ msg.KexAlgos = append(msg.KexAlgos, kexStrictClient)
101+
}
102+
+
103+
}
104+
105+
packet := Marshal(msg)
106+
@@ -581,6 +616,13 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
107+
return err
108+
}
109+
110+
+ if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
111+
+ t.strictMode = true
112+
+ if err := t.conn.setStrictMode(); err != nil {
113+
+ return err
114+
+ }
115+
+ }
116+
+
117+
// We don't send FirstKexFollows, but we handle receiving it.
118+
//
119+
// RFC 4253 section 7 defines the kex and the agreement method for
120+
@@ -615,7 +657,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
121+
return err
122+
}
123+
124+
- if t.sessionID == nil {
125+
+ firstKeyExchange := t.sessionID == nil
126+
+ if firstKeyExchange {
127+
t.sessionID = result.H
128+
}
129+
result.SessionID = t.sessionID
130+
@@ -632,6 +675,12 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
131+
return unexpectedMessageError(msgNewKeys, packet[0])
132+
}
133+
134+
+ if firstKeyExchange {
135+
+ // Indicates to the transport that the first key exchange is completed
136+
+ // after receiving SSH_MSG_NEWKEYS.
137+
+ t.conn.setInitialKEXDone()
138+
+ }
139+
+
140+
return nil
141+
}
142+
143+
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
144+
index acf5a21..4df45fc 100644
145+
--- a/vendor/golang.org/x/crypto/ssh/transport.go
146+
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
147+
@@ -48,6 +48,9 @@ type transport struct {
148+
rand io.Reader
149+
isClient bool
150+
io.Closer
151+
+
152+
+ strictMode bool
153+
+ initialKEXDone bool
154+
}
155+
156+
// packetCipher represents a combination of SSH encryption/MAC
157+
@@ -73,6 +76,18 @@ type connectionState struct {
158+
pendingKeyChange chan packetCipher
159+
}
160+
161+
+func (t *transport) setStrictMode() error {
162+
+ if t.reader.seqNum != 1 {
163+
+ return errors.New("ssh: sequence number != 1 when strict KEX mode requested")
164+
+ }
165+
+ t.strictMode = true
166+
+ return nil
167+
+}
168+
+
169+
+func (t *transport) setInitialKEXDone() {
170+
+ t.initialKEXDone = true
171+
+}
172+
+
173+
// prepareKeyChange sets up key material for a keychange. The key changes in
174+
// both directions are triggered by reading and writing a msgNewKey packet
175+
// respectively.
176+
@@ -111,11 +126,12 @@ func (t *transport) printPacket(p []byte, write bool) {
177+
// Read and decrypt next packet.
178+
func (t *transport) readPacket() (p []byte, err error) {
179+
for {
180+
- p, err = t.reader.readPacket(t.bufReader)
181+
+ p, err = t.reader.readPacket(t.bufReader, t.strictMode)
182+
if err != nil {
183+
break
184+
}
185+
- if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
186+
+ // in strict mode we pass through DEBUG and IGNORE packets only during the initial KEX
187+
+ if len(p) == 0 || (t.strictMode && !t.initialKEXDone) || (p[0] != msgIgnore && p[0] != msgDebug) {
188+
break
189+
}
190+
}
191+
@@ -126,7 +142,7 @@ func (t *transport) readPacket() (p []byte, err error) {
192+
return p, err
193+
}
194+
195+
-func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
196+
+func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool) ([]byte, error) {
197+
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
198+
s.seqNum++
199+
if err == nil && len(packet) == 0 {
200+
@@ -139,6 +155,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
201+
select {
202+
case cipher := <-s.pendingKeyChange:
203+
s.packetCipher = cipher
204+
+ if strictMode {
205+
+ s.seqNum = 0
206+
+ }
207+
default:
208+
return nil, errors.New("ssh: got bogus newkeys message")
209+
}
210+
@@ -169,10 +188,10 @@ func (t *transport) writePacket(packet []byte) error {
211+
if debugTransport {
212+
t.printPacket(packet, true)
213+
}
214+
- return t.writer.writePacket(t.bufWriter, t.rand, packet)
215+
+ return t.writer.writePacket(t.bufWriter, t.rand, packet, t.strictMode)
216+
}
217+
218+
-func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
219+
+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte, strictMode bool) error {
220+
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
221+
222+
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
223+
@@ -187,6 +206,9 @@ func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []
224+
select {
225+
case cipher := <-s.pendingKeyChange:
226+
s.packetCipher = cipher
227+
+ if strictMode {
228+
+ s.seqNum = 0
229+
+ }
230+
default:
231+
panic("ssh: no key material for msgNewKeys")
232+
}

SPECS/moby-compose/moby-compose.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Summary: Define and run multi-container applications with Docker
22
Name: moby-compose
33
Version: 2.17.3
4-
Release: 3%{?dist}
4+
Release: 4%{?dist}
55
License: ASL 2.0
66
Vendor: Microsoft Corporation
77
Distribution: Mariner
@@ -18,6 +18,7 @@ Patch1: patch-server.go-to-support-single-serverWorkerChannel.patch
1818
Patch2: Change-server-stream-context-handling.patch
1919
Patch3: prohibit-more-than-MaxConcurrentStreams-handlers.patch
2020
Patch4: CVE-2023-45288.patch
21+
Patch5: CVE-2023-48795.patch
2122

2223
# Leverage the `generate_source_tarball.sh` to create the vendor sources
2324
# NOTE: govendor-v1 format is for inplace CVE updates so that we do not have to overwrite in the blob-store.
@@ -56,6 +57,9 @@ install -D -m0755 bin/build/docker-compose %{buildroot}/%{_libexecdir}/docker/cl
5657
%{_libexecdir}/docker/cli-plugins/docker-compose
5758

5859
%changelog
60+
* Tue May 28 2024 Bala <balakumaran.kannan@microsoft.com> - 2.17.3-4
61+
- Fix for CVE-2023-48795
62+
5963
* Thu Apr 18 2024 Chris Gunn <chrisgun@microsoft.com> - 2.17.3-3
6064
- Fix for CVE-2023-45288
6165

0 commit comments

Comments
 (0)