├── README.md ├── init ├── dionaea └── kippo ├── scripts └── iface-choice.py ├── setup.bash └── templates ├── dionaea.conf.tmpl ├── kippo.cfg.tmpl └── p0f.init.tmpl /README.md: -------------------------------------------------------------------------------- 1 | Succeeded by [manuka](https://github.com/andrewmichaelsmith/manuka) 2 | 3 | 4 | 5 | honeypot-setup-script 6 | ===================== 7 | 8 | A script to install and deploy a honeypot automatically and without user interaction. 9 | 10 | Currently installs and sets up: 11 | 12 | * kippo 13 | * dionaea 14 | * p0f 15 | 16 | 17 | These will all be installed as system services so running this script once should turn a vanilla install in to a robust honeypot. Aims to use useful _and secure_ defaults. 18 | 19 | Currently tested on **Ubuntu 12.04** 20 | 21 | **Use with caution**: This script will happily and without prompt overwrite files, change the port your SSH server runs and all sorts. It is intended to be run on a vanilla install of Ubuntu 12.04. No thoughts have been made for the integrity of existing installations of softwar - so be careful! 22 | 23 | Usage 24 | --------------------- 25 | **This can script can cause damage to your system. It is meant only to be used on a vanilla installation** 26 | 27 | Only run this if you **know what you are doing**. 28 | 29 | wget -q https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/setup.bash -O /tmp/setup.bash && bash /tmp/setup.bash 30 | 31 | Effects 32 | --------------------- 33 | 34 | * Moves SSH server from port 22 to 65534 35 | * Installs [Dionaea](http://dionaea.carnivore.it/), [Kippo](https://github.com/desaster/kippo), [p0f](http://lcamtuf.coredump.cx/p0f3/#/) 36 | * Sets up Dionaea, Kippo and p0f as system services that run on startup 37 | 38 | Directory Structure 39 | --------------------- 40 | **Logging** 41 | * Dionaea: `/var/dionaea/` 42 | * Kippo: `/var/kippo/` 43 | * p0f: `/var/p0f/` 44 | 45 | **Configuration** 46 | * Dionaea: /etc/dionaea 47 | * Kippo: /etc/kippo 48 | 49 | **Binaries** 50 | * Dionaea: `/usr/bin/dionaea` 51 | * Kippo: `/opt/kippo` 52 | * p0f: `/usr/sbin/p0f` 53 | 54 | -------------------------------------------------------------------------------- /init/dionaea: -------------------------------------------------------------------------------- 1 | ### BEGIN INIT INFO 2 | # Provides: dionaea 3 | # Required-Start: p0f 4 | # Required-Stop: p0f 5 | # Default-Start: 2 3 4 5 6 | # Default-Stop: 0 1 6 7 | # Short-Description: Dionaea Honeypot 8 | # Description: Dionaea Honeypot 9 | # Catches Bugs 10 | ### END INIT INFO 11 | 12 | 13 | # Using the lsb functions to perform the operations. 14 | . /lib/lsb/init-functions 15 | # Process name ( For display ) 16 | NAME=dionaea 17 | # Daemon name, where is the actual executable 18 | DAEMON=/usr/bin/dionaea 19 | 20 | # pid file for the daemon 21 | PIDFILE=/var/run/dionaea.pid 22 | 23 | PARAMETERS="-c /etc/dionaea/dionaea.conf -w /var/dionaea -u nobody -g nogroup -D -p $PIDFILE" 24 | 25 | # If the daemon is not there, then exit. 26 | test -x $DAEMON || exit 5 27 | 28 | case $1 in 29 | start) 30 | # Checked the PID file exists and check the actual status of process 31 | if [ -e $PIDFILE ]; then 32 | status_of_proc -p $PIDFILE $DAEMON "$NAME process" && status="0" || status="$?" 33 | # If the status is SUCCESS then don't need to start again. 34 | if [ $status = "0" ]; then 35 | exit # Exit 36 | fi 37 | fi 38 | # Start the daemon. 39 | log_daemon_msg "Starting the process" "$NAME" 40 | # Start the daemon with the help of start-stop-daemon 41 | # Log the message appropriately 42 | if start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON -- $PARAMETERS ; then 43 | log_end_msg 0 44 | else 45 | log_end_msg 1 46 | fi 47 | ;; 48 | stop) 49 | # Stop the daemon. 50 | if [ -e $PIDFILE ]; then 51 | status_of_proc -p $PIDFILE $DAEMON "Stoppping the $NAME process" && status="0" || status="$?" 52 | if [ "$status" = 0 ]; then 53 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 54 | /bin/rm -rf $PIDFILE 55 | fi 56 | else 57 | log_daemon_msg "$NAME process is not running" 58 | log_end_msg 0 59 | fi 60 | ;; 61 | restart) 62 | # Restart the daemon. 63 | $0 stop && sleep 2 && $0 start 64 | ;; 65 | status) 66 | # Check the status of the process. 67 | if [ -e $PIDFILE ]; then 68 | status_of_proc -p $PIDFILE $DAEMON "$NAME process" && exit 0 || exit $? 69 | else 70 | log_daemon_msg "$NAME Process is not running" 71 | log_end_msg 0 72 | fi 73 | ;; 74 | reload) 75 | # Reload the process. Basically sending some signal to a daemon to reload 76 | # it configurations. 77 | if [ -e $PIDFILE ]; then 78 | start-stop-daemon --stop --signal USR1 --quiet --pidfile $PIDFILE --name $NAME 79 | log_success_msg "$NAME process reloaded successfully" 80 | else 81 | log_failure_msg "$PIDFILE does not exists" 82 | fi 83 | ;; 84 | *) 85 | # For invalid arguments, print the usage message. 86 | echo "Usage: $0 {start|stop|restart|reload|status}" 87 | exit 2 88 | ;; 89 | esac 90 | -------------------------------------------------------------------------------- /init/kippo: -------------------------------------------------------------------------------- 1 | ### BEGIN INIT INFO 2 | # Provides: kippo 3 | # Required-Start: 4 | # Required-Stop: 5 | # Default-Start: 2 3 4 5 6 | # Default-Stop: 0 1 6 7 | # Short-Description: Kippo Honeypot 8 | # Description: Kippo Honeypot 9 | # SSH Honeypot 10 | ### END INIT INFO 11 | 12 | # Using the lsb functions to perform the operations. 13 | . /lib/lsb/init-functions 14 | # Process name ( For display ) 15 | NAME=kippo 16 | # Daemon name, where is the actual executable 17 | DAEMON=/usr/bin/twistd 18 | 19 | # pid file for the daemon 20 | PIDFILE=/var/run/kippo/kippo.pid 21 | 22 | CHUID=kippo 23 | 24 | KIPPODIR=/opt/kippo/ 25 | 26 | #TODO: Dupes here from $KIPPODIR 27 | PARAMETERS="-y /opt/kippo/kippo.tac -l /var/kippo/log/kippo.log --pidfile $PIDFILE -d $KIPPODIR" 28 | 29 | # If the daemon is not there, then exit. 30 | test -x $DAEMON || exit 5 31 | 32 | case $1 in 33 | start) 34 | # Checked the PID file exists and check the actual status of process 35 | if [ -e $PIDFILE ]; then 36 | status_of_proc -p $PIDFILE $DAEMON "$NAME process" && status="0" || status="$?" 37 | # If the status is SUCCESS then don't need to start again. 38 | if [ $status = "0" ]; then 39 | exit # Exit 40 | fi 41 | fi 42 | # Start the daemon. 43 | log_daemon_msg "Starting the process" "$NAME" 44 | # Start the daemon with the help of start-stop-daemon 45 | # Log the message appropriately 46 | if start-stop-daemon --chdir $KIPPODIR --start --quiet --oknodo --pidfile $PIDFILE --chuid $CHUID --exec $DAEMON -- $PARAMETERS ; then 47 | log_end_msg 0 48 | else 49 | log_end_msg 1 50 | fi 51 | ;; 52 | stop) 53 | # Stop the daemon. 54 | if [ -e $PIDFILE ]; then 55 | status_of_proc -p $PIDFILE $DAEMON "Stoppping the $NAME process" && status="0" || status="$?" 56 | if [ "$status" = 0 ]; then 57 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 58 | /bin/rm -rf $PIDFILE 59 | fi 60 | else 61 | log_daemon_msg "$NAME process is not running" 62 | log_end_msg 0 63 | fi 64 | ;; 65 | restart) 66 | # Restart the daemon. 67 | $0 stop && sleep 2 && $0 start 68 | ;; 69 | status) 70 | # Check the status of the process. 71 | if [ -e $PIDFILE ]; then 72 | status_of_proc -p $PIDFILE $DAEMON "$NAME process" && exit 0 || exit $? 73 | else 74 | log_daemon_msg "$NAME Process is not running" 75 | log_end_msg 0 76 | fi 77 | ;; 78 | reload) 79 | # Reload the process. Basically sending some signal to a daemon to reload 80 | # it configurations. 81 | if [ -e $PIDFILE ]; then 82 | start-stop-daemon --stop --signal USR1 --quiet --pidfile $PIDFILE --name $NAME 83 | log_success_msg "$NAME process reloaded successfully" 84 | else 85 | log_failure_msg "$PIDFILE does not exists" 86 | fi 87 | ;; 88 | *) 89 | # For invalid arguments, print the usage message. 90 | echo "Usage: $0 {start|stop|restart|reload|status}" 91 | exit 2 92 | ;; 93 | esac 94 | -------------------------------------------------------------------------------- /scripts/iface-choice.py: -------------------------------------------------------------------------------- 1 | import netifaces 2 | import os 3 | import sys 4 | 5 | def select_iface(iface): 6 | try: 7 | iface = int(iface) 8 | if(iface < 0): 9 | raise IndexError 10 | 11 | return netifaces.interfaces()[iface] 12 | 13 | except IndexError: 14 | print("Number provided was too big or small") 15 | return [] 16 | except ValueError: 17 | print("Please enter an interface number") 18 | return [] 19 | 20 | 21 | def get_args(): 22 | if len(sys.argv) > 1: 23 | return netifaces.interfaces()[int(sys.argv[1])] 24 | 25 | def get_user_input(): 26 | 27 | print("Please choose a network interface to run the honeypot on:\r\n") 28 | 29 | for i, ifaces in enumerate(netifaces.interfaces()): 30 | try: 31 | iface_text = "\t[%d] %s (%s)" % (i,ifaces,netifaces.ifaddresses(ifaces)[netifaces.AF_INET]) 32 | print(iface_text) 33 | except Exception: 34 | pass 35 | 36 | print("\r\n") 37 | 38 | found = [] 39 | while(not found): 40 | found=select_iface(raw_input('Chosen interface: ')) 41 | return found 42 | 43 | def run(): 44 | 45 | 46 | args = get_args() 47 | 48 | found = get_args() if get_args() else get_user_input() 49 | 50 | print found 51 | 52 | f = open(os.path.expanduser('~/.honey_iface'), 'w') 53 | f.write(found) 54 | 55 | if __name__ == "__main__": 56 | run() 57 | 58 | 59 | -------------------------------------------------------------------------------- /setup.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | script_dir="/honeypot-setup-script/" 3 | 4 | if [ -d "$script_dir" ]; 5 | then 6 | cp /honeypot-setup-script/scripts/iface-choice.py /tmp/iface-choice.py 7 | else 8 | sudo wget https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/scripts/iface-choice.py -O /tmp/iface-choice.py 9 | fi 10 | 11 | if [ -d "$script_dir" ]; 12 | then 13 | mkdir /etc/dionaea 14 | cp /honeypot-setup-script/templates/dionaea.conf.tmpl /etc/dionaea/dionaea.conf 15 | 16 | cp /honeypot-setup-script/templates/kippo.cfg.tmpl /tmp/kippo.cfg 17 | else 18 | sudo mkdir /etc/dionaea 19 | sudo wget https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/templates/dionaea.conf.tmpl -O /etc/dionaea/dionaea.conf 20 | 21 | sudo wget https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/templates/kippo.cfg.tmpl -O /tmp/kippo.cfg 22 | fi 23 | 24 | if [ $(dpkg-query -W -f='${Status}' sudo 2>/dev/null | grep -c "ok installed") -eq 0 ] 25 | then 26 | #sudo package is not currently installed on this box 27 | echo '[Error] Please install sudo before contniuing (apt-get install sudo)' 28 | exit 1 29 | fi 30 | 31 | current_user=$(whoami) 32 | 33 | if [ $(sudo -n -l -U ${current_user} 2>&1 | egrep -c -i "not allowed to run sudo|unknown user") -eq 1 ] 34 | then 35 | echo '[Error]: You need to run this script under an account that has access to sudo' 36 | exit 1 37 | fi 38 | 39 | 40 | # update apt repositories 41 | echo '[apt-get] Update on current repositories' 42 | sudo apt-get update &> /dev/null 43 | 44 | #user iface choice 45 | echo '[apt-get] Installing python-pip gcc python-dev' 46 | sudo apt-get update &> /dev/null 47 | sudo apt-get -y install python-pip gcc python-dev &> /dev/null 48 | sudo pip install netifaces 49 | 50 | 51 | python /tmp/iface-choice.py "$@" 52 | iface=$(<~/.honey_iface) 53 | 54 | 55 | # Move SSH server from Port 22 to Port 66534 56 | sudo sed -i 's:Port 22:Port 65534:g' /etc/ssh/sshd_config 57 | sudo service ssh reload 58 | 59 | 60 | ## install p0f ## 61 | echo '[apt-get] Installing p0f' 62 | sudo apt-get install -y p0f &> /dev/null 63 | sudo mkdir /var/p0f/ 64 | 65 | # dependency for add-apt-repository 66 | echo '[apt-get] Installing python-software-properties' 67 | sudo apt-get install -y python-software-properties &> /dev/null 68 | 69 | ## install dionaea ## 70 | 71 | #add dionaea repo 72 | sudo add-apt-repository -y ppa:honeynet/nightly 73 | echo '[apt-get] Updating source list and installing dionaea-phibo' 74 | { 75 | sudo apt-get update 76 | sudo apt-get install -y dionaea-phibo 77 | } &> /dev/null 78 | 79 | #make directories 80 | sudo mkdir -p /var/dionaea/wwwroot 81 | sudo mkdir -p /var/dionaea/binaries 82 | sudo mkdir -p /var/dionaea/log 83 | sudo mkdir -p /var/dionaea/bistreams 84 | sudo chown -R nobody:nogroup /var/dionaea/ 85 | 86 | #edit config 87 | #note that we try and strip :0 and the like from interface here 88 | sudo sed -i "s|%%IFACE%%|${iface%:*}|g" /etc/dionaea/dionaea.conf 89 | 90 | ## install kippo - we want the latest so we have to grab the source ## 91 | 92 | #kippo dependencies 93 | sudo apt-get install -y subversion python-dev openssl python-openssl python-pyasn1 python-twisted iptables 94 | 95 | #install kippo to /opt/kippo 96 | echo '[apt-get] Installing subversion python-dev openssl python-openssl python-pyasn1 python-twisted iptables' 97 | sudo apt-get install -y subversion python-dev openssl python-openssl python-pyasn1 python-twisted iptables &> /dev/null 98 | 99 | #install kippo to /opt/kippo 100 | sudo mkdir /opt/kippo/ 101 | sudo git clone https://github.com/desaster/kippo.git /opt/kippo/ 102 | sudo cp /tmp/kippo.cfg /opt/kippo/ 103 | 104 | #add kippo user that can't login 105 | sudo useradd -r -s /bin/false kippo 106 | 107 | #set up log dirs 108 | sudo mkdir -p /var/kippo/dl 109 | sudo mkdir -p /var/kippo/log/tty 110 | sudo mkdir -p /var/run/kippo 111 | 112 | #delete old dirs to prevent confusion 113 | sudo rm -rf /opt/kippo/dl 114 | sudo rm -rf /opt/kippo/log 115 | 116 | #set up permissions 117 | sudo chown -R kippo:kippo /opt/kippo/ 118 | sudo chown -R kippo:kippo /var/kippo/ 119 | sudo chown -R kippo:kippo /var/run/kippo/ 120 | 121 | #point port 22 at port 2222 122 | #we should have -i $iface here but it was breaking things with virtual interfaces 123 | sudo iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222 124 | 125 | #persist iptables config 126 | sudo iptables-save > /etc/iptables.rules 127 | 128 | #setup iptables restore script 129 | sudo echo '#!/bin/sh' >> /etc/network/if-up.d/iptablesload 130 | sudo echo 'iptables-restore < /etc/iptables.rules' >> /etc/network/if-up.d/iptablesload 131 | sudo echo 'exit 0' >> /etc/network/if-up.d/iptablesload 132 | #enable restore script 133 | sudo chmod +x /etc/network/if-up.d/iptablesload 134 | 135 | #download init files and install them 136 | sudo wget https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/templates/p0f.init.tmpl -O /etc/init.d/p0f 137 | sudo sed -i "s|%%IFACE%%|$iface|g" /etc/init.d/p0f 138 | 139 | sudo wget https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/init/dionaea -O /etc/init.d/dionaea 140 | sudo wget https://raw.github.com/andrewmichaelsmith/honeypot-setup-script/master/init/kippo -O /etc/init.d/kippo 141 | 142 | #install system services 143 | sudo chmod +x /etc/init.d/p0f 144 | sudo chmod +x /etc/init.d/dionaea 145 | sudo chmod +x /etc/init.d/kippo 146 | 147 | sudo update-rc.d p0f defaults 148 | sudo update-rc.d dionaea defaults 149 | sudo update-rc.d kippo defaults 150 | 151 | #start the honeypot software 152 | sudo /etc/init.d/kippo start 153 | sudo /etc/init.d/p0f start 154 | sudo /etc/init.d/dionaea start 155 | 156 | -------------------------------------------------------------------------------- /templates/dionaea.conf.tmpl: -------------------------------------------------------------------------------- 1 | logging = { 2 | default = { 3 | // file not starting with / is taken relative to LOCALESTATEDIR (e.g. /opt/dionaea/var) 4 | file = "/var/dionaea/log/dionaea.log" 5 | levels = "warning,error" 6 | domains = "*" 7 | } 8 | 9 | errors = { 10 | // file not starting with / is taken relative to LOCALESTATEDIR (e.g. /opt/dionaea/var) 11 | file = "/var/dionaea/log/dionaea-errors.log" 12 | levels = "warning,error" 13 | domains = "*" 14 | } 15 | } 16 | 17 | processors = 18 | { 19 | filter-emu = 20 | { 21 | config = { 22 | allow = [{ protocol = ["smbd","epmapper","nfqmirrord","mssqld"] }] 23 | } 24 | next = { 25 | emu = 26 | { 27 | config = { 28 | emulation = { 29 | limits = { 30 | files = "3" 31 | filesize = "524288" // 512 * 1024 32 | sockets = "3" 33 | sustain = "120" 34 | idle = "30" 35 | listen = "30" 36 | cpu = "120" 37 | steps = "1073741824" // 1024 * 1024 * 1024 38 | } 39 | 40 | /** 41 | * api default arguments for development 42 | * disabled by default 43 | * not working yet 44 | */ 45 | api = { 46 | connect = { 47 | host = "127.0.0.1" 48 | port = "4444" 49 | } 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | filter-streamdumper = 58 | { 59 | config = { 60 | allow = [ 61 | { type = ["accept"] } 62 | { type = ["connect"] protocol=["ftpctrl"] } 63 | ] 64 | deny = [ 65 | { protocol = ["ftpdata", "ftpdatacon","xmppclient"] } 66 | ] 67 | } 68 | next = { 69 | streamdumper = { 70 | config = { 71 | path = "bistreams/%Y-%m-%d/" 72 | } 73 | } 74 | } 75 | } 76 | 77 | /* filter-sessions = 78 | { 79 | config = { 80 | allow = [ { protocol = ["ftpctrl","remoteshell"] } ] 81 | } 82 | next = { 83 | python = { 84 | incident = "true" 85 | } 86 | } 87 | } 88 | */ 89 | } 90 | 91 | downloads = 92 | { 93 | dir = "binaries" 94 | tmp-suffix = ".tmp" 95 | } 96 | 97 | bistreams = 98 | { 99 | python = 100 | { 101 | dir = "bistreams" 102 | } 103 | } 104 | 105 | submit = 106 | { 107 | defaults = { 108 | urls = ["http://anubis.iseclab.org/nepenthes_action.php", 109 | "http://onlineanalyzer.norman.com/nepenthes_upload.php", 110 | "http://luigi.informatik.uni-mannheim.de/submit.php?action=verify"] 111 | email = "nepenthesdev@gmail.com" 112 | file_fieldname = "upfile" 113 | MAX_FILE_SIZE = "1500000" 114 | submit = "Submit for analysis" 115 | } 116 | 117 | /** 118 | * joebox is special, due to the TOS you can lookup here 119 | * http://www.joebox.org/resources/service%20terms.txt 120 | * therefore untested and disabled by default 121 | */ 122 | /* 123 | joebox = { 124 | urls = ["http://analysis.joebox.org/submit"] 125 | email = "nepenthesdev@gmail.com" 126 | file_fieldname = "upfile" 127 | MAX_FILE_SIZE = "1500000" 128 | submit = "Submit for analysis" 129 | service = "agree" 130 | xp = "1" 131 | vista = "1" 132 | w7 = "1" 133 | pcap = "1" 134 | } 135 | */ 136 | 137 | /* 138 | yoursection = 139 | { 140 | urls = ["http://127.0.0.1/submit"] 141 | email = "yourmail" 142 | user = "yourusername" 143 | pass = "yourpassword" 144 | } 145 | */ 146 | } 147 | 148 | listen = 149 | { 150 | /* basically we have 3 modes 151 | - getifaddrs - auto 152 | will get a list of all ips and bind a service to each ip 153 | - manual - your decision 154 | addrs has to be provided, and should look like this 155 | addrs = { eth0 = ["1.1.1.1", "1.1.1.2"], eth1 = ["2.1.1.1", "2.1.1.2"] } 156 | you get the idea ... 157 | for most cases with more than one address 158 | addrs = { eth0 = ["0.0.0.0"] } 159 | will do the trick 160 | if you want to throw in ipv6 support as well ... 161 | addrs = { eth0 = ["::"] } 162 | note: ipv6 does not work with surfids yet, 163 | as ipv6 addresses are mapped to ipv4 and surfids fails to retrieve the sensor id for ::ffff:1.2.3.4 164 | - nl, will require a list of interfaces 165 | fnmatch is possible like 166 | interfaces = ["ppp*","tun*"] 167 | and loading the nl module AFTER the python module in the modules section below 168 | nl will use the kernel netlink interface to figure out which addresses exist 169 | at runtime, and start/stop services dynamically per address per interface 170 | */ 171 | 172 | mode = "manual" 173 | addrs = { %%IFACE%% = ["::"] } 174 | } 175 | 176 | modules = { 177 | 178 | curl = 179 | { 180 | protocol = "http" 181 | } 182 | 183 | emu = { 184 | detect = "1" 185 | profile = "1" 186 | } 187 | 188 | pcap = 189 | { 190 | /** 191 | * libpcap 1.0.0 192 | * 193 | * "Arithmetic expression against transport layer headers, like 194 | * tcp[0], does not work against IPv6 packets. It only looks 195 | * at IPv4 packets." 196 | * 197 | * As a consequence, the default filter can not match 198 | * ipv6 tcp rst packets. 199 | * 200 | * If you want to go for rejected ipv6, remove the tcp matching part of the filter 201 | * The code is capable to checking the tcp-rst flag and seq number itself, but 202 | * matching every packet in userspace is expensive. 203 | * Therefore you'll have to hack the code if you want to track ipv6 rejected connections 204 | * 205 | * Format is IFACE = { addrs = MODE } 206 | * currently mode is ignored 207 | */ 208 | 209 | any = { 210 | addrs = "auto" 211 | } 212 | } 213 | 214 | 215 | python = { 216 | // default expands to PREFIX/lib/dionaea/python/ 217 | // ordering is granted 218 | // useful for development 219 | // simply add your devel directory to the list, avoids a make install for new python code 220 | sys_path = ["default"] 221 | 222 | // python imports 223 | imports = [ "log", 224 | "services", 225 | "ihandlers"] 226 | ftp = { 227 | root = "wwwroot" 228 | 229 | /* ftp client section 230 | */ 231 | 232 | /* ports for active ftp 233 | * string indicating a range 234 | */ 235 | active-ports = "63001-64000" 236 | 237 | /* host for active ftp via NAT 238 | * 0.0.0.0 - the initiating connection ip is used for active ftp 239 | * not 0.0.0.0 - gets resolved as hostname and used 240 | */ 241 | active-host = "0.0.0.0" 242 | } 243 | tftp = { 244 | root = "wwwroot" 245 | } 246 | http = { 247 | root = "wwwroot" 248 | max-request-size = "32768" // maximum size in kbytes of the request (32MB) 249 | } 250 | sip = { 251 | udp = { 252 | port = "5060" 253 | } 254 | tcp = { 255 | port = "5060" 256 | } 257 | tls = { 258 | port = "5061" 259 | } 260 | users = "sipaccounts.sqlite" 261 | rtp = { 262 | enable = "yes" 263 | /* how to dump the rtp stream 264 | bistream = dump as bistream 265 | */ 266 | mode = ["bistream", "pcap"] 267 | 268 | pcap = { 269 | path = "rtp/{personality}/%Y-%m-%d/" 270 | filename = "%H:%M:%S_{remote_host}_{remote_port}_in.pcap" 271 | } 272 | } 273 | personalities = { 274 | default = { 275 | domain = "localhost" 276 | name = "softphone" 277 | personality = "generic" 278 | } 279 | /* 280 | next-server = { 281 | domain = "my-domain" 282 | name = "my server" 283 | personality = "generic" 284 | serve = ["10.0.0.1"] 285 | default_sdp = "default" 286 | handle = ["REGISTER", "INVITE", "BYE", "CANCEL", "ACK"] 287 | } 288 | 289 | */ 290 | } 291 | actions = { 292 | bank-redirect = { 293 | do = "redirect" 294 | params = { 295 | } 296 | } 297 | play-hello = { 298 | do = "play" 299 | params = { 300 | file = ".../file.ext" 301 | } 302 | } 303 | } 304 | } 305 | surfids = { 306 | sslmode = "require" 307 | host = "surfids.example.com" // change this 308 | port = "5432" // maybe this 309 | username = "surfids" // this 310 | password = "secret" // and this 311 | dbname = "idsserver" 312 | } 313 | virustotal = { 314 | apikey = "........." // grab it from your virustotal account at My account -> Inbox -> Public API 315 | file = "vtcache.sqlite" 316 | } 317 | mwserv = { // ask your mwserv backend provider for needed values 318 | url = "" // the url to send the submission requests to 319 | maintainer = "" // username of the maintainer of this sensor 320 | guid = "" // guid of this sensor, as generated serverside; typically 8 chars 321 | secret = "" // shared secret used for authentication aka password; typically 48 chars 322 | } 323 | mysql = { 324 | databases = { 325 | information_schema = { 326 | path = ":memory:" 327 | } 328 | 329 | // example how to extend this 330 | // just provide a databasename and path to the database 331 | // the database can be altered by attackers, so ... better use a copy 332 | // psn = { 333 | // path = "/path/to/cc_info.sqlite" 334 | // } 335 | 336 | } 337 | } 338 | submit_http = { // ask your submit_http backend provider for needed values 339 | url = "" // the url to send the submission requests to 340 | email = "" // optional 341 | user = "" // username (optional) 342 | pass = "" // password (optional) 343 | } 344 | logsql = { 345 | mode = "sqlite" // so far there is only sqlite 346 | sqlite = { 347 | file = "logsql.sqlite" 348 | } 349 | } 350 | logxmpp = { 351 | /** 352 | * this section defines a single xmpp logging target 353 | * you can have multiple 354 | */ 355 | carnivore = { 356 | server = "sensors.carnivore.it" 357 | 358 | /** 359 | * as dionaea does not support starttls (xmpp on port 5223), 360 | * we rely on 'legacy ssl' for the xmpp connection (port 5222) 361 | */ 362 | port = "5223" 363 | muc = "dionaea.sensors.carnivore.it" 364 | 365 | /** 366 | * if the server exists, this is a valid account 367 | */ 368 | username = "anonymous@sensors.carnivore.it" 369 | password = "anonymous" 370 | 371 | /** 372 | * setting a resource is possible, but you should not do it 373 | * the default resource is a random string of 8 chars 374 | */ 375 | // resource = "theresource" 376 | config = 377 | { 378 | /** 379 | * this defines a muc channel 380 | */ 381 | anon-events = 382 | { 383 | /** 384 | * incidents matching these events will get relayed to the channel 385 | */ 386 | events = ["^dionaea\x5c.connection\x5c..*", 387 | "^dionaea\x5c.modules\x5c.python\x5c.smb.dcerpc\x5c.*", 388 | "^dionaea\x5c.download\x5c.offer$", 389 | "^dionaea\x5c.download\x5c.complete\x5c.hash$", 390 | "^dionaea\x5c.module\x5c.emu\x5c.profile$", 391 | "^dionaea\x5c.modules\x5c.python\x5c.mysql\x5c.*", 392 | "^dionaea\x5c.modules\x5c.python\x5c.sip\x5c.*" 393 | ] 394 | 395 | /** 396 | * anonymous removes the local host information from all connection messages 397 | * so you can report without getting identified 398 | */ 399 | anonymous = "yes" 400 | } 401 | 402 | anon-files = 403 | { 404 | events = ["^dionaea\x5c.download\x5c.complete\x5c.unique"] 405 | } 406 | } 407 | } 408 | } 409 | p0f = { 410 | /** 411 | * start p0f with 412 | * sudo p0f -i any -u root -Q /tmp/p0f.sock -q -l 413 | */ 414 | path = "un:///tmp/p0f.sock" 415 | } 416 | 417 | fail2ban = { 418 | downloads = "downloads.f2b" 419 | offers = "offers.f2b" 420 | } 421 | 422 | ihandlers = { 423 | handlers = ["ftpdownload", "tftpdownload", "emuprofile", "cmdshell", "store", "uniquedownload", 424 | "logsql", 425 | // "virustotal", 426 | // "mwserv", 427 | // "submit_http", 428 | // "logxmpp", 429 | // "nfq", 430 | "p0f", 431 | // "surfids", 432 | // "fail2ban" 433 | ] 434 | } 435 | 436 | services = { 437 | serve = ["http", "https", "tftp", "ftp", "mirror", "smb", "epmap", "sip","mssql", "mysql"] 438 | } 439 | 440 | } 441 | 442 | nl = 443 | { 444 | lookup_ethernet_addr = "no" // set to yes in case you are interested in the mac address of the remote (only works for lan) 445 | 446 | } 447 | 448 | 449 | /* nc is a test module */ 450 | /* nc = 451 | { 452 | services = [ 453 | { 454 | proto = "redir" 455 | type = "tcp" 456 | host = "::" 457 | port = "4711" 458 | }, 459 | { 460 | proto = "redir" 461 | type = "tcp" 462 | host = "::" 463 | port = "12344" 464 | }, 465 | { 466 | proto = "sink" 467 | type = "tcp" 468 | host = "::" 469 | port = "12345" 470 | throttle = { 471 | in = "8192" 472 | } 473 | timeout = { 474 | listen = "15" 475 | connect = "15" 476 | } 477 | }, 478 | { 479 | proto = "source" 480 | type = "tcp" 481 | host = "::" 482 | port = "12346" 483 | throttle = { 484 | out = "8192" 485 | } 486 | timeout = { 487 | listen = "15" 488 | connect = "15" 489 | } 490 | }, 491 | { 492 | proto = "redir" 493 | type = "tcp" 494 | host = "::" 495 | port = "12347" 496 | throttle = { 497 | in = "8192" 498 | out = "8192" 499 | } 500 | timeout = { 501 | listen = "15" 502 | connect = "15" 503 | } 504 | }, 505 | { 506 | proto = "redir" 507 | type = "tls" 508 | host = "::" 509 | port = "12444" 510 | timeout = { 511 | listen = "15" 512 | connect = "15" 513 | } 514 | }, 515 | 516 | { 517 | proto = "sink" 518 | type = "tls" 519 | host = "::" 520 | port = "12445" 521 | throttle = { 522 | in = "8192" 523 | } 524 | timeout = { 525 | listen = "15" 526 | connect = "5" 527 | } 528 | }, 529 | { 530 | proto = "source" 531 | type = "tls" 532 | host = "::" 533 | port = "12446" 534 | throttle = { 535 | out = "8192" 536 | } 537 | timeout = { 538 | listen = "15" 539 | connect = "15" 540 | } 541 | }, 542 | { 543 | proto = "redir" 544 | type = "tls" 545 | host = "::" 546 | port = "12447" 547 | throttle = { 548 | in = "8192" 549 | out = "8192" 550 | } 551 | timeout = { 552 | listen = "15" 553 | connect = "15" 554 | } 555 | }, 556 | { 557 | proto = "source" 558 | type = "udp" 559 | host = "::" 560 | port = "12544" 561 | timeout = { 562 | connect = "15" 563 | } 564 | }, 565 | { 566 | proto = "sink" 567 | type = "udp" 568 | host = "::" 569 | port = "12545" 570 | timeout = { 571 | connect = "15" 572 | } 573 | }, 574 | { 575 | proto = "redir" 576 | type = "udp" 577 | host = "::" 578 | port = "12546" 579 | timeout = { 580 | connect = "15" 581 | } 582 | } 583 | ] 584 | 585 | clients = [ 586 | { 587 | proto = "source" 588 | type = "tcp" 589 | host = "127.0.0.1" 590 | port = "13344" 591 | timeout = { 592 | connecting = "5" 593 | connect = "15" 594 | reconnect = "5" 595 | } 596 | }, 597 | { 598 | proto = "redir" 599 | type = "tcp" 600 | host = "ip6-localhost" 601 | port = "13345" 602 | timeout = { 603 | connecting = "5" 604 | connect = "15" 605 | reconnect = "5" 606 | } 607 | }, 608 | { 609 | proto = "redir" 610 | type = "tls" 611 | host = "localhost" 612 | port = "13346" 613 | timeout = { 614 | connecting = "5" 615 | connect = "15" 616 | reconnect = "5" 617 | } 618 | }, 619 | { 620 | proto = "source" 621 | type = "tls" 622 | host = "ip6-localhost" 623 | port = "12445" 624 | timeout = { 625 | reconnect = "1" 626 | connect = "1" 627 | } 628 | } 629 | ] 630 | } 631 | */ 632 | } 633 | 634 | 635 | -------------------------------------------------------------------------------- /templates/kippo.cfg.tmpl: -------------------------------------------------------------------------------- 1 | # 2 | # Kippo configuration file (kippo.cfg) 3 | # 4 | 5 | [honeypot] 6 | 7 | # IP addresses to listen for incoming SSH connections. 8 | # 9 | # (default: 0.0.0.0) = any address 10 | #ssh_addr = 0.0.0.0 11 | 12 | # Port to listen for incoming SSH connections. 13 | # 14 | # (default: 2222) 15 | ssh_port = 2222 16 | 17 | # Hostname for the honeypot. Displayed by the shell prompt of the virtual 18 | # environment. 19 | # 20 | # (default: svr03) 21 | hostname = server 22 | 23 | # Directory where to save log files in. 24 | # 25 | # (default: log) 26 | log_path = /var/kippo/log 27 | 28 | # Directory where to save downloaded (malware) files in. 29 | # 30 | # (default: dl) 31 | download_path = /var/kippo/dl 32 | 33 | # Maximum file size (in bytes) for downloaded files to be stored in 'download_path'. 34 | # A value of 0 means no limit. If the file size is known to be too big from the start, 35 | # the file will not be stored on disk at all. 36 | # 37 | # (default: 0) 38 | #download_limit_size = 10485760 39 | 40 | # Directory where virtual file contents are kept in. 41 | # 42 | # This is only used by commands like 'cat' to display the contents of files. 43 | # Adding files here is not enough for them to appear in the honeypot - the 44 | # actual virtual filesystem is kept in filesystem_file (see below) 45 | # 46 | # (default: honeyfs) 47 | contents_path = honeyfs 48 | 49 | # File in the python pickle format containing the virtual filesystem. 50 | # 51 | # This includes the filenames, paths, permissions for the whole filesystem, 52 | # but not the file contents. This is created by the createfs.py utility from 53 | # a real template linux installation. 54 | # 55 | # (default: fs.pickle) 56 | filesystem_file = fs.pickle 57 | 58 | # Directory for miscellaneous data files, such as the password database. 59 | # 60 | # (default: data_path) 61 | data_path = data 62 | 63 | # Directory for creating simple commands that only output text. 64 | # 65 | # The command must be placed under this directory with the proper path, such 66 | # as: 67 | # txtcmds/usr/bin/vi 68 | # The contents of the file will be the output of the command when run inside 69 | # the honeypot. 70 | # 71 | # In addition to this, the file must exist in the virtual 72 | # filesystem {filesystem_file} 73 | # 74 | # (default: txtcmds) 75 | txtcmds_path = txtcmds 76 | 77 | # Public and private SSH key files. If these don't exist, they are created 78 | # automatically. 79 | rsa_public_key = data/ssh_host_rsa_key.pub 80 | rsa_private_key = data/ssh_host_rsa_key 81 | dsa_public_key = data/ssh_host_dsa_key.pub 82 | dsa_private_key = data/ssh_host_dsa_key 83 | 84 | # Enables passing commands using ssh execCommand 85 | # e.g. ssh root@localhost 86 | # 87 | # (default: false) 88 | exec_enabled = true 89 | 90 | # IP address to bind to when opening outgoing connections. Used exclusively by 91 | # the wget command. 92 | # 93 | # (default: not specified) 94 | #out_addr = 0.0.0.0 95 | 96 | # Sensor name use to identify this honeypot instance. Used by the database 97 | # logging modules such as mysql. 98 | # 99 | # If not specified, the logging modules will instead use the IP address of the 100 | # connection as the sensor name. 101 | # 102 | # (default: not specified) 103 | #sensor_name=myhostname 104 | 105 | # Fake address displayed as the address of the incoming connection. 106 | # This doesn't affect logging, and is only used by honeypot commands such as 107 | # 'w' and 'last' 108 | # 109 | # If not specified, the actual IP address is displayed instead (default 110 | # behaviour). 111 | # 112 | # (default: not specified) 113 | #fake_addr = 192.168.66.254 114 | 115 | # SSH Version String 116 | # 117 | # Use this to disguise your honeypot from a simple SSH version scan 118 | # frequent Examples: (found experimentally by scanning ISPs) 119 | # SSH-2.0-OpenSSH_5.1p1 Debian-5 120 | # SSH-1.99-OpenSSH_4.3 121 | # SSH-1.99-OpenSSH_4.7 122 | # SSH-1.99-Sun_SSH_1.1 123 | # SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3.1 124 | # SSH-2.0-OpenSSH_4.3 125 | # SSH-2.0-OpenSSH_4.6 126 | # SSH-2.0-OpenSSH_5.1p1 Debian-5 127 | # SSH-2.0-OpenSSH_5.1p1 FreeBSD-20080901 128 | # SSH-2.0-OpenSSH_5.3p1 Debian-3ubuntu5 129 | # SSH-2.0-OpenSSH_5.3p1 Debian-3ubuntu6 130 | # SSH-2.0-OpenSSH_5.3p1 Debian-3ubuntu7 131 | # SSH-2.0-OpenSSH_5.5p1 Debian-6 132 | # SSH-2.0-OpenSSH_5.5p1 Debian-6+squeeze1 133 | # SSH-2.0-OpenSSH_5.5p1 Debian-6+squeeze2 134 | # SSH-2.0-OpenSSH_5.8p2_hpn13v11 FreeBSD-20110503 135 | # SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1 136 | # SSH-2.0-OpenSSH_5.9 137 | # 138 | # (default: "SSH-2.0-OpenSSH_5.1p1 Debian-5") 139 | ssh_version_string = SSH-2.0-OpenSSH_5.1p1 Debian-5 140 | 141 | # Banner file to be displayed before the first login attempt. 142 | # 143 | # (default: not specified) 144 | #banner_file = 145 | 146 | # Session management interface. 147 | # 148 | # This is a telnet based service that can be used to interact with active 149 | # sessions. Disabled by default. 150 | # 151 | # (default: false) 152 | interact_enabled = false 153 | # (default: 5123) 154 | interact_port = 5123 155 | 156 | # MySQL logging module 157 | # 158 | # Database structure for this module is supplied in doc/sql/mysql.sql 159 | # 160 | # To enable this module, remove the comments below, including the 161 | # [database_mysql] line. 162 | 163 | #[database_mysql] 164 | #host = localhost 165 | #database = kippo 166 | #username = kippo 167 | #password = secret 168 | #port = 3306 169 | 170 | # XMPP Logging 171 | # 172 | # Log to an xmpp server. 173 | # For a detailed explanation on how this works, see: 174 | # 175 | # To enable this module, remove the comments below, including the 176 | # [database_xmpp] line. 177 | 178 | #[database_xmpp] 179 | #server = sensors.carnivore.it 180 | #user = anonymous@sensors.carnivore.it 181 | #password = anonymous 182 | #muc = dionaea.sensors.carnivore.it 183 | #signal_createsession = kippo-events 184 | #signal_connectionlost = kippo-events 185 | #signal_loginfailed = kippo-events 186 | #signal_loginsucceeded = kippo-events 187 | #signal_command = kippo-events 188 | #signal_clientversion = kippo-events 189 | #debug=true 190 | 191 | # Text based logging module 192 | # 193 | # While this is a database logging module, it actually just creates a simple 194 | # text based log. This may not have much purpose, if you're fine with the 195 | # default text based logs generated by kippo in log/ 196 | # 197 | # To enable this module, remove the comments below, including the 198 | # [database_textlog] line. 199 | 200 | #[database_textlog] 201 | #logfile = kippo-textlog.log 202 | -------------------------------------------------------------------------------- /templates/p0f.init.tmpl: -------------------------------------------------------------------------------- 1 | ### BEGIN INIT INFO 2 | # Provides: p0f 3 | # Required-Start: $all 4 | # Required-Stop: 5 | # Default-Start: 2 3 4 5 6 | # Default-Stop: 0 1 6 7 | # Short-Description: p0f 8 | # Description: p0f 9 | # Passive OS Fingerprinting 10 | ### END INIT INFO 11 | 12 | 13 | # Using the lsb functions to perform the operations. 14 | . /lib/lsb/init-functions 15 | # Process name ( For display ) 16 | NAME=p0f 17 | # Daemon name, where is the actual executable 18 | DAEMON=/usr/sbin/p0f 19 | 20 | # pid file for the daemon 21 | PIDFILE=/var/run/p0f.pid 22 | 23 | PARAMETERS="-u root -i %%IFACE%% -Q /tmp/p0f.sock -q -l -d -o /var/p0f/p0f.log" 24 | 25 | # If the daemon is not there, then exit. 26 | test -x $DAEMON || exit 5 27 | 28 | case $1 in 29 | start) 30 | # Checked the PID file exists and check the actual status of process 31 | if [ -e $PIDFILE ]; then 32 | status_of_proc -p $PIDFILE $DAEMON "$NAME process" && status="0" || status="$?" 33 | # If the status is SUCCESS then don't need to start again. 34 | if [ $status = "0" ]; then 35 | exit # Exit 36 | fi 37 | fi 38 | # Start the daemon. 39 | log_daemon_msg "Starting the process" "$NAME" 40 | # Start the daemon with the help of start-stop-daemon 41 | # Log the message appropriately 42 | if start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON -- $PARAMETERS; then 43 | PID=`pidof -s p0f` 44 | if [ $PID ] ; then 45 | echo $PID >$PIDFILE 46 | fi 47 | log_end_msg 0 48 | else 49 | log_end_msg 1 50 | fi 51 | ;; 52 | stop) 53 | # Stop the daemon. 54 | if [ -e $PIDFILE ]; then 55 | status_of_proc -p $PIDFILE $DAEMON "Stoppping the $NAME process" && status="0" || status="$?" 56 | if [ "$status" = 0 ]; then 57 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 58 | /bin/rm -rf $PIDFILE 59 | fi 60 | else 61 | log_daemon_msg "$NAME process is not running" 62 | log_end_msg 0 63 | fi 64 | ;; 65 | restart) 66 | # Restart the daemon. 67 | $0 stop && sleep 2 && $0 start 68 | ;; 69 | status) 70 | # Check the status of the process. 71 | if [ -e $PIDFILE ]; then 72 | status_of_proc -p $PIDFILE $DAEMON "$NAME process" && exit 0 || exit $? 73 | else 74 | log_daemon_msg "$NAME Process is not running" 75 | log_end_msg 0 76 | fi 77 | ;; 78 | reload) 79 | # Reload the process. Basically sending some signal to a daemon to reload 80 | # it configurations. 81 | if [ -e $PIDFILE ]; then 82 | start-stop-daemon --stop --signal USR1 --quiet --pidfile $PIDFILE --name $NAME 83 | log_success_msg "$NAME process reloaded successfully" 84 | else 85 | log_failure_msg "$PIDFILE does not exists" 86 | fi 87 | ;; 88 | *) 89 | # For invalid arguments, print the usage message. 90 | echo "Usage: $0 {start|stop|restart|reload|status}" 91 | exit 2 92 | ;; 93 | esac 94 | --------------------------------------------------------------------------------