경쟁조건(Race Condition)이 무엇이고, 왜 보안 취약점이 되는지
핵심은 “누가 먼저 실행되느냐, 어느 타이밍에 파일이 존재하느냐”에 따라 결과가 달라지는 상황을 공격자가 의도적으로 이용한다는 점이다.
먼저 경쟁조건의 개념부터 정리하자. 경쟁조건이란 여러 프로세스가 같은 자원(파일, 메모리, 권한 등)을 동시에 사용하려고 할 때, 실행 순서나 타이밍에 따라 정상적이지 않은 결과가 발생하는 상태를 말한다. 운영체제는 여러 작업을 동시에 처리하기 때문에, 특정 순간에 “아직 검사하지 않았는데 이미 실행됐다” 같은 틈이 생길 수 있다. 공격자는 바로 이 틈을 노린다.
이 설명에서는 경쟁조건 공격을 이해하기 위해 setuid 백도어 + 심볼릭 링크 예제를 사용하고 있다. 흐름을 단계별로 보면 훨씬 명확하다.
먼저 공격자는 백도어 프로그램을 만든다. 이 프로그램은 실행되면 root 권한을 획득하도록 만들어진 파일이다. 리눅스에서 UID와 GID가 0이면 root 권한을 의미하므로, 이 백도어는 root 권한으로 실행될 수 있어야 한다. 그래서 공격자는 이 파일에 setuid 권한을 설정한다. 이렇게 하면 일반 사용자도 이 프로그램을 실행했을 때 root 권한을 얻게 된다.
다음으로 공격자는 이 백도어 파일을 직접 실행하지 않고, 심볼릭 링크를 하나 만든다. 심볼릭 링크는 실제 파일을 가리키는 “바로가기” 같은 존재다. 예를 들어 racecondition이라는 이름의 심볼릭 링크가 실제 백도어 파일을 가리키도록 만든다. 이 상태에서 일반 사용자가 racecondition을 실행하면, 실제로는 백도어 파일이 실행되면서 root 권한을 얻게 된다. 여기까지는 단순한 setuid 백도어 공격이다.
이제 경쟁조건이 개입되는 부분이 중요하다. 만약 root 관리자가 이 백도어의 존재를 알아차리고 파일을 삭제했다고 가정하자. 그러면 실제 백도어 파일은 사라진다. 하지만 심볼릭 링크는 그대로 남아 있다. 이 시점에서는 링크가 가리킬 대상이 없기 때문에 동작하지 않는다.
그런데 이후에 root 사용자가 같은 이름의 파일을 같은 디렉터리에 다시 생성하게 되면 상황이 달라진다. 심볼릭 링크는 파일의 “이름”을 따라가기 때문에, 새로 생성된 파일을 다시 가리키게 된다. 만약 이 파일이 root 권한으로 실행되거나, setuid가 붙을 수 있는 상황이라면, 공격자는 다시 racecondition 심볼릭 링크를 통해 root 권한을 획득할 수 있다.
이것이 경쟁조건 공격이다.
공격자는 “파일이 삭제된 시점”과 “다시 생성되는 시점” 사이의 타이밍, 그리고 링크가 자동으로 다시 유효해지는 특성을 이용한다. 즉, 관리자가 조치를 했다고 생각한 순간 이후에, 조건이 맞으면 취약점이 다시 살아나는 것이다.
정리하면, 경쟁조건은
- 여러 프로세스가 동시에 같은 자원을 다루고
- 실행 순서나 시간 차이에 따라
- 보안 검사가 무력화되거나 우회되는 상황을 말한다.