我正在尝试用C编写一个蜜罐来复制一个SSH会话。我的目标是低交互蜜罐(类似于Kippo)。
这个想法是:客户端通过SSH连接到honeypot,然后蜜罐会理解并响应预定义的命令(例如wget,env等)。
我坚持的是创建初始SSH连接。我已阅读RFC的SSH以了解SSH会话的启动方式。然后我一直在看OpenSSH,libssh和libssh2库 - 但我看不出如何启动类似于sshd的SSH会话。
不确定我是否可以使用sshd服务创建SSH会话,然后从中运行蜜罐?
希望这是有道理的。对此有任何帮助将非常感激。
答案 0 :(得分:0)
想想我找到了我要找的东西:libssh。在他们的github页面上有一个很好的例子,说明如何在C中实现一个ssh守护进程:https://github.com/substack/libssh/blob/master/examples/samplesshd.c
对于C语言中的基本SSH蜜罐实现,github上的项目由Pete Morris(https://github.com/PeteMo/sshpot)命名为sshpot:
#include "config.h"
#include "auth.h"
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <getopt.h>
#include <errno.h>
#include <sys/wait.h>
#define MINPORT 0
#define MAXPORT 65535
/* Global so they can be cleaned up at SIGINT. */
static ssh_session session;
static ssh_bind sshbind;
/* Print usage information to `stream', exit with `exit_code'. */
static void usage(FILE *stream, int exit_code) {
fprintf(stream, "Usage: sshpot [-h] [-p <port>]\n");
fprintf(stream,
" -h --help Display this usage information.\n"
" -p --port <port> Port to listen on; defaults to 22.\n");
exit(exit_code);
}
/* Return the c-string `p' as an int if it is a valid port
* in the range of MINPORT - MAXPORT, or -1 if invalid. */
static int valid_port(char *p) {
int port;
char *endptr;
port = strtol(p, &endptr, 10);
if (port >= MINPORT && port <= MAXPORT && !*endptr && errno == 0)
return port;
return -1;
}
/* Signal handler for cleaning up after children. We want to do cleanup
* at SIGCHILD instead of waiting in main so we can accept multiple
* simultaneous connections. */
static int cleanup(void) {
int status;
int pid;
pid_t wait3(int *statusp, int options, struct rusage *rusage);
while ((pid=wait3(&status, WNOHANG, NULL)) > 0) {
if (DEBUG) { printf("process %d reaped\n", pid); }
}
/* Re-install myself for the next child. */
signal(SIGCHLD, (void (*)())cleanup);
return 0;
}
/* SIGINT handler. Cleanup the ssh* objects and exit. */
static void wrapup(void) {
ssh_disconnect(session);
ssh_bind_free(sshbind);
ssh_finalize();
exit(0);
}
int main(int argc, char *argv[]) {
int port = DEFAULTPORT;
/* Handle command line options. */
int next_opt = 0;
const char *short_opts = "hp:";
const struct option long_opts[] = {
{ "help", 0, NULL, 'h' },
{ "port", 1, NULL, 'p' },
{ NULL, 0, NULL, 0 }
};
while (next_opt != -1) {
next_opt = getopt_long(argc, argv, short_opts, long_opts, NULL);
switch (next_opt) {
case 'h':
usage(stdout, 0);
break;
case 'p':
if ((port = valid_port(optarg)) < 0) {
fprintf(stderr, "Port must range from %d - %d\n\n", MINPORT, MAXPORT);
usage(stderr, 1);
}
break;
case '?':
usage(stderr, 1);
break;
case -1:
break;
default:
fprintf(stderr, "Fatal error, aborting...\n");
exit(1);
}
}
/* There shouldn't be any other parameters. */
if (argv[optind]) {
fprintf(stderr, "Invalid parameter `%s'\n\n", argv[optind]);
usage(stderr, 1);
}
/* Install the signal handlers to cleanup after children and at exit. */
signal(SIGCHLD, (void (*)())cleanup);
signal(SIGINT, (void(*)())wrapup);
/* Create and configure the ssh session. */
session=ssh_new();
sshbind=ssh_bind_new();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, LISTENADDRESS);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, "ssh-rsa");
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,RSA_KEYFILE);
/* Listen on `port' for connections. */
if (ssh_bind_listen(sshbind) < 0) {
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
return -1;
}
if (DEBUG) { printf("Listening on port %d.\n", port); }
/* Loop forever, waiting for and handling connection attempts. */
while (1) {
if (ssh_bind_accept(sshbind, session) == SSH_ERROR) {
fprintf(stderr, "Error accepting a connection: `%s'.\n",ssh_get_error(sshbind));
return -1;
}
if (DEBUG) { printf("Accepted a connection.\n"); }
switch (fork()) {
case -1:
fprintf(stderr,"Fork returned error: `%d'.\n",-1);
exit(-1);
case 0:
exit(handle_auth(session));
default:
break;
}
}
return 0;
}