ruby-stix2
Ruby implementation for the STIX protocol version 2
Installation
Install the gem as standalone
gem install ruby-stix2
or as part of the bundle
bundle add typhoeus
Usage
The gem implements the Stix2 v2.1 specifications: https://docs.oasis-open.org/cti/stix/v2.1/stix-v2.1.html. Every object is under the Stix2 namespace, and under a more specific namespace.
Example
Stix2::DomainObject::Indicator.new(
type: 'indicator',
id: 'file--1389b98d-a3d3-5190-a996-716fd444059a',
description: 'description',
indicator_types: ['anomalous-activity', 'anonymization'],
pattern: 'pattern',
pattern_type: 'yara',
pattern_version: 1,
valid_from: Time.now,
valid_until: Time.now,
kill_chain_phases: [
{
kill_chain_name: "lockheed-martin-cyber-kill-chain",
phase_name: "reconnaissance"
},
{
kill_chain_name: "foo",
phase_name: "pre-attack"
}
]
)
The real objects can be created just starting from properties. However a Stix2.parse complimentary function is provided. This function gives the user few advantages, listed below.
Parse input
The function accept a Hash (containing the attributes), a string (containing a JSON, on which JSON.parse is
executed). If the input is not hash or string, the function tries to run to_s on the object and then JSON.parse.
Stix2.parse(type: 'indicator')
Stix2.parse('type' => 'indicator')
Stix2.parse('{"type":"indicator"}')
Stix2.parse(MyObject.new(...))
Return
The function infers the type attribute of the input and determines which is the proper instance to create. This
results in a fancy way of processing Stix2 input: basically give whatever you have to it and you will get the proper
Stix2 message.
Storage
The Stix2 standard has several object types, some of which are containers of other objects (like Bundle). However we
may want to save and retrieve Stix2 objects in a fast way. The gem provides a storage support for that.
For any Stix2 attribute that is an identifier (Stix2::Identifier in the gem) the class gives one more method called
_instance to retrieve the actual instance. If we have a threat-actor like this
{
"type": "threat-actor",
"spec_version": "2.1",
"id": "threat-actor--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"created": "2016-04-06T20:03:48.000Z",
"modified": "2016-04-06T20:03:48.000Z",
"threat_actor_types": ["crime-syndicate"],
"name": "Evil Org",
"description": "The Evil Org threat actor group",
"aliases": ["Syndicate 1", "Evil Syndicate 99"],
"roles": ["director"],
"goals": ["Steal bank money", "Steal credit cards"],
"sophistication": "advanced",
"resource_level": "team",
"primary_motivation": "organizational-gain"
}
we know that this object has been created by an identity identity--f431f809-377b-45e0-aa1c-6a4751cae5ff. We can
retrieve the other object if already seen
Stix2.storage_activate # Activate the storage
identity = Stix2::DomainObject::Identity.new(id: 'identity--f431f809-377b-45e0-aa1c-6a4751cae5ff', ...)
threat_actor = Stix2::DomainObject::ThreatActor.new(created_by_ref: 'identity--f431f809-377b-45e0-aa1c-6a4751cae5ff', ...)
threat_actor.created_by_ref # this gives the identifier => identity--f431f809-377b-45e0-aa1c-6a4751cae5ff
threat_actor.created_by_ref_instance # this gives the actual object => Stix2::DomainObject::Identity
Contribution
You can contribute to this project in 2 ways:
- with a PR: just follow the standard github workflow
- by pointing out missing support: open an issue and please provide a json containing the missing support, to simplify the development