I was browsing through the code to eMule (0.26d), and noticed a couple potential problems with the use of UDP sockets with regards to security. It appears the IP of a UDP packet is taken to be trusted, however UDP packets can be easily forged to come from any source.
For example, based on the code from ClientUDPSocket.cpp, it would be possible to send "file not found" UDP packets to people trying to get a particular file, spoofed to be from various sources which have the file. (hope you understand what I mean by this).
The effect being, clients will drop the source and stop asking it for parts. (Through tests I know the client will drop the source, but correct me if Im wrong if this would eventually result in the source dropping the client from its queue).
This problem would seem to affect the following opcodes;
#define OP_REASKFILEPING 0x90 // <HASH 16> #define OP_REASKACK 0x91 // <HASH 16> #define OP_FILENOTFOUND 0x92 #define OP_QUEUEFULL 0x93
I haven't checked into this fully, but after a few tests, it would seem to be the case- let me know if you can think of a flaw in this theory. I have written a rough mod that sends a 'FILENOTFOUND' op to every source IP, spoffed to be from each IP (ie. 100 sources = 1000 spoofed packets), just to check if my theory was correct - but it didn't seem to have any effect - but this could be because of routers and filters etc. But when sending spoofed packets to myself, my client does drop the source.
If this is indeed a problem, a quick solution is to just turn off the UDP port. For the protocol, probably some kind of challenge response would be needed, - perhaps send a 'file ask' packet whenever you get a FILENOTFOUND packet just to be sure.
Cheers,
Shane.
ClientUDPSocket.cpp:---------------------
case OP_FILENOTFOUND: { theApp.downloadqueue->AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP(inet_addr(host)); //assumes the packet is not spoofed if (sender){ sender->UDPReaskFNF(); } else //ASSERT (false); //Need to double check these asserts to make sure it's running well. break; }
DownloadClient.cpp:----------------------
void CUpDownClient::UDPReaskFNF(){ m_bUDPPending = false; theApp.emuledlg->AddDebugLogLine(false,CString("UDP ANSWER FNF : %s"),GetUserName()); theApp.downloadqueue->RemoveSource(this); if (!socket) Disconnected(); }