-- ---------------------------------------------------------------------- Sylvain Robitaille syl_at_alcor.concordia.ca Systems Manager Concordia University Instructional & Information Technology Montreal, Quebec, Canada ---------------------------------------------------------------------- --- newchannels.c.original Wed May 12 07:19:27 1999 +++ newchannels.c Wed Sep 29 14:35:50 1999 _at__at_ -16,6 +16,11 _at__at_ */ /* + * Revision 1.50unoff 1999/09/29 14:27:52 <syl_at_alcor.concordia.ca> + * ssh-agent symlink DoS exploit protection added + */ + +/* * $Id: newchannels.c,v 1.49 1999/02/22 08:14:01 tri Exp $ * $Log: newchannels.c,v $ * Revision 1.49 1999/02/22 08:14:01 tri _at__at_ -317,7 +322,77 _at__at_ #define STATUS_TERMINATE 0x003f -/* Data structure for channel data. This is iniailized in channel_allocate +/* + * 1999/09/29 Sylvain Robitaille: Used for mailing to the sysadmin(s) if + * we catch someone trying the exploit to cause the agent + * socket to be created at the other end of a sym-link. + */ +#define MAIL_RECIPIENT "sysadm" +#define MAIL_COMMAND "/usr/bin/mailx -s 'URGENT: POSSIBLE SSH-AGENT SYMLINK ATTACK' " MAIL_RECIPIENT + +/* + * Mail a complaint to the sysadmin. + */ +void mail_report(char *dirname, char *linkname, struct stat *st) +{ + FILE *mail_pipe; + struct passwd *pw; + struct group *gr; + char usrname[17]; + char grpname[17]; + char target[PATH_MAX]; + char filename[PATH_MAX]; + int count; + + if ((mail_pipe = popen(MAIL_COMMAND, "w")) == NULL) + { + snprintf(target, sizeof(target) - 1, "can't open pipe to %s\n", + MAIL_COMMAND); + log_msg(target); + exit(1); + } + + /* reconstruct the full path to the file */ + if (dirname[strlen(dirname)] == '/') dirname[strlen(dirname)] = 0; + snprintf(filename, sizeof(filename) - 1, "%s/%s", dirname, linkname); + + /* Figure out who owns the file. */ + pw = getpwuid(st->st_uid); + if (!pw) { + snprintf(usrname, sizeof(usrname) - 1, "%d", st->st_uid); + } else { + snprintf(usrname, sizeof(usrname) - 1, "%s", pw->pw_name); + } + + gr = getgrgid(st->st_gid); + if (!gr) { + snprintf(grpname, sizeof(grpname) - 1, "%d", st->st_gid); + } else { + snprintf(grpname, sizeof(grpname) - 1, "%s", gr->gr_name); + } + + /* + * Get the link's target. NOTE: The target may not necessarily + * already exist, so we don't bother getting stats on it, but we + * do want to know its path. + */ + count = readlink(filename, target, sizeof(target) - 1); + if (count < 0) { + snprintf(target, sizeof(target) - 1, "unreadable!"); + } else { + target[count] = '\0'; + } + + (void) fprintf(mail_pipe, "File: %s exists as a symbolic link\n", filename); + (void) fprintf(mail_pipe, "Owner: %s.%s\n", usrname, grpname); + (void) fprintf(mail_pipe, "Target: %s\n", target); + (void) fprintf(mail_pipe, "Mode: %o\n", 07777 & st->st_mode); + (void) fflush(mail_pipe); + + (void) pclose(mail_pipe); +} + +/* Data structure for channel data. This is initialized in channel_allocate and cleared in channel_free. */ typedef struct _at__at_ -2395,6 +2470,33 _at__at_ return 0; } + /* + * 1999/09/28 Sylvain Robitaille: Check that there isn't already a + * file by the same name. If there is, and it's a symbolic + * link, we probably have a DoS attempt. Else, if the file + * exists and is not already a socket, complain and fail. + * + * File exists but is a socket is acceptable, since that + * socket might be a remnant (did the machine crash while + * that socket was still open?) + */ + ret = lstat(channel_forwarded_auth_socket_name, &st); + if (!ret && S_ISLNK(st.st_mode)) { + packet_send_debug("* Remote error: Agent socket creation failed: File exists as a symbolic link."); + packet_send_debug("* Remote error: Authentication fowarding disabled."); + log_msg("Agent socket creation failed: File %s is a symbolic link.", + channel_forwarded_auth_socket_name); + mail_report(channel_forwarded_auth_socket_dir_name, + channel_forwarded_auth_socket_name, &st); + return 0; + } else if (!ret && !S_ISSOCK(st.st_mode)) { + packet_send_debug("* Remote error: Agent socket creation failed: File exists and is not a socket."); + packet_send_debug("* Remote error: Authentication fowarding disabled."); + log_msg("Agent socket creation failed: File %s is not a socket.", + channel_forwarded_auth_socket_name); + return 0; + } + /* Create the socket. */ sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) -- ---------------------------------------------------------------------- Sylvain Robitaille syl_at_alcor.concordia.ca Systems Manager Concordia University Instructional & Information Technology Montreal, Quebec, Canada ----------------------------------------------------------------------Received on Wed Sep 29 1999 - 21:25:11 NZST
This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:39 NZDT