unified2 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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/example/connect.rb DELETED
@@ -1,20 +0,0 @@
1
- require 'rubygems'
2
- require 'datamapper'
3
- require 'dm-mysql-adapter'
4
- require 'models'
5
-
6
- class Connect
7
-
8
- def self.setup
9
- @connection = DataMapper.setup(:default, {
10
- :adapter => "mysql",
11
- :host => "localhost",
12
- :database => "rUnified2",
13
- :username => "rUnified2",
14
- :password => "password"
15
- })
16
- DataMapper.finalize
17
- DataMapper.auto_upgrade!
18
- end
19
-
20
- end
data/example/models.rb DELETED
@@ -1,194 +0,0 @@
1
- class Event
2
- include DataMapper::Resource
3
- storage_names[:default] = "events"
4
-
5
- timestamps :created_at, :updated_at
6
-
7
- property :id, Serial, :index => true
8
-
9
- property :event_id, Integer, :index => true
10
-
11
- property :sensor_id, Integer, :index => true
12
-
13
- property :source_ip, String, :index => true
14
-
15
- property :source_port, Integer
16
-
17
- property :destination_ip, String, :index => true
18
-
19
- property :destination_port, Integer
20
-
21
- property :severity_id, Integer, :index => true
22
-
23
- property :classification_id, Integer, :index => true
24
-
25
- property :category_id, Integer, :index => true
26
-
27
- property :user_id, Integer, :index => true
28
-
29
- property :protocol, String, :index => true
30
-
31
- property :link_type, Integer
32
-
33
- property :packet_length, Integer
34
-
35
- property :packet, Text
36
-
37
- belongs_to :sensor
38
-
39
- belongs_to :classification
40
-
41
- belongs_to :signature
42
-
43
- validates_uniqueness_of :uid
44
-
45
- def update_sensor
46
- sensor.update(:last_event_id => self.event_id)
47
- sensor.save
48
- end
49
-
50
- end
51
-
52
- class Sensor
53
- include DataMapper::Resource
54
- timestamps :created_at, :updated_at
55
-
56
- property :id, Serial, :index => true
57
-
58
- property :hostname, Text, :index => true
59
-
60
- property :interface, String
61
-
62
- property :name, String, :index => true
63
-
64
- property :last_event_id, Integer, :index => true
65
-
66
- property :signatures_md5, String, :length => 32, :index => true
67
-
68
- property :generators_md5, String, :length => 32, :index => true
69
-
70
- property :classifications_md5, String, :length => 32, :index => true
71
-
72
- has n, :events
73
-
74
- validates_uniqueness_of :hostname, :name
75
-
76
- def events_count
77
- last_event_id
78
- end
79
-
80
- def self.find(object)
81
- name = object.name ? object.name : object.hostname
82
-
83
- sensor = first_or_create({:hostname => object.hostname, :interface => object.interface}, {
84
- :hostname => object.hostname,
85
- :interface => object.interface,
86
- :name => name,
87
- })
88
-
89
- sensor
90
- end
91
-
92
- end
93
-
94
- class Signature
95
- include DataMapper::Resource
96
- storage_names[:default] = "signatures"
97
-
98
- timestamps :created_at, :updated_at
99
-
100
- property :id, Serial, :index => true
101
-
102
- property :signature_id, Integer, :index => true
103
-
104
- property :generator_id, Integer, :index => true
105
-
106
- property :name, Text
107
-
108
- has n, :events
109
-
110
- validates_uniqueness_of :name
111
-
112
- def self.import(options={})
113
-
114
- if options.has_key?(:signatures)
115
-
116
- options[:signatures].each do |key, value|
117
- signature = Signature.get(:signature_id => key)
118
- next if signature && options[:force]
119
-
120
- if signature
121
- signature.update(value)
122
- else
123
- value.merge!(:signature_id => key, :generator_id => 1)
124
- Signature.create(value)
125
- end
126
-
127
- end
128
-
129
- end
130
-
131
- if options.has_key?(:generators)
132
-
133
- options[:generators].each do |key, value|
134
- genid, sid = key.split('.')
135
- signature = Signature.get(:signature_id => sid, :generator_id => genid)
136
- next if signature && options[:force]
137
-
138
- if signature
139
- signature.update(value)
140
- else
141
- value.merge!(:signature_id => sid, :generator_id => genid)
142
- Signature.create(value)
143
- end
144
-
145
- end
146
-
147
- end
148
-
149
- end
150
- end
151
-
152
- class Classification
153
- include DataMapper::Resource
154
-
155
- storage_names[:default] = "classifications"
156
-
157
- timestamps :created_at, :updated_at
158
-
159
- property :id, Serial, :index => true
160
-
161
- property :classification_id, Integer, :index => true
162
-
163
- property :name, Text
164
-
165
- property :short, String
166
-
167
- property :severity_id, Integer, :index => true
168
-
169
- has n, :events
170
-
171
- # belongs_to :severity
172
-
173
- validates_uniqueness_of :name, :classification_id
174
-
175
- def self.import(options={})
176
-
177
- if options.has_key?(:classifications)
178
-
179
- options[:classifications].each do |key,value|
180
- classification = Classification.get(:classification_id => key)
181
- next if classification && options[:force]
182
-
183
- if classification
184
- classification.update(value)
185
- else
186
- value.merge!(:classification_id => key)
187
- Classification.create(value)
188
- end
189
- end
190
-
191
- end
192
- end
193
-
194
- end
@@ -1,73 +0,0 @@
1
- $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- $:.unshift File.join(File.dirname(__FILE__), "..", "example")
3
-
4
- require 'unified2'
5
- require 'connect'
6
- require 'pp'
7
-
8
- # Initialize Database Connection
9
- Connect.setup
10
-
11
- # Unified2 Configuration
12
- Unified2.configuration do
13
-
14
- # Sensor Configurations
15
- sensor :interface => 'en1', :name => 'Example Sensor'
16
-
17
- # Load signatures, generators & classifications into memory
18
- load :signatures, 'seeds/sid-msg.map'
19
- load :generators, 'seeds/gen-msg.map'
20
- load :classifications, 'seeds/classification.config'
21
- end
22
-
23
- # Locate the sensor in the database using
24
- # the hostname and interface. If this fails
25
- # rUnified2 will create a new sensor record.
26
- sensor = Sensor.find(Unified2.sensor)
27
- Unified2.sensor.id = sensor.id
28
-
29
- # Load the classifications, generators &
30
- # signatures into the database and store the
31
- # md5 in the sensor record. This will only
32
- # update if the md5s DO NOT match.
33
- [[Classification,:classifications], [Signature, :signatures], [Signature, :generators]].each do |klass, method|
34
- unless sensor.send(:"#{method}_md5") == Unified2.send(method).send(:md5)
35
- klass.send(:import, { method => Unified2.send(method).send(:data), :force => true })
36
- sensor.update(:"#{method}_md5" => Unified2.send(method).send(:md5))
37
- end
38
- end
39
-
40
- # Monitor the unfied2 log and process the data.
41
- # The second argument is the last event processed by
42
- # the sensor. If the last_event_id column is blank in the
43
- # sensor table it will begin at the first available event.
44
- Unified2.watch('seeds/unified2', sensor ? sensor.last_event_id + 1 : :first) do |event|
45
- next if event.signature.blank?
46
-
47
- puts event
48
-
49
- insert_event = Event.new({
50
- :event_id => event.id,
51
- :checksum => event.checksum,
52
- :created_at => event.timestamp,
53
- :sensor_id => event.sensor.id,
54
- :source_ip => event.source_ip,
55
- :source_port => event.source_port,
56
- :destination_ip => event.destination_ip,
57
- :destination_port => event.destination_port,
58
- :severity_id => event.severity,
59
- :protocol => event.protocol,
60
- :link_type => event.payload.linktype,
61
- :packet_length => event.payload.length,
62
- :packet => event.payload.hex,
63
- :classification_id => event.classification.id,
64
- :signature_id => event.signature.id
65
- })
66
-
67
- if insert_event.save
68
- insert_event.update_sensor
69
- else
70
- STDERR.puts "VALIDATION ERROR OR RECORD ALREADY EXISTS #{insert_event.errors}"
71
- end
72
-
73
- end
data/example/search.rb DELETED
@@ -1,14 +0,0 @@
1
- $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
- $:.unshift File.join(File.dirname(__FILE__), "..", "example")
3
-
4
- require 'unified2'
5
- require 'connect'
6
- require 'pp'
7
-
8
- Connect.setup
9
-
10
- @sensor = Sensor.first
11
-
12
- @sensor.events.each do |event|
13
- puts event.signature.name
14
- end
data/example/untitled.rb DELETED
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # http://192.168.1.254/xslt?PAGE=A06&THISPAGE=&NEXTPAGE=A06
4
-
5
- @file = File.open('/Users/mephux/Source/passwords/wpa.txt')
6
-
7
- require 'rubygems'
8
- require 'mechanize'
9
-
10
- a = Mechanize.new
11
-
12
- a.get('http://192.168.1.254/xslt?PAGE=A06&THISPAGE=&NEXTPAGE=A06') do |page|
13
-
14
- @file.each_line do |password|
15
- next unless password[/^e/]
16
-
17
- puts password
18
- login_form = page.form_with(:action => '/xslt', :method => 'POST')
19
- login_form['PASSWORD'] = password
20
- page = a.submit login_form
21
-
22
- if page.body =~ /The password is incorrect./
23
- puts 'FAIL'
24
- else
25
- puts 'W0ots'
26
- puts password
27
- exit -1
28
- end
29
- end
30
-
31
- end
@@ -1,54 +0,0 @@
1
- require 'unified2/event_ip4'
2
- require 'unified2/event_ip6'
3
- require 'unified2/record_header'
4
- require 'unified2/packet'
5
-
6
- module Unified2
7
-
8
- class Construct < ::BinData::Record
9
- record_header :header
10
-
11
- choice :data, :selection => :type_selection do
12
- packet "packet"
13
- event_ip4 "ev4"
14
- event_ip6 "ev6"
15
- end
16
-
17
- # padding
18
- string :read_length => :padding_length
19
-
20
- def type_selection
21
- case header.u2type.to_i
22
- when 1
23
- # define UNIFIED2_EVENT 1
24
- when 2
25
- # define UNIFIED2_PACKET 2
26
- "packet"
27
- when 7
28
- # define UNIFIED2_IDS_EVENT 7
29
- "ev4"
30
- when 66
31
- # define UNIFIED2_EVENT_EXTENDED 66
32
- when 67
33
- # define UNIFIED2_PERFORMANCE 67
34
- when 68
35
- # define UNIFIED2_PORTSCAN 68
36
- when 72
37
- # define UNIFIED2_IDS_EVENT_IPV6 72
38
- "ev6"
39
- else
40
- "unknown type #{header.u2type}"
41
- end
42
- end
43
-
44
- # sometimes the data needs extra padding
45
- def padding_length
46
- if header.u2length > data.num_bytes
47
- header.u2length - data.num_bytes
48
- else
49
- 0
50
- end
51
- end
52
- end
53
-
54
- end
@@ -1,26 +0,0 @@
1
- require 'unified2/primitive/ipv4'
2
-
3
- module Unified2
4
-
5
- class EventIP4 < ::BinData::Record
6
-
7
- endian :big
8
-
9
- uint32 :sensor_id
10
- uint32 :event_id
11
- uint32 :event_second
12
- uint32 :event_microsecond
13
- uint32 :signature_id
14
- uint32 :generator_id
15
- uint32 :signature_revision
16
- uint32 :classification_id
17
- uint32 :priority_id
18
- ipv4 :ip_source
19
- ipv4 :ip_destination
20
- uint16 :sport_itype
21
- uint16 :dport_icode
22
- uint8 :protocol
23
- uint8 :packet_action
24
- end
25
-
26
- end
@@ -1,23 +0,0 @@
1
- module Unified2
2
-
3
- class EventIP6 < ::BinData::Record
4
- endian :big
5
-
6
- uint32 :sensor_id
7
- uint32 :event_id
8
- uint32 :event_second
9
- uint32 :event_microsecond
10
- uint32 :signature_id
11
- uint32 :generator_id
12
- uint32 :signature_revision
13
- uint32 :classification_id
14
- uint32 :priority_id
15
- uint128 :ip_source
16
- uint128 :ip_destination
17
- uint16 :sport_itype
18
- uint16 :dport_icode
19
- uint8 :protocol
20
- uint8 :packet_action
21
- end
22
-
23
- end
@@ -1,16 +0,0 @@
1
- module Unified2
2
-
3
- class Packet < ::BinData::Record
4
- endian :big
5
-
6
- uint32 :sensor_id
7
- uint32 :event_id
8
- uint32 :event_second
9
- uint32 :packet_second
10
- uint32 :packet_microsecond
11
- uint32 :linktype
12
- uint32 :packet_length
13
- string :packet_data, :read_length => :packet_length
14
- end
15
-
16
- end
@@ -1,19 +0,0 @@
1
- module Unified2
2
- module Primitive
3
-
4
- class IPV4 < ::BinData::Primitive
5
- array :octets, :type => :uint8, :initial_length => 4
6
-
7
- def set(val)
8
- ints = val.split(/\./).collect { |int| int.to_i }
9
- self.octets = ints
10
- end
11
-
12
- def get
13
- self.octets.collect { |octet| "%d" % octet }.join(".")
14
- end
15
-
16
- end
17
-
18
- end
19
- end
@@ -1,10 +0,0 @@
1
- module Unified2
2
-
3
- class RecordHeader < ::BinData::Record
4
- endian :big
5
-
6
- uint32 :u2type
7
- uint32 :u2length
8
- end
9
-
10
- end