unified2 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/ChangeLog.rdoc +6 -0
  2. data/LICENSE.txt +1 -1
  3. data/README.md +72 -0
  4. data/example/{basic-example.rb → example.rb} +3 -2
  5. data/example/seeds/{unified2 → unified2.log} +0 -0
  6. data/gemspec.yml +2 -0
  7. data/lib/unified2/classification.rb +17 -3
  8. data/lib/unified2/config_file.rb +34 -10
  9. data/lib/unified2/constructor/construct.rb +83 -0
  10. data/lib/unified2/constructor/event_ip4.rb +47 -0
  11. data/lib/unified2/constructor/event_ip6.rb +44 -0
  12. data/lib/unified2/constructor/packet.rb +30 -0
  13. data/lib/unified2/constructor/primitive/ipv4.rb +31 -0
  14. data/lib/unified2/{primitive.rb → constructor/primitive.rb} +0 -0
  15. data/lib/unified2/constructor/record_header.rb +17 -0
  16. data/lib/unified2/constructor.rb +1 -0
  17. data/lib/unified2/core_ext/string.rb +10 -2
  18. data/lib/unified2/event.rb +250 -100
  19. data/lib/unified2/exceptions/file_not_found.rb +6 -3
  20. data/lib/unified2/exceptions/file_not_readable.rb +6 -3
  21. data/lib/unified2/exceptions/unknown_load_type.rb +6 -3
  22. data/lib/unified2/payload.rb +82 -13
  23. data/lib/unified2/protocol.rb +141 -0
  24. data/lib/unified2/sensor.rb +22 -0
  25. data/lib/unified2/signature.rb +28 -4
  26. data/lib/unified2/version.rb +2 -2
  27. data/lib/unified2.rb +84 -13
  28. data/spec/event_spec.rb +112 -0
  29. data/spec/spec_helper.rb +45 -1
  30. data/spec/unified2_spec.rb +87 -1
  31. metadata +45 -25
  32. data/README.rdoc +0 -60
  33. data/Rakefile.compiled.rbc +0 -775
  34. data/example/connect.rb +0 -20
  35. data/example/models.rb +0 -194
  36. data/example/mysql-example.rb +0 -73
  37. data/example/search.rb +0 -14
  38. data/example/untitled.rb +0 -31
  39. data/lib/unified2/construct.rb +0 -54
  40. data/lib/unified2/event_ip4.rb +0 -26
  41. data/lib/unified2/event_ip6.rb +0 -23
  42. data/lib/unified2/packet.rb +0 -16
  43. data/lib/unified2/primitive/ipv4.rb +0 -19
  44. data/lib/unified2/record_header.rb +0 -10
data/ChangeLog.rdoc CHANGED
@@ -1,3 +1,9 @@
1
+ === 0.5.0 / 2011-03-18
2
+
3
+ * major refactoring
4
+ * Added eth, ip, udp, icmp, and TCP header support
5
+ * Added basic specs and fully documented the source
6
+
1
7
  === 0.4.0 / 2011-03-14
2
8
 
3
9
  * added checksum support for sensor
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 mephux
1
+ Copyright (c) 2011 Dustin Willis Webber
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # unified2
2
+
3
+ * [Homepage](http://github.com/mephux/unified2)
4
+ * [Issues](http://github.com/mephux/unified2/issues)
5
+ * [Documentation](http://rubydoc.info/gems/unified2/frames)
6
+ * [Email](mailto:dustin.webber at gmail.com)
7
+
8
+ ## Description
9
+
10
+ A ruby interface for unified2 output. rUnified2 allows you to manipulate unified2 output for custom storage and/or analysis.
11
+
12
+ ## Features
13
+
14
+ * Monitor/Read unified2 logs & manipulate the data.
15
+ * Numerous connivence methods
16
+ * Simple & Intuitive to Use
17
+
18
+ ## Examples
19
+
20
+ require 'unified2'
21
+
22
+ #
23
+ # Load rules into memory
24
+ #
25
+
26
+ Unified2.configuration do
27
+ # Sensor Configurations
28
+ sensor :id => 1, :name => 'Test Sensor', :interface => 'en1'
29
+
30
+ # Load signatures, generators & classifications into memory
31
+ load :signatures, 'sid-msg.map'
32
+ load :generators, 'gen-msg.map'
33
+ load :classifications, 'classification.config'
34
+ end
35
+
36
+ #
37
+ # Unified2#watch
38
+ #
39
+ # Watch a unified2 file for changes and process the results.
40
+ #
41
+
42
+ Unified2.watch('/var/log/snort/merged.log', :last) do |event|
43
+ next if event.signature.name.blank?
44
+ puts event
45
+ end
46
+
47
+ # Unified2#read
48
+ # Parse a unified2 file and process the results.
49
+
50
+ Unified2.read('/var/log/snort/merged.log') do |event|
51
+
52
+ puts event.protocol #=> "TCP"
53
+
54
+ puts event.protocol.to_h #=> {:length=>379, :seq=>3934511163, :ack=>1584708129 ... }
55
+
56
+ end
57
+
58
+ ## Requirements
59
+
60
+ * bindata ~> 1.3.1
61
+ * hexdump: ~> 0.1.0
62
+ * packetfu: ~> 1.0.0
63
+
64
+ ## Install
65
+
66
+ `$ gem install unified2`
67
+
68
+ == Copyright
69
+
70
+ Copyright (c) 2011 Dustin Willis Webber
71
+
72
+ See LICENSE.txt for details.
@@ -1,6 +1,5 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
  require 'unified2'
3
- require 'pp'
4
3
 
5
4
  # Unified2 Configuration
6
5
  Unified2.configuration do
@@ -10,7 +9,9 @@ Unified2.configuration do
10
9
 
11
10
  # Load signatures, generators & classifications into memory
12
11
  load :signatures, 'seeds/sid-msg.map'
12
+
13
13
  load :generators, 'seeds/gen-msg.map'
14
+
14
15
  load :classifications, 'seeds/classification.config'
15
16
 
16
17
  end
@@ -19,7 +20,7 @@ end
19
20
  # The second argument is the last event processed by
20
21
  # the sensor. If the last_event_id column is blank in the
21
22
  # sensor table it will begin at the first available event.
22
- Unified2.watch('seeds/unified2', :first) do |event|
23
+ Unified2.watch('seeds/unified2.log', :first) do |event|
23
24
  next if event.signature.blank?
24
25
 
25
26
  puts event
File without changes
data/gemspec.yml CHANGED
@@ -9,6 +9,8 @@ homepage: https://github.com/mephux/unified2
9
9
  dependencies:
10
10
  bindata: ~> 1.3.1
11
11
  hexdump: ~> 0.1.0
12
+ packetfu: ~> 1.0.0
13
+ pcaprub: ~> 0.9.2
12
14
 
13
15
  development_dependencies:
14
16
  ore-tasks: ~> 0.4
@@ -1,8 +1,21 @@
1
1
  module Unified2
2
+ #
3
+ # Classification
4
+ #
2
5
  class Classification
3
6
 
4
7
  attr_accessor :id, :name, :short, :severity
5
-
8
+
9
+ #
10
+ # Initialize classification
11
+ #
12
+ # @param [Hash] classification Classification attributes
13
+ #
14
+ # @option classification [Integer] :classification_id Classification id
15
+ # @option classification [String] :name Classification name
16
+ # @option classification [String] :short Classification short name
17
+ # @option classification [String] :severity Classification severity id
18
+ #
6
19
  def initialize(classification={})
7
20
  @id = classification[:classification_id]
8
21
  @name = classification[:name]
@@ -10,5 +23,6 @@ module Unified2
10
23
  @severity = classification[:severity]
11
24
  end
12
25
 
13
- end
14
- end
26
+ end # class Classification
27
+
28
+ end # module Unified2
@@ -1,8 +1,17 @@
1
1
  module Unified2
2
+ #
3
+ # Configuration file
4
+ #
2
5
  class ConfigFile
3
6
 
4
7
  attr_accessor :type, :path, :md5, :data
5
8
 
9
+ #
10
+ # Initialize configuration file
11
+ #
12
+ # @param [String, Symbol] type Configuration file type
13
+ # @param [String] path Configuration file path
14
+ #
6
15
  def initialize(type, path)
7
16
  @type = type
8
17
  @path = path
@@ -10,9 +19,24 @@ module Unified2
10
19
  @md5 = Digest::MD5.hexdigest(@path)
11
20
  import
12
21
  end
22
+
23
+ #
24
+ # Size
25
+ #
26
+ # @return [Integer] Configuration size
27
+ #
28
+ def size
29
+ @data.size
30
+ end
13
31
 
14
32
  private
15
-
33
+
34
+ #
35
+ # Configuration Import
36
+ #
37
+ # Parse the configuration files and store
38
+ # them in memory as a hash.
39
+ #
16
40
  def import
17
41
  file = File.open(@path)
18
42
 
@@ -25,9 +49,8 @@ module Unified2
25
49
  next unless line[/^config\s/]
26
50
  count += 1
27
51
 
28
- # attempted-dos,Attempted Denial of Service,2
29
52
  data = line.gsub!(/config classification: /, '')
30
- short, name, severity = data.to_s.split(',')
53
+ short, name, severity = data.to_s.split(',').map(&:strip)
31
54
 
32
55
  @data[count.to_s] = {
33
56
  :short => short,
@@ -40,13 +63,13 @@ module Unified2
40
63
 
41
64
  file.each_line do |line|
42
65
  next if line[/^\#/]
43
- generator_id, alert_id, name = line.split(' || ')
66
+ generator_id, alert_id, name = line.split(' || ').map(&:strip)
44
67
  id = "#{generator_id}.#{alert_id}"
45
68
 
46
69
  @data[id] = {
47
- :generator_id => generator_id,
70
+ :generator_id => generator_id.to_i,
48
71
  :name => name,
49
- :signature_id => alert_id
72
+ :signature_id => alert_id.to_i
50
73
  }
51
74
  end
52
75
 
@@ -54,7 +77,7 @@ module Unified2
54
77
 
55
78
  file.each_line do |line|
56
79
  next if line[/^\#/]
57
- id, body, *reference_data = line.split(' || ')
80
+ id, body, *reference_data = line.split(' || ').map(&:strip)
58
81
 
59
82
  references = {}
60
83
  reference_data.each do |line|
@@ -67,7 +90,7 @@ module Unified2
67
90
  end
68
91
 
69
92
  @data[id] = {
70
- :signature_id => id,
93
+ :signature_id => id.to_i,
71
94
  :name => body,
72
95
  :generator_id => 1
73
96
  }
@@ -76,5 +99,6 @@ module Unified2
76
99
  end
77
100
  end
78
101
 
79
- end
80
- end
102
+ end # class ConfigFile
103
+
104
+ end # module Unified2
@@ -0,0 +1,83 @@
1
+ require 'unified2/constructor/event_ip4'
2
+ require 'unified2/constructor/event_ip6'
3
+ require 'unified2/constructor/record_header'
4
+ require 'unified2/constructor/packet'
5
+
6
+ module Unified2
7
+ #
8
+ # Unified2 Constructor Namespace
9
+ #
10
+ module Constructor
11
+ #
12
+ # Unified2 Construction
13
+ #
14
+ class Construct < ::BinData::Record
15
+ #
16
+ # Rename record_header to header
17
+ # to simplify and cut down on verbosity
18
+ #
19
+ record_header :header
20
+
21
+ #
22
+ # Unified2 data types
23
+ #
24
+ # Currently rUnified2 only supports packet,
25
+ # event_ip4 and event_ip6.
26
+ #
27
+ choice :data, :selection => :type_selection do
28
+ packet "packet"
29
+ event_ip4 "ev4"
30
+ event_ip6 "ev6"
31
+ end
32
+
33
+ #
34
+ # String padding
35
+ #
36
+ string :read_length => :padding_length
37
+
38
+ #
39
+ # Type Selection
40
+ #
41
+ # Deterime and call data type based on
42
+ # the unified2 type attribute
43
+ #
44
+ def type_selection
45
+ case header.u2type.to_i
46
+ when 1
47
+ # define UNIFIED2_EVENT 1
48
+ when 2
49
+ # define UNIFIED2_PACKET 2
50
+ "packet"
51
+ when 7
52
+ # define UNIFIED2_IDS_EVENT 7
53
+ "ev4"
54
+ when 66
55
+ # define UNIFIED2_EVENT_EXTENDED 66
56
+ when 67
57
+ # define UNIFIED2_PERFORMANCE 67
58
+ when 68
59
+ # define UNIFIED2_PORTSCAN 68
60
+ when 72
61
+ # define UNIFIED2_IDS_EVENT_IPV6 72
62
+ "ev6"
63
+ else
64
+ "unknown type #{header.u2type}"
65
+ end
66
+ end
67
+
68
+ #
69
+ # Sometimes the data needs extra padding
70
+ #
71
+ def padding_length
72
+ if header.u2length > data.num_bytes
73
+ header.u2length - data.num_bytes
74
+ else
75
+ 0
76
+ end
77
+ end
78
+
79
+ end # class Construct
80
+
81
+ end # module Construct
82
+
83
+ end # module Unified2
@@ -0,0 +1,47 @@
1
+ require 'unified2/primitive/ipv4'
2
+
3
+ module Unified2
4
+
5
+ module Constructor
6
+ #
7
+ # Event IP Version 4
8
+ #
9
+ class EventIP4 < ::BinData::Record
10
+
11
+ endian :big
12
+
13
+ uint32 :sensor_id
14
+
15
+ uint32 :event_id
16
+
17
+ uint32 :event_second
18
+
19
+ uint32 :event_microsecond
20
+
21
+ uint32 :signature_id
22
+
23
+ uint32 :generator_id
24
+
25
+ uint32 :signature_revision
26
+
27
+ uint32 :classification_id
28
+
29
+ uint32 :priority_id
30
+
31
+ ipv4 :ip_source
32
+
33
+ ipv4 :ip_destination
34
+
35
+ uint16 :sport_itype
36
+
37
+ uint16 :dport_icode
38
+
39
+ uint8 :protocol
40
+
41
+ uint8 :packet_action
42
+
43
+ end # class EventIP4
44
+
45
+ end # module Constructor
46
+
47
+ end # module Unified2
@@ -0,0 +1,44 @@
1
+ module Unified2
2
+
3
+ module Constructor
4
+ #
5
+ # Event IP Version 6
6
+ #
7
+ class EventIP6 < ::BinData::Record
8
+ endian :big
9
+
10
+ uint32 :sensor_id
11
+
12
+ uint32 :event_id
13
+
14
+ uint32 :event_second
15
+
16
+ uint32 :event_microsecond
17
+
18
+ uint32 :signature_id
19
+
20
+ uint32 :generator_id
21
+
22
+ uint32 :signature_revision
23
+
24
+ uint32 :classification_id
25
+
26
+ uint32 :priority_id
27
+
28
+ uint128 :ip_source
29
+
30
+ uint128 :ip_destination
31
+
32
+ uint16 :sport_itype
33
+
34
+ uint16 :dport_icode
35
+
36
+ uint8 :protocol
37
+
38
+ uint8 :packet_action
39
+
40
+ end # class EventIP6
41
+
42
+ end # module Constructor
43
+
44
+ end # module Unified2
@@ -0,0 +1,30 @@
1
+ module Unified2
2
+
3
+ module Constructor
4
+ #
5
+ # Event Packet
6
+ #
7
+ class Packet < ::BinData::Record
8
+ endian :big
9
+
10
+ uint32 :sensor_id
11
+
12
+ uint32 :event_id
13
+
14
+ uint32 :event_second
15
+
16
+ uint32 :packet_second
17
+
18
+ uint32 :packet_microsecond
19
+
20
+ uint32 :linktype
21
+
22
+ uint32 :packet_length
23
+
24
+ string :packet_data, :read_length => :packet_length
25
+
26
+ end # class Packet
27
+
28
+ end # module Constructor
29
+
30
+ end # module Unified2
@@ -0,0 +1,31 @@
1
+ module Unified2
2
+
3
+ module Constructor
4
+ #
5
+ # Unified2 Primitive Namespace
6
+ #
7
+ module Primitive
8
+ #
9
+ # BinData Primitive IP4 Constructor
10
+ #
11
+ class IPV4 < ::BinData::Primitive
12
+ array :octets, :type => :uint8, :initial_length => 4
13
+
14
+ # IPV4#set
15
+ def set(value)
16
+ ints = value.split(/\./).collect { |int| int.to_i }
17
+ self.octets = ints
18
+ end
19
+
20
+ # IPV4#get
21
+ def get
22
+ self.octets.collect { |octet| "%d" % octet }.join(".")
23
+ end
24
+
25
+ end # class IPV4
26
+
27
+ end # class Primitive
28
+
29
+ end # module Constructor
30
+
31
+ end # module Unified2
@@ -0,0 +1,17 @@
1
+ module Unified2
2
+
3
+ module Constructor
4
+ #
5
+ # Unified2 Header
6
+ #
7
+ class RecordHeader < ::BinData::Record
8
+ endian :big
9
+
10
+ uint32 :u2type
11
+ uint32 :u2length
12
+
13
+ end # class RecordHeader
14
+
15
+ end # module Constructor
16
+
17
+ end # module Unified2
@@ -0,0 +1 @@
1
+ require 'unified2/constructor/construct'
@@ -1,8 +1,16 @@
1
+ #
2
+ # String monkeypatches
3
+ #
1
4
  class String
2
-
5
+ #
6
+ # Blank?
7
+ #
8
+ # @return [true, false] If the string
9
+ # is blank or empty return true.
10
+ #
3
11
  def blank?
4
12
  return true if (self.nil? || self == '')
5
13
  false
6
14
  end
7
15
 
8
- end
16
+ end # class String