Protocol: talk Affected Operating System: Linux and probably BSD based systems Requirements: account on system Security Compromise: appear as any user during talk and respond to any talk request I don't know if this is a common and known problem. This is a problem I encountered during the writing of my own talk client, whereafter I immediately exploited it by patching get_names.c from the talk client which is included in NetKit-B-0.05 for linux (the small patch is included below). Patching other operatings systems should be easy. Basically the talk protocol works like this, providing you have two users (A and B), two talk clients (client A and client B) and two system talk daemons (daemon A and daemon B) and A wants to speak to B: 1) User A starts up client A supplying he wants to speak to B. 2) Client A sends a LOOK_UP specifying A and B to daemon B. 3) There is no connection waiting from B so daemon B responds with a failure. 4) Client A sends an ANNOUNCE and his name to daemon B. 5) Client A sends a LEAVE_INVITE to daemon A (local daemon), specifying his own name and the TCP address and port which is waiting for connect. 6) Daemon B prints a message on the screen of user B specifying A wants to talk to him. 7) User B starts up client B supplying he wants to speak to A. 8) Client B sends a LOOK_UP specifying B and A to daemon A. 9) Daemon A returns the TPC address and port. 10) Client B connects to the TCP address and port. 11) Client A and client B, and thus A and B, happily talk. The protocol trusts the client for supplying the correct user name. However every user on the system can modify the source code and rebuild it since it doesn't has to run as root (priviliged ports). By modifying the source code of talk (get_names.c) of the NetKit-B-0.05 you make the talk client think you are another user. This can easily be done by modifying one line of source code: +++ patched_names.c Wed Apr 17 21:36:47 1996 @@ -113,7 +113,7 @@ msg.addr.sa_family = htons(AF_INET); msg.ctl_addr.sa_family = htons(AF_INET); msg.id_num = htonl(0); - strncpy(msg.l_name, my_name, NAME_SIZE); + strncpy(msg.l_name, "root", NAME_SIZE); msg.l_name[NAME_SIZE - 1] = '\0'; strncpy(msg.r_name, his_name, NAME_SIZE); msg.r_name[NAME_SIZE - 1] = '\0'; What happends when user A runs this modified client is simple. Not his name but the name "root" is sent to the remote daemon (line 4) and the local daemon (line 5). Both daemons do not check this, but take it for granted. After this B tries to make a connect to "root" and client B sends a request indicating he wants to talk to "root" (line 8). Daemon A does a lookup for "root" and B and finds a perfect match and sends back to client B the IP address and port number (line 9) and client B connects (line 10). In this example A and B happily talk (line 11), but what if our A wasn't a good civilian and asked B his password due to system failure (or whatever). No protocol should be easily trusted but this makes it for a hacker pretty easy to social engineer around and gather system passwords. Note that another implication of this problem is that when A wants to talk to the root, B can reply to this talk request by applying the above patch. When B does a LOOK_UP as root at the daemon of A he will still be given the IP address and port number which he connects and again seems to be root. A fix to this problem could be that local daemon immediately verifies that the specified is also the user that binded the specified socket. Another fix could be that both clients do an AUTH lookup. Rombout de Backer (r@idb.nl) I'd like to hear suggestions. This information is for free use and may be copied freely (please do), but please keep the whole text intact including this footnote. --- -- [ route@infonexus.com ] Guild member, Information enthusiast, Hacker, demon ...this universe is MINE... I am *GOD* here...