근래에 긱뉴스(GeekNews)에서 재밌는 글을 봤다: https://news.hada.io/topic?id=29027
안전한 러스트에서 시스템적인 결함까지는 안전하게 처리해주진 못한다. 라는 내용이다.
TOCTOU (Time-of-Check to Time-of-Use)
우선 TOCTOU란 단어 그대로 상태를 검사하는 시점과 그 결과를 바탕으로 실제 사용하는 시점 사이에 틈이 생겨 발생하는 취약점이다. 해당 취약점은 프로세스 간 환경이나 멀티 스레드 환경에서 일어나기 쉽다.
발생 원리는 다음과 같이 일어난다.
- 프로그램이 특정 조건이 안전한지 또는 유효한지 확인한다. (예: 이 파일이 존재하는가?, 이 파일에 쓰기 권한이 있는가?)
- 검사가 끝난 직후에 프로그램이 다음 코드를 실행하기 전 엄청 짧은 틈이 생긴다. 이때 공격자나 다른 프로세스가 개입하여 상태를 바꾼다. (예: 심볼릭 링크로 일반 파일을 관리자 권한이 필요한 중요한 시스템 파일로 바꿔치기)
- 프로그램은 1번의 검사 결과가 유효하다고 가정하고 작업을 수행한다. 하지만 이미 상태가 변경되었기 때문에 의도치 않은 동작이 발생한다.
예시를 보자
use std::path::Path;
use std::fs::File;
let path = Path::new("temp.txt");
// 1. 파일이 있는지 확인
if path.exists() {
// 다른 프로세스가 temp.txt를 지우고,
// 동일한 이름으로 /etc/shadow를 가리키는 심볼릭 링크를 생성한다고 가정
// 2. 파일 열기
// 프로그램은 안전하다고 가정하고 열었지만, 실제로는 시스템 파일을 건드리게 됨
let mut file = File::open(&path).unwrap();
// todo..
}
대강 위와 같이 진행된다.
위쪽에 레퍼런스한 글을 보면 std::fs가 유닉스 기반의 File Descriptor 기반이 아니라 문자열 기반이라 TOCTOU를 일으키기 너무 쉽다는 점을 지적한다.
흠 근데 개인적으로 이건 '러스트' 뿐만 아니라 도구를 어떤식으로 제공해줄 건지에 따른 언어의 철학에 따라 갈린다고 생각한다. 따라서 러스트를 타겟팅해서 까는 건 약간 이해가 안 간다.
뭐 외에도 다른 여러 지적이 있는데, CLI 툴에서 에러 코드를 제대로 안 내고 패닉나서 이를 이용해서 작업을 성공하게 착각시킬 수도 있다고도 하고..
사실 프로그램 설계자측 문제라고 생각한다.
뭐 그래서 이것들을 근거로 급진적으로 러스트 도구들을 넣고있는 우분투를 비판하는 내용이다.