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/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