The past several years have seen an explosion of hype about Rust. For 6 years in a row, devs have voted Rust as the most loved programming language. And it’s no surprise. Rust adds real innovation to systems programming, a field that was stagnant for decades. So of course, there’s growing interest in the benefits of Rust for security engineers.
So what do we, as security engineers, need to know about Rust? In this article we’ll explain exactly that. First, we’ll give you a small taste of how Rust makes low-level coding safer. Then we’ll look at common vulnerabilities that affect Rust software. Finally, we’ll conclude with an overview of tools that help find exploits in Rust code.
Let’s dive in!
How Rust improves safety
As security pros, we’re all aware of the memory bugs that plague C and C++. However, Rust handles memory much more safely. Thanks to the compiler, Rust can detect and prevent common memory issues that lead to exploits in older systems languages like C. At the same time, it doesn’t have a garbage collector like Java or Python, making it simpler and faster than interpreted languages.
For example, let’s say you have the following code in C:
char* some_memory = malloc(12);
free(some_memory);
// and then later...
free(some_memory);
This is called a double freeing bug. Even though hackers can exploit this bug, it’s an easy and common mistake. C will let you do this, and it happens all the time.
In rust, however, the equivalent code won’t even compile. Consider the following Rust code that attempts to free a resource twice:
fn main() {
let url = String::from("https://cng.ngo");
println!("{}", url);
drop(url);
drop(url);
}
If this code were to run, it could try to free already free’d memory, leading to weird behavior. And such behavior is a great source of exploits. What will Rust do?
rustc -o main main.rs
error[E0382]: use of moved value: `url`
--> main.rs:5:8
|
2 | let url = String::from("https://cng.ngo");
| --- move occurs because `url` has type `std::string::String`, which does not implement the `Copy` trait
3 | println!("{}", url);
4 | drop(url);
| --- value moved here
5 | drop(url);
| ^^^ value used here after move
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
exit status 1
Perfect, Rust notices that we try to use a freed resource and won’t even let the code compile. Imagine the billions of dollars that could save in industry. After all, memory exploitation has been a top source of hacks for decades.
But it’s not all rainbows and sunshine! Rust code is cool, but it’s not nearly perfect. Let’s learn about some types of vulnerabilities that do affect Rust programs.
Common vulnerabilities in Rust
Remember how we said Rust code is memory safe? Well, in order to work with custom hardware, support inline assembly, and do cool hacky things that devs sometimes need, Rust allows you to mark code as unsafe. When code is marked unsafe, the normal safety checks don’t apply, and all those scary C memory bugs can affect your application.
For example, we could try to create a raw pointer to a random location in memory and dereference it:
fn main() {
let address = 0x012345usize;
let r = address as *const i32;
unsafe {
println!("{}", *r);
}
}
Running this results in a segmentation fault, as we would expect. Yet, this is a realistic scenario. Imagine we were coding for an embedded device with important data hardcoded at a certain memory location. In that case, the ability to do this would be crucial, even if unsafe in theory.
That’s why Rust gives us the option. However, being too loose about using unsafe Rust can lead to the same old exploits we see in unsafe langs, so it’s important to only use this feature when it’s truly necessary.
Rust is also vulnerable to supply chain attacks targeting it’s Crates dependency ecosystem. By infecting a crate with malicious code, you can further infect any app that depends on that crate. Typosquatting and the usual gang of supply chain attack suspects we know from Python’s pip and Javascript’s npm apply here as well.
Common sense about Rust for Security Engineers
It’s worth mentioning two additional sources of vulnerabilities. Although these should be common sense for any security pros.
- The business logic of your app.
- Relying on outdated versions of Rust itself.
If you have a flaw in the basic logic of your app, no language can solve that for you perfectly. For example, Rust’s secure memory model won’t help if you’ve created a SIM card vulnerable to a cloning attack. Similarly, using an old, vulnerable version of Rust will surely lead to disaster. This is common sense for security engineers, and you should already know better, so we won’t explore those anymore
So you have a basic idea of how Rust apps become vulnerable. Unsafe code, supply chain attacks, and classic logic and versioning issues all add up to potential hacks for Rust apps. But how can you actually begin exploiting them?
To answer that question, let’s see some tools security engineers use to find bugs in Rust code.
Tools for hacking Rust apps
Probably the most well known and beloved tool for hacking Rust apps is Rust fuzz. This GitHub org gives you integration with AFL, the top fuzzer for C and C++, as well as a fuzzer for Cargo. You can’t go wrong – it’s easy to use and has found literally thousands of exploits in actual Rust programs.
In addition to Rust fuzz, security engineers curious about finding security holes in Rust code should check out Cargo Geiger. This tool gives you everything you need to find problem with a codebase’s dependency graph quickly and easily.
Finally, you will want to look at Mozilla’s Rust Code Analysis library on Github. With this, you can find coding issues that may lead to deeper security bugs. Whether you’re a blue teamer patching up bad code, or a red teamer looking for your next exploit, static analysis is the perfect place to start your hunt for bugs.
Conclusion – Why Rust for Security Engineers?
Rust is a language that’s drastically changing how computer security works. For nearly half a century, memory bugs have been the basic building block of hacking. With Rust, software safety increases immensely right from the start. Bugs are still possible, but the mistakes that lead to bugs are harder for devs to make.
This means less hacks, less crashes, and less glitches. It’s good news for pretty much everyone who’s interested in computers being safe and secure.
Leave a Reply