ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Mitigation의 종류
    표튜터와 함께하는 Pwnable/Pwnable 개념 및 정리 2019. 2. 15. 07:25
    Mitigation

    ASLR :  Address Space Layout Randomization

    메모리상의 공격을 어렵게 하기위해  스택, 힙, 라이브러리 등의 주소를 
    랜덤으로 프로세스 주소 공간에 배치하여 실행할 때마다 데이터의 주소가 바뀌게 하는 기법을 의미함

    /proc : process의 줄임말로 이 디렉터리에 프로세스의 정보들이 저장됨
    /proc/self : 현재 실행되고 있는 프로세스의 정보가 담겨있는 디렉토리
    /proc/self/maps : 현재 실행되고 있는 프로세스의 주소맵

    ASLR 해제 명령어 : echo 0 > /proc/sys/kernel/randomize_va_space
    randomize_va_space = 0 : ASLR 해제
    randomize_va_space = 1 : 랜덤 스택 & 랜덤 라이브러리 설정
    randomize_va_space = 2 : 랜덤 스택 & 랜덤 라이브러리 & 랜덤 힙 설정

    DEP : Data Execution Prevention. / NX : Non-Executable
    code가 저장되는 .text영역을 제외한 모든영역의 실행권한을 제거한다.(.data / stack / heap )
    데이터 실행 방지의 의미로 스택이나 힙의 실행권한을 없애주는 기법이다.

    버퍼오버플로우로 ret를 스택상의 쉘코드를 넣어놓은 주소로 덮었을 때
    DEP가 설정되있지 않다면 바로 쉘코드가 실행되지만 DEP가 적용되있다면
    실행권한이 없으므로 쉘코드가 실행되지않고 프로그램에 대한 예외처리 후 종료된다.

    gcc  -z execstack dep.c -o dep  -> heap과 stack에 실행권한을 줄 수 있음

    그냥 컴파일 gcc -o test test.c로 하게되면 NX/DEP가 켜져있다.


    NX bit가 걸려있을 경우 우회방법은 2가지가 있다. RTL (Return to Library)

    1. system( )를 사용해서 /bin/sh을 실행시킨다.

    2. mprotect()를 이용하여 실행권한을 부여한다.(shellcode사용)

    -> 보통 system()이 없을 때 사용한다.


    ASCII - Armor 

    공유라이브러리 영역의 상위 주소에 0x00을 포함시키는 방법이다.
    RTL(Return To Library) 공격에 대응하기 위한 방법으로, 
    공격자가 라이브러리를 호출하는 Buffer Overflow 공격(RTL)을
     해도 NULL 바이트가 삽입된 주소로는 접근할 수 없다.

    Stack Canary

    함수 진입 시 스택에 SFP(Saved Frame Pointer)와 ret정보를 저장할 때, 
    이 정보들이 공격자에 의해 덮어씌워지는 것으로부터 보호하기위해 
    스택상의 변수들의 공간과 SFP사이에 특정한 값을 추가하는데 이 값을 Canary라고 합니다. 
    이 Canary값이 변조되는 것을 통해 공격을 탐지함
    공격이 탐지되면 프로그램이 중료되며 " *** stack smashing detected *** " 라는 경고문이 출력된다.


    RELRO : Relocation Read-Only

    ELF바이너리 또는 프로세스의 데이터 섹션을 보호하는 기술로
    메모리가 변경되는 것을 보호한다.



    RELRO의 종류는 PartialFull 두 가지가 있다.

    Partial의 경우 got의 상태가 Writable이며
    함수 호출 시 해당 함수의 주소를 알아온다.
    컴파일 옵션 : gcc -WI, -z, relro

    Full의 경우 got의 상태가 Read-Only이며
    ELF 실행 시 GOT에 모든 라이브러리 주소가 바인딩된다.
    컴파일 옵션 : gcc -WI, -z, relro, -z, now
    (컴파일 시에 Full-RELRO 옵션을 주면 (.ctors, .dtors, .jcr, .dynamic, .got)섹션이 읽기전용 상태(Read-Only)가 됨)

    * RELRO가 적용되있지 않으면 *
    ctors, .dtors, .jcr, .dynamic, .got의 섹션에 데이터를 쓸 수 있다.


    * Partial RELRO가 적용되어 있을 때 *
    ctors, .dtors, .jcr, .dynamic 섹션에 데이터 쓰기를 시도하면 Segmentation fault가 일어난다.
    그 이유는 ctors, .dtors, .jcr, .dynamic 섹션 write기능이 없기 때문이다.

    하지만 GOT의 경우 Write권한이 있음으로 데이터 쓰기가 가능하다.
    즉, Partial RELRO의 경우 GOT Overwrite가 가능하다.


    * Full RELRO가 적용되어 있을 때 *
    Full RELRO의 경우에도 ctors, .dtors, .jcr, .dynamic 섹션에 데이터 쓰기를 시도하면 
    Write권한이 없기 때문에Segmentation fault가 일어난다.
     또한 GOT를 변경하려해도 Write 권한이 없기 때문에 Segmentation fault가 일어나며
     당연히 GOT Overwrite도 불가하다.



    이렇게 보면 Full RELRO가 읽기 전용이라 안전해보이지만 Partial RELRO가 더 많이 사용된다.
    그 이유는 Full RELRO의 경우에는 프로세스가 시작 시, linker에 의해 
    모든 메모리에 대하여 재배치가 일어나 실행이 느려지기 때문이다.

    PIE : Position Independent Executable


    바이너리 주소가 상대적인 주소로 랜덤하게 매핑시키는 기법을 의미한다.

    ASLR 비슷하지만 PIE 경우 Code(Text)영역을 포함한 

    모든 영역(Data, Stack, Heap, Libc) 랜덤하게 매핑시킨다는 차이점이 있다.


    PIE 위치 독립 실행파일이다.

    PIE는 전체가 위치 독립 코드(PIC)로 이루어진 실행 가능한 바이너리를 의미한다.


    * 위치 독립 실행 코드(PIC : Position-Independent Code)란? *


    메모리의 어느 공간에든 위치할 있으며 수정 없이 실행될 있는 위치 독립 코드를 의미한다.

    코드를 사용하는 각각의 프로세스들은 코드를 서로 다른 주소에서 실행할 있으며 실행 시에 재배치 필요없다.

    코드를 서로 다른 주소에서 실행시킬 수 있는 이유는 바로 어떤 베이스가 와도(어떤 메모리에 로드되어도)

     코드영역이 offset으로 되어있기 때문에 offset을 더해주면 해당 위치를 찾을 수 있기 때문이다.


    참고 : https://xn--vj5b11biyw.kr/127


    PIE 적용된 바이너리에서 코드영역의 주소를 찾는방법이 있다.

    이유는 Code영역의 경우에도 랜덤하게 매핑되는데

    바뀌는 부분은 Base부분이고 할당된 작은 주소값들(offset임)이 고정적이기 때문이다.

    , Code영역에 할당된 주소는 고정적인 값이며 바뀌는 부분은 base부분만이다.

    => PIE가 걸려있으면 Code영역의 Base 부분이 변한다!




    반응형

    댓글

Designed by Tistory.