
Démontre un use-after-free en Rust dans un serveur web avec du code vulnérable et un déclencheur multithread pour montrer la corruption mémoire et une possible exécution de code.
// uaf_server.rs - Vulnerable Rust HTTP server with use-after-free
use std::sync::{Arc, Mutex};
use std::thread;
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
struct SharedBuffer {
data: Vec<u8>,
}
impl SharedBuffer {
fn new() -> Self { SharedBuffer { data: vec![0; 1024] } }
}
fn handle_client(mut stream: TcpStream, buffer: Arc<Mutex<SharedBuffer>>) {
// Simulate reading request and writing response.
let mut buf = [0; 512];
stream.read(&mut buf).unwrap();
let b = buffer.lock().unwrap();
let ptr = b.data.as_ptr() as *mut u8; // raw pointer
// Drop the lock early? In unsafe block we might send the pointer to another thread.
// Here we simulate a bug: the SharedBuffer is dropped, but we later use the pointer.
drop(b);
// After lock is released, another thread could replace the Vec, freeing the old allocation.
// Unsafe write through the dangling pointer.
unsafe {
*ptr = 42; // use after free!
}
stream.write(b"HTTP/1.1 200 OK\r\n\r\nHello").unwrap();
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
let buffer = Arc::new(Mutex::new(SharedBuffer::new()));
for stream in listener.incoming() {
let stream = stream.unwrap();
let buf_clone = Arc::clone(&buffer);
thread::spawn(move || {
handle_client(stream, buf_clone);
});
}
}
Un serveur web écrit en Rust utilise du code unsafe pour partager un buffer entre les threads. Une condition de course mène à un use‑after‑free, pouvant entraîner une corruption mémoire ou une divulgation d'informations.
Vec sous un verrou, le verrou est libéré, puis le vecteur est remplacé par un autre thread, ce qui libère la mémoire alors que le pointeur est toujours utilisé.rustc uaf_server.rs
./uaf_server
python trigger_uaf.py