SSH honeypot, deployed in the wild, collecting and sharing data

Welcome to SecureHoney.net

11 Oct 2013 • 4 min read

HoneypotThis website will be used to document the progress of my final year project; building an SSH honeypot in C. For more details see the about page.

I'm currently learning the programming language C as I progress with this project, so the code might not be perfect. I've previously programmed in Java and PHP - which inherit a lot of their syntax from C.

My aim is to document all the challenges I'm presented with as the project unfolds and eventually I'd like to log and analyse attacks on the honeypot.

Why build a honeypot?

I took a module in my second year called Computer Networks. I was gripped by this module, partly because I previously worked in web development, but mainly because the topic of network security and cyber attacks fascinates me.

When it came to choosing a final year project; it was a no brainer for me. The prospect of creating a honeypot to analyse cyber-attack techniques fills me with genuine excitement!

To gain a better understanding of what malicious software is; over the summer I studied a course at Coursera.org entitled Malicious Software and its Underground Economy: Two Sides to Every Story (run by Royal Holloway, University of London), which I highly recommend. The course covers how various types of malware work including analysis of their coding. A lot of this analysis is done on C and machine code.

So there are two main reasons that I want to build a honeypot:

  1. To explore and analyse cyber-attacks
  2. To learn C and to understand networking in C

The programming begins...

So, this week I started writing the code. I started simple, with a C server which allows a single connection from a client and just echo's back any text received from the client. The code can be seen below:

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

#define DEFAULT_PORT    (1234)
#define MAX_LINE        (1000)
#define LISTENQ         (1024)

int Readline(int fd, void *vptr, int maxlen);
int Writeline(int fc, const void *vptr, int maxlen);

int main(int argc, char *argv[]) {
  
  int welcomeSocket;
  int clientSocket;
  char *client_input;
  short unsigned int port;
  char buffer[MAX_LINE];
  struct sockaddr_in servaddr;
  char *endptr;

  /* set port from supplied argument otherwise use default */
  if (argc == 2) {
    port = strtol(argv[1], &endptr, 0);
    if (*endptr) {
      printf("ERROR: invalid port number.\n");
      exit(EXIT_FAILURE);
    }
  } else if (argc < 2 ){
    port = DEFAULT_PORT;
  } else {
    printf("ERROR: invalid arguments.\n");
    exit(EXIT_FAILURE);
  }

  if( (welcomeSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    printf("ERROR: can't create welcome socket.\n");
    exit(EXIT_FAILURE);
  }

  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(port);

  if( bind(welcomeSocket, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){
    printf("ERROR: can't call bind().\n");
    exit(EXIT_FAILURE);
  }

  if( listen(welcomeSocket, LISTENQ) < 0) {
    printf("ERROR: can't call listen().\n");
    exit(EXIT_FAILURE);
  }

  while(1) {
    memset(&buffer, 0, sizeof(buffer));
    if ( (clientSocket = accept(welcomeSocket, NULL, NULL)) < 0) {
      printf("ERROR: can't call accept().\n");
      exit(EXIT_FAILURE);
    }

    int rl;
    while((rl = Readline(clientSocket, buffer, MAX_LINE-1)) > 0){
      printf("Received: (%d chars) %s",rl-1,buffer);
      if(strstr(buffer,"wget") != NULL){
        printf("This is the url to get: %.*s", sizeof(buffer)-5, buffer + 5);
      }
      Writeline(clientSocket, buffer, strlen(buffer));
      memset(&buffer, 0, sizeof(buffer));
    }
  }
  
  if( close(clientSocket) < 0) {
    printf("ERROR: can't close socket");
    exit(EXIT_FAILURE);
  }

  return 0;

}

int Readline(int sockd, void *vptr, int maxlen) {
    int n, rc;
    char    c, *buffer;

    buffer = vptr;

    for ( n = 1; n < maxlen; n++ ) {
        
        if ( (rc = read(sockd, &c, 1)) == 1 ) {
            *buffer++ = c;
            if ( c == '\n' )
                break;
        }
        else if ( rc == 0 ) {
            if ( n == 1 )
                return 0;
            else
                break;
        }
        else {
            if ( errno == EINTR )
                continue;
            return -1;
        }
    }

    *buffer = 0;
    return n;
}

int Writeline(int sockd, const void *vptr, int n) {
    int      nleft;
    int     nwritten;
    const char *buffer;

    buffer = vptr;
    nleft  = n;

    while ( nleft > 0 ) {
        if ( (nwritten = write(sockd, buffer, nleft)) <= 0 ) {
            if ( errno == EINTR )
                nwritten = 0;
            else
                return -1;
        }
        nleft  -= nwritten;
        buffer += nwritten;
    }

    return n;
}

// references: http://www.paulgriffiths.net/program/c/srcs/echoservsrc.html

The code for this project will be stored on GitHub, so feel free to browse through the code, make any comments or suggestions etc.

The current server.c works using a general insecure socket. My task for this week is to create a secure socket so I can start using as SSH client to connect to the server.

Image credit: "Honey jar" by Nic McPhee, flickr.com/photos/nicmcphee/411317929

About the author

Simon BellSimon Bell is an award-winning Cyber Security Researcher, Software Engineer, and Web Security Specialist. Simon's research papers have been published internationally, and his findings have featured in Ars Technica, The Hacker News, PC World, among others. He founded Secure Honey, an open-source honeypot and threat intelligence project, in 2013. He has a PhD in Information Security and a BSc in Computer Science.

Follow Simon on Twitter: @SimonByte