Computer Security

#18 struct cred overwrite 기법 본문

리눅스 커널 해킹

#18 struct cred overwrite 기법

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

struct cred overwrite

 

 

 

정형화된 특정한 기법이라기보단, 권한 상승을 일으키는 방법론으로써, 태스크의 권한에 대한 정보를 담고 있는 cred 구조체를 덮어써서 root 권한을 획득하는 작업이다.

 

하나의 태스크의 모든 메타 데이터를 담고 있는 task_struct 구조체에는 cred 구조체를 가리키는 포인터 멤버가 있다.

 

이 cred 구조체는 태스크의 권한에 대한 정보를 담고 있기  때문에, 이 cred 구조체의 멤버를 덮어 쓰는 것으로 태스크의 권한을 바꿀 수 있다.

 

 

 

 


struct task_struct

task_struct

태스크의 모든 메타 데이터를 담고 있는 구조체이다.

 

do_fork()함수에 의해 생성 된다.

 

권한과 관련된 멤버 중에서 cred 멤버가 바로 현재 태스크가 특정 작업을 할 때 참조되는 권한 정보이다.

 

comm 멤버는 태스크의 이름이 저장된 멤버이다. 이 멤버도 디버깅에 유용하게 사용된다.

 

task_struct 구조체는 커널 버전,옵션에 따라 멤버가 바뀌기 때문에, task_struct 구조체로부터 cred 멤버의 주소를 알아내려 할 경우, 디버깅을 통해 cred 멤버의 offset을 구해야 한다.

 

 

 

 


struct cred

struct cred

태스크의 권한 정보를 담고 있는 구조체이다.

 

이중 uid, gid, suid 등의 멤버를 0으로 덮을 경우 root 권한을 획득하게 된다.

 

만약 user권한일 경우 해당 멤버들이 1000(0x3e8)로 초기화 되어 있다.

 

 

 

 


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

struct_cred_overwrite

 

start.sh : qemu script

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

exp.c : struct cred overwrite기법을 이용해 권한 상승을 일으키는 exploit code

 

 

 


1. 다양한 취약점이 터지는 디바이스 드라이버 예제인 test.c 파일을 살펴보자.

test.c

AAR case 에서는, 임의의 주소의 값을 읽어올 수 있는 기능이 있다.

 

AAW case 에서는, 임의의 주소에 원하는 값을 쓸 수 있는 기능이 있다.

 

TASK_STRUCT case 에서는, 현재 태스크의 task_struct 구조체의 주소를 불러오는 get_current()함수를 이용해서, task_struct구조체의 주소를 leak 할 수 있는 기능이 있다.

 

 

 

 


2. exp.c 파일을 살펴보자.

exp.c

struct cred overwrite 기법을 이용해 권한 상승을 일으키는 exploit code이다.

 

step1. 

현재의 태크스의 task_struct구조체의 주소를 leak 해온다.

leak한 task_struct 구조체 주소로부터 cred 멤버까지의 offset인 1592를 더해서 cred 멤버가 위치한 주소를 구한다.

 

step2.

cred 멤버가 위치한 주소를 역참조 해서, cred 구조체의 주소를 구하는 것을 볼 수 있다.

 

step3.

cred 구조체의 주요 멤버들을 0으로 덮어써서 권한 상승을 일으키는 것을 볼 수 있다.

 

 

 


조금 더 구체적으로 알아 보자.

 

step1.

현재 태스크의 task_struct 구조체의 주소를 leak 해오는 부분

1. task_struct 주소 leak

 

2. cred 위치 계산

 

 


step2.

이전 과정에서 구한 cred 멤버가 위치한 주소를 역참조 해서, cred 구조체의 주소를 구하는 부분

3. cred 구조체 주소 읽기

 

 

 


step3.

cred 구조체의 주요 멤버들을 0으로 덮어써서 권한 상승을 일으키는 부분

 

4. cred 구조체의 주요 멤버 덮어쓰기

 

 

 

 

 


3. ./start.sh 를 실행해보자.

./start.sh

 

start.sh를 실행한 후, exp를 실행한 결과이다.

 

user권한에서 root권한을 획득 한 것을 볼 수 있다.

 

 

 

 


KASLR과의 연관성

 

 

취약점이 터지는 상황에 따라 다르지만, 일반적으로 AAW 혹은 UAF 상황에서 이 struct cred overwrite기법을 이용할 수 있다.

 

AAW를 이용하는 상황에서는 KASLR 우회를 다소 신경써야 한다.

 

UAF를 이용하는 상황에서는 KASLR 우회를 신경쓰지 않아도 된다.

 

 

 

 

 


KADR/SSP와의 연관성

 

 

이 기법은 별도의 ROP payload를 구성할 필요가 없는 기법이기 때문에 KADR의 영향을 받지 않는다.(별도의 primitive를 구성하는 경우 제외)

 

또한, 스택 버퍼 오버플로우 취약점으로 트리거할 수 있는 기법도 아니기 때문에 SSP와의 연관성도 없다.

 

 

 

 


SMEP/SMAP/KPTI와의 연관성

 

cred 구조체를 덮는 방법은 rip 레지스터를 조작하여 커널의 흐름을 변경하는 기법이 아니기 때문에 SMEP/SMAP/KPTI의 영향을 전혀 받지 않는다.

 

즉, struct cred overwrite 기법을 이용하면 위 세가지의 보호 기법은 기본적으로 우회가 가능하다.

 

 

 

 

 


struct cred overwrite 최종 정리

 

 

 

이 기법은 태스크의 권한을 담당하는 cred 구조체의 멤버를 덮어써서 권한 상승을 일으키는 기법이다.

 

AAW 혹은 UAF 취약점 등을 이용해 트리거가 가능하다.

 

대부분의 인텔 아키텍쳐 보호 기법을 우회할 수 있는 매우 강력한 공격 방법론이다.

 

 

반응형

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

#20 Kernel UAF 1  (0) 2022.08.28
#19 Stack based BOF  (1) 2022.08.27
#17 kernel stack pivoting 기법  (0) 2022.08.25
#16 cr4 overwrite 기법  (0) 2022.08.24
#15 kernel ROP 기법  (0) 2022.08.23
Comments