--
----------------------------------------------------------------------
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