Segurança de aplicações Rust: top-10 vulnerabilidades para iniciantes

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Segurança de aplicações Rust: top-10 vulnerabilidades para iniciantes

\n\n

Rust é considerada uma das linguagens de programação mais seguras graças ao seu sistema de ownership (propriedade) e tipagem estrita. No entanto, mesmo em Rust é possível cometer erros, especialmente ao usar blocos unsafe ou ao trabalhar incorretamente com bibliotecas externas. Neste artigo, analisaremos as top-10 vulnerabilidades que desenvolvedores iniciantes em Rust enfrentam e mostraremos como evitá-las.

\n\n

1. Uso inseguro de código unsafe

\n\n

A principal característica do Rust é a segurança de memória sem coletor de lixo. No entanto, a palavra-chave unsafe desativa algumas verificações do compilador. Iniciantes frequentemente abusam dela sem entender as consequências.

\n\n
// Perigoso: desreferenciar ponteiro bruto sem verificação\nfn dangerous() {\n    let ptr = 0x12345 as *const i32;\n    unsafe {\n        println!("Valor: {}", *ptr); // Pode causar segfault\n    }\n}\n\n// Seguro: usar métodos verificados\nfn safe() {\n    let x = 42;\n    let ptr = &x as *const i32;\n    unsafe {\n        if !ptr.is_null() {\n            println!("Valor: {}", *ptr);\n        }\n    }\n}
\n\n

Recomendação: Use unsafe apenas quando realmente necessário e sempre verifique se os ponteiros são nulos.

\n\n

2. Vazamentos de memória via Box::leak e ciclos Rc

\n\n

Embora Rust previna a maioria dos vazamentos de memória, referências cíclicas com Rc ou RefCell podem causar vazamentos. Box::leak também é perigoso, pois "esquece" intencionalmente a memória.

\n\n
use std::rc::Rc;\nuse std::cell::RefCell;\n\n#[derive(Debug)]\nstruct Node {\n    value: i32,\n    next: Option<Rc<RefCell<Node>>>,\n}\n\nfn create_cycle() {\n    let a = Rc::new(RefCell::new(Node { value: 1, next: None }));\n    let b = Rc::new(RefCell::new(Node { value: 2, next: None }));\n    \n    // Criando ciclo: a -> b -> a\n    a.borrow_mut().next = Some(b.clone());\n    b.borrow_mut().next = Some(a.clone());\n    // A memória nunca será liberada!\n}
\n\n

Solução: Use Weak<T> para quebrar referências cíclicas ou repense a arquitetura.

\n\n

3. Condições de corrida (Data Races) em código multithread

\n\n

Rust garante a ausência de data races em código seguro, mas o uso incorreto de unsafe ou das traits Send/Sync pode causar problemas.

\n\n
use std::thread;\nuse std::sync::Arc;\nuse std::sync::Mutex;\n\n// Perigoso: compartilhar estado mutável sem sincronização\nfn data_race_example() {\n    let mut counter = 0;\n    let mut handles = vec![];\n    \n    for _ in 0..10 {\n        handles.push(thread::spawn(|| {\n            counter += 1; // Erro de compilação: cannot borrow\n        }));\n    }\n}\n\n// Seguro: usar Mutex\nfn safe_mutex() {\n    let counter = Arc::new(Mutex::new(0));\n    let mut handles = vec![];\n    \n    for _ in 0..10 {\n        let counter = Arc::clone(&counter);\n        handles.push(thread::spawn(move || {\n            let mut num = counter.lock().unwrap();\n            *num += 1;\n        }));\n    }\n}
\n\n

4. Estouro de buffer (Buffer Overflow)

\n\n

Em Rust, o estouro de buffer é improvável em código seguro, mas possível ao usar unsafe ou ao trabalhar com FFI (Foreign Function Interface).

\n\n
// Perigoso: cópia insegura para buffer\nfn unsafe_copy(src: &[u8], dst: &mut [u8]) {\n    unsafe {\n        std::ptr::copy_nonoverlapping(\n            src.as_ptr(),\n            dst.as_mut_ptr(),\n            src.len() // Se src.len() > dst.len() - estouro!\n        );\n    }\n}\n\n// Seguro: usar slice::copy_from_slice\nfn safe_copy(src: &[u8], dst: &mut [u8]) {\n    if src.len() <= dst.len                

Blogs

Book Recommendations