The following line is the source of the segfault (sshkey.c): key->cert->principals[key->cert->nprincipals++] = principal;
With gdb, we can see that the pointer returned by reallocarray() is invalid:
(gdb) p key->cert->principals
$1 = (char **) 0x5585dfb0
(gdb) x 0x5585dfb0
0x5585dfb0: Cannot access memory at address 0x5585dfb0
(gdb) x 0x55555585dfb0
0x55555585dfb0: 0x5585e230
As we can see the pointer is valid, but the address has been truncated: 32 bits instead of 64, and so we get a segfault.
The program has been compiled with HAVE_REALLOCARRAY=1, and the glibc version does support it (v.2.28), but we need to use __GNU_SOURCE to have the prototypes.
If we look at includes.h, we include stdlib.h (where reallocarray is supposed to be defined) and THEN we set __GNU_SOURCE, so we end up with the prototype of reallocarray to NOT be included.
We end up with a warning during the compilation:
sshkey.c:1947:27: warning: implicit declaration of function ‘reallocarray’; did you mean ‘recallocarray’? [-Wimplicit-function-declaration]
key->cert->principals = reallocarray(key->cert->principals,
But because we don't have -Werror, the code is still compiled and the compiler assumes the function returns an integer... (32 bit).
The linking phase is working just fine, and the function reallocarray is properly linked, but the code in ncrack assumes the return value is a 32bit integer instead of a 64bit pointer and we end up with a truncated address.
The fix is pretty trivial: we need to define __GNU_SOURCE BEFORE including stdlib.h
The code used to work fine in the past because we had #include <malloc.h> (which contains the prototype of reallocarray), but it got removed by this commit 440751f515ffb7f88c308288 and we ended up with this missing prototype.
Defining __GNU_SOURCE instead of including malloc.h is better because the latter is deprecated.
After applying this patch and compiling ncrack, we get:
$ ./ncrack --pairwise --user root --pass vagrant $HOSTNAME:22
Starting Ncrack 0.8 ( http://ncrack.org ) at 2021-05-10 09:30 PDT
Ncrack done: 1 service scanned in 3.00 seconds.
Ncrack finished.
On Centos 8 (7 as well?) ncrack segfaults when the SSH plugin is being used.
Build ncrack with the default flags for centos (
$RPM_OPT_FLAGS
):The following line is the source of the segfault (sshkey.c):
key->cert->principals[key->cert->nprincipals++] = principal;
With gdb, we can see that the pointer returned by
reallocarray()
is invalid:As we can see the pointer is valid, but the address has been truncated: 32 bits instead of 64, and so we get a segfault.
The program has been compiled with
HAVE_REALLOCARRAY=1
, and the glibc version does support it (v.2.28), but we need to use__GNU_SOURCE
to have the prototypes. If we look atincludes.h
, we includestdlib.h
(where reallocarray is supposed to be defined) and THEN we set__GNU_SOURCE
, so we end up with the prototype ofreallocarray
to NOT be included.We end up with a warning during the compilation:
But because we don't have
-Werror
, the code is still compiled and the compiler assumes the function returns an integer... (32 bit). The linking phase is working just fine, and the function reallocarray is properly linked, but the code in ncrack assumes the return value is a 32bit integer instead of a 64bit pointer and we end up with a truncated address.The fix is pretty trivial: we need to define
__GNU_SOURCE
BEFORE including stdlib.h The code used to work fine in the past because we had#include <malloc.h>
(which contains the prototype ofreallocarray
), but it got removed by this commit 440751f515ffb7f88c308288 and we ended up with this missing prototype. Defining__GNU_SOURCE
instead of includingmalloc.h
is better because the latter is deprecated.After applying this patch and compiling ncrack, we get: