Starting with Artillery

On Friday I arrived home looking forward to a well-earned rest; unfortunately Dave Kennedy seemed to have other ideas for my weekend as he announced the alpha release of a new honeypot, Artillery.

Artillery is a combination of a honeypot, file monitoring and integrity, alerting, and brute force prevention tool. It’s extremely light weight, has multiple different methods for detecting specific attacks and eventually will also notify you of insecure nix configurations.

Installation of Artillery is currently really simple, download via svn, run the installer script, edit the config file (if necessary) and run:

$svn co artillery/
$nano config

N.B. don’t make the same daft error I made initially by editing the files in the svn download. Once the script has been run, cd to /var/artillery.
Artillery goes beyond typical honeypots, as it actively blocks remote clients and protects the system it’s running on. Artillery listens on a number of common ports (configurable, look at the PORTS variable), if it receives a connection on any of the fake ports it permanently blocks the source IP address by adding a DROP rule to iptables.
From my experience Artillery gets results REALLY quickly. After getting the system online I performed a quick test from another host under my control and starting writing up this post; in the time it’s taken to write the content above Artillery has already added 8 addresses  to iptables:

Chain INPUT (policy ACCEPT)
target     prot opt source                                destination
DROP       all  --         anywhere
DROP       all  --    anywhere
DROP       all  --        anywhere
DROP       all  --                        anywhere
DROP       all  --                      anywhere
DROP       all  --          anywhere
DROP       all  --  anywhere
DROP       all  --                         anywhere

Other functionality included in Artillery mirrors that of Tripwire, monitoring the contents of different directories (again, configurable) and generating alerts if the contents of the directories and files changes.
I really like the premise of Artillery, and Dave in his usual fashion is coding like a madman adding fixes and new functionality (new version, 0.1.1 was released 24hrs after initial announcement). I’d be wary where you set this system up to test it though due to the automatic lockout; if Artillery is on a remote system, and you connect to a dummy port from your location to test you’ve just been locked out of your own server 😉
Looking forward to seeing Artillery mature, thanks Dave.
–Andrew Waite

Join the conversation


  1. Artillery seems to work great on Debian based systems with no modifications to the source. I also use CentOS 6 but to get it working on that, I had to change fileopen1=file(“/var/log/auth.log”) to fileopen1= file(“/var/log/secure”) in
    I also had to change buy adding ‘path’ as a global variable, then on the reinstall turn off automatic updating since it updates the source code to, works like a charm.

  2. artillery$ grep Popen * -R –include=’*.py’
    massive popen abuse, as if python would lack an api for file operations
    src/ subprocess.Popen(“touch /var/artillery/banlist.txt”, shell=True).wait()
    src/ subprocess.Popen(“mkdir /var/artillery”, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).wait()
    src/ subprocess.Popen(“touch /var/artillery/banlist.txt”, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).wait()
    src/ subprocess.Popen(“mkdir /var/artillery/logs/”, shell=True).wait()
    src/ subprocess.Popen(“touch /var/artillery/logs/alerts.log”, shell=True).wait()
    src/ subprocess.Popen(“mkdir /var/artillery/logs/”, shell=True).wait()
    src/ subprocess.Popen(“touch /var/artillery/logs/alerts.log”, shell=True).wait()
    src/ subprocess.Popen(“mv /var/artillery/database/temp.database /var/artillery/database/integrity.database”, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).wait()
    this one may be prone to command injection:
    src/ proc = subprocess.Popen(“ls -al %s” % (filename), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    these indicate the whole process always has to run as root:
    src/ subprocess.Popen(“iptables -A INPUT -s %s -j DROP” % (line), shell=True).wait()
    src/ subprocess.Popen(“iptables -I INPUT 1 -s %s -j DROP” % ip, shell=True).wait()
    unattended auto update?, get write access on the repo and own all deployments with instant root:
    src/ subprocess.Popen(“cd /var/artillery;svn update”, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    src/ compare_files = subprocess.Popen(“diff /var/artillery/database/integrity.database /var/artillery/database/temp.database”, shell=True, stdout=subprocess.PIPE)
    some serious design flaws
    linux got inotify, much better approach than checking all files in some interval
    inotify would have been a much better choice again
    services run as root (never drops privs), sends a random string, never closes the socket, and bans the ip, you’ll never have the remote close the connection did not close it yourself.
    after some time you’ll run out of fds and the service will crash.
    you could have used pcap and ban remotes where the response sent was RST instead, would work for all ports, without any threads.
    the iptables rules set never expire, the service does not create a chain/table for itself but messes up INPUT, fail2ban would have been a much better choice.

Leave a comment

Your email address will not be published. Required fields are marked *