File: common\crypto_libsodium.cpp
Function: AES_GCM_DecryptContext::Decrypt()

Throughout the code responsible for handling incoming messages there is an assumption that the maximal incoming message size is 1300 bytes:

/// Max size of UDP payload.  Includes API payload and
/// any headers, but does not include IP/UDP headers
/// (IP addresses, ports, checksum, etc.
const int k_cbSteamNetworkingSocketsMaxUDPMsgLen = 1300;
/// Use larger limits for what we are willing to receive.
const int k_cbSteamNetworkingSocketsMaxEncryptedPayloadRecv = k_cbSteamNetworkingSocketsMaxUDPMsgLen;
const int k_cbSteamNetworkingSocketsMaxPlaintextPayloadRecv = k_cbSteamNetworkingSocketsMaxUDPMsgLen;

However, when receiving the messages from the UDP socket, they are read with a size limit of 1300 + 1024:

// Recv socket data from any sockets that might have data, and execute the callbacks.
// EI-DBG: Actual recv buffer is 1024 MORE than the max length...
char buf[ k_cbSteamNetworkingSocketsMaxUDPMsgLen + 1024 ];

sockaddr_storage from;
socklen_t fromlen = sizeof(from);
int ret = ::recvfrom( pSock->m_socket, buf, sizeof( buf ), 0, (sockaddr *)&from, &fromlen );

This size mismatch breaks the incoming MTU assumption made when handling incoming encrypted messages, enabling an attacker to do the following:

  1. Find a game server / client that was compiled to use libsodium for the symmetric cryptography layer (default library is OpenSSL)
  2. Establish a connection with the target using the sockets protocol
  3. Send a large encrypted message, of size > 1300
  4. The encrypted message will be decrypted into a stack buffer of size 1300 bytes, leading to an overflow

Crash Trace:

*** stack smashing detected ***: <unknown> terminated