상세 컨텐츠

본문 제목

Linux ASLR 취약점 (CVE-2016-3672)

국내외 보안동향

by 알약(Alyac) 2016. 4. 13. 10:00

본문

Linux ASLR 취약점 (CVE-2016-3672)


최근 보안연구원이 Linux ASLR 중 비교적 오래된 취약점을 수정하였습니다. 이 취약점은 x86 디바이스 상에서 32비트 프로그램을 사용하는 모든 권한의 사용자가 RLIMIT_STACK 자원을 "제한없음"으로 설정해 놓는 방법으로 ASLR을 우회하는 취약점 입니다. 


해당 취약점은 CVE-2016-3672, CNNVD-201604-092 식별번호를 할당받았습니다. 


* ASLR(Address Space Layout Randomization)

ASLR이란 리눅스의 메모리 보호 메커니즘으로, 프로세스 내에서 매핑되는 오프젝트에 대하여 호출 및 실행시 실행하는 주소를 랜덤화 하는 기법입니다. 



TEST


사용자는 다음 절차를 통하여 시스템이 해당 취약점에 영향을 받는지 여부를 확인할 수 있습니다. 


1. 메모리 맵을 보여주는 더미 프로그램을 만듭니다. 


#include <stdio.h>


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

{

    char cmd[256];

    sprintf(cmd, "cat /proc/%d/maps", getpid());

    system(cmd);

    return 0;

}


2. 위 프로그램을 컴파일 합니다. 


$ gcc show_maps.c -o show_maps        # In a i386 machine

$ gcc show_maps.c -o show_maps -m32   # In a 64-bit machine


3. 해당 프로그램을 실행시켜 ASLR이 동작하는지 확인합니다.

 

$ for i in `seq 1 10`; do ./show_maps | grep "r-xp.*libc"; done

f75c4000-f7769000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f75db000-f7780000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f7557000-f76fc000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f7595000-f773a000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f7574000-f7719000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f75af000-f7754000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f7530000-f76d5000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f7529000-f76ce000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f75c2000-f7767000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so

f75fe000-f77a3000 r-xp 00000000 08:01 784726     /lib32/libc-2.19.so


만약 ibc-2.19.so문서가 랜덤한 위치에 맵핑된다면, 이는 ASLR이 정상으로 동작하는걸 의미합니다. 


그렇다면, RLIMIT_STACK을 'unlimited'로 설정해 놓은 후 동일하게 테스트를 해봅니다.


$ ulimit -a | grep stack

stack size              (kbytes, -s) 8192

$ ulimit -s unlimited

stack size              (kbytes, -s) unlimited

$ for i in `seq 1 10`; do ./show_maps | grep "r-xp.*libc"; done

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so

5559a000-5573f000 r-xp 00000000 08:01 784726      /lib32/libc-2.19.so


libc-2.19.so 문서가 동일한 위치에 맵핑되었는데, 이는 ASLR이 동작하지 않는다는 것을 의미합니다. 


이 방법은 매우 오래된 ASLR 우회 방법중 하나이지만, 현재의 Linux 시스템 중에도 여전히 해당 취약점이 존재합니다. 



취약점 설명


해당 취약점은 Stack의 크기를 'unlimited'로 설정되어 있을 때, ASLR Linux는 모든 mmap 주소를 랜덤화합니다. 이는 즉, i386과 x86_64에서 legacy 모드에서 x86_32를 에뮬레이팅 할 때, 프로그램은 스택과 실행가능한 문서만 랜덤화를 시키며, 다른 mmapped문서들(libraries, vDSO등)은 무시하게 되며, 심지어 리눅스에서는 실행가능한 문서들까지 랜덤화 시키지 않습니다. 


mmap_legacy_base()함수를 이용하여 stack의 크기가 'inlimited'로 설정되어 있는 라이브러리의 위치를 계산해 봅시다.

 

static unsigned long mmap_legacy_base(void)

{

    if (mmap_is_ia32())

        return TASK_UNMAPPED_BASE;

    else

        return TASK_UNMAPPED_BASE + mmap_rnd();

}


해당 시스템이 32비트 시스템(i386) 혹은 32비트 에뮬레이터 시스템(x86_32)에서 실행될 때, 해당 함수는 어떠한 랜덤한 오프셋도 더하지 않습니다. 



취약점의 이용


공격자는 스택의 크기를 'unlimited'로 설정해 놓은 후 32비트 프로그램을 실행시키면 됩니다. 이런 방법은 주로 어플리케이션(공격)의 권한을 상승시키는 것입니다.


영향


x86시스템에서 동작하는 32비트 어플리케이션을 실행할 수 있는 권한을 가진 공격자는 해당 취약점을 이용하여 ASLR을 우회(setuid, setgid를 포함)할 수 있습니다. 주의할 것은, 이 자체는 취약점이 아니고, ASLR을 사용하지 않도록 하는 하나의 방식이며, 공격자들이 다른 취약점과 결합하여 사용하고 있습니다. i386의 사용률이 넓기 때문에, 영향을 받는 시스템과 사용자도 매우 많을 것으로 추정됩니다.


패치


취약점 패치는 다음과 같습니다.


diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c

index 96bd1e2..389939f 100644

--- a/arch/x86/mm/mmap.c

+++ b/arch/x86/mm/mmap.c

@@ -94,18 +94,6 @@ static unsigned long mmap_base(unsigned long rnd)

 }

 

 /*

- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64

- * does, but not when emulating X86_32

- */

-static unsigned long mmap_legacy_base(unsigned long rnd)

-{

-   if (mmap_is_ia32())

-       return TASK_UNMAPPED_BASE;

-   else

-       return TASK_UNMAPPED_BASE + rnd;

-}

-

-/*

  * This function, called very early during the creation of a new

  * process VM image, sets up which VM layout function to use:

  */

@@ -116,7 +104,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)

    if (current->flags & PF_RANDOMIZE)

        random_factor = arch_mmap_rnd();

 

-   mm->mmap_legacy_base = mmap_legacy_base(random_factor);

+   mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor;

 

    if (mmap_is_legacy()) {

        mm->mmap_base = mm->mmap_legacy_base;



해당 패치방법은 legacy모드의 i386 및 x86_32상의 라이브러리, vDSO 및 mmap 리퀘스트에 대한 랜덤화를 진행하며, 다음 Linux 버전에서 해당 취약점은 패치될 예정입니다. 





출처 : 

http://hmarco.org/bugs/CVE-2016-3672-Unlimiting-the-stack-not-longer-disables-ASLR.html

관련글 더보기

댓글 영역