Rust for Cyber Security

Build memory-safe security tools with Rust - zero-cost abstractions, no garbage collector, and compile-time safety guarantees.


Why Rust for Security

Rust is a systems programming language that guarantees memory safety without a garbage collector. Its ownership system prevents the entire class of vulnerabilities that plague C/C++ security tools.

  • Memory safety - No buffer overflows, use-after-free, or dangling pointers
  • No undefined behavior - The compiler catches what C/C++ compilers miss
  • Performance - Matches C/C++ speed with zero-cost abstractions
  • Modern tooling - Cargo, built-in testing, and excellent documentation
  • Growing ecosystem - Security tools like rustscan, ripgrep, and nmap-rs
Memory Safety Revolution

Microsoft estimates that 70% of their security vulnerabilities are memory safety issues. Rust eliminates this entire category at compile time.

Rust Basics

rust
use std::net::TcpStream;
use std::time::Duration;

#[derive(Debug)]
struct ScanResult {
    host: String,
    port: u16,
    is_open: bool,
}

fn scan_port(host: &str, port: u16) -> ScanResult {
    let addr = format!("{}:{}", host, port);
    let is_open = TcpStream::connect_timeout(
        &addr.parse().unwrap(),
        Duration::from_millis(500)
    ).is_ok();

    ScanResult {
        host: host.to_string(),
        port,
        is_open,
    }
}

fn main() {
    let host = "192.168.1.1";
    let ports = vec![22, 80, 443, 8080];

    for port in ports {
        let result = scan_port(host, port);
        if result.is_open {
            println!("Port {} is OPEN", result.port);
        }
    }
}

Ownership & Borrowing

Rust's ownership system ensures memory safety at compile time without a garbage collector.

rust
// Ownership: each value has exactly one owner
fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // s1 is moved to s2, s1 is no longer valid

    // Borrowing: references without taking ownership
    let s3 = String::from("world");
    let len = calculate_length(&s3);  // borrow s3
    println!("Length of '{}' is {}", s3, len);  // s3 is still valid
}

fn calculate_length(s: &String) -> usize {
    s.len()
}  // s goes out of scope, but since it doesn't own the value, nothing happens

Network Scanner

Build a concurrent port scanner using Rust's threads and error handling.

rust
use std::net::{TcpStream, ToSocketAddrs};
use std::time::Duration;
use std::thread;

fn scan(host: &str, port: u16) -> bool {
    let addr = format!("{}:{}", host, port);
    let timeout = Duration::from_millis(200);

    TcpStream::connect_timeout(&addr.parse().unwrap(), timeout).is_ok()
}

fn main() {
    let host = "scanme.nmap.org";
    let start_port = 1;
    let end_port = 1024;

    let mut handles = vec![];

    for port in start_port..=end_port {
        let host = host.to_string();
        let handle = thread::spawn(move || {
            if scan(&host, port) {
                println!("Port {} is open", port);
            }
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

Error Handling

Rust uses Result<T, E> and Option<T> for explicit error handling.

rust
use std::fs;
use std::io;

fn read_config(path: &str) -> Result<String, io::Error> {
    let content = fs::read_to_string(path)?;
    Ok(content)
}

fn main() {
    match read_config("/etc/passwd") {
        Ok(content) => println!("Config: {}", content),
        Err(e) => eprintln!("Error reading config: {}", e),
    }

    // Using Option for nullable values
    let config_value: Option<String> = get_env_var("API_KEY");
    match config_value {
        Some(key) => println!("API Key: {}", key),
        None => println!("No API key found"),
    }
}

Web Scanner Example

Build a simple web vulnerability scanner using Rust's HTTP libraries.

rust
use reqwest::Client;
use std::error::Error;

async fn check_sql_injection(url: &str) -> Result<bool, Box<dyn Error>> {
    let client = Client::new();
    let payload = "' OR '1'='1";

    let response = client
        .get(&format!("{}?id={}", url, payload))
        .send()
        .await?;

    let body = response.text().await?;

    // Check for SQL error indicators
    let indicators = [
        "sql syntax",
        "mysql_fetch",
        "ORA-",
        "PostgreSQL",
        "SQLite",
    ];

    for indicator in indicators {
        if body.to_lowercase().contains(&indicator.to_lowercase()) {
            return Ok(true);
        }
    }

    Ok(false)
}
Legal Notice

Only scan systems you own or have explicit permission to test. Unauthorized scanning is illegal.

Resources