ruby-stix2 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +7 -1
  3. data/README.md +49 -3
  4. data/lib/stix2/base.rb +7 -0
  5. data/lib/stix2/common.rb +80 -15
  6. data/lib/stix2/confidence_scale.rb +106 -0
  7. data/lib/stix2/custom_object.rb +20 -0
  8. data/lib/stix2/cyberobservable_objects/email_message.rb +1 -1
  9. data/lib/stix2/cyberobservable_objects/network_traffic.rb +1 -1
  10. data/lib/stix2/cyberobservable_objects/process.rb +17 -0
  11. data/lib/stix2/cyberobservable_objects/user_account.rb +4 -4
  12. data/lib/stix2/cyberobservable_objects/x509_certificate.rb +3 -1
  13. data/lib/stix2/domain_objects/malware.rb +1 -1
  14. data/lib/stix2/enum.rb +59 -0
  15. data/lib/stix2/extension_definition.rb +10 -0
  16. data/lib/stix2/extensions/alternate_data_stream_type.rb +9 -0
  17. data/lib/stix2/extensions/archive_file.rb +8 -0
  18. data/lib/stix2/extensions/http_request.rb +12 -0
  19. data/lib/stix2/extensions/icmp.rb +8 -0
  20. data/lib/stix2/extensions/ntfs.rb +10 -0
  21. data/lib/stix2/extensions/pdf.rb +11 -0
  22. data/lib/stix2/extensions/raster_image.rb +10 -0
  23. data/lib/stix2/extensions/socket.rb +13 -0
  24. data/lib/stix2/extensions/tcp.rb +8 -0
  25. data/lib/stix2/extensions/unix_account.rb +10 -0
  26. data/lib/stix2/extensions/windows_pe_optional_header_type.rb +37 -0
  27. data/lib/stix2/extensions/windows_pe_section_type.rb +10 -0
  28. data/lib/stix2/extensions/windows_pebinary.rb +21 -0
  29. data/lib/stix2/extensions/windows_process.rb +13 -0
  30. data/lib/stix2/extensions/windows_service.rb +14 -0
  31. data/lib/stix2/external_reference.rb +1 -5
  32. data/lib/stix2/identifier.rb +2 -12
  33. data/lib/stix2/kill_chain_phase.rb +3 -7
  34. data/lib/stix2/languages.rb +236 -0
  35. data/lib/stix2/meta_objects/data_markings/base.rb +1 -4
  36. data/lib/stix2/meta_objects/data_markings/granular_marking.rb +1 -5
  37. data/lib/stix2/meta_objects/data_markings/object_marking.rb +2 -12
  38. data/lib/stix2/meta_objects/language_content.rb +1 -1
  39. data/lib/stix2/ov.rb +6 -0
  40. data/lib/stix2/relationship_objects/sighting.rb +1 -1
  41. data/lib/stix2/storage.rb +21 -15
  42. data/lib/stix2/version.rb +1 -1
  43. data/lib/stix2.rb +35 -7
  44. data/ruby-stix2.gemspec +9 -5
  45. metadata +40 -6
  46. data/lib/stix2/boolean.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 123ddb57694307c96be2fbdf9a9d9f8c9ac55fbbbf35dc7f71c196aadad728b6
4
- data.tar.gz: fff53b71f98c23069d7c3dd0da2a4ca3799f424a162f10629029361b0624800e
3
+ metadata.gz: f69ada6e1bf635fb01ca7cfed49ed184447e14e8b85c2b5ff14e1640d1f18738
4
+ data.tar.gz: 56712374f185dc57787679dd8060eb32320cbff393fada2d5285a924bc48b3a1
5
5
  SHA512:
6
- metadata.gz: e7aae57f5bf2b8415431df88dd2999ed85cfbf56f9f1634e750a0f00a53375c6dff96060ae96a4052eb2efca4471d38ac8244f1824f7f8f03df18ac883430517
7
- data.tar.gz: 63a3575a2886265784846dccb94fe8e32f300ca4c3c8006311f27acb19c0dc3a87c792b2aa4530c73b5ce5e1a2fd8064a2bcf50c051778dd743e7f4fa6831d2a
6
+ metadata.gz: cc04f1a76a4e79f2e57365201e1fdadaa4f29eecb1c61f2e4f7a4be4d9201b238ee36aac3f5c6bd094acc77ae2be8720b41d0e0a8a2b62a52279304c4fc8bb64
7
+ data.tar.gz: 852ae67a130e1a0338fd0d44af58746caab042d92b7b2bbd3c09c4edba2b0860eb0ff4a2c76a9346c802b8b7a47150e4bfae2b6039b31c082fed9f4da3b7e8ea
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-stix2 (0.1.0)
4
+ ruby-stix2 (0.1.1)
5
5
  hashie (~> 5.0.0)
6
6
 
7
7
  GEM
@@ -11,6 +11,9 @@ GEM
11
11
  coderay (1.1.3)
12
12
  docile (1.4.0)
13
13
  hashie (5.0.0)
14
+ io-console (0.6.0)
15
+ irb (1.7.0)
16
+ reline (>= 0.3.0)
14
17
  method_source (1.0.0)
15
18
  minitest (5.18.1)
16
19
  pry (0.13.1)
@@ -20,6 +23,8 @@ GEM
20
23
  byebug (~> 11.0)
21
24
  pry (>= 0.13, < 0.15)
22
25
  rake (13.0.6)
26
+ reline (0.3.5)
27
+ io-console (~> 0.5)
23
28
  simplecov (0.22.0)
24
29
  docile (~> 1.1)
25
30
  simplecov-html (~> 0.11)
@@ -32,6 +37,7 @@ PLATFORMS
32
37
 
33
38
  DEPENDENCIES
34
39
  bundler (~> 2.3)
40
+ irb (~> 1.7.0)
35
41
  minitest (~> 5.18.1)
36
42
  pry (~> 0.13.0)
37
43
  pry-byebug (~> 3.10.1)
data/README.md CHANGED
@@ -12,7 +12,7 @@ gem install ruby-stix2
12
12
  or as part of the bundle
13
13
 
14
14
  ```
15
- bundle add typhoeus
15
+ bundle add ruby-stix2
16
16
  ```
17
17
 
18
18
  # Usage
@@ -69,7 +69,7 @@ Stix2 message.
69
69
  # Storage
70
70
 
71
71
  The Stix2 standard has several object types, some of which are containers of other objects (like `Bundle`). However we
72
- may want to save and retrieve Stix2 objects in a fast way. The gem provides a `storage` support for that.
72
+ may want to save and retrieve Stix2 objects in a fast way. The gem provides a `Stix::Storage` support for that.
73
73
 
74
74
  For any Stix2 attribute that is an `identifier` (`Stix2::Identifier` in the gem) the class gives one more method called
75
75
  `_instance` to retrieve the actual instance. If we have a `threat-actor` like this
@@ -98,7 +98,7 @@ we know that this object has been created by an identity `identity--f431f809-377
98
98
  retrieve the other object if already seen
99
99
 
100
100
  ```ruby
101
- Stix2.storage_activate # Activate the storage
101
+ Stix2::Storage.activate # Activate the storage
102
102
 
103
103
  identity = Stix2::DomainObject::Identity.new(id: 'identity--f431f809-377b-45e0-aa1c-6a4751cae5ff', ...)
104
104
  threat_actor = Stix2::DomainObject::ThreatActor.new(created_by_ref: 'identity--f431f809-377b-45e0-aa1c-6a4751cae5ff', ...)
@@ -107,6 +107,48 @@ threat_actor.created_by_ref # this gives the identifier => identity--f431f809-37
107
107
  threat_actor.created_by_ref_instance # this gives the actual object => Stix2::DomainObject::Identity
108
108
  ```
109
109
 
110
+ # Spec versions
111
+
112
+ This gem implements the spec version `2.1`. However older version (especially 2.0) can be compatible. To force the gem
113
+ to accept another spec version, just add them to the `SPEC_VERSIONS` variable.
114
+
115
+ ```ruby
116
+ Stix2::SPEC_VERSIONS << '2.0'
117
+ ```
118
+
119
+ # Custom Definitions
120
+
121
+ The Stix2 standard includes several extensions to base objects. All extensions are widely described in the standard
122
+ itself, please refer to it. However two of them need more attention for how they are implemented in this gem.
123
+
124
+ ## Extension Definition
125
+
126
+ This object allows the definition of new properties. One special property is `toplevel-property-extension` that allows
127
+ the definition of properties on the top-level of an object. According to the standard thos properties should be
128
+ defined solely on the object that is actually using the property. However due to the `hashie`-based implementation
129
+ the gem declares the new properties on the class itself. This is a known limitation of the current implementation and
130
+ it may be fixed in the future.
131
+
132
+ ## Custom Object
133
+
134
+ A `CustomObject` can also be used within the Gem. The standard defines the rules that must be fulfilled for a custom
135
+ object. Since those rules are several, the code stacks all the errors altogether and raises an exception when some
136
+ errors happen. The exception is RuntimeError, that gives the user a string. It is suboptimal to have multiple errors
137
+ in a string, and it may be fixed in the future.
138
+
139
+ # Confidence
140
+
141
+ A Stix2 object can have the property `confidence` set. This value can be expressed according to several conficence
142
+ scales. To make this conversion smooth, an object offers the method `confidence_scale` that is an instance of
143
+ `Stix2::ConfidenceScale`. This class offers method for all the scales the standard includes.
144
+
145
+ ```ruby
146
+ indicator = Stix2::DomainObject::Indicator.new(confidence: i)
147
+ indicator.confidence # This is the raw integer
148
+ indicator.confidence_scale.to_admiralty_credibility # this is a string in this scale
149
+ indicator.confidence_scale.to_admiralty_credibility_strix # this is a string in stix mode
150
+ ```
151
+
110
152
  # Contribution
111
153
 
112
154
  You can contribute to this project in 2 ways:
@@ -114,3 +156,7 @@ You can contribute to this project in 2 ways:
114
156
  - with a PR: just follow the standard github workflow
115
157
  - by pointing out missing support: open an issue and please provide a json containing the missing support, to simplify
116
158
  the development
159
+
160
+ # See also
161
+
162
+ Ruby Stix2: https://github.com/crondaemon/ruby-taxii2
data/lib/stix2/base.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Stix2
2
+ class Base < Hashie::Dash
3
+ include Hashie::Extensions::Dash::PredefinedValues
4
+ include Hashie::Extensions::IndifferentAccess
5
+ include Hashie::Extensions::Dash::Coercion
6
+ end
7
+ end
data/lib/stix2/common.rb CHANGED
@@ -1,44 +1,55 @@
1
1
  module Stix2
2
- class Common < Hashie::Dash
3
- include Hashie::Extensions::Dash::PredefinedValues
4
- include Hashie::Extensions::IndifferentAccess
5
- include Hashie::Extensions::Dash::Coercion
2
+ SPEC_VERSIONS = ['2.1']
6
3
 
4
+ class Common < Stix2::Base
7
5
  property :type, required: true, coerce: String
8
- property :spec_version, coerce: String, values: ['2.1']
6
+ property :spec_version, coerce: String, values: Stix2::SPEC_VERSIONS
9
7
  property :id, coerce: Identifier
10
8
  property :created_by_ref, coerce: Identifier
11
9
  property :created, coerce: Time
12
10
  property :modified, coerce: Time
13
- property :revoked, coerce: Stix2::Boolean
11
+ property :revoked, coerce: ->(value){ Stix2.to_bool(value) }
14
12
  property :labels, coerce: Array[String]
15
- property :confidence, coerce: Integer
13
+ property :confidence, coerce: ->(value){ int = Integer(value) ; [0..100].include?(int) ; int }
16
14
  property :lang, coerce: String
17
15
  property :external_references, coerce: Array[ExternalReference]
18
16
  property :object_marking_refs, coerce: Array[Stix2::MetaObject::DataMarking::ObjectMarking]
19
17
  property :granular_markings, coerce: Array[MetaObject::DataMarking::GranularMarking]
20
- property :defanged, coerce: Stix2::Boolean
18
+ property :defanged, coerce: ->(value){ Stix2.to_bool(value) }
21
19
  property :extensions, coerce: Hash
22
20
 
23
21
  def initialize(options = {})
24
22
  Hashie.symbolize_keys!(options)
25
23
  type = to_dash(self.class.name.split('::').last)
26
24
  if options[:type]
27
- raise("Property 'type' must be '#{type}'") if options[:type] != type
25
+ if !options[:type].start_with?('x-') && options[:type] != type
26
+ raise("Property 'type' must be '#{type}'")
27
+ end
28
28
  else
29
29
  options[:type] = type
30
30
  end
31
+ process_toplevel_property_extension(options[:extensions])
31
32
  super(options)
32
- Stix2.storage_add(self)
33
+ process_extensions(options)
34
+ Stix2::Storage.add(self)
33
35
  end
34
36
 
35
37
  def method_missing(m, *args, &block)
36
- super(m, args, block) if !m.to_s.end_with?('_instance')
38
+ if !m.to_s.end_with?('_instance')
39
+ # :nocov:
40
+ super(m, args, block)
41
+ return
42
+ # :nocov:
43
+ end
37
44
  # Retrieve the original method
38
45
  ref_method = m.to_s.gsub(/_instance$/, '')
39
46
  obj = send(ref_method)
40
47
  raise("Can't get a Stix2::Identifier from #{ref_method}") if !obj.is_a?(Stix2::Identifier)
41
- Stix2.storage_find(obj)
48
+ Stix2::Storage.find(obj)
49
+ end
50
+
51
+ def confidence_scale
52
+ Stix2::ConfidenceScale.new(confidence)
42
53
  end
43
54
 
44
55
  private
@@ -48,15 +59,69 @@ module Stix2
48
59
  end
49
60
 
50
61
  def self.validate_array(list, valid_values)
51
- excess = (Array(list) - valid_values)
62
+ excess = (Array(list).map(&:to_s) - valid_values.map(&:to_s))
52
63
  excess.empty? || raise("Invalid values: #{excess}")
53
64
  list
54
65
  end
55
66
 
56
67
  def self.hash_dict(hsh)
57
- invalids = hsh.keys.map(&:to_s) - HASH_ALGORITHM_OV
58
- invalids.empty? || raise("Invalid values: #{invalids}")
68
+ validate_array(hsh.keys, HASH_ALGORITHM_OV)
59
69
  hsh
60
70
  end
71
+
72
+ def process_toplevel_property_extension(extensions)
73
+ extension_definition = extensions&.find{ |key, val| key.to_s.start_with?('extension-definition') }
74
+ return if !extension_definition
75
+
76
+ id = extension_definition.first
77
+ type = extension_definition.last[:extension_type]
78
+ if type == 'toplevel-property-extension'
79
+ Stix2::Storage.active? || raise('Stix.storage must be active to use toplevel-property-extension')
80
+ ext = Stix2::Storage.find(id)
81
+ ext.extension_properties.each do |prop|
82
+ self.class.class_eval do
83
+ property prop
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ def process_extensions(options)
90
+ options[:extensions]&.each do |id, value|
91
+ case id.to_s
92
+ when /[A-Z]/
93
+ raise('Invalid extension name format.')
94
+ when 'archive-ext'
95
+ extensions[id] = Stix2::Extensions::ArchiveFile.new(value)
96
+ when /^extension-definition/
97
+ # Ignore it, already processes
98
+ when 'socket-ext'
99
+ extensions[id] = Stix2::Extensions::Socket.new(value)
100
+ when 'icmp-ext'
101
+ extensions[id] = Stix2::Extensions::Icmp.new(value)
102
+ when 'http-request-ext'
103
+ extensions[id] = Stix2::Extensions::HttpRequest.new(value)
104
+ when 'ntfs-ext'
105
+ extensions[id] = Stix2::Extensions::Ntfs.new(value)
106
+ when 'tcp-ext'
107
+ extensions[id] = Stix2::Extensions::Tcp.new(value)
108
+ when 'windows-process-ext'
109
+ extensions[id] = Stix2::Extensions::WindowsProcess.new(value)
110
+ when 'windows-service-ext'
111
+ extensions[id] = Stix2::Extensions::WindowsService.new(value)
112
+ when 'unix-account-ext'
113
+ extensions[id] = Stix2::Extensions::UnixAccount.new(value)
114
+ when 'pdf-ext'
115
+ extensions[id] = Stix2::Extensions::Pdf.new(value)
116
+ when 'raster-image-ext'
117
+ extensions[id] = Stix2::Extensions::RasterImage.new(value)
118
+ when 'windows-pebinary-ext'
119
+ extensions[id] = Stix2::Extensions::WindowsPebinary.new(value)
120
+ else
121
+ # Ensure we have a hash
122
+ value.is_a?(Hash) || raise("Custom extension must be Hash: #{value}")
123
+ end
124
+ end
125
+ end
61
126
  end
62
127
  end
@@ -0,0 +1,106 @@
1
+ module Stix2
2
+ class ConfidenceScale
3
+ SCALE_NONE_LOW_MED_HIGH = {
4
+ 0..0 => { scale: 'None', stix: 0 },
5
+ 1..29 => { scale: 'Low', stix: 15 },
6
+ 30..69 => { scale: 'Med', stix: 50 },
7
+ 70..100 => { scale: 'High', stix: 85 }
8
+ }.freeze
9
+
10
+ SCALE_0_10 = {
11
+ 0..4 => { scale: 0, stix: 0 },
12
+ 5..14 => { scale: 1, stix: 10 },
13
+ 15..24 => { scale: 2, stix: 20 },
14
+ 25..34 => { scale: 3, stix: 30 },
15
+ 35..44 => { scale: 4, stix: 40 },
16
+ 45..54 => { scale: 5, stix: 50 },
17
+ 55..64 => { scale: 6, stix: 60 },
18
+ 65..74 => { scale: 7, stix: 70 },
19
+ 75..84 => { scale: 8, stix: 80 },
20
+ 85..94 => { scale: 9, stix: 90 },
21
+ 95..100 => { scale: 10, stix: 100 }
22
+ }.freeze
23
+
24
+ SCALE_ADMIRALTY_CREDIBILITY = {
25
+ 0..19 => { scale: 5, stix: 10 },
26
+ 20..39 => { scale: 4, stix: 30 },
27
+ 40..59 => { scale: 3, stix: 50 },
28
+ 60..79 => { scale: 2, stix: 70 },
29
+ 80..100 => { scale: 1, stix: 90 }
30
+ }.freeze
31
+
32
+ SCALE_WEP = {
33
+ 0..0 => { scale: 'Impossible', stix: 0 },
34
+ 1..19 => { scale: 'Highly Unlikely/Almost Certainly Not', stix: 10 },
35
+ 20..39 => { scale: 'Unlikely/Probably Not', stix: 30 },
36
+ 40..59 => { scale: 'Even Chance', stix: 50 },
37
+ 60..79 => { scale: 'Likely/Probable', stix: 70 },
38
+ 80..99 => { scale: 'Highly likely/Almost Certain', stix: 90 },
39
+ 100..100 => { scale: 'Certain', stix: 100 }
40
+ }.freeze
41
+
42
+ SCALE_DNI = {
43
+ 0..9 => { scale: 'Almost No Chance / Remote' , stix: 5 },
44
+ 10..19 => { scale: 'Very Unlikely / Highly Improbable', stix: 15 },
45
+ 20..39 => { scale: 'Unlikely / Improbable', stix: 30 },
46
+ 40..59 => { scale: 'Roughly Even Chance / Roughly Even Odds', stix: 50 },
47
+ 60..79 => { scale: 'Likely / Probable', stix: 70 },
48
+ 80..89 => { scale: 'Very Likely / Highly Probable', stix: 85 },
49
+ 90..100 => { scale: 'Almost Certain / Nearly Certain', stix: 95 }
50
+ }.freeze
51
+
52
+ def initialize(value = nil)
53
+ @value = value
54
+ end
55
+
56
+ def to_none_low_med_high
57
+ !@value && 'Not Specified'
58
+ find_range(SCALE_NONE_LOW_MED_HIGH, :scale)
59
+ end
60
+
61
+ def to_none_low_med_high_stix
62
+ !@value && 'Not Specified'
63
+ find_range(SCALE_NONE_LOW_MED_HIGH, :stix)
64
+ end
65
+
66
+ def to_0_10
67
+ !@value && 6
68
+ find_range(SCALE_0_10, :scale)
69
+ end
70
+
71
+ def to_0_10_stix
72
+ find_range(SCALE_0_10, :stix)
73
+ end
74
+
75
+ def to_admiralty_credibility
76
+ find_range(SCALE_ADMIRALTY_CREDIBILITY, :scale)
77
+ end
78
+
79
+ def to_admiralty_credibility_stix
80
+ find_range(SCALE_ADMIRALTY_CREDIBILITY, :stix)
81
+ end
82
+
83
+ def to_wep
84
+ find_range(SCALE_WEP, :scale)
85
+ end
86
+
87
+ def to_wep_stix
88
+ find_range(SCALE_WEP, :stix)
89
+ end
90
+
91
+ def to_dni_scale
92
+ find_range(SCALE_DNI, :scale)
93
+ end
94
+
95
+ def to_dni_scale_stix
96
+ find_range(SCALE_DNI, :stix)
97
+ end
98
+
99
+ private
100
+
101
+ def find_range(constant, type)
102
+ !@value || 'Not Specified'
103
+ constant.find{ |k,v| k.cover?(@value) }.last[type]
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,20 @@
1
+ module Stix2
2
+ class CustomObject < Stix2::Common
3
+ include Hashie::Extensions::IgnoreUndeclared
4
+
5
+ property :id, coerce: Identifier
6
+
7
+ def initialize(options)
8
+ Hashie.symbolize_keys!(options)
9
+ raise('A CustomObject must have at least one property') if options[:type] && options.count == 1
10
+ errors = Hash.new{ |k, v| k[v] = [] }
11
+ options.each do |key, value|
12
+ errors['Too short'] << key if key != :id && key.size < 3
13
+ errors['Invalid name'] << key if !key.match?(/^[a-z0-9_]*$/)
14
+ errors['Too long'] << key if key.size > 250
15
+ end
16
+ raise("Error creating CustomObject: #{errors}") if !errors.empty?
17
+ super(options)
18
+ end
19
+ end
20
+ end
@@ -1,7 +1,7 @@
1
1
  module Stix2
2
2
  module CyberobservableObject
3
3
  class EmailMessage < Base
4
- property :is_multipart, required: true, coerce: Stix2::Boolean
4
+ property :is_multipart, required: true, coerce: ->(value){ Stix2.to_bool(value) }
5
5
  property :date, coerce: Time
6
6
  property :content_type, coerce: String
7
7
  property :from_ref, coerce: Identifier
@@ -3,7 +3,7 @@ module Stix2
3
3
  class NetworkTraffic < Base
4
4
  property :start, coerce: Time
5
5
  property :end, coerce: Time
6
- property :is_active, coerce: ->(v){ boolean(v) }
6
+ property :is_active, coerce: ->(v){ Stix2.to_bool(v) }
7
7
  property :src_ref, coerce: Identifier
8
8
  property :dst_ref, coerce: Identifier
9
9
  property :src_port, coerce: Integer
@@ -0,0 +1,17 @@
1
+ module Stix2
2
+ module CyberobservableObject
3
+ class Process < Base
4
+ property :is_hidden, coerce: ->(value){ Stix2.to_bool(value) }
5
+ property :pid, coerce: Integer
6
+ property :created_time, coerce: Time
7
+ property :cwd, coerce: String
8
+ property :command_line, coerce: String
9
+ property :environment_variables, coerce: Hash
10
+ property :opened_connection_refs, coerce: Array[Identifier]
11
+ property :creator_user_ref, coerce: Identifier
12
+ property :image_ref, coerce: Identifier
13
+ property :parent_ref, coerce: Identifier
14
+ property :child_refs, coerce: Array[Identifier]
15
+ end
16
+ end
17
+ end
@@ -6,10 +6,10 @@ module Stix2
6
6
  property :account_login, coerce: String
7
7
  property :account_type, values: ACCOUNT_TYPE_OV
8
8
  property :display_name, coerce: String
9
- property :is_service_account, coerce: Stix2::Boolean
10
- property :is_privileged, coerce: Stix2::Boolean
11
- property :can_escalate_privs, coerce: Stix2::Boolean
12
- property :is_disabled, coerce: Stix2::Boolean
9
+ property :is_service_account, coerce: ->(value){ Stix2.to_bool(value) }
10
+ property :is_privileged, coerce: ->(value){ Stix2.to_bool(value) }
11
+ property :can_escalate_privs, coerce: ->(value){ Stix2.to_bool(value) }
12
+ property :is_disabled, coerce: ->(value){ Stix2.to_bool(value) }
13
13
  property :account_created, coerce: Time
14
14
  property :account_expires, coerce: Time
15
15
  property :credential_last_changed, coerce: Time
@@ -1,7 +1,9 @@
1
+ require 'stix2/cyberobservable_objects/x509_v3_extension_type'
2
+
1
3
  module Stix2
2
4
  module CyberobservableObject
3
5
  class X509Certificate < Base
4
- property :is_self_signed, coerce: ->(v){ boolean(v) }
6
+ property :is_self_signed, coerce: ->(v){ Stix2.to_bool(v) }
5
7
  property :hashes, coerce: ->(hsh){ hash_dict(hsh) }
6
8
  property :version, coerce: String
7
9
  property :serial_number, coerce: String
@@ -4,7 +4,7 @@ module Stix2
4
4
  property :name, coerce: String
5
5
  property :description, coerce: String
6
6
  property :malware_types, coerce: ->(v){ validate_array(v, Stix2::MALWARE_TYPE_OV) }
7
- property :is_family, coerce: ->(v){ is_boolean?(v) }
7
+ property :is_family, coerce: ->(v){ Stix2.to_bool(v) }
8
8
  property :aliases, coerce: Array[String]
9
9
  property :kill_chain_phases, coerce: Array[KillChainPhase]
10
10
  property :first_seen, coerce: Time
data/lib/stix2/enum.rb CHANGED
@@ -29,4 +29,63 @@ module Stix2
29
29
  'REG_QWORD',
30
30
  'REG_INVALID_TYPE'
31
31
  ].freeze
32
+
33
+ EXTENSION_TYPE_ENUM = [
34
+ 'new-sdo',
35
+ 'new-sco',
36
+ 'new-sro',
37
+ 'property-extension',
38
+ 'toplevel-property-extension'
39
+ ].freeze
40
+
41
+ NETWORK_SOCKET_ADDRESS_FAMILY_ENUM = [
42
+ 'AF_UNSPEC',
43
+ 'AF_INET',
44
+ 'AF_IPX',
45
+ 'AF_APPLETALK',
46
+ 'AF_NETBIOS',
47
+ 'AF_INET6',
48
+ 'AF_IRDA',
49
+ 'AF_BTH'
50
+ ].freeze
51
+
52
+ NETWORK_SOCKET_TYPE_ENUM = [
53
+ 'SOCK_STREAM',
54
+ 'AF_ISOCK_DGRAMNET',
55
+ 'SOCK_RAW',
56
+ 'SOCK_RDM',
57
+ 'SOCK_SEQPACKET'
58
+ ].freeze
59
+
60
+ WINDOWS_INTEGRITY_LEVEL_ENUM = [
61
+ 'low',
62
+ 'medium',
63
+ 'high',
64
+ 'system'
65
+ ].freeze
66
+
67
+ WINDOWS_SERVICE_START_TYPE_ENUM = [
68
+ 'SERVICE_AUTO_START',
69
+ 'SERVICE_BOOT_START',
70
+ 'SERVICE_DEMAND_START',
71
+ 'SERVICE_DISABLED',
72
+ 'SERVICE_SYSTEM_ALERT'
73
+ ].freeze
74
+
75
+ WINDOWS_SERVICE_TYPE_ENUM = [
76
+ 'SERVICE_KERNEL_DRIVER',
77
+ 'SERVICE_FILE_SYSTEM_DRIVER',
78
+ 'SERVICE_WIN32_OWN_PROCESS',
79
+ 'SERVICE_WIN32_SHARE_PROCESS'
80
+ ].freeze
81
+
82
+ WINDOWS_SERVICE_STATUS_ENUM = [
83
+ 'SERVICE_CONTINUE_PENDING',
84
+ 'SERVICE_PAUSE_PENDING',
85
+ 'SERVICE_PAUSED',
86
+ 'SERVICE_RUNNING',
87
+ 'SERVICE_START_PENDING',
88
+ 'SERVICE_STOP_PENDING',
89
+ 'SERVICE_STOPPED'
90
+ ].freeze
32
91
  end
@@ -0,0 +1,10 @@
1
+ module Stix2
2
+ class ExtensionDefinition < Stix2::Common
3
+ property :name, required: true, coerce: String
4
+ property :description, coerce: String
5
+ property :schema, required: true, coerce: String
6
+ property :version, required: true, coerce: String
7
+ property :extension_types, required: true, coerce: ->(values){ validate_array(values, EXTENSION_TYPE_ENUM) }
8
+ property :extension_properties, coerce: Array[String]
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Stix2
2
+ module Extensions
3
+ class AlternateDataStreamType < Stix2::Base
4
+ property :name, required: true, coerce: String
5
+ property :hashes, coerce: ->(hsh){ hash_dict(hsh) }
6
+ property :size, coerce: Integer
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Stix2
2
+ module Extensions
3
+ class ArchiveFile < Stix2::Base
4
+ property :contains_refs, required: true, coerce: Array[Identifier]
5
+ property :comment, coerce: String
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ module Stix2
2
+ module Extensions
3
+ class HttpRequest < Stix2::Base
4
+ property :request_method, required: true, coerce: String
5
+ property :request_value, required: true, coerce: String
6
+ property :request_version, coerce: String
7
+ property :request_header, coerce: Hash
8
+ property :message_body_length, coerce: Integer
9
+ property :message_body_data_ref, coerce: Identifier
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Stix2
2
+ module Extensions
3
+ class Icmp < Stix2::Base
4
+ property :icmp_type_hex, required: true, coerce: ->(value){ Stix2.is_hex?(value) && value }
5
+ property :icmp_code_hex, required: true, coerce: ->(value){ Stix2.is_hex?(value) && value }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'stix2/extensions/alternate_data_stream_type'
2
+
3
+ module Stix2
4
+ module Extensions
5
+ class Ntfs < Stix2::Base
6
+ property :sid, coerce: String
7
+ property :alternate_data_streams, coerce: Array[AlternateDataStreamType]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Stix2
2
+ module Extensions
3
+ class Pdf < Stix2::Base
4
+ property :version, coerce: String
5
+ property :is_optimized, coerce: ->(value){ Stix2.to_bool(value) }
6
+ property :document_info_dict, Hash[String => String]
7
+ property :pdfid0, coerce: String
8
+ property :pdfid1, coerce: String
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Stix2
2
+ module Extensions
3
+ class RasterImage < Stix2::Base
4
+ property :image_height, coerce: Integer
5
+ property :image_width, coerce: Integer
6
+ property :bits_per_pixel, coerce: Integer
7
+ property :exif_tags, coerce: Hash
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Stix2
2
+ module Extensions
3
+ class Socket < Stix2::Base
4
+ property :address_family, required: true, values: NETWORK_SOCKET_ADDRESS_FAMILY_ENUM
5
+ property :is_blocking, coerce: ->(value){ Stix2.to_bool(value) }
6
+ property :is_listening, coerce: ->(value){ Stix2.to_bool(value) }
7
+ property :options, coerce: ->(hsh){ hsh.keys.all?{ |k| k.is_a?(Integer) } && hsh }
8
+ property :socket_type, values: NETWORK_SOCKET_TYPE_ENUM
9
+ property :socket_descriptor, coerce: Integer
10
+ property :socket_handle, coerce: Integer
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module Stix2
2
+ module Extensions
3
+ class Tcp < Stix2::Base
4
+ property :src_flags_hex, coerce: ->(value) { Stix2.is_hex?(value) && value }
5
+ property :dst_flags_hex, coerce: ->(value) { Stix2.is_hex?(value) && value }
6
+ end
7
+ end
8
+ end