ruby-stix2 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -1
- data/README.md +49 -3
- data/lib/stix2/base.rb +7 -0
- data/lib/stix2/common.rb +80 -15
- data/lib/stix2/confidence_scale.rb +106 -0
- data/lib/stix2/custom_object.rb +20 -0
- data/lib/stix2/cyberobservable_objects/email_message.rb +1 -1
- data/lib/stix2/cyberobservable_objects/network_traffic.rb +1 -1
- data/lib/stix2/cyberobservable_objects/process.rb +17 -0
- data/lib/stix2/cyberobservable_objects/user_account.rb +4 -4
- data/lib/stix2/cyberobservable_objects/x509_certificate.rb +3 -1
- data/lib/stix2/domain_objects/malware.rb +1 -1
- data/lib/stix2/enum.rb +59 -0
- data/lib/stix2/extension_definition.rb +10 -0
- data/lib/stix2/extensions/alternate_data_stream_type.rb +9 -0
- data/lib/stix2/extensions/archive_file.rb +8 -0
- data/lib/stix2/extensions/http_request.rb +12 -0
- data/lib/stix2/extensions/icmp.rb +8 -0
- data/lib/stix2/extensions/ntfs.rb +10 -0
- data/lib/stix2/extensions/pdf.rb +11 -0
- data/lib/stix2/extensions/raster_image.rb +10 -0
- data/lib/stix2/extensions/socket.rb +13 -0
- data/lib/stix2/extensions/tcp.rb +8 -0
- data/lib/stix2/extensions/unix_account.rb +10 -0
- data/lib/stix2/extensions/windows_pe_optional_header_type.rb +37 -0
- data/lib/stix2/extensions/windows_pe_section_type.rb +10 -0
- data/lib/stix2/extensions/windows_pebinary.rb +21 -0
- data/lib/stix2/extensions/windows_process.rb +13 -0
- data/lib/stix2/extensions/windows_service.rb +14 -0
- data/lib/stix2/external_reference.rb +1 -5
- data/lib/stix2/identifier.rb +2 -12
- data/lib/stix2/kill_chain_phase.rb +3 -7
- data/lib/stix2/languages.rb +236 -0
- data/lib/stix2/meta_objects/data_markings/base.rb +1 -4
- data/lib/stix2/meta_objects/data_markings/granular_marking.rb +1 -5
- data/lib/stix2/meta_objects/data_markings/object_marking.rb +2 -12
- data/lib/stix2/meta_objects/language_content.rb +1 -1
- data/lib/stix2/ov.rb +6 -0
- data/lib/stix2/relationship_objects/sighting.rb +1 -1
- data/lib/stix2/storage.rb +21 -15
- data/lib/stix2/version.rb +1 -1
- data/lib/stix2.rb +35 -7
- data/ruby-stix2.gemspec +9 -5
- metadata +40 -6
- data/lib/stix2/boolean.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f69ada6e1bf635fb01ca7cfed49ed184447e14e8b85c2b5ff14e1640d1f18738
|
4
|
+
data.tar.gz: 56712374f185dc57787679dd8060eb32320cbff393fada2d5285a924bc48b3a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
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 `
|
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.
|
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
data/lib/stix2/common.rb
CHANGED
@@ -1,44 +1,55 @@
|
|
1
1
|
module Stix2
|
2
|
-
|
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:
|
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
|
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
|
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
|
-
|
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
|
-
|
33
|
+
process_extensions(options)
|
34
|
+
Stix2::Storage.add(self)
|
33
35
|
end
|
34
36
|
|
35
37
|
def method_missing(m, *args, &block)
|
36
|
-
|
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.
|
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
|
-
|
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
|
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){
|
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
|
10
|
-
property :is_privileged, coerce: Stix2
|
11
|
-
property :can_escalate_privs, coerce: Stix2
|
12
|
-
property :is_disabled, coerce: Stix2
|
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){
|
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){
|
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,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,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,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
|