Computer Security

#9 SMEP 우회 본문

리눅스 커널 해킹

#9 SMEP 우회

쿠리 Kuri 2022. 8. 17. 18:30
반응형

SMEP(Supervisor Mode Execution Prevention) 

 

커널 공간에서 유저 공간에 대한 실행 권한을 제한하는 보호 기법. 즉, ring 0 권한 일 때, ring3와 관련된 코드를 실행할 수 없다는 것이다.

 

유저 공간의 NX bit(1) 보호 기법과 유사하다.

 

cr4 레지스터에 SMEP를 on/off 하는 제어 비트가 있다.

 

우회하기 위해 kernel ROP(2) 작성이 필요하다.

 

 

 

 

(1) NX bit : 특정한 지역의 메모리에 실행되는곳, 실행 안되는곳, 편집 불가능한곳을 만드는 exploit 보안 기법이다.

ex) 데이터, 스택 및 힙 세그먼트는 실행 불가능한 반면 텍스트 세그먼트는 쓰기 불가능으로 만들어 지는것

 

(2) ROP : 반환 지향형 프로그래밍(ROP: Return-oriented programming)

  • 어셈블리 gadget(3) 들을 chaining 하여 프로그램의 흐름을 공격자가 원하는 대로 바꾸는 공격 기법.
  • 다양한 메모리 보호 기법들을 우회하기 용이한 기법이다.
  • 보통 유저공간에서는 ASLR 과 NX bit 보호 기법을 우회하기 위해 사용한다.

 

(3) gadget: 공격자가 원하는 동작을 하기 위한 어셈블리 코드 조각을 뜻한다.

 

 


commit_creds(prepare_kernel_cred(0))

 

prepare_kernel_cred(0) 은 root credentials 를 준비하는 역할

commit_creds() 는 현재 태스크의 credentials 를 인자로 받은 credentials로 갱신하는 역할

즉, 현재 태스크의 권한을 root로 바꾸는 코드

 

커널 공격자들은 대부분 이 코드를 실행하는 것을 공격 목표로 한다.

 

 

 


우리는 아래의 파일들로 실습 할 것이다.

smep_bypass

 

nosmep.sh : SMEP를 적용하지 않은 qemu script

smep.sh : SMEP을 적용한 qemu script

test.c : 간단한 취약점이 터지는 디바이스 드라이버 예제

exp.c : 취약점을 이용해 권한 상승을 일으키는 exploit code

 

 

 


 

1. 커널의 흐름을 원하는 대로 조작할 수 있는 디바이스 드라이버 예제인 test.c 를 살펴보자.

test.c

test_init( )함수에서 misc 디바이스를 등록하여 /dev 경로에 test라는 디바이스가 생성되는 것을 알 수 있다.

 

test_write() 함수에서 copy_from_user 함수를 이용해 유저로부터 주소를 전달 받아, 그 주소를 실행하는 것을 볼 수 있다.

 

 

 


2.test 드라이버에서 터지는 취약점을 이용해 권한 상승을 일으키는 exploit code 인 exp.c 코드를 분석 해보자.

exp.c

write() 함수를 이용해 test 드라이버에 payload(1) 함수의 주소를 전달한다.

 

전체적인 흐름은 ret2usr 라는 기법을 이용한다.

 

 

 

(1)  payload함수:  commit_ceds(prepare_kernel_cred(0)) 코드를 실행한 후, /bin/sh 를 실행하는 역할이다.

 

 


3. nosmep.sh 실행을 하여 실습 해보도록 하자.

./nosmep.sh

SMEP 보호 기법을 적용하지 않은 nosmep.sh를 실행한 후, exp를 실행한 결과이다.

 

test 드라이버의 취약점을 이용해 user 권한에서 root권한을 획득 한 것을 볼 수 있다.

 

 

전체적인 흐름

 

 

커널공간 : test.c     ,      유저공간 : exp.c

 

 

커널 공간 misc_register(&test_driver)   -->  유저공간 fd=open("/dev/test", O_RDWR) 

--> 유저공간 write(fd,&ptr,sizeof(ptr))   --> 커널공간 test_write() 

--> 커널공간 copy_from_user(&fp_exec,...)  -->  커널공간 fp_exec()

 

 


4. SMEP 기법이 적용된 smep.sh를 실행 해보자.

SMEP 보호기법을 적용한 smep.sh를 실행한 후, exp를 실행한 결과

SMEP에 의해 userspace code를 실행할 수 없다는 kernel panic이 발생한 것을 볼 수 있다.

 

SMEP보호기법이란 커널공간에서 유저공간의 코드를 실행하는것을 막아주는 기법이기 때문에, tset드라이버의 취약점 때문에, 커널에서 exp.c 코드의 payload 함수를 실행하게 되는데, 이 payload함수는 유저공간의 text영역에 존재하는 코드이기 때문에,  kernel panic이 발생한 것이다.

 

 

 


5. SMEP 우회 방법

 

  • 커널 영역에 있는 어셈블리 gadget을 이용해 kernel ROP를 작성해야 한다.
  • kernel ROP를 작성할 경우, 유저 공간의 코드는 실행되지 않으므로 SMEP를 우회할 수 있다.
  • ROP payload로 commit_creds(prepare_kernel_cred(0)) 코드를 구현한다.
  • 유저 공간에서 gadget을 구하듯이 objdump, rp++ 등을 이용해 vmlinux 이미지에서  kernel gadget을 구하면 된다.

 

반응형

'리눅스 커널 해킹' 카테고리의 다른 글

#11 KADR 우회  (0) 2022.08.19
#10 SMAP 우회  (0) 2022.08.18
#8 KASLR 우회  (0) 2022.08.16
#7 리눅스 커널 보호 기법  (0) 2022.08.15
#6 리눅스 CTF에서의 환경 셋팅  (0) 2022.08.14
Comments