Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Segfault can be triggered with printw #54

Open
kpcyrd opened this issue Oct 26, 2018 · 2 comments
Open

Segfault can be triggered with printw #54

kpcyrd opened this issue Oct 26, 2018 · 2 comments

Comments

@kpcyrd
Copy link

kpcyrd commented Oct 26, 2018

During some tests my program segfaulted and the backtrace was indicating a crash in the way pancurses uses libncursesw.

extern crate pancurses;

use pancurses::{initscr, endwin};

fn main() {
    let crash = "!~&@%+ S";

    let window = initscr();
    window.printw(crash);
    window.refresh();
    window.getch();
    endwin();
}

The segfault is due to a read from an invalid pointer:

<Could not read memory at 0xffffffffb9772078>

Backtrace:

pwndbg> bt
#0  0x00006de9c1c0d5d5 in __wcslen_avx2 () from /usr/lib/libc.so.6
#1  0x00006de9c1b51883 in wcsrtombs () from /usr/lib/libc.so.6
#2  0x00006de9c1afee34 in vfprintf () from /usr/lib/libc.so.6
#3  0x00006de9c1bb6c5f in __vsnprintf_chk () from /usr/lib/libc.so.6
#4  0x00006de9c1ce5f5a in _nc_printf_string_sp () from /usr/lib/libncursesw.so.6
#5  0x00006de9c1cdf862 in vwprintw () from /usr/lib/libncursesw.so.6
#6  0x00006de9c1cdf9f5 in wprintw () from /usr/lib/libncursesw.so.6
#7  0x00000b979d7ec874 in pancurses::window::Window::printw (self=0x7929b9772b28, string=...) at /home/user/.cargo/registry/src/github.heygears.com-1ecc6299db9ec823/pancurses-0.16.0/src/window.rs:487
#8  0x00000b979d7ec905 in pancrash::main () at src/main.rs:9
#9  0x00000b979d7ec780 in std::rt::lang_start::{{closure}} () at libstd/rt.rs:74
#10 0x00000b979d7f4e93 in std::rt::lang_start_internal::{{closure}} () at libstd/rt.rs:59
#11 std::panicking::try::do_call () at libstd/panicking.rs:310
#12 0x00000b979d80c1ca in __rust_maybe_catch_panic () at libpanic_unwind/lib.rs:103
#13 0x00000b979d7fb0f6 in std::panicking::try () at libstd/panicking.rs:289
#14 std::panic::catch_unwind () at libstd/panic.rs:392
#15 std::rt::lang_start_internal () at libstd/rt.rs:58
#16 0x00000b979d7ec758 in std::rt::lang_start (main=0xb979d7ec8c0 <pancrash::main>, argc=1, argv=0x7929b9772da8) at libstd/rt.rs:74
#17 0x00000b979d7ec9aa in main ()
#18 0x00006de9c1ad0223 in __libc_start_main () from /usr/lib/libc.so.6
#19 0x00000b979d7ec5ce in _start ()
pwndbg> 
@kpcyrd
Copy link
Author

kpcyrd commented Oct 26, 2018

After some digging, this is a format string vulnerability, you can print internal memory like this:

extern crate pancurses;

use pancurses::{initscr, endwin};

fn main() {
    //let crash = "!~&@%+ S";
    let crash = "%p\n%p\n%p\n%p";

    let window = initscr();
    window.printw(crash);
    window.refresh();
    window.getch();
    endwin();
}

Since we don't want to support that, the printw function needs to look like this:

    /// Add a string to the window at the current cursor position.
    pub fn printw<T: AsRef<str>>(&self, string: T) -> i32 {
        let f = CString::new("%s").unwrap();
        let s = CString::new(string.as_ref()).unwrap();
        unsafe { curses::wprintw(self._window, f.as_ptr(), s.as_ptr()) }
    }

This bug probably exists in some of the other functions as well.

@Shnatsel
Copy link

So arbitrary input was erroneously passed to libncursesw where it expected a format string? Nice find!

Once a fix is published, this issue should be added to the Rust security advisory database.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants