Description
This issue is to report several problems linked:
- libbacktrace (embeded in every rust-compiled program) is fragile (a bad input could generate a crash, I don't have checked for code-execution at this moment)
- a race condition exists with
os::self_exe_name
that could permit to exploit the previous issue by replacing at runtime the binary by a specially crafted elf.
I will first speak about the race, and next about libbacktrace.
First, about os::self_exe_name
: it is a function that return an Option about the running binary (the filepath to the binary used for launch the running processus).
The function is used in rustc:
- by librustc to infer the default sysroot directory (rustc and rustdoc use it)
- by libbacktrace under bsd system for gets the binary symbols
(but note that for others platforms, libbacktrace obtain symbols by itself using similar method thanos::self_exe_name
, so there is the same problem) - by severals tests
The implementation (sys::os::load_self
) is platform dependant:
- freebsd: sysctl()
- dragonfly: readlink(/proc)
- linux, android: readlink(/proc)
- macos, ios: _NSGetExecutablePath()
- windows: GetModuleFileNameW()
Just returning a filepath is subject to race condition for many usages. The libbacktrace usage is one of them.
libbacktrace is initialized on sys::backtrace::print()
call (so not at the beginning of the processus). This function is called by sys::backtrace::write()
. And on panic, a backtrace is showed if RUST_BACKTRACE
environment is setted.
So, when a panic occurs, libbacktrace will read the previously obtained filepath (from os::self_exe_name
or by itself). It will open this filepath, parse the ELF structure, search for symbols and addresses... and do all the thing it need for print a pretty backtrace.
The problem is libbacktrace seems not robust enought for specially crafted ELF. I have started to test it with afl-fuzzer, and it reports severals crashs (that may or not be suceptible to produce code-execution).
As libbacktrace is embeded in (near to) every rust-compiled programs, it could be a dangerous thing.
To successfully exploit it, the following conditions are required:
- run libbacktrace code:
- RUST_BACKTRACE environment variable to be setted
- trigger a
panic
in running process
- have libbacktrace read a crafted-elf:
- replace the file of the running program by another one after the start of the program, and before the panic
The conditions are relatively high for simple exploitation, but as it is a problem present in (near to) every rust-compiled code, some attention should be need.