일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- write up
- 드론
- 컴퓨터구조
- 시스템프로그래밍
- Bandit
- 시그널
- Pwnable.kr
- 리눅스 커널
- px4
- wargame
- 시스템
- Leviathan
- radare2
- 리눅스
- pwn.college
- 워게임
- css
- C++
- 리버싱
- 시스템 프로그래밍
- pwncollege
- 시스템해킹
- 커널
- 리눅스커널
- kernel
- C언어
- 알고리즘
- 프로그래밍
- 어셈블리어
- 취약점
- Today
- Total
Computer Security
#9 SMEP 우회 본문
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로 바꾸는 코드
커널 공격자들은 대부분 이 코드를 실행하는 것을 공격 목표로 한다.
우리는 아래의 파일들로 실습 할 것이다.
nosmep.sh : SMEP를 적용하지 않은 qemu script
smep.sh : SMEP을 적용한 qemu script
test.c : 간단한 취약점이 터지는 디바이스 드라이버 예제
exp.c : 취약점을 이용해 권한 상승을 일으키는 exploit code
1. 커널의 흐름을 원하는 대로 조작할 수 있는 디바이스 드라이버 예제인 test.c 를 살펴보자.
test_init( )함수에서 misc 디바이스를 등록하여 /dev 경로에 test라는 디바이스가 생성되는 것을 알 수 있다.
test_write() 함수에서 copy_from_user 함수를 이용해 유저로부터 주소를 전달 받아, 그 주소를 실행하는 것을 볼 수 있다.
2.test 드라이버에서 터지는 취약점을 이용해 권한 상승을 일으키는 exploit code 인 exp.c 코드를 분석 해보자.
write() 함수를 이용해 test 드라이버에 payload(1) 함수의 주소를 전달한다.
전체적인 흐름은 ret2usr 라는 기법을 이용한다.
(1) payload함수: commit_ceds(prepare_kernel_cred(0)) 코드를 실행한 후, /bin/sh 를 실행하는 역할이다.
3. 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에 의해 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 |