근래에 긱뉴스(GeekNews)에서 재밌는 글을 봤다: https://news.hada.io/topic?id=29027

안전한 러스트에서 시스템적인 결함까지는 안전하게 처리해주진 못한다. 라는 내용이다.

TOCTOU (Time-of-Check to Time-of-Use)

우선 TOCTOU란 단어 그대로 상태를 검사하는 시점과 그 결과를 바탕으로 실제 사용하는 시점 사이에 틈이 생겨 발생하는 취약점이다. 해당 취약점은 프로세스 간 환경이나 멀티 스레드 환경에서 일어나기 쉽다.

발생 원리는 다음과 같이 일어난다.

  1. 프로그램이 특정 조건이 안전한지 또는 유효한지 확인한다. (예: 이 파일이 존재하는가?, 이 파일에 쓰기 권한이 있는가?)
  2. 검사가 끝난 직후에 프로그램이 다음 코드를 실행하기 전 엄청 짧은 틈이 생긴다. 이때 공격자나 다른 프로세스가 개입하여 상태를 바꾼다. (예: 심볼릭 링크로 일반 파일을 관리자 권한이 필요한 중요한 시스템 파일로 바꿔치기)
  3. 프로그램은 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 툴에서 에러 코드를 제대로 안 내고 패닉나서 이를 이용해서 작업을 성공하게 착각시킬 수도 있다고도 하고..

사실 프로그램 설계자측 문제라고 생각한다.

뭐 그래서 이것들을 근거로 급진적으로 러스트 도구들을 넣고있는 우분투를 비판하는 내용이다.