포너블 스터디 #2

연 구

2019.05.19 15:43

포너블 스터디 #2

이번 글에서는 이전 글에서 실습했던 간단한 Stack overflow를 막기위한 방법중 하나인 "Stack canary" 를 알아보겠습니다.

 

Canary

Canary(이하 카나리)의 간단한 아이디어는 이렇습니다.

지역변수로 사용하는 스택영역과 SFP, RET같은 민감한 정보가 있는 스택영역 사이에 카나리를 위치시키고, 만약 이 카나리가 달라졌다면 지역변수 스택영역을 벗어나려는 시도가 있었다고 판단할수 있다!

입니다. 그렇다면 카나리는 어떤 형식으로 프로그램에서 사용되는지 알아보도록 하겠습니다.

 

|           0x00000789      64488b042528.  mov rax, qword fs:[0x28]    ; [0x28:8]=0x19d0 rcx ; '('
|           0x00000792      488945f8       mov qword [canary], rax
...
중략
...
|           0x00000806      488b4df8       mov rcx, qword [canary]
|           0x0000080a      6448330c2528.  xor rcx, qword fs:[0x28]
|       ,=< 0x00000813      7405           je 0x81a

카나리의 구현은 한 쌍으로 볼 수 있습니다. 먼저 초기의 깔끔한 카나리를 fs:[0x28]에서 불러와 지역변수 로 가지고 있습니다. 그리고 함수가 끝나기 직전에 지역변수 에 저장한 값과 원본의 fs:[0x28]를 비교하고 틀리면 프로그램을 날려버립니다.

여기서 주의할건 카나리를 지역변수로 저장한다는겁니다. 다시금 스택 오버플로우의 과정을 살펴보면

  • 지역변수 영역을 가득채운다.
  • 지역변수 영역을 벗어나 SFP, RET에 값을 덮어쓴다.

스택 오버플로우 공격을 위해선 기본적으로 지역변수 영역으로 사용되는 스택을 가득채워야 SFP, RET, etc...에 접근할 수 있다는겁니다. 그러면 지역변수에 위치한 카나리를 오염시킬수밖에 없지요.

 

Canary LEAK !

이론적으로 카나리가 존재하면 스택 오버플로우는 100% 막을수있습니다. 하지만 카나리의 약점이 몇가지 존재합니다.

 

랜덤

카나리는 항상 다른 값을 가집니다. 그렇다면 함수들 각각에 새로운 값을 가질까요? 정답은 '아니다.' 입니다. 그렇다면 다른 값을 가질땐 언제일까요? 그건 '프로그램을 시작할 때 새로운 값을 가진다' 입니다. 말이 길어졌지만 중요한건 함수와 함수들 간은 같은 카나리를 가진다. 입니다.

0x000055555555477e in hi ()
gef➤  i reg $rax
rax            0xb7e08afb9d02d000       0xb7e08afb9d02d000

0x00005555555547ca in bye ()
gef➤  i reg $rax
rax            0xb7e08afb9d02d000       0xb7e08afb9d02d000

위 결과에서 함수 hi()와 bye()가 같은 카나리를 가지고 있다는걸 알 수 있습니다. 프로그램은 하나의 함수로 이뤄진 경우는 거의 없습니다. 만약 취약한 함수로 인해 카나리가 노출된다면 다른 함수에서도 동일한 카나리로 공격을 수행할 수 있습니다.

 

fork

NAME
       fork - create a child process

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       pid_t fork(void);

DESCRIPTION
       fork()  creates  a new process by duplicating the calling process.  The new process is referred to as the child process.  The calling
       process is referred to as the parent process.

fork는 프로세스를 복사해 자식 프로세서를 생성합니다. 여기서 복사가 가지는 의미가 꽤 중요한데 만약 항상 수행중인 프로세스에서 사용자의 요청이 들어오면 fork하여 서비스를 제공하는 프로그램이 있다고 과정해봅시다.

그렇다면 이 프로그램에서 사용하는 카나리는 항상 동일한 카나리가 잡히게 되고, 만약 이 카나리를 구한다면 언제든지 같은 카나리를 사용할 수 있습니다.

'연 구' 카테고리의 다른 글

포너블 스터디 #4  (0) 2019.06.01
포너블 스터디 #3  (0) 2019.05.25
포너블 스터디 #2  (0) 2019.05.19
MBR을 알아보는 시간  (0) 2018.10.16
How are virtual functions implemented?  (0) 2018.10.13
PHP Comparison Operator  (2) 2018.07.22