Honeyd

Περιγραφή

Το honeyd είναι ένα ανοιχτού κώδικα, χαμηλής διαδραστικότητας εικονικό honeypot που επιτρέπει την δημιουργία εικονικών συστημάτων σε ένα δίκτυο. Τα εικονικά αυτά συστήματα μπορούν να προσομοιώσουν διαφόρων τύπων λειτουργικά συστήματα καθώς και ένα μεγάλο αριθμό από υπηρεσίες που αυτά παρέχουν. Δημιουργός του είναι ο Niels Provos.

Τρόπος λειτουργίας

Η προσομοίωση των συστημάτων γίνεται χρησιμοποιώντας την τεχνική ARP spoofing. Τo honeyd μπορεί να ρυθμιστεί ώστε να καλύπτει το εύρος όλων των αχρησιμοποίητων IP διευθύνσεων στο δίκτυο.

Παράδειγμα αρχείου ρυθμίσεων

Χρησιμοποιώντας το παρακάτω αρχείο ρυθμίσεων, το honeyd προσομοιώνει ένα σύστημα Windows , που έχει ανοιχτά τα TCP port 25 kai 139. Συγκεκριμένα για το port 25 (SMTP) έχουμε ενεργοποιήσει ένα python script που αναποκρίνεται προσομοιώνοντας ένα υποσύνολο των εντολών του πρωτοκόλλου SMTP κατά το RFC821

create template
set template personality "Microsoft Windows XP Professional SP1"
add template tcp port 25 "python /tmp/smtp.py"
add template tcp port 139 open
set template default tcp action block
set template uid 65534 gid 65534

create default
set default default tcp action block
set default default udp action block
set default default icmp action block

bind 10.0.0.8 template

Script υπηρεσιών για το Honeyd

Τα απλής μορφής script υπηρεσιών για το honeyd μπορούν να γραφούν σε μια scripting γλώσσα (Python, Perl, Bash script κλπ) . Συνήθως υλοποιούνται ως state machines, δέχονται δεδομένα από το standard input (stdin) και ανταποκρίνονται γράφοντας στο stadard output (stdout). To stderr μπορεί να χρησιμοποιηθεί για καταγραφή συμβάντων (logging) από την εκάστοτε εικονική υπηρεσία.
Το παράδειγμα που ακολουθεί είναι γραμμένο σε Python και προσομοιώνει μια υπηρεσία SMTP

/*
 * Copyright (c) 2011 Lekkas Kwstas <kwstasl@gmail.com>
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import sys
import time
import re


DATE = time.strftime("%a, %d %b %Y %H:%M:%S +0200", time.localtime())
DOMAIN = 'test.org'
RCPTTO = 0
MAILFROM = 0
DATA = 0
CRLF='\r\n'
mail = 
list = []

sys.stdout.write('220 test.org ESMTP Sendmail 8.13.8/8.13.8; '+DATE+CRLF)
sys.stdout.flush();

while True:
        input = sys.stdin.readline()
        input.strip()   # strip white spaces
        input_case = input  # keep case sensitive input
        input = input.upper()
        list = input.split()
    
        if len(list) == 0 and DATA == 1:
            mail = mail + CRLF

        elif len(list) == 0:
            sys.stdout.write('500 5.5.1 Command unrecognized: ""'+CRLF)
            sys.stdout.flush()

        elif list[0] == 'QUIT' and DATA == 0:
            sys.stdout.write('221 2.0.0 '+DOMAIN+' closing connection'+CRLF)
            sys.stdout.flush()
            sys.exit(0)

        elif list[0] == 'HELO' and DATA == 0:
            if len(list) == 1:
                sys.stdout.write('501 5.0.0 helo requires domain address'+CRLF)
                sys.stdout.flush()

            else:
                sys.stdout.write('250-'+DOMAIN+' Hello '+list[1]+', pleased to meet you'+CRLF)
                sys.stdout.flush()
        
        elif list[0] == 'EHLO' and DATA == 0:
            if len(list) == 1:
                sys.stdout.write('501 5.0.0 helo requires domain address'+CRLF)
                sys.stdout.flush()

            else:
                sys.stdout.write('250-'+DOMAIN+' Hello '+list[1]+', pleased to meet you'+CRLF)
                sys.stdout.write('250-ENHANCEDSTATUSCODES'+CRLF)
                sys.stdout.write('250-PIPELINING'+CRLF)
                sys.stdout.write('250-EXPN'+CRLF)
                sys.stdout.write('250-VERB'+CRLF)
                sys.stdout.write('250-8BITMIME'+CRLF)
                sys.stdout.write('250-SIZE 10000000'+CRLF)
                sys.stdout.write('250-DSN'+CRLF)
                sys.stdout.write('250-ETRN'+CRLF)
                sys.stdout.write('250-DELIVERBY'+CRLF)
                sys.stdout.write('250 HELP'+CRLF)
                sys.stdout.flush()

        elif list[0] == 'NOOP' and DATA == 0:
            sys.stdout.write('250 2.0.0 OK'+CRLF)
            sys.stdout.flush()
            
        elif list[0] == 'HELP' and DATA == 0:
            pr = sys.stdout.write
            sys.stdout.write('214-2.0.0 This is sendmail'+CRLF)
            sys.stdout.write('214-2.0.0 Topics:'+CRLF)
            sys.stdout.write('214-2.0.0      HELO    EHLO       MAIL    RCPT    DATA'+CRLF)
            sys.stdout.write('214-2.0.0      RSET    NOOP       QUIT    HELP    VRFY'+CRLF)
            sys.stdout.write('214-2.0.0      EXPN    VERB       ETRN    DSN     AUTH'+CRLF)
            sys.stdout.write('214-2.0.0      STARTTLS'+CRLF)
            sys.stdout.write('214-2.0.0 For more info use "HELP <topic>".'+CRLF)
            sys.stdout.write('214-2.0.0 To report bugs in the implementation see'+CRLF)
            sys.stdout.write('214-2.0.0         http://www.sendmail.org/email-addresses.html'+CRLF)
            sys.stdout.write('214-2.0.0 For local information send email to Postmaster at your site.'+CRLF)
            sys.stdout.write('214 2.0.0 End of HELP info'+CRLF)
            sys.stdout.flush()

        elif list[0] == 'RSET' and DATA == 0:
            MAILFROM = 0
            RCPTTO = 0
            
        elif list[0] == 'MAIL' and DATA == 0:
            p = re.compile('MAIL(\s)+FROM(\s)*:(\s)*.+@.+[.].+(\r)*\n')
            if MAILFROM == 1:
                sys.stdout.write('503 5.5.0 Sender already specified')
                sys.stdout.flush()
            elif p.match(input) != None:  # we have a match
                addrl = input_case.split(':')
                addr = addrl[1]
                addr = addr.strip()
                sys.stdout.write('250 2.1.0 '+addr+'... Sender ok'+CRLF)
                sys.stdout.flush()
                MAILFROM = 1
            else:
                MAILFROM = 0
                er = ""
                if len(list) > 1:
                    er = list[1]
                else:
                    er = ""
                sys.stdout.write('501 5.5.2 Syntax error in parameters scanning "'+er+'"'+CRLF)
                sys.stdout.flush()
            
        elif list[0] == 'RCPT' and DATA == 0:
            p = re.compile('RCPT(\s)+TO(\s)*:(\s)*.+@.+[.].+(\r)*\n')
            if p.match(input) != None:  # we have a match
                addrl = input_case.split(':')
                addr = addrl[1]
                addr = addr.strip()
                sys.stdout.write('250 2.1.5 '+addr+'... Recipient ok'+CRLF)
                sys.stdout.flush()
                RCPTTO = 1
            else:
                RCPTTO = 0
                er = ""
                if len(list) > 1:
                    er = list[1]
                else:
                    er = ""
                sys.stdout.write('501 5.5.2 Syntax error in parameters scanning "'+er+'"'+CRLF)
                sys.stdout.flush()
            

        elif list[0] == 'DATA' and DATA == 0:
            if MAILFROM == 0:
                sys.stdout.write('503 5.0.0 Need MAIL command'+CRLF)
                sys.stdout.flush()
            elif RCPTTO == 0:
                sys.stdout.write('503 5.0.0 Need RCPT (recipient)'+CRLF)
                sys.stdout.flush()
            else:
                sys.stdout.write('354 Enter mail, end with "." on a line by itself'+CRLF)
                sys.stdout.flush()
                DATA = 1
                
        else:
            p = re.compile('[.](\r)*\n')
            if DATA == 1 and p.match(input) == None:
                mail = mail + input_case
            elif DATA == 1 and p.match(input) != None:  # we have a '.' by itself
                sys.stdout.write('250 2.0.0 oBV492kc002213 Message accepted for delivery'+CRLF)
                sys.stdout.flush()
                DATA = 0
                RCPTTO = 0
                MAILFROM = 0
                sys.stderr.write('---- MAIL START ---- '+CRLF)
                sys.stderr.write(mail)                          # logging
                sys.stderr.write('---- MAIL END ----'+CRLF)
                sys.stderr.flush()
                mail = ""
            else:
               sys.stdout.write('500 5.5.1 Command unrecognized: ""'+CRLF)
               sys.stdout.flush()