unified2 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/example/unified2 ADDED
Binary file
data/gemspec.yml ADDED
@@ -0,0 +1,14 @@
1
+ name: unified2
2
+ summary: "A ruby interface for unified2 output."
3
+ description: "A ruby interface for unified2 output. rUnified2 allows you to manipulate unified2 output for custom storage and/or analysis."
4
+ license: MIT
5
+ authors: Dustin Willis Webber
6
+ email: dustin.webber@gmail.com
7
+ homepage: https://github.com/mephux/unified2
8
+
9
+ development_dependencies:
10
+ bindata: ~> 1.3.1
11
+ hexdump: ~> 0.1.0
12
+ ore-tasks: ~> 0.4
13
+ rspec: ~> 2.4
14
+ yard: ~> 0.6.0
@@ -0,0 +1,14 @@
1
+ module Unified2
2
+ class Classification
3
+
4
+ attr_accessor :id, :name, :short, :priority
5
+
6
+ def initialize(classification={})
7
+ @id = classification[:classification_id]
8
+ @name = classification[:name]
9
+ @short = classification[:short]
10
+ @priority = classification[:priority]
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,54 @@
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
@@ -0,0 +1,8 @@
1
+ class String
2
+
3
+ def blank?
4
+ return true if (self.nil? || self == '')
5
+ false
6
+ end
7
+
8
+ end
@@ -0,0 +1 @@
1
+ require 'unified2/core_ext/string'
@@ -0,0 +1,315 @@
1
+ require 'ipaddr'
2
+ require 'json'
3
+ require 'unified2/classification'
4
+ require 'unified2/payload'
5
+ require 'unified2/sensor'
6
+ require 'unified2/signature'
7
+
8
+ module Unified2
9
+
10
+ class Event
11
+
12
+ attr_accessor :id, :metadata, :packet
13
+
14
+ def initialize(id)
15
+ @id = id
16
+ end
17
+
18
+ def packet_time
19
+ if @packet.has_key?(:packet_second)
20
+ @packet[:packet_second]
21
+ @timestamp = Time.at(@packet[:packet_second].to_i)
22
+ end
23
+ end
24
+
25
+ def event_time
26
+ if @packet.has_key?(:event_second)
27
+ @timestamp = Time.at(@packet[:event_second].to_i)
28
+ end
29
+ end
30
+ alias :timestamp :event_time
31
+
32
+ def microseconds
33
+ if @metadata.has_key?(:event_microsecond)
34
+ @microseconds = @metadata[:event_microsecond]
35
+ end
36
+ end
37
+
38
+ def sensor
39
+ @sensor ||= Unified2.sensor
40
+ end
41
+
42
+ def packet_action
43
+ if @metadata.has_key?(:event_second)
44
+ @packet_action = @metadata[:packet_action]
45
+ end
46
+ end
47
+
48
+ def protocol
49
+ if @metadata.has_key?(:protocol)
50
+ @protocol = determine_protocol(@metadata[:protocol])
51
+ end
52
+ end
53
+
54
+ def icmp?
55
+ return true if protocol == :ICMP
56
+ false
57
+ end
58
+
59
+ def tcp?
60
+ return true if protocol == :TCP
61
+ false
62
+ end
63
+
64
+ def udp?
65
+ return true if protocol == :UDP
66
+ false
67
+ end
68
+
69
+ def classification
70
+ if @metadata.is_a?(Hash)
71
+ @classification = Classification.new(@metadata[:classification]) if @metadata[:classification]
72
+ end
73
+ end
74
+
75
+ def signature
76
+ if @metadata.is_a?(Hash)
77
+ @signature = Signature.new(@metadata[:signature])
78
+ end
79
+ end
80
+
81
+ def generator_id
82
+ if @metadata.is_a?(Hash)
83
+ @metadata[:generator_id] if @metadata.has_key?(:generator_id)
84
+ end
85
+ end
86
+
87
+ def ip_source
88
+ if @metadata.is_a?(Hash)
89
+ @metadata[:ip_source] if @metadata.has_key?(:ip_source)
90
+ end
91
+ end
92
+ alias :source_ip :ip_source
93
+
94
+ # Add ICMP type
95
+ def source_port
96
+ return 0 if icmp?
97
+ @source_port = @metadata[:sport_itype] if @metadata.has_key?(:sport_itype)
98
+ end
99
+
100
+ def ip_destination
101
+ if @metadata.is_a?(Hash)
102
+ @metadata[:ip_destination] if @metadata.has_key?(:ip_destination)
103
+ end
104
+ end
105
+ alias :destination_ip :ip_destination
106
+
107
+ # Add ICMP code
108
+ def destination_port
109
+ return 0 if icmp?
110
+ @source_port = @metadata[:dport_icode] if @metadata.has_key?(:dport_icode)
111
+ end
112
+
113
+ def severity
114
+ @severity = @metadata[:priority_id] if @metadata.has_key?(:priority_id)
115
+ end
116
+
117
+ def payload
118
+ if @packet.is_a?(Hash)
119
+ Payload.new(@packet)
120
+ else
121
+ Payload.new
122
+ end
123
+ end
124
+
125
+ def load(event)
126
+ if event.data.respond_to?(:signature_id)
127
+ @metadata ||= build_event_metadata(event)
128
+ end
129
+
130
+ if event.data.respond_to?(:packet_data)
131
+ @packet ||= build_packet_metadata(event)
132
+ end
133
+ end
134
+
135
+ def to_h
136
+ if @metadata.is_a?(Hash)
137
+ if @packet.is_a?(Hash)
138
+ data = {}
139
+ data.merge!(@metadata)
140
+ data.merge!(@packet)
141
+ return data
142
+ end
143
+ else
144
+ if @packet.is_a?(Hash)
145
+ return @packet
146
+ end
147
+ end
148
+ end
149
+
150
+ def to_i
151
+ @id.to_i
152
+ end
153
+
154
+ def json
155
+ to_h.to_json
156
+ end
157
+
158
+ def to_s
159
+ data = %{
160
+ #############################################################################
161
+ Event ID: #{id}
162
+ Timestamp: #{timestamp}
163
+ Severity: #{severity}
164
+ Protocol: #{protocol}
165
+ Source IP: #{source_ip}:#{source_port}
166
+ Destination IP: #{destination_ip}:#{destination_port}
167
+ Signature: #{signature.name}
168
+ Payload:
169
+
170
+ }
171
+ if payload.blank?
172
+ data + '#############################################################################'
173
+ else
174
+ payload.dump(:width => 30, :output => data)
175
+ data + "#############################################################################"
176
+ end
177
+ end
178
+
179
+ private
180
+
181
+ def build_event_metadata(event)
182
+ @event_hash = {}
183
+
184
+ @event_hash = {
185
+ :ip_destination => event.data.ip_destination,
186
+ :priority_id => event.data.priority_id,
187
+ :signature_revision => event.data.signature_revision,
188
+ :event_id => event.data.event_id,
189
+ :protocol => event.data.protocol,
190
+ :sport_itype => event.data.sport_itype,
191
+ :event_second => event.data.event_second,
192
+ :packet_action => event.data.packet_action,
193
+ :dport_icode => event.data.dport_icode,
194
+ :sensor_id => event.data.sensor_id,
195
+ :generator_id => event.data.generator_id,
196
+ :ip_source => event.data.ip_source,
197
+ :event_microsecond => event.data.event_microsecond
198
+ }
199
+
200
+ build_classifications(event)
201
+
202
+ if event.data.generator_id.to_i == 1
203
+ build_signature(event)
204
+ else
205
+ build_generator(event)
206
+ end
207
+
208
+ @event_hash
209
+ end
210
+
211
+ def build_packet_metadata(event)
212
+ @packet_hash = {}
213
+ @packet_hash = {
214
+ :linktype => event.data.linktype,
215
+ :packet_microsecond => event.data.packet_microsecond,
216
+ :packet_second => event.data.packet_second,
217
+ :payload => event.data.packet_data,
218
+ :event_second => event.data.event_second,
219
+ :packet_length => event.data.packet_length
220
+ }
221
+
222
+ @packet_hash
223
+ end
224
+
225
+ def build_generator(event)
226
+ if Unified2.generators
227
+ if Unified2.generators.has_key?("#{event.data.generator_id}.#{event.data.signature_id}")
228
+ sig = Unified2.generators["#{event.data.generator_id}.#{event.data.signature_id}"]
229
+
230
+ @event_hash[:signature] = {
231
+ :signature_id => event.data.signature_id,
232
+ :revision => event.data.signature_revision,
233
+ :name => sig[:name],
234
+ :references => sig[:references],
235
+ :blank => false
236
+ }
237
+ end
238
+ end
239
+
240
+ unless @event_hash.has_key?(:signature)
241
+ @event_hash[:signature] = {
242
+ :signature_id => event.data.signature_id,
243
+ :revision => 0,
244
+ :name => "Unknown Signature #{event.data.signature_id}",
245
+ :references => [],
246
+ :blank => true
247
+ }
248
+ end
249
+ end
250
+
251
+ def build_signature(event)
252
+ if Unified2.signatures
253
+ if Unified2.signatures.has_key?(event.data.signature_id.to_s)
254
+ sig = Unified2.signatures[event.data.signature_id.to_s]
255
+
256
+ @event_hash[:signature] = {
257
+ :signature_id => event.data.signature_id,
258
+ :revision => event.data.signature_revision,
259
+ :name => sig[:name],
260
+ :references => sig[:references]
261
+ }
262
+ end
263
+ end
264
+
265
+ unless @event_hash.has_key?(:signature)
266
+ @event_hash[:signature] = {
267
+ :signature_id => event.data.signature_id,
268
+ :revision => 0,
269
+ :name => "Unknown Signature #{event.data.signature_id}",
270
+ :references => []
271
+ }
272
+ end
273
+ end
274
+
275
+ def build_classifications(event)
276
+ if Unified2.classifications
277
+ if Unified2.classifications.has_key?("#{event.data.classification_id}")
278
+ classification = Unified2.classifications["#{event.data.classification_id}"]
279
+
280
+ @event_hash[:classification] = {
281
+ :classification_id => event.data.classification_id,
282
+ :name => classification[:name],
283
+ :short => classification[:short],
284
+ :priority => classification[:priority]
285
+ }
286
+ end
287
+ end
288
+
289
+ unless @event_hash.has_key?(:classification)
290
+ @event_hash[:classification] = {
291
+ :classification_id => event.data.classification_id,
292
+ :name => 'Unknown',
293
+ :short => 'n/a',
294
+ :priority => 0
295
+ }
296
+ end
297
+ end
298
+
299
+ def determine_protocol(protocol)
300
+ case protocol.to_i
301
+ when 1
302
+ :ICMP # ICMP (Internet Control Message Protocol) packet type.
303
+ when 2
304
+ :IGMP # IGMP (Internet Group Message Protocol) packet type.
305
+ when 6
306
+ :TCP # TCP (Transmition Control Protocol) packet type.
307
+ when 17
308
+ :UDP # UDP (User Datagram Protocol) packet type.
309
+ else
310
+ :'N/A'
311
+ end
312
+ end
313
+
314
+ end
315
+ end
@@ -0,0 +1,26 @@
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
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,4 @@
1
+ module Unified2
2
+ class FileNotFound < StandardError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Unified2
2
+ class FileNotReadable < StandardError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Unified2
2
+ class UnknownLoadType < StandardError
3
+ end
4
+ end
@@ -0,0 +1,2 @@
1
+ require 'unified2/exceptions/file_not_found'
2
+ require 'unified2/exceptions/file_not_readable'
@@ -0,0 +1,16 @@
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
@@ -0,0 +1,32 @@
1
+ require 'hexdump'
2
+
3
+ module Unified2
4
+ class Payload
5
+
6
+ attr_accessor :linktype, :length
7
+
8
+ def initialize(payload={})
9
+ @payload = payload[:payload]
10
+ @length = payload[:packet_length].to_i
11
+ @linktype = payload[:linktype]
12
+ end
13
+
14
+ def blank?
15
+ return true unless @payload
16
+ false
17
+ end
18
+
19
+ def raw
20
+ @payload.to_s
21
+ end
22
+
23
+ def hex
24
+ @payload.to_s.unpack('H*')
25
+ end
26
+
27
+ def dump(options={})
28
+ Hexdump.dump(@payload, options)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,19 @@
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
@@ -0,0 +1 @@
1
+ require 'primitive/ipv4'
@@ -0,0 +1,10 @@
1
+ module Unified2
2
+
3
+ class RecordHeader < ::BinData::Record
4
+ endian :big
5
+
6
+ uint32 :u2type
7
+ uint32 :u2length
8
+ end
9
+
10
+ end
@@ -0,0 +1,26 @@
1
+ module Unified2
2
+ class Sensor
3
+
4
+ attr_accessor :id, :hostname,
5
+ :interface, :name
6
+
7
+ def initialize(options={})
8
+ @id = options[:id] || 0
9
+ @name = options[:name] || ""
10
+ @hostname ||= Socket.gethostname
11
+ @interface ||= options[:interface] || nil
12
+ end
13
+
14
+ def update(attributes={})
15
+ return self if attributes.empty?
16
+
17
+ attributes.each do |key, value|
18
+ next unless self.respond_to?(key.to_sym)
19
+ instance_variable_set(:"@#{key}", value)
20
+ end
21
+
22
+ self
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ module Unified2
2
+
3
+ class Signature
4
+
5
+ attr_accessor :id, :revision, :name, :references
6
+
7
+ def initialize(signature={})
8
+ @id = signature[:signature_id] || 0
9
+ @revision = signature[:revision]
10
+ @name = signature[:name].strip
11
+ @references = signature[:references]
12
+ @blank = signature[:blank]
13
+ end
14
+
15
+ def blank?
16
+ @blank
17
+ end
18
+
19
+ def references
20
+ @references
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ module Unified2
2
+ # unified2 version
3
+ VERSION = "0.1.1"
4
+ end