Skip to content

Commit d1869da

Browse files
committed
There is a buffer overflow bug in Shadowsocks UDP packet encoding. In the EncodeUDPPacket function of proxy/shadowsocks/protocol.go, a fixed-size buffer of 2048 bytes is created using buf.New().
However, the actual size of a UDP packet includes: IV: 16 bytes (e.g., for aes-128-gcm) Destination address: 7~258 bytes (depending on IPv4/IPv6/domain) Payload: variable, up to 2048 bytes AEAD authentication tag: 16 bytes When the incoming payload is large (close to 2048 bytes), the total size exceeds the buffer capacity. When b.Extend() is called in AEADCipher.EncodePacket() to allocate space for the authentication tag, it triggers panic: extending out of bound, causing the process to crash. Fix Before creating the buffer, calculate the required buffer size based on IV length, maximum address length (258 bytes), payload length, and AEAD overhead (16 bytes). If the required size exceeds the default buffer size (2048 bytes), use buf.NewWithSize() to allocate a sufficiently large buffer.
1 parent 7227b98 commit d1869da

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

proxy/shadowsocks/protocol.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,30 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
186186
user := request.User
187187
account := user.Account.(*MemoryAccount)
188188

189-
buffer := buf.New()
190189
ivLen := account.Cipher.IVSize()
190+
// Calculate required buffer size: IV + max address length (1+255+2) + payload + AEAD overhead (16)
191+
neededSize := ivLen + 258 + int32(len(payload)) + 16
192+
193+
var buffer *buf.Buffer
194+
if neededSize > buf.Size {
195+
buffer = buf.NewWithSize(neededSize)
196+
} else {
197+
buffer = buf.New()
198+
}
199+
191200
if ivLen > 0 {
192201
common.Must2(buffer.ReadFullFrom(rand.Reader, ivLen))
193202
}
194203

195204
if err := addrParser.WriteAddressPort(buffer, request.Address, request.Port); err != nil {
205+
buffer.Release()
196206
return nil, newError("failed to write address").Base(err)
197207
}
198208

199209
buffer.Write(payload)
200210

201211
if err := account.Cipher.EncodePacket(account.Key, buffer); err != nil {
212+
buffer.Release()
202213
return nil, newError("failed to encrypt UDP payload").Base(err)
203214
}
204215

0 commit comments

Comments
 (0)