aboutsummaryrefslogtreecommitdiff
path: root/share/security/advisories/FreeBSD-SA-96:21.talkd.asc
blob: 36e9cfea6b05d37e10a814c98ae8074d656f89ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
-----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-----