- Criticality: Medium
- Component: SOCKS5 UDP proxy relay (
CDatagramSocketProxy / CProxyStateMachine)
- File:
src/Proxy.cpp:1374 (write), buffer declared in src/Proxy.h:248
- CWE: CWE-787 (Out-of-bounds Write) / CWE-120 (Buffer Copy without Checking Size of Input)
- Reachability: Local outbound path; requires a SOCKS5 UDP proxy to be configured and active, plus an outbound UDP datagram larger than 5110 bytes.
- Impact: Heap out-of-bounds write (memory corruption) of the bytes past the end of the fixed
m_buffer[5120].
Summary
When aMule sends a UDP datagram through a SOCKS5 proxy, CDatagramSocketProxy::SendTo
prepends a 10-byte SOCKS5 UDP request header into a fixed 5120-byte buffer
(m_buffer[PROXY_BUFFER_SIZE]) and then memcpys the entire payload (nBytes) right
after that header — without any bounds check. If the payload is larger than
PROXY_BUFFER_SIZE - PROXY_UDP_OVERHEAD_IPV4 (5120 − 10 = 5110) bytes, the copy writes
past the end of the buffer, corrupting adjacent heap/struct memory.
The sibling receive path, CDatagramSocketProxy::RecvFrom, performs exactly the size
check that is missing here (it allocates a dynamic buffer when the datagram would not
fit), which confirms the omission in SendTo is an oversight rather than an intended
invariant.
Affected code
src/Proxy.cpp — CDatagramSocketProxy::SendTo (no size guard before the copy):
uint32 CDatagramSocketProxy::SendTo(const amuleIPV4Address& addr, const void* buf, uint32 nBytes)
{
...
if (m_proxyTCPSocket.GetUseProxy()) {
if (m_udpSocketOk) {
m_proxyTCPSocket.GetBuffer()[0] = SOCKS5_RSV; // :1368
m_proxyTCPSocket.GetBuffer()[1] = SOCKS5_RSV;
m_proxyTCPSocket.GetBuffer()[2] = 0; // FRAG
m_proxyTCPSocket.GetBuffer()[3] = SOCKS5_ATYP_IPV4_ADDRESS;
PokeUInt32( m_proxyTCPSocket.GetBuffer()+4, StringIPtoUint32(addr.IPAddress()));
RawPokeUInt16( m_proxyTCPSocket.GetBuffer()+8, ENDIAN_HTONS( addr.Service() ) );
memcpy(m_proxyTCPSocket.GetBuffer() + PROXY_UDP_OVERHEAD_IPV4, buf, nBytes); // :1374 UNBOUNDED
nBytes += PROXY_UDP_OVERHEAD_IPV4;
sent = CLibUDPSocket::SendTo(...);
}
}
...
}
The destination is a fixed-size member buffer:
src/Proxy.h:
const unsigned int PROXY_BUFFER_SIZE = 5*1024; // :178 == 5120
const unsigned int PROXY_UDP_OVERHEAD_IPV4 = 10; // :496
...
char *GetBuffer() { return m_buffer; } // :230
...
char m_buffer[PROXY_BUFFER_SIZE]; // :248
So the writable space after the 10-byte header is 5120 - 10 = 5110 bytes, and
memcpy(... + 10, buf, nBytes) overflows whenever nBytes > 5110.
Why this is a real defect (the receive path proves it)
CDatagramSocketProxy::RecvFrom — the mirror of SendTo — contains the exact guard that
SendTo lacks:
// src/Proxy.cpp RecvFrom
if (nBytes + PROXY_UDP_MAXIMUM_OVERHEAD > PROXY_BUFFER_SIZE) { // :1300
bufUDP = new char[nBytes + PROXY_UDP_MAXIMUM_OVERHEAD]; // dynamic buffer when too big
} else {
bufUDP = m_proxyTCPSocket.GetBuffer();
}
SendTo writes into GetBuffer() directly with no equivalent check, so the asymmetry is
the bug.
Attack vector / trigger
- The user has configured a SOCKS5 proxy with UDP support and the UDP ASSOCIATE
negotiation has succeeded (m_udpSocketOk == true).
- aMule sends an outbound UDP datagram whose payload exceeds 5110 bytes through this
proxy (CDatagramSocketProxy::SendTo, reached via MuleUDPSocket-style send paths).
- Line 1374 copies the oversized payload past the end of
m_buffer[5120], corrupting
whatever follows the buffer in the enclosing object/heap.
nBytes is the size of an outbound datagram that aMule itself assembles, so it is not
directly attacker-controlled over the wire; this is why the criticality is Medium rather
than High. The harm requires an outbound UDP packet larger than 5110 bytes while a SOCKS5
UDP proxy is active. Standard eD2K/Kad UDP datagrams are normally well under this size, but
the interface places no upper bound on the payload, so any present or future caller passing
a larger buffer corrupts the heap.
Impact
- Out-of-bounds heap write of
nBytes - 5110 bytes immediately after m_buffer. Because
m_buffer is an inline member of CProxyStateMachine, the overflow corrupts adjacent
members and/or heap metadata, leading to crashes or potentially exploitable corruption.
- No read-side OOB; the defect is purely the unbounded write.
Suggested fix
Mirror the bound that RecvFrom already uses — reject or truncate payloads that do not fit
after the SOCKS5 UDP header:
if (nBytes > PROXY_BUFFER_SIZE - PROXY_UDP_OVERHEAD_IPV4) {
// Payload does not fit in the fixed SOCKS5 UDP relay buffer; drop it.
return 0;
}
memcpy(m_proxyTCPSocket.GetBuffer() + PROXY_UDP_OVERHEAD_IPV4, buf, nBytes);
(Alternatively, allocate a dynamic buffer for oversized datagrams exactly as RecvFrom
does at Proxy.cpp:1300.)
CDatagramSocketProxy/CProxyStateMachine)src/Proxy.cpp:1374(write), buffer declared insrc/Proxy.h:248m_buffer[5120].Summary
When aMule sends a UDP datagram through a SOCKS5 proxy,
CDatagramSocketProxy::SendToprepends a 10-byte SOCKS5 UDP request header into a fixed 5120-byte buffer
(
m_buffer[PROXY_BUFFER_SIZE]) and thenmemcpys the entire payload (nBytes) rightafter that header — without any bounds check. If the payload is larger than
PROXY_BUFFER_SIZE - PROXY_UDP_OVERHEAD_IPV4(5120 − 10 = 5110) bytes, the copy writespast the end of the buffer, corrupting adjacent heap/struct memory.
The sibling receive path,
CDatagramSocketProxy::RecvFrom, performs exactly the sizecheck that is missing here (it allocates a dynamic buffer when the datagram would not
fit), which confirms the omission in
SendTois an oversight rather than an intendedinvariant.
Affected code
src/Proxy.cpp—CDatagramSocketProxy::SendTo(no size guard before the copy):The destination is a fixed-size member buffer:
src/Proxy.h:So the writable space after the 10-byte header is
5120 - 10 = 5110bytes, andmemcpy(... + 10, buf, nBytes)overflows whenevernBytes > 5110.Why this is a real defect (the receive path proves it)
CDatagramSocketProxy::RecvFrom— the mirror ofSendTo— contains the exact guard thatSendTolacks:SendTowrites intoGetBuffer()directly with no equivalent check, so the asymmetry isthe bug.
Attack vector / trigger
negotiation has succeeded (
m_udpSocketOk == true).proxy (
CDatagramSocketProxy::SendTo, reached viaMuleUDPSocket-style send paths).m_buffer[5120], corruptingwhatever follows the buffer in the enclosing object/heap.
nBytesis the size of an outbound datagram that aMule itself assembles, so it is notdirectly attacker-controlled over the wire; this is why the criticality is Medium rather
than High. The harm requires an outbound UDP packet larger than 5110 bytes while a SOCKS5
UDP proxy is active. Standard eD2K/Kad UDP datagrams are normally well under this size, but
the interface places no upper bound on the payload, so any present or future caller passing
a larger buffer corrupts the heap.
Impact
nBytes - 5110bytes immediately afterm_buffer. Becausem_bufferis an inline member ofCProxyStateMachine, the overflow corrupts adjacentmembers and/or heap metadata, leading to crashes or potentially exploitable corruption.
Suggested fix
Mirror the bound that
RecvFromalready uses — reject or truncate payloads that do not fitafter the SOCKS5 UDP header:
(Alternatively, allocate a dynamic buffer for oversized datagrams exactly as
RecvFromdoes at
Proxy.cpp:1300.)