micetrap 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ *.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.2@micetrap
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in micetrap.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ micetrap (0.0.1)
5
+ trollop
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ configuration (1.2.0)
11
+ diff-lcs (1.1.2)
12
+ guard (0.2.2)
13
+ open_gem (~> 1.4.2)
14
+ thor (~> 0.14.3)
15
+ guard-rspec (0.1.9)
16
+ guard (>= 0.2.2)
17
+ launchy (0.3.7)
18
+ configuration (>= 0.0.5)
19
+ rake (>= 0.8.1)
20
+ open_gem (1.4.2)
21
+ launchy (~> 0.3.5)
22
+ rake (0.8.7)
23
+ rspec (2.3.0)
24
+ rspec-core (~> 2.3.0)
25
+ rspec-expectations (~> 2.3.0)
26
+ rspec-mocks (~> 2.3.0)
27
+ rspec-core (2.3.1)
28
+ rspec-expectations (2.3.0)
29
+ diff-lcs (~> 1.1.2)
30
+ rspec-mocks (2.3.0)
31
+ thor (0.14.6)
32
+ trollop (1.16.2)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler (~> 1.0.7)
39
+ guard
40
+ guard-rspec
41
+ micetrap!
42
+ rspec (~> 2.3.0)
43
+ trollop
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at http://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch('^spec/(.*)_spec.rb')
6
+ watch('^lib/(.*)\.rb') { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('^spec/spec_helper.rb') { "spec" }
8
+ end
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :default => :spec
data/Readme.md ADDED
@@ -0,0 +1,114 @@
1
+ #micetrap
2
+ ___
3
+ _.-| | |\__/,| (`\
4
+ { | | |o o |__ _) )
5
+ "-.|___| _.( T ) ` /
6
+ .--'-`-. _((_ `^--' /_< \
7
+ .+|______|__.-||__)`-'(((/ (((/
8
+
9
+ Catch hackers on the fly with micetrap!
10
+
11
+ Micetrap opens a server on either a given or random port, emulating fake
12
+ vulnerable services. Port scanners such as Nmap, when fingerprinting ports
13
+ to discover service names and versions, will get apparently legitimate
14
+ responses from common services such as FTP, HTTP or MySQL servers,
15
+ therefore misleading potential attackers with false information.
16
+
17
+ Depending on the operating system you are using, micetrap will try its best
18
+ to +look feasible+ by choosing the appropriate fake services and versions
19
+ to emulate. Whenever possible, micetrap will provide a bit outdated versions
20
+ which are more likely to be vulnerable, and thus making the attacker focus
21
+ on those ports. While the attacker tries to exploit these ports, she is
22
+ essentially sending certain packets -- which get properly captured and
23
+ logged by micetrap. This information might be useful to discover what kind
24
+ of attacks are being tried against your machine, therefore giving you time
25
+ and the opportunity to defend appropriately.
26
+
27
+ Running micetrap with sudo will allow it to use default, unsuspicious ports,
28
+ which may give you advantage at tricking a smart attacker.
29
+
30
+ ##Install
31
+
32
+ gem install micetrap
33
+
34
+ ...or, if you want to be able to use it with sudo:
35
+
36
+ sudo gem install micetrap
37
+
38
+ Micetrap currently runs on Ruby versions 1.8.7 and 1.9.2.
39
+
40
+ ##Usage
41
+
42
+ Just fire up the server with some fake service, such an ftp server:
43
+
44
+ micetrap ftp --port 8765
45
+
46
+ If everything is ok, you will see something like this:
47
+
48
+ (some timestamp) ::: Ftp trap listening on ::ffff:0.0.0.0:8765 :::
49
+
50
+ TL;DR: Most port scanners such as _nmap_ have some kind of fingerprinting
51
+ capabilities. This means that, in order to discover which services and
52
+ versions run behind a specific port, they send special packets or _probes_
53
+ which make different services and versions react differently. By capturing
54
+ the response and matching against with a database, most of the time they
55
+ can reliably determine what service and version is running behind that port.
56
+
57
+ Port scanners usually start by sending a blank probe, since many servers
58
+ respond with a welcome banner telling interesting stuff about them. Micetrap
59
+ only responds to those early blank probes. Let's try to port-scan this fake
60
+ ftp service with nmap fingerprinting:
61
+
62
+ nmap 127.0.0.1 -p 8765 -A
63
+
64
+ We are scanning localhost, port 8765, and -A means service version detection
65
+ and OS guessing. After a while, in our micetrap server terminal we see:
66
+
67
+ (timestamp) Recorded a probe coming from ::ffff:127.0.0.1:51082 containing
68
+ the following: (empty line)
69
+
70
+ (timestamp) ::: Responded misleadingly: let's drive those hackers nuts! :::
71
+
72
+ These gets logged inside a .log file within the current directory.
73
+ And in the nmap terminal:
74
+
75
+ Starting Nmap 5.35DC1 ( http://nmap.org ) at (timestamp)
76
+ Nmap scan report for localhost (127.0.0.1)
77
+ Host is up (0.00017s latency).
78
+ PORT STATE SERVICE VERSION
79
+ 8765/tcp open ftp Mac OS X Server ftpd
80
+
81
+ The faked service/version is random (you can start an ftp server which looks
82
+ like lukemftpd, Mac OS X server ftpd or PureFTPd for example), but it is
83
+ consistent within the same server, so that every scan reports the same service
84
+ and version.
85
+
86
+ ## U mad? Evil hackers
87
+
88
+ Probably.
89
+
90
+ ##Available services
91
+
92
+ For now there are a bunch of ftp, http, torrent, mysql and samba services,
93
+ mostly Mac-ish.
94
+
95
+ ##Contribute!
96
+
97
+ If you want to contribute with more services and versions to empower micetrap
98
+ and be a superhero, you shall follow these steps:
99
+
100
+ * Fork the project.
101
+ * Install _nmap_ and look for a file called nmap-service-probes in your system.
102
+ This file contains regexes used to match responses from scanned services.
103
+ * You only have to devise a string which fits in one of this regexes and then
104
+ add it in the corresponding service file (in lib/micetrap/services/ftp.rb for
105
+ example if it's an ftp server).
106
+ * Commit, do not mess with rakefile, version, or history.
107
+ If you want to have your own version, that is fine but bump version
108
+ in a commit by itself I can ignore when I pull.
109
+ * Send me a pull request. Bonus points for topic branches.
110
+ * Profit!
111
+
112
+ ## Copyright
113
+
114
+ Copyright (c) 2011 Josep M. Bach. See LICENSE for details.
data/bin/micetrap ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'trollop' unless defined?(Trollop)
5
+ require 'micetrap'
6
+ require 'micetrap/version'
7
+
8
+ SERVICES = Micetrap.services
9
+
10
+ opts = Trollop::options do
11
+ version "micetrap #{Micetrap::VERSION} (c) 2011 Josep M. Bach"
12
+ banner <<-EOS
13
+ Micetrap opens a server on either a given or random port, emulating fake
14
+ vulnerable services. Port scanners such as Nmap, when fingerprinting ports
15
+ to discover service names and versions, will get apparently legitimate
16
+ responses from common services such as FTP, HTTP or MySQL servers,
17
+ therefore misleading potential attackers with false information.
18
+
19
+ Depending on the operating system you are using, micetrap will try its best
20
+ to +look feasible+ by choosing the appropriate fake services and versions
21
+ to emulate. Whenever possible, micetrap will provide a bit outdated versions
22
+ which are more likely to be vulnerable, and thus making the attacker focus
23
+ on those ports. While the attacker tries to exploit these ports, she is
24
+ essentially sending certain packets -- which get properly captured and
25
+ logged my micetrap. This information might be useful to discover what kind
26
+ of attacks are being tried against your machine, therefore giving you time
27
+ and the opportunity to defend appropriately.
28
+
29
+ Fire up a simple ftp micetrap like this:
30
+
31
+ sudo micetrap ftp
32
+
33
+ Running it with sudo will allow you to use default, unsuspicious ports,
34
+ which may give you advantage at tricking a smart attacker.
35
+
36
+ If you don't want to use system ports, you can run micetrap without having
37
+ root privileges like this:
38
+
39
+ micetrap ftp --port 9999 (or whatever non-system port you like)
40
+
41
+ The available services are are:
42
+ #{SERVICES.join(', ')}
43
+
44
+ Usage:
45
+ [sudo] micetrap <service> [options]
46
+
47
+ where [options] are:
48
+ EOS
49
+ opt :port, "A specific port to use", :default => nil, :type => :integer
50
+ stop_on SERVICES
51
+ end
52
+
53
+ service = ARGV.shift.to_sym
54
+ Trollop::die "You need to specify a service, which must be one of the following: #{SERVICES.join(', ')}\n\nMaybe you just feel a bit lost.." unless SERVICES.include?(service)
55
+
56
+ # Show a nice banner
57
+ ANSI = {:RESET=>"\e[0m", :BOLD=>"\e[1m", :UNDERLINE=>"\e[4m", :LGRAY=>"\e[0;37m", :GRAY=>"\e[1;30m", :RED=>"\e[31m", :GREEN=>"\e[32m", :YELLOW=>"\e[33m", :BLUE=>"\e[34m", :MAGENTA=>"\e[35m", :CYAN=>"\e[36m", :WHITE=>"\e[37m"}
58
+
59
+ puts "Starting #{ANSI[:BOLD]}Micetrap#{ANSI[:RESET]}..."
60
+ puts "Loading fake #{ANSI[:RED]}#{service}#{ANSI[:RESET]} server... (press Ctrl-C to exit)\n"
61
+ Micetrap::Server.new(opts.update(:service => service)).fire!
@@ -0,0 +1,5 @@
1
+ if RUBY_VERSION =~ /1\.8/
2
+ class Array
3
+ alias :sample :choice
4
+ end
5
+ end
data/lib/micetrap.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'core_ext/array'
2
+
3
+ require 'micetrap/services/exceptions'
4
+ require 'micetrap/services/base'
5
+
6
+ require 'micetrap/logger'
7
+ require 'micetrap/server'
8
+
9
+ module Micetrap
10
+ class << self
11
+ def services
12
+ [:ftp, :torrent, :samba, :http, :mysql]
13
+ end
14
+ end
15
+ end
16
+
17
+ Micetrap.services.each do |service|
18
+ require "micetrap/services/#{service}"
19
+ end
@@ -0,0 +1,37 @@
1
+ module Micetrap
2
+ class Logger
3
+ TIMESTAMP_FORMAT = "%Y-%m-%d__%H-%M"
4
+
5
+ attr_reader :filename
6
+
7
+ def initialize(service_name)
8
+ @service_name = service_name
9
+ @filename = ['micetrap',
10
+ service_name,
11
+ Time.now.strftime(TIMESTAMP_FORMAT)
12
+ ].join('_') + '.log'
13
+ end
14
+
15
+ def file
16
+ @file ||= File.new(@filename, 'a')
17
+ end
18
+
19
+ def log_probe(line, remote_host, remote_port)
20
+ content = line.strip.length > 0 ? line : '(empty line)'
21
+ logged = "\n#{Time.now} Recorded a probe coming from #{remote_host}:#{remote_port} containing the following: #{content}"
22
+ File.open(@filename, 'a') do |f|
23
+ f.write logged
24
+ end
25
+ puts logged
26
+ end
27
+
28
+ def log_message(line)
29
+ logged = "\n#{Time.now} ::: #{line} :::"
30
+ File.open(@filename, 'a') do |f|
31
+ f.write logged
32
+ end
33
+ puts logged
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,22 @@
1
+ require 'socket'
2
+
3
+ module Micetrap
4
+ class Server
5
+ attr_reader :service
6
+ attr_reader :port
7
+
8
+ def initialize(options)
9
+ raise StandardError.new("Service cannot be empty!") unless options[:service]
10
+ @service =
11
+ eval("Micetrap::Services::#{options[:service].to_s.capitalize}").new
12
+ @port = options[:port] # Optional
13
+ rescue NameError=>e
14
+ raise Services::UnrecognizedServiceException.new("Service #{options[:service].to_s.capitalize} is not recognized")
15
+ end
16
+
17
+ def fire!
18
+ @service.fire port
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,83 @@
1
+ module Micetrap
2
+ module Services
3
+ class Base
4
+
5
+ class ClientQuitError < RuntimeError; end
6
+
7
+ attr_reader :logger
8
+
9
+ def initialize
10
+ @logger = Logger.new self.name.downcase.to_sym
11
+ end
12
+
13
+ def fire port = nil
14
+ port = port ? port.to_i : default_ports.sample
15
+ begin
16
+ server = TCPServer.open(port || 0)
17
+ rescue Errno::EACCES
18
+ puts "Looks like you are trying to use a system port, for which you need root privileges.\nRun micetrap with another port if you don't want to sudo!\n"
19
+ exit(1)
20
+ end
21
+ @port = server.addr[1]
22
+ @addrs = server.addr[2..-1].uniq
23
+
24
+ logger.log_message "#{name} trap listening on #{@addrs.collect{|a|"#{a}:#{port}"}.join(' ')}"
25
+ listen(server)
26
+ end
27
+
28
+ def listen(server)
29
+ # Handle Ctrl-C to exit!
30
+ interrupted = false
31
+ trap("INT") do
32
+ puts "Gracefully exiting...";
33
+ interrupted = true;
34
+ Kernel.exit(0)
35
+ end
36
+
37
+ while not interrupted do
38
+ socket = server.accept
39
+ Thread.start do
40
+ read_from(socket)
41
+ end
42
+ end
43
+ end
44
+
45
+ def read_from(socket)
46
+ s = socket
47
+
48
+ port = s.peeraddr[1]
49
+ name = s.peeraddr[2]
50
+ addr = s.peeraddr[3]
51
+
52
+ begin
53
+ while line = s.gets # read a line at a time
54
+ raise ClientQuitError if line =~ /^die\r?$/
55
+
56
+ logger.log_probe line, name, port
57
+
58
+ if line.strip == ""
59
+ s.write response
60
+ logger.log_message "Responded misleadingly: let's drive those hackers nuts!"
61
+ s.close
62
+ Kernel.exit(0)
63
+ end
64
+ end
65
+ rescue ClientQuitError
66
+ logger.log_message "#{name}:#{port} disconnected"
67
+ ensure
68
+ s.close # close socket on error
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def default_ports; []; end;
75
+ def response; ""; end;
76
+
77
+ def name
78
+ self.class.name.split('::').last
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,5 @@
1
+ module Micetrap
2
+ module Services
3
+ class UnrecognizedServiceException < StandardError; end;
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ module Micetrap
2
+ module Services
3
+ class Ftp < Base
4
+
5
+ protected
6
+
7
+ def default_ports
8
+ [21]
9
+ end
10
+
11
+ def response
12
+ @response ||=
13
+ [
14
+ "220-FTP server (lukemftpd 1.1) ready.\r\n",
15
+ "220 Welcome to Pure-FTPd 1.8\r\n",
16
+ "220--------------------------------------------------------------------------------\r\n220-This is the \"Banner\" message for the Mac OS X Server's FTP server process.\r\n",
17
+ ].sample
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module Micetrap
2
+ module Services
3
+ class Http < Base
4
+
5
+ protected
6
+
7
+ def default_ports
8
+ [80, 8080]
9
+ end
10
+
11
+ def response
12
+ @response ||=
13
+ [
14
+ "HTTP/1\.0 200 OK\r\nContent-Type: text/html\r\n\r\n<html>\n<body>\n<ul><li>\n<i>com\.apple\.KernelEventAgent</i>\n",
15
+ ].sample
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Micetrap
2
+ module Services
3
+ class Mysql < Base
4
+
5
+ protected
6
+
7
+ def default_ports
8
+ [3306]
9
+ end
10
+
11
+ def response
12
+ @response ||=
13
+ [
14
+ ".\0\0\0\n4.0.13\0...\0",
15
+ ].sample
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Micetrap
2
+ module Services
3
+ class Samba < Base
4
+
5
+ protected
6
+
7
+ def default_ports
8
+ [135, 139, 445]
9
+ end
10
+
11
+ def response
12
+ @response ||=
13
+ [
14
+ "smbd: error while loading shared libraries: libattr.so.1: cannot open shared object file: No such file or directory\n",
15
+ ].sample
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Micetrap
2
+ module Services
3
+ class Torrent < Base
4
+
5
+ protected
6
+
7
+ def default_ports
8
+ []
9
+ end
10
+
11
+ def response
12
+ @response ||=
13
+ [
14
+ "\x13BitTorrent protocol\0\0\0\0\0\0\0\0",
15
+ ].sample
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Micetrap
2
+ VERSION = "0.1.0"
3
+ end
data/micetrap.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "micetrap/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "micetrap"
7
+ s.version = Micetrap::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Josep M. Bach"]
10
+ s.email = ["josep.m.bach@gmail.com"]
11
+ s.homepage = "http://github.com/txus/micetrap"
12
+ s.summary = %q{Catch evil hackers on the fly by placing open-port traps emulating fake vulnerable services!}
13
+ s.description = %q{Catch evil hackers on the fly by placing open-port traps emulating fake vulnerable services!}
14
+
15
+ s.rubyforge_project = "micetrap"
16
+
17
+ s.add_runtime_dependency 'trollop'
18
+ s.default_executable = "micetrap"
19
+
20
+ s.add_development_dependency 'bundler', '~> 1.0.7'
21
+ s.add_development_dependency 'rspec', '~> 2.3.0'
22
+ s.add_development_dependency 'guard'
23
+ s.add_development_dependency 'guard-rspec'
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
28
+ s.require_paths = ["lib"]
29
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+
5
+ describe Logger do
6
+
7
+ describe "#initialize" do
8
+ it 'initializes the filename' do
9
+ Time.stub_chain('now.strftime').and_return "2011-01-03__20-30"
10
+ logger = Logger.new :ftp
11
+ logger.filename.should == "micetrap_ftp_2011-01-03__20-30.log"
12
+ end
13
+ end
14
+
15
+ describe "instance methods" do
16
+
17
+ subject { Logger.new :ftp }
18
+
19
+ describe "#file" do
20
+ it 'returns the log file' do
21
+ file = double('file')
22
+ File.stub(:new).and_return file
23
+ subject.file.should be(file)
24
+ end
25
+ end
26
+
27
+ describe "#log_probe" do
28
+ it 'logs a scanned service along with the scanner info' do
29
+ file = double('file')
30
+ now = Time.now
31
+ Time.stub(:now).and_return now
32
+ File.stub(:new).and_return file
33
+
34
+ expected_string = "\n#{now} Recorded a probe coming from hackerz.com:5978 containing the following: ###EVILPROBE###"
35
+
36
+ File.should_receive(:open).and_yield file
37
+ file.should_receive(:write).with expected_string
38
+
39
+ subject.log_probe "###EVILPROBE###", "hackerz.com", 5978
40
+ end
41
+ end
42
+
43
+ describe "#log_message" do
44
+ it 'logs a misc messagescanned service along with the scanner info' do
45
+ file = double('file')
46
+ now = Time.now
47
+ Time.stub(:now).and_return now
48
+ File.stub(:new).and_return file
49
+
50
+ expected_string = "\n#{now} ::: Warning! :::"
51
+
52
+ File.should_receive(:open).and_yield file
53
+ file.should_receive(:write).with expected_string
54
+
55
+ subject.log_message "Warning!"
56
+ end
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+
5
+ module Services
6
+ class Test
7
+ end
8
+ end
9
+
10
+ describe Server do
11
+ describe "#initialize" do
12
+ it 'initializes the service' do
13
+ server = Server.new :service => :test
14
+ server.service.should be_a(Services::Test)
15
+ end
16
+ it 'assigns a custom port if given' do
17
+ server = Server.new :service => :test,
18
+ :port => 80
19
+ server.port.should be(80)
20
+ end
21
+
22
+ context 'when given an invalid service' do
23
+ it 'raises' do
24
+ expect {
25
+ Server.new :service => :foo
26
+ }.to raise_error(Services::UnrecognizedServiceException)
27
+ end
28
+ end
29
+ context 'when service is blank' do
30
+ it 'raises' do
31
+ expect {
32
+ Server.new :service => nil
33
+ }.to raise_error(StandardError, "Service cannot be empty!")
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "#fire!" do
39
+ it 'fires the service' do
40
+ test_service = double('service')
41
+ Services::Test.should_receive(:new).and_return test_service
42
+ server = Server.new :service => :test
43
+ server.stub(:port).and_return 80
44
+ test_service.should_receive(:fire).with(80)
45
+
46
+ server.fire!
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+ module Services
5
+ describe Base do
6
+ describe "#fire" do
7
+
8
+ before(:each) do
9
+ subject.stub(:listen)
10
+ end
11
+
12
+ context 'when given a port' do
13
+ it 'fires up the service on that port' do
14
+ server = double('server', :addr => [1,2,3])
15
+ TCPServer.should_receive(:open).with(5900).and_return server
16
+ subject.fire 5900
17
+ end
18
+ end
19
+ context 'when port is nil' do
20
+ it 'fires up the service on one of the default ports' do
21
+ server = double('server', :addr => [1,2,3])
22
+ subject.stub_chain('default_ports.sample') { 445 }
23
+ TCPServer.should_receive(:open).with(445).and_return server
24
+
25
+ subject.fire
26
+ end
27
+ context 'but when no default ports are specified' do
28
+ it 'uses the port 0' do
29
+ server = double('server', :addr => [1,2,3])
30
+ subject.stub(:default_ports) { [] }
31
+ TCPServer.should_receive(:open).with(0).and_return server
32
+
33
+ subject.fire
34
+ end
35
+ end
36
+ end
37
+ it 'logs a message telling the trap is listening' do
38
+ server = double('server', :addr => [1,2,3])
39
+ TCPServer.stub(:open).and_return server
40
+ subject.logger.should_receive(:log_message).with do |arg|
41
+ arg.should include('Base trap listening')
42
+ end
43
+ subject.fire
44
+ end
45
+ end
46
+ describe "#listen", :blocking => true do
47
+ it 'calls read_from every time a connection is accepted' do
48
+ Kernel.stub(:exit)
49
+ connection = double('connection')
50
+ server = double('server', :addr => [1,2,3], :accept => connection)
51
+
52
+ subject.should_receive(:read_from).with(connection).any_number_of_times
53
+ puts "Press Ctrl-C to resume specs! Don't worry, it's all under control :)"
54
+ subject.listen(server)
55
+ end
56
+ end
57
+ describe "#read_from" do
58
+ let(:peeraddr) { [ nil, 4983, 'hackerz.com', '293.13.23.32'] }
59
+ let(:socket) do
60
+ double :socket, :peeraddr => peeraddr
61
+ end
62
+ before(:each) do
63
+ socket.should_receive(:close).any_number_of_times
64
+ end
65
+
66
+ context 'when the socket contains a line with die' do
67
+ it 'dies' do
68
+ socket.should_receive(:gets).and_return 'die'
69
+ subject.logger.should_not_receive(:log_probe)
70
+ subject.logger.should_receive(:log_message).with("hackerz.com:4983 disconnected")
71
+
72
+ subject.read_from(socket)
73
+ end
74
+ end
75
+
76
+ context 'otherwise' do
77
+ it 'logs the probe' do
78
+ socket.should_receive(:gets).and_return 'some probe', nil
79
+ subject.logger.should_receive(:log_probe).with 'some probe', 'hackerz.com', 4983
80
+
81
+ subject.read_from(socket)
82
+ end
83
+ context 'when the line is blank' do
84
+ it 'does respond with the appropriate response' do
85
+ Kernel.stub(:exit)
86
+ socket.should_receive(:gets).and_return '', nil
87
+ subject.logger.stub(:log_probe)
88
+ appropriate_response = double :response
89
+ subject.should_receive(:response).and_return appropriate_response
90
+
91
+ socket.should_receive(:write).with(appropriate_response)
92
+ subject.logger.should_receive(:log_message)
93
+
94
+ subject.read_from(socket)
95
+ end
96
+ end
97
+ context 'when the line contains any other thing' do
98
+ it 'does not respond' do
99
+ socket.should_receive(:gets).and_return 'some evil probe', nil
100
+ subject.logger.stub(:log_probe)
101
+
102
+ subject.should_not_receive(:response)
103
+ socket.should_not_receive(:write)
104
+
105
+ subject.read_from(socket)
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+ module Services
5
+ describe Ftp do
6
+
7
+ describe "#default_ports" do
8
+ it 'returns the default ports' do
9
+ Ftp.new.send(:default_ports).should include(21)
10
+ end
11
+ end
12
+ describe "#response" do
13
+ it 'returns a response' do
14
+ Ftp.new.send(:response).should be_a(String)
15
+ end
16
+ it 'caches the response for cohesion' do
17
+ service = Ftp.new
18
+ response = service.send(:response)
19
+ service.instance_variable_get(:@response).should == response
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+ module Services
5
+ describe Http do
6
+
7
+ describe "#default_ports" do
8
+ it 'returns the default ports' do
9
+ Http.new.send(:default_ports).should =~ [80, 8080]
10
+ end
11
+ end
12
+ describe "#response" do
13
+ it 'returns a response' do
14
+ Http.new.send(:response).should be_a(String)
15
+ end
16
+ it 'caches the response for cohesion' do
17
+ service = Http.new
18
+ response = service.send(:response)
19
+ service.instance_variable_get(:@response).should == response
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+ module Services
5
+ describe Mysql do
6
+
7
+ describe "#default_ports" do
8
+ it 'returns the default ports' do
9
+ Mysql.new.send(:default_ports).should include(3306)
10
+ end
11
+ end
12
+ describe "#response" do
13
+ it 'returns a response' do
14
+ Mysql.new.send(:response).should be_a(String)
15
+ end
16
+ it 'caches the response for cohesion' do
17
+ service = Mysql.new
18
+ response = service.send(:response)
19
+ service.instance_variable_get(:@response).should == response
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+ module Services
5
+ describe Samba do
6
+
7
+ describe "#default_ports" do
8
+ it 'returns the default ports' do
9
+ Samba.new.send(:default_ports).should =~ [135, 139, 445]
10
+ end
11
+ end
12
+ describe "#response" do
13
+ it 'returns a response' do
14
+ Samba.new.send(:response).should be_a(String)
15
+ end
16
+ it 'caches the response for cohesion' do
17
+ service = Samba.new
18
+ response = service.send(:response)
19
+ service.instance_variable_get(:@response).should == response
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Micetrap
4
+ module Services
5
+ describe Torrent do
6
+
7
+ describe "#default_ports" do
8
+ it 'returns the default ports' do
9
+ Torrent.new.send(:default_ports).should == []
10
+ end
11
+ end
12
+ describe "#response" do
13
+ it 'returns a response' do
14
+ Torrent.new.send(:response).should be_a(String)
15
+ end
16
+ it 'caches the response for cohesion' do
17
+ service = Torrent.new
18
+ response = service.send(:response)
19
+ service.instance_variable_get(:@response).should == response
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts "Run `bundle install` to install missing gems"
7
+ exit e.status_code
8
+ end
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+
12
+ require 'micetrap'
13
+ require 'rspec'
14
+
15
+ # Requires supporting files with custom matchers and macros, etc,
16
+ # in ./support/ and its subdirectories.
17
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: micetrap
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Josep M. Bach
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-06 00:00:00 +01:00
18
+ default_executable: micetrap
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: trollop
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 0
44
+ - 7
45
+ version: 1.0.7
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 2
58
+ - 3
59
+ - 0
60
+ version: 2.3.0
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: guard
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: guard-rspec
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ type: :development
88
+ version_requirements: *id005
89
+ description: Catch evil hackers on the fly by placing open-port traps emulating fake vulnerable services!
90
+ email:
91
+ - josep.m.bach@gmail.com
92
+ executables:
93
+ - micetrap
94
+ extensions: []
95
+
96
+ extra_rdoc_files: []
97
+
98
+ files:
99
+ - .gitignore
100
+ - .rspec
101
+ - .rvmrc
102
+ - Gemfile
103
+ - Gemfile.lock
104
+ - Guardfile
105
+ - Rakefile
106
+ - Readme.md
107
+ - bin/micetrap
108
+ - lib/core_ext/array.rb
109
+ - lib/micetrap.rb
110
+ - lib/micetrap/logger.rb
111
+ - lib/micetrap/server.rb
112
+ - lib/micetrap/services/base.rb
113
+ - lib/micetrap/services/exceptions.rb
114
+ - lib/micetrap/services/ftp.rb
115
+ - lib/micetrap/services/http.rb
116
+ - lib/micetrap/services/mysql.rb
117
+ - lib/micetrap/services/samba.rb
118
+ - lib/micetrap/services/torrent.rb
119
+ - lib/micetrap/version.rb
120
+ - micetrap.gemspec
121
+ - spec/micetrap/logger_spec.rb
122
+ - spec/micetrap/server_spec.rb
123
+ - spec/micetrap/services/base_spec.rb
124
+ - spec/micetrap/services/ftp_spec.rb
125
+ - spec/micetrap/services/http_spec.rb
126
+ - spec/micetrap/services/mysql_spec.rb
127
+ - spec/micetrap/services/samba_spec.rb
128
+ - spec/micetrap/services/torrent_spec.rb
129
+ - spec/spec_helper.rb
130
+ has_rdoc: true
131
+ homepage: http://github.com/txus/micetrap
132
+ licenses: []
133
+
134
+ post_install_message:
135
+ rdoc_options: []
136
+
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ requirements: []
156
+
157
+ rubyforge_project: micetrap
158
+ rubygems_version: 1.3.7
159
+ signing_key:
160
+ specification_version: 3
161
+ summary: Catch evil hackers on the fly by placing open-port traps emulating fake vulnerable services!
162
+ test_files:
163
+ - spec/micetrap/logger_spec.rb
164
+ - spec/micetrap/server_spec.rb
165
+ - spec/micetrap/services/base_spec.rb
166
+ - spec/micetrap/services/ftp_spec.rb
167
+ - spec/micetrap/services/http_spec.rb
168
+ - spec/micetrap/services/mysql_spec.rb
169
+ - spec/micetrap/services/samba_spec.rb
170
+ - spec/micetrap/services/torrent_spec.rb
171
+ - spec/spec_helper.rb