--
----------------------------------------------------------------------
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 Thu Sep 30 11:50:11 1999
***************
*** 16,21 ****
--- 16,26 ----
*/
/*
+ * 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
***************
*** 317,323 ****
#define STATUS_TERMINATE 0x003f
! /* Data structure for channel data. This is iniailized in channel_allocate
and cleared in channel_free. */
typedef struct
--- 322,398 ----
#define STATUS_TERMINATE 0x003f
! /*
! * 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)-1] == '/') dirname[strlen(dirname)-1] = 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
***************
*** 2395,2400 ****
--- 2470,2502 ----
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)
Received on Thu Sep 30 1999 - 17:36:45 NZST
This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:39 NZDT