6 레이스 컨디션
학습목표 내용 레이스 컨디션의 기본 개념을 이해한다 하드 링크와 심볼릭 링크를 이해하고 이를 이용할 수 있다. 임시 파일에 대한 레이스 컨디션 취약점을 이해한다. 레이스 컨디션 공격에 대한 대응책을 이해한다 내용 레이스 컨디션 공격에 대한 이해 레이스 컨디션 공격에 대한 대응책
레이스 컨디션 공격에 대한 이해 레이스 컨디션 공격의 기본 아이디어 바꿔치기 레이스 컨디션 공격의 기본적인 아이디어는 관리자 권한의 프로그램에 의해 생성되고 사용되는 임시 파일에 대한 것 어떤 프로그램은 실행 도중에 임시 파일을 생성하여 사용 이런 프로그램에서 임시 파일을 생성한 후 그 파일에 접근하는 아주 짧은 시간 동안 끼어들 여유가 생기게 된다
레이스 컨디션 공격에 대한 이해 파일 링크 파일을 잇는 끈 하드 링크(Hard Link)와 심볼릭 링크(Symbolic Link) 하드링크 a.txt 파일을 관리자 소유로 /root 디렉터리에 생성, 파일 안에 적당한 문구 작성 [그림 6-2] /root 디렉터리 밑에 생성한 a.txt 파일 확인 다른 옵션 없이 두 파일을 ln(link) 명령어로 연결 [그림 6-3] 링크한 파일의 링크 수 확인 ls -al /root/a.txt ln /root/a.txt /wishfree/race/link.txt
레이스 컨디션 공격에 대한 이해 파일 링크 링크된 link.txt 파일을 확인해보면 /root/a.txt 파일과 내용이 똑같음 [그림 6-4] a.txt 파일과 링크한 link.txt 파일 내용 확인 하드링크된 파일 수정하면 원래파일 /root/a.txt 파일도 똑같이 수정 두 파일중 하나를 삭제하면 파일의 내용은 바뀌지 않고 링크의 숫자만 하나 줄어듬 하드링크는 두 파일이 각각 동일한 수준의 데이터를 가지면서 로그데이터 동기화 하드링크 제약 : 링크하고자 하는 파일이 다른 파티션에 존재하면 안됨 cat link.txt
레이스 컨디션 공격에 대한 이해 파일 링크 심볼릭 링크 하드 링크와 달리 실제 두 파일을 생성 링크하지 않음 데이터가 있는 파일이 처음부터 하나뿐이고, 심볼링 링크는 원본 파일 데이터 가리키는 링크 정보만을 가짐
실습 6-1 심볼릭 링크 기능 알아보기 심볼릭 링크 생성하기 심볼릭 링크는 ln 명령에 ‘-s’옵션을 이용 [그림 6-7] 심볼릭 링크한 symlink.txt 파일 확인 원본 파일은 일반 계정의 소유 [그림 6-8] a.txt 파일 소유자 확인 1 ln -s /root/a.txt /wishfree/race/symlink.txt
실습 6-1 심볼릭 링크 기능 알아보기 심볼릭 링크 파일 수정하기 symlink 파일을 관리자 권한으로 둔 채 symlink.txt 파일을 편집하면 수정 가능 [그림 6-9] symlink.txt 파일 내용 수정 후 a.txt 파일 내용 확인 2
실습 6-1 심볼릭 링크 기능 알아보기 원본 파일과 권한의 차이가 있는 심볼릭 링크 파일 수정하기 심볼릭 링크 파일을 일반 계정의 소유로, 원본 파일을 관리자 계정으로 수정 불가능 [그림 6-10] a.txt 파일과 symlink.txt 파일 소유자 변경 링크에서는 원본 파일 삭제하면 링크 숫자가 줄지만, 심볼릭 링크된 파일 영향 없음 [그림 6-11] 원본 파일 삭제 후 심볼릭 링크 파일 확인 3 ln -s /root/a.txt /wishfree/race/symlink.txt
실습 6-1 심볼릭 링크 기능 알아보기 원본 파일과 권한의 차이가 있는 심볼릭 링크 파일 수정하기 심볼릭 링크된 파일 남아 있지만 파일은 삭제로 표시(윈도우의 단축 아이콘과 비슷한 개념) [그림 6-12] 심볼릭 링크된 파일 내용 확인 3
실습 6-1 심볼릭 링크 기능 알아보기 동일 권한의 원본 파일 재생성하기 4 chmod 777 /root su wishfree [그림 6-13] 일반 계정 소유의 a.txt 파일 생성 [그림 6-14] a.txt와 symlink.txt 파일 내용 확인 4 chmod 777 /root su wishfree touch a.txt ls -al /root/a.txt cat a.txt cat /wishfree/race/symlink.txt
실습 6-1 심볼릭 링크 기능 알아보기 동일 권한의 원본 파일 재생성하기 새로 생성된 a.txt는 기존에 심볼릭 링크된 파일인 symlink.txt를 수정하면 함께 바뀜 [그림 6-15] symlink.txt 파일 수정 후 파일 내용 확인 [그림 6-16] symlink.txt 파일 수정 후 a.txt 파일 내용 확인 4 (printf "Fixed....\n") >> ./symlink.txt cat ./symlink.txt cat /root/a.txt
실습 6-1 심볼릭 링크 기능 알아보기 동일 권한의 원본 파일 재생성하기 같이 생성되었던 원본 파일과 심볼릭 링크는 원본 파일이 삭제되더라도 원본 파일의 이름과 위치를 기억하고 계속 그 파일을 바라보는 상태로 남는다. 삭제된 원본 파일 대신 처음 원본 파일과는 다르지만 똑같은 경로에 같은 파일명으로 파일 생성 심볼릭 링크 파일은 새로 생성된 파일에 여전히 심볼릭 링크 파일로 존재 4
레이스 컨디션 공격에 대한 이해 심볼릭 링크와 레이스 컨디션 공격 실행되는 프로그램에 대한 레이스 컨디션 공격 수행 조건 파일 소유자가 root이고 SetUID 비트를 가져야 함 생성되는 임시 파일의 이름을 알고 있어야 함 lsof 명령어로 특정 파일에 접근하는 프로세스 목록 확인 특정 프로세스가 사용하는 파일 목록 출력 가능
레이스 컨디션 공격에 대한 이해 심볼릭 링크와 레이스 컨디션 공격 페도라 시스템에서 동작하는 SSH(Secure Shell) 데몬이 사용하는 파일 목록을 알고 싶을 때, ps -ef 명령으로 SSH 데몬의 프로세스 ID 확인, lsof 명령으로 해당 프로세스 ID가 접근하는 파일 목록 확인 ssh 데몬의 프로세스 아이디 1165 [그림 6-20] SSHD의 프로세스 아이디 확인 ps -ef | grep ssh
레이스 컨디션 공격에 대한 이해 lsof 명령으로 프로세스 아이디가 1165번인 프로세스가 사용하는 파일 목록을 확인 [그림 6-21] SSHD가 사용하는 파일 목록 확인 lsof -p 1165
레이스 컨디션 공격에 대한 이해 생성된 임시 파일 확인하면 임시 파일 이름으로 프로그램이 실행되기 전 심볼릭 링크 파일 생성 가능 [그림 6-22] 프로그램 실행 전 임시 파일을 심볼릭 링크로 미리 생성
레이스 컨디션 공격에 대한 이해 프로그램이 임시 파일을 사용하기 위해 생성하기 전 해당 임시 파일이 이미 존재하고 있는지 여부를 판단하지 않는다면 프로그램은 다음과 같이 실행 [그림 6-23] 임시 파일이 심볼릭 링크 파일로 교체된 후 프로그램 실행 절차
레이스 컨디션 공격에 대한 이해 임시 파일 생성하는 프로그램들은 임시 파일 생성 전에 임시 파일의 존재 여부 확인 파일이 존재할 경우 파일 지우고 재생성, 다음과 같은 프로세스를 프로그램 로직에 넣음 ➊ 임시 파일 존재 여부 확인 ➋ 임시 파일이 있다면 삭제하고 재생성 ➌ 임시 파일에 접근하고 처리 레이스 컨디션 공격 코드는 다음과 같은 작업 반복 수행 ➊ 임시 파일이 존재하는 경우 심볼릭 링크 파일인지 여부 확인 ➋ 심볼릭 링크가 아닐 경우 임시 파일을 삭제 ➌ 임시 파일을 심볼릭 링크로 생성 정상 프로세스 - ➊ 임시 파일 존재 여부 확인 정상 프로세스 - ➋ 임시 파일이 이미 있다면 삭제하고 재생성 공격 프로세스 - ➊ 임시 파일이 존재하는 경우 심볼릭 링크 파일인지 확인 공격 프로세스 - ➋ 심볼릭 링크가 아닐 경우 임시 파일을 삭제 공격 프로세스 - ➌ 임시 파일을 심볼릭 링크로 생성 정상 프로세스 - ➌ 임시 파일에 접근하고 처리
실습 6-2 레이스 컨디션 수행하기 tempbug.c : 파일명과 파일 내용의 두 인수를 주면 해당 내용을 파일에 쓰는 역할 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> int main (int argc, char * argv []){ struct stat st; FILE * fp; if (argc != 3) { fprintf (stderr, "usage : %s file message\n", argv [0]); exit(EXIT_FAILURE); }
실습 6-2 레이스 컨디션 수행하기 sleep (20); // 공격을 위해 파일이 생성된 후, 파일을 열기까지 20초 동안 // 시간 간격을 두었다. 이 시간 간격 안에 실습을 마쳐야 한다. if ((fp = fopen (argv [1], "w")) == NULL) { fprintf (stderr, "Can't open\n"); exit(EXIT_FAILURE); } fprintf (fp, "%s\n", argv [2]); fclose (fp); fprintf (stderr, "Write Ok\n"); exit(EXIT_SUCCESS);
실습 6-2 레이스 컨디션 수행하기 공격 대상 파일 생성하기 /etc/shadow 파일에 대해 공격 수행 전, 파일 백업 tempbug.c 컴파일, SetUID 권한 부여 [그림 6-24] 취약 프로그램인 tempbug 생성 후 확인 1 cp /etc/shadow /etc/shadow.backup gcc -o tempbug tempbug.c chmod 4755 tempbug ls -al tempbug
실습 6-2 레이스 컨디션 수행하기 공격 대상 파일 실행하기 temp 파일 생성,이 파일에‘root::12519:0:99999:7:::’을 쓰도록 백그라운드(&)로 실행 [그림 6-25] temp 파일에 root 관련 내용을 저장하도록 tempbug 실행 2 touch temp ./tempbug temp "root::12519:0:99999:7:::" &
실습 6-2 레이스 컨디션 수행하기 파일 바꿔치기 먼저 생성했던 temp 파일삭제 /etc/shadow 파일에 대한 심볼릭 링크파일을 tempbug가 접근하고자 하는 temp 파일로 바꿔치기(20초 이내 완료) [그림 6-26] 생성된 temp 파일 삭제 후 /etc/shadow 파일에 대한 심볼릭 링크 파일 생성 3 rm temp ln -s /etc/shadow ./temp fg
실습 6-2 레이스 컨디션 수행하기 공격 결과 확인 temp 파일에 입력되었어야 할 내용이 /etc/shadow 파일에 입력된 것 확인 [그림 6-27] 변경된 /etc/shadow 파일 내용 확인 시스템 정상 상태 확인 공격 뒤에는 /etc/shadow 파일 복구 4 cat /etc/shadow 5 mv /etc/shadow.backup /etc/shadow
레이스 컨디션 공격에 대한 이해 레이스 컨디션 공격의 다른 경우 어떤 프로그램이 중요한 데이터를 암호화하여 가지고 있고, 프로그램 실행 전에 암호화된 파일을 복호화한 뒤 메모리에 로드하고 복호화된 임시 파일을 삭제할 때 레이스 컨디션으로 수행할 프로세스 레이스 컨디션 공격 성공시 프로그램 실행
레이스 컨디션 공격에 대한 대응책 프로그램 로직 중에 임시 파일 생성 후, 임시 파일에 접근하기 전에 임시 파일에 대한 심볼릭 링크 설정 여부와 권한에 대한 검사 과정 추가 safeopen.c int safeopen(char *filename){ struct stat st, st2; int fd; ➊ if (lstat (filename, &st) != 0) return -1; ➋ if (!S_ISREG(st.st_mode))
레이스 컨디션 공격에 대한 대응책 ➌ if (st.st_uid != 0) return -1; fd = open (filename, O_RDWR, 0); if (fd <0 ) ➍ if (fstat (fd, &st2) != 0){ close (fd); } ➎ if (st.st_ino != st2.st_ino) || st.st_dev != st2.st_dev){ return fd;
레이스 컨디션 공격에 대한 대응책 ➊ if (lstat (filename, &st) != 0) : 심볼릭 링크의 유무에 대한 정보 반환 ➋ if (!S_ISREG(st.st_mode)) : 구조체 st에 대한 st_mode 값으로 파일의 종류에 대해 확인 •S_ISBLK - 블록 파일 테스트 •S_ISCHR - 문자 파일 테스트 •S_ISDIR - 디렉터리 테스트 •S_ISFIFO - FIFO 테스트 •S_ISREG - 일반적인 파일 테스트 •S_ISLNK - 기호 링크 테스트 ➌ if (st.st_uid != 0) : 생성된 파일의 소유자가 root가 아닌 경우 검사, 공격자가 자신이 생성한 파일 삭제, 접근하고자 하는 파일이 일반 계정 소유의 파일인지 확인 ➍ if (fstat (fd, &st2) != 0) : 파일 포인터에 의해 열린 파일 정보 모아 st2 구조체에 전달 전달되는 데이터에는 장치(device), I-노드, 링크 개수, 파일 소유자의 사용자 ID 소유자의 그룹 ID, 바이트 단위 크기, 마지막 접근 시간, 마지막 수정된 시간, 마지막 바뀐 시간, 파일 시스템 입출력(I/O) 데이터 블록의 크기, 할당된 데이터 블록의 수 등이 있다. ➎ if (st.st_ino != st2.st_ino) || st.st_dev != st2.st_dev) : 최초 파일에 대한 정보를 저장하고 있는 st와 파일을 연 후 st2에 저장된 I-노드 값, 장치(device) 값의 변경 여부 확인