Home ASLR
Post
Cancel

ASLR 보호기법 이론 및 실습


List of Contents

ASLR

  • ASLR(Address Space Layout Randomization)이란?
    • 메모리 손상 취약점 공격을 방지하기 위한 기술입니다.
    • 스택, 힙, 라이브러리 등의 주소를 랜덤한 영역에 배치하여, 공격에 필요한 Target address를 예측하기 어렵게 만듭니다.
    • 프로그램이 실행 될 때 마다 각 주소들이 변경됩니다.
  • 예를 들어 RTL 공격을 하기 위해서는 공유 라이브러리에서 사용하려는 함수의 주소를 알아야합니다.
    • 이러한 주소 값들이 고정적인 주소를 가지고 있으면 매우 쉽게 공격 당할 수 있습니다.
    • 하지만 ASLR의 적용으로 인해 프로그램이 호출 될때 마다 스택, 힙, 라이브러리 영역의 주소가 변경되면 공격에 어려워집니다.(불가능하지는 않습니다.)

Set ASLR

명령어 : echo 0 > /proc/sys/kernel/randomize_va_space

옵션

0 : ASLR 해제

1 : 랜덤 스택 & 랜덤 라이브러리 설정

2 : 랜덤 스택 & 랜덤 라이브러리 설정 & 랜덤 힙 설정

Check the protection techniques of binary files.

checksec

  • checksec에서 다음과 같은 결과를 출력합니다.
    • System-wide ASLR (kernel.randomize_va_space): On (Setting: 2)
1
2
3
4
5
6
7
8
9
10
11
12
❯ checksec --proc ASLR
* System-wide ASLR (kernel.randomize_va_space): Full (Setting: 2)

  Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.
  This, among other things, implies that shared libraries will be loaded to random
  addresses. Also for PIE-linked binaries, the location of code start is randomized.

  See the kernel file 'Documentation/sysctl/kernel.txt' for more details.

* Does the CPU support NX: Yes

         COMMAND    PID RELRO           STACK CANARY      NX/PaX        PIE                     FORTIFY

Memory map

  • 다음과 같이 메모리의 변화를 확인 할 수 있습니다.
    • “/proc//maps” 파일을 통해 프로세스의 메모리 구조는 및 주소를 확인 할 수 있습니다.
    • randomize_va_space에 2를 설정한 환경입니다.
    • 프로그램을 처음 실행했을 때와 두번째 실행했을 때의 메모리 배치가 다른 것을 확인 할 수 있습니다.
Memory area첫번째 실행두번째 실행
Stack0x7ffea624c000 ~ 0x7ffea626d0000x7ffc75b23000 ~ 0x7ffc75b44000
Libc0x7fb51e026000 ~ 0x7fb51e6180000x7f6adb39b000 ~ 0x7f6adb98d000
Heap0x0229e000 ~ 0x022bf0000x01198000 ~ 0x011b9000

Example

Source code

  • 아래 코드는 다음과 같은 동작을 합니다.
    • heap, stack, libc 의 주소를 출력합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
char *global = "Lazenca.0x0";
  
int main(){
    char *heap = malloc(100);
    char *stack[] = {"LAZENCA.0x0"};
 
    printf("[Heap]  address: %p\n", heap);
    printf("[Stack] address: %p\n", stack);
    printf("[libc]  address: %p\n",**(&stack + 3));
    printf("[.data] address: %p\n",global);
    gets(heap);
    return 0;
}

**echo 0 > /proc/sys/kernel/randomize_va_space**

  • 다음과 같이 프로그램을 실행할 때 마다 Heap, Stack, Libc의 주소영역이 변경되지 않습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root# ./ASLR
[Heap]  address: 0x5555555592a0
[Stack] address: 0x7fffffffe550
[libc]  address: 0x7ffff7dee083
[.data] address: 0x555555556004
^C
root# ./ASLR
[Heap]  address: 0x5555555592a0
[Stack] address: 0x7fffffffe550
[libc]  address: 0x7ffff7dee083
[.data] address: 0x555555556004
^C
root# ./ASLR
[Heap]  address: 0x5555555592a0
[Stack] address: 0x7fffffffe550
[libc]  address: 0x7ffff7dee083
[.data] address: 0x555555556004
^C

**echo 1 > /proc/sys/kernel/randomize_va_space**

  • 다음과 같이 프로그램을 실행할 때 마다 Stack, Libc의 주소 영역이 변경됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root# ./ASLR
[Heap]  address: 0x5555555592a0
[Stack] address: 0x7ffd20331870
[libc]  address: 0x7f151ca9e083
[.data] address: 0x555555556004
^C
root# ./ASLR
[Heap]  address: 0x5555555592a0
[Stack] address: 0x7fff1cc94850
[libc]  address: 0x7f54005fb083
[.data] address: 0x555555556004
^C
root# ./ASLR
[Heap]  address: 0x5555555592a0
[Stack] address: 0x7ffe4e92c970
[libc]  address: 0x7f5810012083
[.data] address: 0x555555556004
^C

**echo 2 > /proc/sys/kernel/randomize_va_space**

  • 다음과 같이 프로그램을 실행할 때 마다 Heap, Stack, Libc의 주소 영역이 변경됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root# ./ASLR
[Heap]  address: 0x55a5438c42a0
[Stack] address: 0x7ffc850a2de0
[libc]  address: 0x7f06e06c9083
[.data] address: 0x555555556004
^C
root# ./ASLR
[Heap]  address: 0x56535a9f52a0
[Stack] address: 0x7fff8c206c00
[libc]  address: 0x7f43326d1083
[.data] address: 0x555555556004
^C
root# ./ASLR
[Heap]  address: 0x5610becc32a0
[Stack] address: 0x7ffca8604b70
[libc]  address: 0x7f09e251e083
[.data] address: 0x555555556004
^C

.data

  • 앞의 예제에서 ASLR의 설정을 2로 설정하였으나 .data 영역의 주소는 변경되지 않습니다.
  • 해당 영역을 주소도 매번 새로운 주소에 할당하기 위해서는 PIE를 적용해야 합니다.
    • 해당 설명은 06.PIE 의 내용을 참고 하세요
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root# ./ASLR
[Heap]  address: 0x55a5438c42a0
[Stack] address: 0x7ffc850a2de0
[libc]  address: 0x7f06e06c9083
[.data] address: 0x55a5438c1004
^C
root# ./ASLR
[Heap]  address: 0x56535a9f52a0
[Stack] address: 0x7fff8c206c00
[libc]  address: 0x7f43326d1083
[.data] address: 0x56535a9f2004
^C
root# ./ASLR
[Heap]  address: 0x5610becc32a0
[Stack] address: 0x7ffca8604b70
[libc]  address: 0x7f09e251e083
[.data] address: 0x5610becc0004
^C

How to detect ASLR in the “Checksec.sh” file

  • 다음과 같은 방법으로 시스템의 ASLR 설정여부를 확인합니다.
    • /proc/1/status” 파일 내에 ‘PaX’단어를 검색하고 검색 결과에서 ‘R’이 존재하는지 확인합니다.
      • 위 조건을 모두 만족하면 “ASLR enabled”로 판단합니다.
    • /proc/1/status” 파일 내에 ‘PaX’라는 단어가 없을 경우 ‘sysctl’ 명령어를 이용해 확인합니다.
      • ‘sysctl’ 명령어를 통해 출력된 내용 중 “kernel.randomize_va_space =”의 값을 확인해 ASLR 설정을 판단합니다.

Checksec.sh - line 285

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
29
30
31
32
33
34
35
36
37
38
# check for system-wide ASLR support
aslrcheck() {
  # PaX ASLR support
  if !(cat /proc/1/status 2> /dev/null | grep -q 'Name:') ; then
    echo -n -e ':\033[33m insufficient privileges for PaX ASLR checks\033[m\n'
    echo -n -e '  Fallback to standard Linux ASLR check'
  fi
   
  if cat /proc/1/status 2> /dev/null | grep -q 'PaX:'; then
    printf ": "
    if cat /proc/1/status 2> /dev/null | grep 'PaX:' | grep -q 'R'; then
      echo -n -e '\033[32mPaX ASLR enabled\033[m\n\n'
    else
      echo -n -e '\033[31mPaX ASLR disabled\033[m\n\n'
    fi
  else
    # standard Linux 'kernel.randomize_va_space' ASLR support
    # (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description)
    printf " (kernel.randomize_va_space): "
    if /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then
      echo -n -e '\033[33mOn (Setting: 1)\033[m\n\n'
      printf "  Description - Make the addresses of mmap base, stack and VDSO page randomized.\n"
      printf "  This, among other things, implies that shared libraries will be loaded to \n"
      printf "  random addresses. Also for PIE-linked binaries, the location of code start\n"
      printf "  is randomized. Heap addresses are *not* randomized.\n\n"
    elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then
      echo -n -e '\033[32mOn (Setting: 2)\033[m\n\n'
      printf "  Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n"
      printf "  This, among other things, implies that shared libraries will be loaded to random \n"
      printf "  addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n"
    elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then
      echo -n -e '\033[31mOff (Setting: 0)\033[m\n'
    else
      echo -n -e '\033[31mNot supported\033[m\n'
    fi
    printf "  See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n"
  fi
}
  • 먼저 “/proc/1/status” 파일을 이용해 ASLR 설정여부를 확인합니다.
    • 하지만 해당 시스템에서는 ”/proc/1/status”를 이용해 ASLR이 적용되었는지 확인 할 수 없습니다.
    • 해당 파일에 “Pax” 정보가 없기 때문입니다.
  • 그렇기 때문에 다음과 같이 ‘sysctl’ 명령어를 이용해 ASLR 설정 여부를 판단할 수 있습니다.
    • 해당 시스템의 설정 값은 ‘2’ 입니다.

sysctl -a | grep 'kernel.randomize_va_space = '

1
2
3
4
5
6
7
8
9
10
11
12
13
root$ sysctl -a | grep 'kernel.randomize_va_space = '
sysctl: permission denied on key 'fs.protected_hardlinks'
sysctl: permission denied on key 'fs.protected_symlinks'
sysctl: permission denied on key 'kernel.cad_pid'
kernel.randomize_va_space = 2
sysctl: permission denied on key 'kernel.unprivileged_userns_apparmor_policy'
sysctl: permission denied on key 'kernel.usermodehelper.bset'
sysctl: permission denied on key 'kernel.usermodehelper.inheritable'
sysctl: permission denied on key 'net.ipv4.tcp_fastopen_key'
sysctl: permission denied on key 'net.ipv6.conf.all.stable_secret'
sysctl: permission denied on key 'net.ipv6.conf.default.stable_secret'
sysctl: permission denied on key 'net.ipv6.conf.ens33.stable_secret'
sysctl: permission denied on key 'net.ipv6.conf.lo.stable_secret'
This post is licensed under GNU AGPL by the author.