Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Dangling pointer used in pub function channel_forward_listen(), resulting in an Use-After-Free bug #344

Open
quitbug opened this issue Jan 18, 2025 · 0 comments · May be fixed by #345
Open

Comments

@quitbug
Copy link

quitbug commented Jan 18, 2025

Hi, I hv noticed that there is a dangling pointer used in the pub function channel_forward_listen(). When the host parameter is not None, it will generate a dangling pointer passed in raw::libssh2_channel_forward_listen_ex(), which results in a later Use-After-Free bug.

pub fn channel_forward_listen(
        &self,
        remote_port: u16,
        host: Option<&str>,
        queue_maxsize: Option<u32>,
    ) -> Result<(Listener, u16), Error> {
        let mut bound_port = 0;
        let host = host.map(|s| CString::new(s)).transpose()?;
        let inner = self.inner();
        unsafe {
            let ret = raw::libssh2_channel_forward_listen_ex(
                inner.raw,
                host.map(|s| s.as_ptr()).unwrap_or(null()),
                remote_port as c_int,
                &mut bound_port,
                queue_maxsize.unwrap_or(0) as c_int,
            );
            let err = inner.last_error();
            Listener::from_raw_opt(ret, err, &self.inner).map(|l| (l, bound_port as u16))
        }
    }

To reproduce the UAF, compile the below code:

    use std::net::TcpStream;
    use ssh2::Session;

    // Connect to the local SSH server
    let tcp = TcpStream::connect("127.0.0.1:22").unwrap();
    // Connect to the local SSH server
    let mut sess = Session::new().unwrap();
    sess.set_tcp_stream(tcp);
    sess.handshake().unwrap();

    sess.userauth_password("username", "password").unwrap();
    assert!(sess.authenticated());
    let (mut listen, port) = sess.channel_forward_listen(39249, Some("1.2.3.4"), None).unwrap();

Suggested Fix:
Change the code host.map(|s| s.as_ptr()).unwrap_or(null()) to host.as_ref().map(|s| s.as_ptr()).unwrap_or(null())

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

Successfully merging a pull request may close this issue.

1 participant