rosieblue
article thumbnail
728x90

KASLR

KASLR가 적용되면 커널 코드 및 데이터 부분이 임의의 주소에 배치되게 됨.

KASLR는 커널 3.14버전에서 처음으로 지원하였고, 4.12버전에서부터는 디폴트로 KASLR를 적용하게 됨

KASLR 안 적용하려면 커널 명령줄에 nokaslr를 적용하면 됨

 

실습파일에서는 nokaslr가 그냥 적용되어있기 때문에 아래처럼 바꿔줘야한다.

(수정 전)
_kernel_cmdline="console=ttyS0 mitigations=off nokaslr norandmaps"
(수정 후)
_kernel_cmdline="console=ttyS0 mitigations=off norandmaps"

위 처럼 run.sh를 수정해서 _kernel_cmdline에서 nokaslr를 없애면 항상 kaslr가 적용된다.

 

 

버전 별 패치 내역

v3.14
v4.6
v4.8
  • (8391c73c96f2) x86: KASLR 재배치 범위 확장 (64비트 전용)
  • (021182e52fe0) x86: 페이지 테이블에 KASLR 적용
  • (a95ae27c2ee1) x86: vmalloc 할당 영역에 KASLR 적용
v4.9
v4.12
  • (6807c84652b0) x86: KASLR 활성화를 기본값으로 설정
v4.17
  • (f2b9ba871beb) ARM64: 커널 모듈 재배치 범위를 4GB로 축소
v5.2
  • (b569c1843498) x86: 5-level paging 시스템에서 KASLR 범위 확장
  • (b2d24b97b2a9) S390 아키텍처 KASLR 지원 추가
  • (b2eed9b58811) ARM64: 커널 모듈 재배치 범위를 2GB로 축소

 

KASLR의 취약점 

ASLR를 생각해보자. 일단 ASLR이 한 번 적용되고 나서부터는 바이너리 실행 도중에 또 랜덤 재배치 되지 않았다.

KASLR도 마찬가지로, kernel이 재시작, 즉 '재부팅' 되기 전까지 전까지는 계속 주소가 고정되어 있다.

따라서 brute force를 통해 계속 예측할 수 있당

 

특히 아주아주 취약한 것은 엔트로피가 너무 작다는 것이다.

16bit 이상의 엔트로피(2byte이상)를 가지는 ASLR와는 달리, KASLR는 32bit환경에서는 최대 8bit만, 64bit 환경에서는 최대 9it의 엔트로피를 가진다.

즉, 8bit정도만 랜덤화된다는 이야기이다;; 따라서 저정도만 bruteforce하면 바로 뚫리게 된다

 

아래 그림보면 흰 글씨로 된 주소는 계속 고정이고 빨간색으로 된 글자만 랜덤화되는 것을 볼 수 있다

x86-64 리눅스 커널 KASLR (9비트 엔트로피)

 

아래 환경은 더 취약하다....

x86 64비트 리눅스 커널 KASLR (6비트 엔트로피)

 

이를 해결하기 위해 함수 단위로 코드를 재배치하는 패치가 이루어지고 있다고 하긴 한다! (하지만 아직까지는 커널에 적용되지는 않았다구 한다)

 

  ASLR (사용자 영역 랜덤화) KASLR (커널 영역 랜덤화)
목적 바이너리 섹션(스택, 힙, 라이브러리 등...) 랜덤화 커널 코드 및 데이터 랜덤화
적용 시점 바이너리 시작할 때 재부팅 시
재배치 주소 공간 사용자 주소 공간 커널 주소 공간
한계 바이너리 실행 도중에는 랜덤화 안됨 재부팅 하고 나서는 랜덤화 안됨. 엔트로피 작음
비고 코드 영역과 데이터 영역은 따로 PIE 해줘야함  

 

실제로 KASLR가 적용되고 난 후 주소를 찍어보면 아래처럼 랜덤화되어서 나온다(쥐똥만큼이지만..)

dreamhack@dh-lke:~$ sudo grep _stext /boot/System.map-`uname -r`  # 기본 주소
ffffffff81000000 T _stext
dreamhack@dh-lke:~$ sudo grep _stext /proc/kallsyms  # 실제 주소
ffffffff8a000000 T _stext

 

profile

rosieblue

@Rosieblue

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!