본문으로 바로가기

해커스쿨 FTZ level5

category Wargame/FTZ 2017. 8. 11. 14:33

level5 --- what is your name?

 

 

우선 level5 디렉토리의 hint 파일을 보자.

 

 

 

 

힌트를 보고 눈치가 빠른 사람은 레이스 컨디션에 대한 문제라는 것을 직감할 수 있다.

 

레이스 컨디션(Race Condition)은 경쟁상태라는 뜻으로 경쟁 상태에서 발생하는 취약점이라는 의미이다.

그러면 경쟁 상태란 무엇일까? 경쟁 상태란 다수의 프로세스가 서로 동일한 자원을 할당 받기 위해 경쟁하는 상태이다. 위 힌트는 파일 소유의 경쟁 상태에서 발생하는 취약점이다.

 

레이스 컨디션(Race Condition)에 취약점이 존재하기 위한 최소한의 조건은 아래와 같다.

 

1. 다른 계정의 권한에 접근해 권한을 획득해야 하므로 SetUID가 걸려 있어야 한다.

2. 임시 파일을 생성해야 한다.

3. 공격자가 임시로 생성되는 파일명을 정확하게 알아야 한다.

 

hint에서 제시된 레이스 컨디션의 상황에 대해서 살펴보자.

 

1. /tmp 디렉토리에 level5.tmp라는 이름의 임시 파일을 생성한다.

2. 임시 파일이 생성되면 내용을 쓰고 파일을 읽은후 파일을 삭제하고 프로그램을 종료한다. 단, 임시 파일의 생성에 실패하면 프로그램을 종료한다.

 

위와 같은 실행 상황에서 레이스 컨디션에 대한 문제가 발생한다. 2가지의 문제점이 발생하는데 파일에 생성에 성공하면 생성된 파일에 내용을 쓰는 부분과 파일을 삭제할 때 문제가 발생한다. 확인해보기 위해서 직접 대상 파일을 실행해 보면 각각의 문제점이 발생하는 부분의 흐름을 바꾸려고 시도해 보는것도 좋겠지만 너무 빠르게 상황이 흘러가서 흐름을 바꾸기 힘들다. 즉, 틈은 있지만 시간 간격이 짧기 때문에 공격용 프로그램을 타이밍에 맞추어 작성해야 한다.

 

우리가 공격하기 위해서는 취약한 프로세스가 파일을 생성하기 전에 공격하는 프로세스에서 먼저 파일을 생성한 후 취약한 프로세스에서 생성할 파일명으로 링크를 만들어 두면 취약한 프로세스는 공격 프로세스가 만든 링크에 내용을 쓰고 링크를 삭제한다.

 

이제 공격과정을 보면 아래와 같은 순서로 공격을 한다.

 

1. 공격 프로세스가 /tmp/lvl6pass.txt 파일을 만든다.

2. 공격 프로세스가 /tmp/lvl6pass.txt 파일을 원본으로 하는 /tmp/level5.tmp 파일을 만든다. (/tmp/level5.tmp는 힌트가 알려준 임시파일 이다.)

3. 취약한 프로세스를 실행한다.

4. 취약한 프로세스가 /tmp/level5.tmp를 실행하려고 하지만 이미 존재하므로 추가로 파일을 만들지 않는다.

5. 취약한 프로세스가 이미 만들어진 /tmp/level5.tmp 링크에 내용을 쓴다. (/tmp/level5.tmp가 공격 프로세스가 만든 /tmp/lvl6pass.txt에 링크 되어 있기 때문에 /tmp/level5.tmp 내용이 /tmp/lvl6pass.txt에도 똑같이 남아있다.)

6. 취약한 프로세스가 내용을 다 쓴 후 /tmp/level5.tmp 파일을 삭제하고 종료한다. (/tmp/lvl6pass.txt에는 내용이 남아있다.)

 

여기서 중요한 점은 취약한 프로세스가 4번 과정을 수행하기 전에 1, 2번 과정을 수행해야만 공격이 성공적으로 이루어진다.

즉, 타이밍 잡기가 힘들다. 타이밍을 잡기 위해서 반복해서 공격을 하면 성공할 수 있다.

 

레이스 컨디션 과정을 알아 보았으니 문제를 분석해보자.

 

hint에서 파일명을 알려주었기 때문에 파일을 찾아야할 필요는 없지만 공부하는 입장이기 때문에 파일을 찾아보자. 파일명, 권한과 같이 2가지 방법이 있다.

 

 

 

파일명으로 위와 같이쉽게 찾을 수 있다. 이번에는 파일의 권한으로 찾아보자.

 

 

파일의 권한으로도 쉽게 찾을 수 있다. 이제 /usr/bin/level5 파일을 실행해 보자.

 

 

 

위와 같이 /usr/bin/level5 파일을 실행해도 아무일 없이 프롬프트가 떨어진다. /usr/bin/level5 파일 실행시 만들어지는 임시파일을 확인해 보려고 확인했지만 너무 빨리 만들어지고 삭제되어서 확인을 하기 힘들다.

 

제대로 /usr/bin/level5를 분석해 보기 위해 gdb를 통해서 분석해 보자. 여기서, level5의 계정은 권한이 없어서 level6 계정으로 분석을 해야한다.

아직 level6의 passwd를 얻지 못했다면 이 부분을 뛰어 넘고 level6의 passwd를 얻은 후에 다시 분석을 하길 바란다.

 

전체적인 리버싱 결과는 아래와 같다.

 

 

 

이제 세부적으로 리버싱 해보자.

 

 

퍼미션 0600을 스택에 올리고 파일명인 "tmp/level5.tmp"를 스택에 올린 후 creat()함수를 호출한다. 따라서 (tmp/level5.tmp, 0x180)이라는 함수가 호출된다. 파일 권한을 뜻하는 0x180은 2진수로 000110000000이다. 이것을 퍼미션 할당 단위로 바꾸면 000  110  000  000 이고 0600이라는 것을 알 수 있다.

 

 

/tmp/level5.tmp 파일이 정상적으로 생성되었으면 <main+71>으로 넘어가는 부분이다.

우선 파일 생성에 실패한 경우부터 살펴 보자.

 

 

"Can not creat a temporary file.\n"을 스택에 올리고 printf() 함수를 출력한다. printf("Can not creat a temporary file.\n") 라는 함수가 실행된다.

 

 

"/tmp/level5.tmp"를 스택에 올리고 remove() 함수를 호출한다. remove("/tmp/level5.tmp")라는 함수가 실행된다.

 

 

0을 스택에 올리고 exit() 함수를 호출한다. exit(0) 함수가 호출되면서 프로그램이 종료된다.

 

여기부터는 파일 생성이 성공했을 때의 부분이다.

 

 

 

"next password : what the hell\n"이라는 문자열을 스택에 올리고 strlen() 함수를 호출한다. strlen("next password : what the hell\n") 이라는 함수가 실행되어 문자열의 길이가 반환된다.

 

 

 

<main+89>는 패스워드 문자열의 길이를 말하고 이것을 스택에 올린다. 문자열의 길이는 0x1f로 10진수로 바꾸면 31이다. 31은 "next password : what the hell\n"의 문자열의 길이다. 그 후 "next password : what the hell\n"이라는 문지열을 스택에 올린다. <main+98>은 fd 파일 디스크립터를 의미하고 이것도 스택에 올린다. 마지막으로 write()함수를 호출한다.

write(fd, "next password : what the hell\n", 0x1f) 함수가 실행된다. 따라서 /tmp/level5.tmp에 "next password : what the hell\n"라는 내용이 쓰인다.

 

 

파일 디스크립터(fd)를 스택에 올리고 close() 함수를 호출한다. 즉, close(fd)라는 코드가 실행된다. 따라서 파일 디스크립터가 닫힌다.

 

 

"tmp/level5.tmp" 문자열을 스택에 올린다. remove()함수를 호출한다. 최종적으로 remove("tmp/level5.tmp") 함수가 호출되어 tmp/level5.tmp 임시 파일이 삭제된다.

 

이제 리버싱 분석이 끝났으니 공격해보자.

 

위에서 타이밍을 잡기 위해서는 소스코드를 작성해야 한다. 다음과 같이 작성해 보자.

 

 

 

백그라운드로 프로세스를 실행하는데 /usr/bin/level5를 10번 실행하는 소스코드이다. 실행해 보자.

 

 

다음과 같이 실행 과정을 보면 두번째 공격을 시작할 틈이 없다. 공격 프로세스와 취약한 프로세스를 동시에 실행할 부분도 구현할 필요가 있다.

아래와 같이 소스코드를 작성해보자.

 

 

 

위의 소스코드를 컴파일 후 실행해보자.

 

 

위와 같이 취약한 프로그램이 실행되는 타이밍보다 공격 프로그램의 실행이 늦은 경우 lRacecondition.txt 파일에 패스워드가 쓰여지는 타이밍을 놓친다.

타이밍을 맞추기 위해 반복문의 수를 100회 1000회 10000회로 늘리면 확률이 그만큼 올라간다.

 

아래와 같이 실행해 보자.

 

 

하지만 이렇게 실행하면 타이밍을 맞추기 힘들다. 좀 더 자동화 된 방법을 생각해보자.

 

셸스크립트를 사용하는 방법이다. 아래와 같이 사용하면 좀 더 편리하게 패스워드를 얻을 수 있다.

 

'Wargame > FTZ' 카테고리의 다른 글

해커스쿨 FTZ level7  (0) 2017.08.19
해커스쿨 FTZ level6  (0) 2017.08.17
해커스쿨 FTZ level4  (0) 2017.08.01
해커스쿨 FTZ level3  (0) 2017.07.31
해커스쿨 FTZ level2  (0) 2017.07.28