• 버퍼, 힙 오버플로우 (정보보안기사)

    2022. 2. 22.

    by. TONY07

    정보보안기사 필기 준비중이여서 정리하면서 진행하고 있습니다. 내용이 부족할 수도 있습니다.

    버퍼오버플로우 (Buffer Overflow Attack BOF 공격)

    프로그램에 버퍼를 조작할 수 있는 버그가 존재할 경우 컴퓨터(서버)에게 해커가 원하는 일을 하도록 지시시켜 공격하는 것이다.

    간단한 예시로 실습해보겠습니다.

    #include <stdio.h>
    int main(int argc, char* argv[]){
        char buffer[10];
        strcpy(buffer,argv[1]);
        printf("Hello %s", buffer);
        return 0;
    }

    코드를 컴파일하고 실행시켰을 경우 첫 번째 인자에 10자 이상의 문자를 입력하면 버퍼 오버플로우가 발생하게 된다. 악의적인 해커가 컴퓨터의 루트 권한을 뺏어서 컴퓨터에게 무자비한 짓을 할 수 있다.

    흔히들 RET나 SFP를 조작한다.

    SFP : 스택 베이스값이다. 크기 4바이트 이며 이전의 EBP값을 가지고 있다. 현재 함수가 끝나면 이전 함수의 EBP가 필요하게 되는데 이전 함수의 EBP를 저장하는 공간이 EBP이다.

    RET : 반환 주소값 다음에 실행할 명령이 위치한 메모리 주소값이 RET이기 때문이다. 그래서 RET부분을 자기가 원하는 코드가 있는 곳의 메모리주소로 덮어쓰면 자기가 원하는 명령을 실행시킬 수 있다.
    ex) : 쉘을 실행하는 코드를 저장한 뒤에 그 메모리 주소를 RET 부분에 쓰면 함수 종료 후에 실행시키게 된다.

    칼리리눅스를 실행하여 하는데 ASLR을 해제해야한다. 어느정도 알고 있는 내용이여서 패스하였다.

    사용 권장 🤬 : strcat(), strcpy(), gets(), scanf()

    사용 권장 😍 : strncat(), strncpy(), fgets() ...

     

    발생하는 이유?

    복귀주소가 함수가 사용하는 지역변수의 데이터에 의해 침범 당했을 때 발생하게 된다.
    개발자가 실수로 지역변수가 할당된 크기보다 큰 크기를 입력해버리면 복귀주소가 입력한 데이터에 의해 다른 값으로 변경되기 때문에 함수가 종료될 때 전혀 관계없는 복귀주소를 실행하게 되어서 애플리케이션이 뜻하지 않게 종료된다.

    악의적인 해커가 이러한 취약점을 알고서 데이터의 길이와 내용을 적절히 조정하여 버퍼 오버플로우를 일으켜서 특정 코드를 실행시키게 하는 해킹 기법을 버퍼오버플로우 공격이라고 한다.

    BOF에 취약한 함수는 gets, scanf, strcat, strcpy, sprintf 가 있다.
    문자열의 길이를 체크하지 않기때문에 스택의 값이 변조된다.

     


    힙오버플로우 (Heap Overflow Attack)

    힙 데이터 영역에서 일어나는 버퍼 오버플로우로써 스택기반 오버플로우 와는 다른 방법으로 공격한다.

    방법 : 버퍼오버플로우시켜 접근해 포인터가 가르키는 값을 변경하여 임의의 파일에 접근하거나 임의의 코드를 실행시킨다.

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<string.h>
    
    int main(){
            u_long address_diff;
            char *buf1 = (char *)malloc(16);
            char *buf2 = (char *)malloc(16);
    
            address_diff = (u_long)buf2-(u_long)buf1;
            memset(buf2, 'A',15);
            buf2[15] = '\0';
    
            memset(buf1,'B', (u_int)(address_diff+8));
            printf("After bufferoverflow buf2 = %s\n",buf2);
            return 0;
    }

    칼리리눅스 에서 gdb를 이용하여 힙오버플로우를 확인해보자.

    위와 같이 32비트로 컴파일을 시켜주자.

    gdb를 실행 후 disas main 을 확인해보면 32비트로 컴파일 된것들을 확인할 수 있다.

    소스코드 확인법

    list(단축 l )로 소스를 볼 수 있고
    출력 코드수를 설정할 수도 있다. set listsize 20

    보면 buf1과 buf2가 동적할당 시키고 다음코드에 브레이크를 달았다.

    아직 동적할당만 하고 값을 넣어주지 않았기에 0이 들어가있다.

    13줄로 가서 address_diff 와 buf1을 확인해보자.

     

    buf1과 buf2가 0x20 만큼 차이가 난다는것을 확인 할 수 있다.

    0x5655a1a0 ~ 0x5655a1c0 까지 확인한 결과 buf2만 A로 변경되었다.

    아래와 같이 16번줄에서 브레이크를 설정하고 continue 해본 결과 아래와 같이 buf1이 buf2 공간이 B로 덮어씌어져 있는것을 확인할 수 있다.

     

    '자격증' 카테고리의 다른 글

    nmap 사용 (정보보안기사)  (0) 2022.02.23

    댓글