patches for easier mirroring, to eliminate a special copy, to make www.freebsd.org/security a full copy of security.freebsd.org and be eventually be the same. For now files are just sitting there. The symlinks are missing. Discussed on: www (repository location) Discussed with: simon (so)
357 lines
11 KiB
Text
357 lines
11 KiB
Text
-----BEGIN PGP SIGNED MESSAGE-----
|
|
|
|
=============================================================================
|
|
FreeBSD-SA-96:21 Security Advisory
|
|
FreeBSD, Inc.
|
|
|
|
Topic: unauthorized access via buffer overrun in talkd
|
|
|
|
Category: core
|
|
Module: talkd
|
|
Announced: 1997-01-18
|
|
Affects: 1.0, 1.1, 2.1.0, 2.1.5, 2.1.6, 2.1.6.1
|
|
Corrected: 2.2-current as of 1997-01-18
|
|
2.1-stable as of 1197-01-18
|
|
FreeBSD only: no
|
|
|
|
Patches: ftp://freebsd.org/pub/CERT/patches/SA-96:21/
|
|
References: AUSCERT AA-97.01 (Australian CERT organization),
|
|
SEI CERT VU#5942 (internal tracking reference only)
|
|
|
|
=============================================================================
|
|
|
|
I. Background
|
|
|
|
Buffer overrun (aka stack overflow) exploits in system
|
|
supplied and locally installed utilities are commonly
|
|
used by individuals wishing to obtain unauthorized access to
|
|
computer systems. The FreeBSD team has been reviewing and
|
|
fixing the source code pool to eliminate potential exploits
|
|
based on this technique.
|
|
|
|
Recently, the Australian CERT organization received information
|
|
of a buffer-overrun vulnerability in the talkd daemon shipped in
|
|
most modern BSD based systems.
|
|
|
|
|
|
II. Problem Description
|
|
|
|
To quote AUSCERT:
|
|
|
|
talk is a communication program which copies text from one
|
|
users terminal to that of another, possibly remote, user.
|
|
talkd is the daemon that notifies a user that someone else wishes
|
|
to initiate a conversation.
|
|
|
|
As part of the talk connection, talkd does a DNS lookup
|
|
for the hostname of the host where the connection is being
|
|
initiating from. Due to insufficient bounds checking on
|
|
the buffer where the hostname is stored, it is possible to
|
|
overwrite the internal stack space of talkd. By carefully
|
|
manipulating the hostname information, it is possible to
|
|
force talkd to execute arbitrary commands. As talkd runs
|
|
with root privileges, this may allow intruders to remotely
|
|
execute arbitrary commands with these privileges.
|
|
|
|
This attack requires an intruder to be able to make a
|
|
network connection to a vulnerable talkd program and provide
|
|
corrupt DNS information to that host.
|
|
|
|
This type of attack is a particular instance of the problem
|
|
described in CERT advisory CA-96.04 "Corrupt Information
|
|
from Network Servers". This advisory is available from:
|
|
|
|
ftp://info.cert.org/pub/cert_advisories/
|
|
|
|
Recent versions of FreeBSD 2.2 -current may not be affected
|
|
with this vulnerability due to improved security in
|
|
new versions of BIND, which sanity-check the results of
|
|
reverse name lookups performed by the DNS system.
|
|
|
|
|
|
III. Impact
|
|
|
|
|
|
Intruders may be able to remotely execute arbitrary commands
|
|
with root privileges.
|
|
|
|
Access to a valid user account on the local system is not
|
|
required.
|
|
|
|
|
|
IV. Workaround
|
|
|
|
Disable the ntalkd program found in /etc/inetd.conf by
|
|
commenting the appropriate line out and reconfiguring inetd.
|
|
|
|
# grep -i ntalk /etc/inetd.conf
|
|
ntalk dgram udp wait root /usr/libexec/ntalkd ntalkd
|
|
|
|
After editing /etc/inetd.conf, reconfigure inetd by sending
|
|
it a HUP signal.
|
|
|
|
# kill -HUP `cat /var/run/inetd.pid`
|
|
|
|
V. Solution
|
|
|
|
The patches found at the following URL fix this vulnerability.
|
|
Patches are available for FreeBSD 2.1.x (-stable) and -current.
|
|
|
|
Acknowledgment:
|
|
|
|
These patches were based off of published work provided by
|
|
BSDI, Inc.
|
|
|
|
After applying these patches, recompile and re-install the
|
|
affected utilities.
|
|
|
|
For FreeBSD -current (2.2 prerelease and 3.0 prerelease)
|
|
systems:
|
|
|
|
Index: announce.c
|
|
===================================================================
|
|
RCS file: /cvs/freebsd/src/libexec/talkd/announce.c,v
|
|
retrieving revision 1.6
|
|
diff -u -r1.6 announce.c
|
|
--- announce.c 1997/01/14 06:20:58 1.6
|
|
+++ announce.c 1997/01/18 08:27:04
|
|
@@ -34,7 +34,7 @@
|
|
*/
|
|
|
|
#ifndef lint
|
|
-static char sccsid[] = "@(#)announce.c 8.2 (Berkeley) 1/7/94";
|
|
+static char sccsid[] = "@(#)announce.c 8.3 (Berkeley) 4/28/95";
|
|
#endif /* not lint */
|
|
|
|
#include <sys/types.h>
|
|
@@ -43,13 +43,17 @@
|
|
#include <sys/time.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/socket.h>
|
|
+
|
|
#include <protocols/talkd.h>
|
|
+
|
|
#include <errno.h>
|
|
-#include <syslog.h>
|
|
-#include <unistd.h>
|
|
+#include <paths.h>
|
|
#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
#include <string.h>
|
|
-#include <paths.h>
|
|
+#include <syslog.h>
|
|
+#include <unistd.h>
|
|
+#include <vis.h>
|
|
|
|
extern char hostname[];
|
|
|
|
@@ -78,7 +82,7 @@
|
|
|
|
#define max(a,b) ( (a) > (b) ? (a) : (b) )
|
|
#define N_LINES 5
|
|
-#define N_CHARS 120
|
|
+#define N_CHARS 256
|
|
|
|
/*
|
|
* Build a block of characters containing the message.
|
|
@@ -100,33 +104,37 @@
|
|
char line_buf[N_LINES][N_CHARS];
|
|
int sizes[N_LINES];
|
|
char big_buf[N_LINES*N_CHARS];
|
|
- char *bptr, *lptr, *ttymsg();
|
|
+ char *bptr, *lptr, *vis_user;
|
|
int i, j, max_size;
|
|
|
|
i = 0;
|
|
max_size = 0;
|
|
gettimeofday(&clock, &zone);
|
|
localclock = localtime( &clock.tv_sec );
|
|
- (void)sprintf(line_buf[i], " ");
|
|
+ (void)snprintf(line_buf[i], N_CHARS, " ");
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
|
|
- hostname, localclock->tm_hour , localclock->tm_min );
|
|
+ (void)snprintf(line_buf[i], N_CHARS,
|
|
+ "Message from Talk_Daemon@%s at %d:%02d ...",
|
|
+ hostname, localclock->tm_hour , localclock->tm_min );
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], "talk: connection requested by %s@%s",
|
|
- request->l_name, remote_machine);
|
|
+
|
|
+ vis_user = malloc(strlen(request->l_name) * 4 + 1);
|
|
+ strvis(vis_user, request->l_name, VIS_CSTYLE);
|
|
+ (void)snprintf(line_buf[i], N_CHARS,
|
|
+ "talk: connection requested by %s@%s", vis_user, remote_machine);
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s",
|
|
- request->l_name, remote_machine);
|
|
+ (void)snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s",
|
|
+ vis_user, remote_machine);
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], " ");
|
|
+ (void)snprintf(line_buf[i], N_CHARS, " ");
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
Index: talkd.c
|
|
===================================================================
|
|
RCS file: /cvs/freebsd/src/libexec/talkd/talkd.c,v
|
|
retrieving revision 1.5
|
|
diff -u -r1.5 talkd.c
|
|
--- talkd.c 1997/01/14 06:21:01 1.5
|
|
+++ talkd.c 1997/01/18 08:26:44
|
|
@@ -71,7 +71,7 @@
|
|
void timeout();
|
|
long lastmsgtime;
|
|
|
|
-char hostname[MAXHOSTNAMELEN];
|
|
+char hostname[MAXHOSTNAMELEN + 1];
|
|
|
|
#define TIMEOUT 30
|
|
#define MAXIDLE 120
|
|
|
|
For FreeBSD 2.1 based systems:
|
|
|
|
--- announce.c 1995/05/30 05:46:38 1.3
|
|
+++ announce.c 1997/01/18 08:33:55 1.3.4.1
|
|
@@ -32,7 +32,7 @@
|
|
*/
|
|
|
|
#ifndef lint
|
|
-static char sccsid[] = "@(#)announce.c 8.2 (Berkeley) 1/7/94";
|
|
+static char sccsid[] = "@(#)announce.c 8.3 (Berkeley) 4/28/95";
|
|
#endif /* not lint */
|
|
|
|
#include <sys/types.h>
|
|
@@ -41,15 +41,18 @@
|
|
#include <sys/time.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/socket.h>
|
|
+
|
|
#include <protocols/talkd.h>
|
|
-#include <sgtty.h>
|
|
+
|
|
#include <errno.h>
|
|
-#include <syslog.h>
|
|
-#include <unistd.h>
|
|
+#include <paths.h>
|
|
#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
#include <string.h>
|
|
-#include <paths.h>
|
|
-
|
|
+#include <syslog.h>
|
|
+#include <unistd.h>
|
|
+#include <vis.h>
|
|
+
|
|
extern char hostname[];
|
|
|
|
/*
|
|
@@ -77,7 +80,7 @@
|
|
|
|
#define max(a,b) ( (a) > (b) ? (a) : (b) )
|
|
#define N_LINES 5
|
|
-#define N_CHARS 120
|
|
+#define N_CHARS 256
|
|
|
|
/*
|
|
* Build a block of characters containing the message.
|
|
@@ -99,33 +102,37 @@
|
|
char line_buf[N_LINES][N_CHARS];
|
|
int sizes[N_LINES];
|
|
char big_buf[N_LINES*N_CHARS];
|
|
- char *bptr, *lptr, *ttymsg();
|
|
+ char *bptr, *lptr, *vis_user;
|
|
int i, j, max_size;
|
|
|
|
i = 0;
|
|
max_size = 0;
|
|
gettimeofday(&clock, &zone);
|
|
localclock = localtime( &clock.tv_sec );
|
|
- (void)sprintf(line_buf[i], " ");
|
|
+ (void)snprintf(line_buf[i], N_CHARS, " ");
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
|
|
- hostname, localclock->tm_hour , localclock->tm_min );
|
|
+ (void)snprintf(line_buf[i], N_CHARS,
|
|
+ "Message from Talk_Daemon@%s at %d:%02d ...",
|
|
+ hostname, localclock->tm_hour , localclock->tm_min );
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], "talk: connection requested by %s@%s",
|
|
- request->l_name, remote_machine);
|
|
+
|
|
+ vis_user = malloc(strlen(request->l_name) * 4 + 1);
|
|
+ strvis(vis_user, request->l_name, VIS_CSTYLE);
|
|
+ (void)snprintf(line_buf[i], N_CHARS,
|
|
+ "talk: connection requested by %s@%s", vis_user, remote_machine);
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s",
|
|
- request->l_name, remote_machine);
|
|
+ (void)snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s",
|
|
+ vis_user, remote_machine);
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
- (void)sprintf(line_buf[i], " ");
|
|
+ (void)snprintf(line_buf[i], N_CHARS, " ");
|
|
sizes[i] = strlen(line_buf[i]);
|
|
max_size = max(max_size, sizes[i]);
|
|
i++;
|
|
Index: talkd.c
|
|
===================================================================
|
|
RCS file: /home/ncvs/src/libexec/talkd/talkd.c,v
|
|
retrieving revision 1.3
|
|
retrieving revision 1.3.4.1
|
|
diff -u -r1.3 -r1.3.4.1
|
|
--- talkd.c 1995/05/30 05:46:44 1.3
|
|
+++ talkd.c 1997/01/18 08:33:56 1.3.4.1
|
|
@@ -69,7 +69,7 @@
|
|
void timeout();
|
|
long lastmsgtime;
|
|
|
|
-char hostname[MAXHOSTNAMELEN];
|
|
+char hostname[MAXHOSTNAMELEN + 1];
|
|
|
|
#define TIMEOUT 30
|
|
#define MAXIDLE 120
|
|
|
|
|
|
=============================================================================
|
|
FreeBSD, Inc.
|
|
|
|
Web Site: http://www.freebsd.org/
|
|
Confidential contacts: security-officer@freebsd.org
|
|
PGP Key: ftp://freebsd.org/pub/CERT/public_key.asc
|
|
Security notifications: security-notifications@freebsd.org
|
|
Security public discussion: security@freebsd.org
|
|
|
|
Notice: Any patches in this document may not apply cleanly due to
|
|
modifications caused by digital signature or mailer software.
|
|
Please reference the URL listed at the top of this document
|
|
for original copies of all patches if necessary.
|
|
=============================================================================
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
Version: 2.6.3ia
|
|
Charset: noconv
|
|
|
|
iQCVAwUBMuCVAVUuHi5z0oilAQGx7gQAiiptKNx7xoeHec1jmBFLsoGBrxO9H3TC
|
|
0FHl4n3p/MQEO3OEfChepC5coTAe00SjOEpnAZIinHbtVzNaodPs0hyMbQ7UnpPq
|
|
wIRlxsPhxVuS+rbrY62pvn1Iagr4SaMAaseGK18f+Tq2Lbwc6//1bTOBn+Ms980F
|
|
VaXsIaKYinQ=
|
|
=yj1H
|
|
-----END PGP SIGNATURE-----
|