dvash 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "dvash"
5
- s.version = "0.0.3"
5
+ s.version = "0.0.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Ari Mizrahi"]
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.description = "Part honeypot, part defense system. Opens up ports and simulates services in order to look like an attractive target. Hosts that try to connect to the fake services are considered attackers and blocked from all access."
11
11
  s.email = "codemunchies@gmail.com"
12
12
  s.executables = ["dvash"]
13
- s.files = ["etc/dvash-baseline.conf", "lib/dvash/honeyports/ipv4/http.rb", "lib/dvash/honeyports/ipv6/http.rb", "lib/dvash/os/linux.rb", "lib/dvash/os/mac.rb", "lib/dvash/os/windows.rb", "lib/dvash/application.rb", "lib/dvash/validation.rb", "lib/dvash.rb", "dvash.gemspec", "Gemfile"]
13
+ s.files = ["etc/dvash-baseline.conf", "lib/dvash/honeyports/ipv4/http.rb", "lib/dvash/honeyports/ipv6/http.rb", "lib/dvash/os/linux.rb", "lib/dvash/os/mac.rb", "lib/dvash/os/windows.rb", "lib/dvash/application.rb", "lib/dvash/core.rb", "lib/dvash.rb", "dvash.gemspec", "Gemfile"]
14
14
  s.homepage = "http://github.com/codemunchies/dvash"
15
15
  s.require_paths = ["lib"]
16
16
  s.rubygems_version = "1.8.25"
@@ -2,6 +2,7 @@ require 'dvash/application'
2
2
 
3
3
  require 'optparse'
4
4
 
5
+ #
5
6
  # Dvash Defense
6
7
  #
7
8
  # Written By: Ari Mizrahi
@@ -12,37 +13,51 @@ require 'optparse'
12
13
  #
13
14
  # Heavily inspired by The Artillery Project by Dave Kennedy (ReL1K) with a
14
15
  # passion for ruby and a thirst for knowledge.
16
+ #
15
17
 
16
18
  module Dvash
17
19
 
18
- # Start a new Dvash instance
19
20
  def self.start(paths={})
20
21
 
21
- # Set default options
22
+ #
23
+ # Set default path to config and log files
24
+ # TODO: These settings assume Linux default paths, should determine the operating system then configure accordingly
25
+ #
22
26
  paths[:config_path] = '/etc/dvash.conf'
23
27
  paths[:log_path] = '/var/log/dvash.conf'
24
28
 
25
- # Command-line interface
29
+ #
30
+ # A command-line interface using OptionParser
31
+ #
26
32
  OptionParser.new do |opts|
27
33
  opts.banner = "Usage: #{__FILE__} [options]"
28
34
 
35
+ #
36
+ # Option to set an alternate configuration file
37
+ #
29
38
  opts.on("--config-file [PATH]", "Set path to config file") do |arg|
30
39
  paths[:config_path] = arg
31
40
  end
32
41
 
42
+ #
43
+ # Option to set an alternate log file destination and filename
44
+ #
33
45
  opts.on("--log-file [PATH]", "Set path to log file") do |arg|
34
46
  paths[:log_path] = arg
35
47
  end
36
48
  end.parse!
37
49
 
50
+ #
38
51
  # Create and start an Application instance
39
- #begin
52
+ #
53
+ begin
40
54
  application = Dvash::Application.new(paths)
41
55
  application.start
42
- #rescue
43
- # puts "couldn't start application" # replace me
44
- # exit
45
- #end
56
+ rescue
57
+ # TODO: Use 'logger' gem to output debug information
58
+ puts "couldn't start application"
59
+ exit
60
+ end
46
61
 
47
62
 
48
63
  end
@@ -1,26 +1,55 @@
1
- require 'dvash/validation'
1
+ require 'dvash/core'
2
2
 
3
3
  require 'parseconfig'
4
4
 
5
5
  module Dvash
6
6
 
7
- class Application < Validation
7
+ class Application < Core
8
8
 
9
+ #
10
+ # Methods that should run when the Dvash Application object is created
11
+ # Requires one argument of type Array including paths to configuration
12
+ # file and destination for log file
13
+ #
9
14
  def initialize(paths)
15
+ #
16
+ # Create @honey_threads Array to hold all 'honeyport' threads
17
+ #
10
18
  @honey_threads = Array.new
19
+ #
20
+ # Load passed Array paths into @paths for use in the class
21
+ #
11
22
  @paths = paths
12
-
23
+ #
24
+ # Call method to load the configuration file
25
+ #
13
26
  load_conf
27
+ #
28
+ # Call method to validate the operating system and load necessary Dvash methods
29
+ #
14
30
  validate_os
15
31
  end
16
32
 
33
+ #
34
+ # Fire in the hole!
35
+ #
17
36
  def start
37
+ #
38
+ # Make sure we are running with elevated privileges
39
+ #
18
40
  unless valid_user?
19
- puts "invalid user" # replace me
41
+ # TODO: Use 'logger' gem to output debug information
42
+ puts "invalid user"
20
43
  exit
21
44
  end
22
45
 
46
+ #
47
+ # Call method to load all 'honeyports' set as 'true' in the configuration file
48
+ #
23
49
  load_honeyport
50
+ #
51
+ # Start all loaded threads
52
+ #
24
53
  @honey_threads.each { |thr| thr.join }
25
54
  end
26
55
 
@@ -3,12 +3,18 @@ require 'securerandom'
3
3
 
4
4
  module Dvash
5
5
 
6
- class Validation
6
+ class Core
7
7
 
8
+ #
9
+ # Validates user, must be root
10
+ #
8
11
  def valid_user?
9
12
  Process.uid == 0
10
13
  end
11
14
 
15
+ #
16
+ # Validates an IP address, must be valid IPv4 or IPv6 address
17
+ #
12
18
  def valid_ip?(address)
13
19
  begin
14
20
  IPAddr.new("#{address}")
@@ -18,6 +24,11 @@ module Dvash
18
24
  end
19
25
  end
20
26
 
27
+ #
28
+ # Validates the operating system, must be windows, os x, or linux
29
+ # Creates a new instance the operating system specific Dvash libraries required to block IP addresses properly
30
+ # @@os is used as a class variable to call its methods from within a Honeyport
31
+ #
21
32
  def validate_os
22
33
  system = RUBY_PLATFORM
23
34
  case system
@@ -34,34 +45,57 @@ module Dvash
34
45
  # TODO: BSD support
35
46
  exit
36
47
  else
37
- puts "invalid operating system" # replace me
48
+ # TODO: Use 'logger' gem to output debug information
49
+ puts "invalid operating system"
38
50
  exit
39
51
  end
40
52
  end
41
53
 
54
+ #
55
+ # Loads the configuration file using ParseConfig
56
+ #
42
57
  def load_conf
43
58
  begin
44
59
  @@cfgfile = ParseConfig.new(@paths[:config_path])
45
60
  rescue
46
- puts "invalid configuration file" # replace me
61
+ # TODO: Use 'logger' gem to output debug information
62
+ puts "invalid configuration file"
47
63
  exit
48
64
  end
49
65
  end
50
66
 
67
+ #
68
+ # Load all Honeyports set 'true' in the configuration file
69
+ #
51
70
  def load_honeyport
71
+ #
72
+ # Read 'honeyports' group in configuration file, parse keys and values
73
+ #
52
74
  @@cfgfile['honeyports'].each do |key, value|
53
75
  if value == 'true' then
54
76
  ipver, proto = key.split("_")
77
+ #
78
+ # Load methods for all 'honeyports' set to 'true'
79
+ #
55
80
  require "dvash/honeyports/#{ipver}/#{proto}"
81
+ #
82
+ # Push the loaded 'honeyport' into a thread
83
+ #
56
84
  @honey_threads << Thread.new { Dvash::Honeyport.new.send(key) }
57
85
  end
58
86
  end
59
87
  end
60
88
 
89
+ #
90
+ # Return a string of random characters 64 bytes long
91
+ #
61
92
  def random_data
62
93
  SecureRandom.random_bytes(64)
63
94
  end
64
95
 
96
+ #
97
+ # Return the client source IP address from a TCPServer object
98
+ #
65
99
  def client_ip(client)
66
100
  client.peeraddr[3]
67
101
  end
@@ -10,17 +10,38 @@
10
10
  ###############################################################################
11
11
  module Dvash
12
12
 
13
- class Honeyport < Validation
13
+ class Honeyport < Core
14
14
 
15
15
  def ipv4_http
16
+ #
17
+ # Create a new IPv4 TCPServer object
18
+ #
16
19
  server = TCPServer.new(80)
20
+ #
21
+ # Infinite loop listens on port 80 pretending to be an HTTP server
22
+ #
17
23
  loop do
24
+ #
25
+ # Fork a new instance of the TCPServer object when a client connects
26
+ # TODO: Maybe we should not send junk data until after the client IP has been validated
27
+ #
18
28
  Thread.fork(server.accept) do |client|
19
- # send the client junk data
29
+ #
30
+ # Send the connected client junk data
31
+ #
20
32
  client.puts(random_data)
33
+ #
34
+ # Make sure the client has a valid IP address
35
+ #
21
36
  if valid_ip?(client_ip(client)) then
37
+ #
38
+ # Block the IP address
39
+ #
22
40
  @@os.block_ip(client_ip(client))
23
41
  end
42
+ #
43
+ # Close the connection to the client and kill the forked process
44
+ #
24
45
  client.close
25
46
  end
26
47
  end
@@ -10,17 +10,38 @@
10
10
  ###############################################################################
11
11
  module Dvash
12
12
 
13
- class Honeyport < Validation
13
+ class Honeyport < Core
14
14
 
15
- def ipv4_http
15
+ def ipv6_http
16
+ #
17
+ # Create a new IPv6 TCPServer object
18
+ #
16
19
  server = TCPServer.new('::', 80)
20
+ #
21
+ # Infinite loop listens on port 80 pretending to be an HTTP server
22
+ #
17
23
  loop do
24
+ #
25
+ # Fork a new instance of the TCPServer object when a client connects
26
+ # TODO: Maybe we should not send junk data until after the client IP has been validated
27
+ #
18
28
  Thread.fork(server.accept) do |client|
19
- # send the client junk data
29
+ #
30
+ # Send the connected client junk data
31
+ #
20
32
  client.puts(random_data)
33
+ #
34
+ # Make sure the client has a valid IP address
35
+ #
21
36
  if valid_ip?(client_ip(client)) then
37
+ #
38
+ # Block the IP address
39
+ #
22
40
  @@os.block_ip(client_ip(client))
23
41
  end
42
+ #
43
+ # Close the connection to the client and kill the forked process
44
+ #
24
45
  client.close
25
46
  end
26
47
  end
@@ -1,40 +1,66 @@
1
1
  module Dvash
2
2
 
3
- class Linux < Validation
3
+ class Linux < Core
4
4
 
5
5
  def initialize
6
+ #
7
+ # Check to make sure we have binaries for iptables using the paths
8
+ # set in the configuration file
9
+ #
6
10
  unless File.exist?(@@cfgfile['iptables']['ipv4'])
11
+ # TODO: Use 'logger' gem to output debug information
7
12
  puts "can't find iptables"
8
13
  exit
9
14
  end
10
15
 
11
- # do not create if it has already been created
16
+ #
17
+ # Do not create a new iptables chain if one already exists
18
+ #
12
19
  unless `"#{@@cfgfile['iptables']['ipv4']}" -L INPUT`.include?('DVASH')
13
- # create a new chain
20
+ #
21
+ # Create a new DVASH chain
22
+ #
14
23
  system("#{@@cfgfile['iptables']['ipv4']} -N DVASH")
15
- # flush the new chain
24
+ #
25
+ # Flush the DVASH chain
26
+ #
16
27
  system("#{@@cfgfile['iptables']['ipv4']} -F DVASH")
17
- # associate new chain to INPUT chain
28
+ #
29
+ # Associate the DVASH chain to INPUT chain
30
+ #
18
31
  system("#{@cfgfile['iptables']['ipv4']} -I INPUT -j DVASH")
19
32
  end
20
33
 
21
- # do not create if it has already been created
34
+ #
35
+ # Do not create a new ip6tables chain if one already exists
36
+ #
22
37
  unless `"#{@@cfgfile['iptables']['ipv6']}" -L INPUT`.include?('DVASH')
23
- # create a new chain
38
+ #
39
+ # Create a new DVASH chain
40
+ #
24
41
  system("#{@@cfgfile['iptables']['ipv6']} -N DVASH")
25
- # flush the new chain
42
+ #
43
+ # Flush the DVASH chain
44
+ #
26
45
  system("#{@@cfgfile['iptables']['ipv6']} -F DVASH")
27
- # associate new chain to INPUT chain
46
+ #
47
+ # Associate the DVASH chain to INPUT chain
48
+ #
28
49
  system("#{@@cfgfile['iptables']['ipv6']} -I INPUT -j DVASH")
29
50
  end
30
51
  end
31
52
 
32
53
  def block_ip(address)
33
-
54
+ #
55
+ # Block the client IP address using iptables binaries set in the configuration file
56
+ #
34
57
  if IPAddr.new("#{address}").ipv4? then
35
58
  system("#{@@cfgfile['iptables']['ipv4']} -I DVASH -s #{address} -j DROP")
36
59
  end
37
60
 
61
+ #
62
+ # Block the client IP address using ip6tables binaries set in the configuration file
63
+ #
38
64
  if IPAddr.new("#{address}").ipv6? then
39
65
  system("#{@@cfgfile['iptables']['ipv6']} -I DVASH -s #{address} -j DROP")
40
66
  end
@@ -1,15 +1,23 @@
1
1
  module Dvash
2
2
 
3
- class Mac < Validation
3
+ class Mac < Core
4
4
 
5
5
  def initialize
6
+ #
7
+ # Check to make sure we have binaries for ipfw using the paths
8
+ # set in the configuration file
9
+ #
6
10
  unless File.exist?(@@cfgfile['ipfw']['ipfw'])
11
+ # TODO: Use 'logger' gem to output debug information
7
12
  puts "can't find ipfw"
8
13
  exit
9
14
  end
10
15
  end
11
16
 
12
17
  def block_ip(address)
18
+ #
19
+ # Block the client IP address using ipfw binaries set in the configuration file
20
+ #
13
21
  system("#{@@cfgfile['ipfw']['ipfw']} -q add deny src-ip #{address}")
14
22
  end
15
23
 
@@ -1,10 +1,13 @@
1
1
  module Dvash
2
2
 
3
- class Windows
3
+ class Windows < Core
4
4
 
5
5
  def block_ip(address)
6
-
7
- # TODO
6
+ #
7
+ # Windows 7 and newer compatible
8
+ # Blackholes the client IP address by sending traffic to a non-existing gateway
9
+ #
10
+ system("route add #{address} mask 255.255.255.255 10.255.255.255 if 1 -p")
8
11
  end
9
12
 
10
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dvash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -59,7 +59,7 @@ files:
59
59
  - lib/dvash/os/mac.rb
60
60
  - lib/dvash/os/windows.rb
61
61
  - lib/dvash/application.rb
62
- - lib/dvash/validation.rb
62
+ - lib/dvash/core.rb
63
63
  - lib/dvash.rb
64
64
  - dvash.gemspec
65
65
  - Gemfile