This page contains suggested practices for developing and consuming CybOX content. There’s a similar page for Structured Threat Information eXpression (STIX™).
Note that these are simply suggested practices. In many cases, operational or technical concerns may prohibit you from implementing them or they may just not make sense in your situation. That’s perfectly fine, these are just suggestions.
CybOX IDs are XML QNames. Each ID includes both a namespace portion (optional) and an ID portion (required) separated by a colon (:). The recommend approach to creating CybOX IDs is to define a producer namespace and namespace prefix, then use the form:
[ns prefix]:[construct type]-[GUID]
The “ns prefix” should be a namespace prefix bound to a namespace owned/controlled by the producer of the content.
Some examples:
acme:event-ce431003-ad07-4c96-bd7a-a50a3196e2a0
acme:action-bf8bc5d5-c7e6-46b0-8d22-7500fea77196
acme:observable-79090715-8d6a-46b7-943b-c0bb9e063788
acme:fileobj-965e1140-2c22-4408-a423-b7acc08290a7
In order to use this approach, you will need to define that namespace prefix in the head of your XML document:
<cybox:Observables xmlns:acme="http://acme.example.com" ...
This format provides high assurance that IDs will be both unique and meaningful, because the producer namespace denotes who’s producing it, the construct name denotes what it is, and the GUID guarantees uniqueness.
When generating CybOX Observables and Objects from source data that contains identification information, CybOX authors should record the mapping of their source IDs to their newly generated CybOX IDs using some storage mechanism outside of CybOX (e.g., a database). This will allow authors to quickly refer to and/or alter source data when new information regarding a particular CybOX Observable or Object presents itself in the future. Newly generated IDs may contain a namespace prefix which refers to the source vendor or tool used to generate the source data.
In many cases, you’ll have an option to either include a component (an object, for example) within the parent component or to reference the component by ID to a representation in a global location.
For example, an Object can include Related Objects. One way of doing this is to include the related object inline in the parent object:
<cybox:Object id="acme:fileobj-f7304dae-94c6-4592-b943-398e1e6916a7">
<cybox:Properties xsi:type="FileObj:FileObjectType">
<!-- SNIP -->
</cybox:Properties>
<cybox:Related_Objects>
<cybox:Related_Object id="acme:mutexobj-3c1221bd-2037-45ec-8129-4ba8d791e86b">
<cybox:Properties xsi:type="MutexObj:MutexObjectType">
<!-- SNIP -->
</cybox:Properties>
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.0">Created</cybox:Relationship>
</cybox:Related_Object>
</cybox:Object>
The other alternative is to reference that TTP, which would be represented elsewhere:
<cybox:Object id="acme:fileobj-f7304dae-94c6-4592-b943-398e1e6916a7">
<cybox:Properties xsi:type="FileObj:FileObjectType">
<!-- SNIP -->
</cybox:Properties>
<cybox:Related_Objects>
<cybox:Related_Object idref="acme:mutexobj-3c1221bd-2037-45ec-8129-4ba8d791e86b" />
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.0">Created</cybox:Relationship>
</cybox:Related_Object>
</cybox:Object>
These situations are a judgment call, but when making that judgment you should consider whether the related construct (object in this case) has value individually or only within the context of the parent? If it only has value in the parent, embedding it may be appropriate. Otherwise it’s probably better to reference it. If you’re unsure, it’s generally safer to reference it.
When creating references, you will typically use the idref
attribute:
<cybox:Related_Object idref="acme:mutexobj-3c1221bd-2037-45ec-8129-4ba8d791e86b" />
In a VERY limited set of circumstances (e.g., when specifying Attachments or Links within the Email_Message Object), you will use the object_reference
attribute rather than idref
. The object_reference
field, like the idref
field, specifies a unique ID reference to an Object defined elsewhere. Unlike the general use of idref
which references the full Object, the object_reference
field allows for the re-use of the defined Properties of one Object within another, without allowing the embedding of the full Object in the location from which it is being referenced. Thus, this ID reference is intended to resolve to just the Properties of the Object that it points to. Situations where object_reference
should be used rather than idref
are explicitly documented within the object property schemas that utilize this approach.
<cybox:Observable id="example:Observable-db066ea1-925b-43df-a341-f513ece3ae94">
<cybox:Object id="example:Object-e0e87eef-6315-410f-8025-086968129f41">
<cybox:Properties xsi:type="EmailMessageObj:EmailMessageObjectType">
<EmailMessageObj:Header>
<EmailMessageObj:Subject>Syria strategic plans leaked</EmailMessageObj:Subject>
</EmailMessageObj:Header>
<EmailMessageObj:Attachments>
<EmailMessageObj:File object_reference="example:Object-107a9290-30aa-4059-aa01-b441f6aa0cc6"/>
<EmailMessageObj:Attachments>
</cybox:Properties>
</cybox:Object>
</cybox:Observable>
When using either the idref
or object_reference
attribute, you should avoid putting any other attributes
or elements in the reference element.
Many places in CybOX use controlled vocabularies to represent data. When possible, you should use the vocabularies included in the CybOX defaults. If necessary, you can use your own vocabulary or even use strings outside of any vocabularies.
If you do this to add values that you think might be useful for other CybOX users, you should let us know by subscribing and submitting comments to the CTI Users List or the CTI TC Public Comment List so we can consider adding it to the default vocabulary.
To remove ambiguity regarding the timezone, all times should include an explicit timezone if possible.
CybOX observables are capable of representing both instance observables (specific events or properties that were observed) or pattern observables (patterns of events or properties that may potentially be observed). The conditional nature of patterns is expressed through the use of the @condition attribute on the fields within the observable. If the @condition attribute is set, that denotes that the field is part of a pattern.
Because it doesn’t make sense to mix pattern fields with instance field, if @condition is set on any fields it should be set on all fields. You should not mix and match fields with @condition set and fields without @condition set.
CybOX Objects schemas define sets of properties for common cyber objects.
To support practical use, CybOX provides an extensive set of Object property specifications by default.
This predefined set includes a broad range of object types across the cyber domain (network, host, files, memory, devices, etc.), as well as objects of varying levels of specificity/abstraction intended for differing use cases.
The approach to defining Objects (especially those across varying levels of specificity/abstraction) is intended to pursue architectural consistency and reuse by having more complex or specific variations on Objects leverage other more abstract existing Objects for sets of properties.
There are two primary variations of this:
It is suggested practice to always utilize the most specific CybOX Object possible for the context you are looking to convey and based on the properties you need to represent.
One clear exception to this is if conformance to a specific language Profile is required and that Profile restricts the set of available objects or directly specifies a particular Object to be used.
CybOX supports a broad range of Object types and provides the capability to relate/associate Objects together along with a characterization of how they are related.
To encourage consistency in the characterization of relationships between Objects, CybOX provides a default controlled vocabulary (ObjectRelationshipVocab-1.1) for use with the Relationship field. This vocabulary contains a broad range of values to characterize many of the potentially relevant Object-to-Object relationships.
Desired Association (Network-centric Object relationships) | Source Object | Related Object | “Relationship” Vocabulary Value |
---|---|---|---|
A network naming structure (e.g., Domain or Hostname) and an IP Address it resolves to |
Domain_Name Object | Address Object | “Resolved_To” |
Address Object | Domain_Name Object | “Resolved_To” | |
Hostname Object | Address Object | “Resolved_To” | |
Address Object | Hostname Object | “Resolved_To” | |
An IP Address and an Autonomous System | Address Object | AS Object | “Contained_By” |
AS Object | Address Object | “Contains” | |
A network naming structure (e.g., Domain or Hostname) and a Whois response | Domain_Name Object | Whois Object | “Characterized_By” |
Whois Object | Domain_Name Object | “Characterizes” | |
Hostname Object | Whois Object | “Characterized_By” | |
Whois Object | Hostname Object | “Characterizes” | |
A network naming structure (e.g., Domain or Hostname) and a DNS Query | Domain_Name Object | DNS_Query Object | “Properties_Queried_By” |
DNS_Query Object | Domain_Name | “Properties_Queried” | |
Hostname Object | DNS_Query Object | “Properties_Queried_By” | |
DNS_Query Object | Hostname Object | “Properties_Queried” | |
A network naming structure (e.g., Domain or Hostname) and a DNS Record | Domain_Name Object | DNS_Record Object | “Characterized_By” |
DNS_Record Object | Domain_Name Object | “Characterizes” | |
Hostname Object | DNS_Record Object | “Characterized_By” | |
DNS_Record )Object | Hostname Object | “Characterizes” | |
A DNS Record and a resolving IP Address within that record | DNS_Record Object | Address Object | “Contains” |
Address Object | DNS_Record Object | “Contained_Within” | |
A DNS Query and a DNS Record that resulted from the query | DNS_Query Object | DNS Record Object | “Searched_For” |
DNS Record Object | DNS_Query Object | “Searched_For_By” | |
A URL and the Domain contained within it | URI Object | Domain_Name Object | “Contains” |
Domain_Name Object | URI Object | “Extracted_From” | |
One Domain and another Domain that is a sub-part of it | Domain_Name Object (supra) | Domain_Name Object (sub) | “Supra-domain_Of” |
or “FQDN_Of” | |||
Domain_Name Object (sub) | Domain_Name Object (supra) | “Sub-domain_Of” |
Desired Association (Host-centric Object relationships) | Source Object | Related Object | “Relationship” Vocabulary Value |
---|---|---|---|
The characteristics of a File and the actual bits of the file | File Object | Artifact Object | “Characterizes” |
Artifact Object | File Object | “Characterized_By” | |
An Email and characteristics of a file attachment to the email | Email_Message Object | File Object | “Contains” |
File Object | Email_Message Object | “Contained_Within” | |
An Email and the actual bits of a file attachment to the email | Email_Message Object | Artifact Object | “Contains” |
Artifact Object | Email_Message Object | “Contained_Within” | |
An Email and a Link (URL) within the email | Email_Message Object | Link | “Contains” |
Link Object | Email_Message Object | “Contained_Within” | |
A File and another File contained within it | File Object (outer) | FileObject (inner) | “Contains” |
File Object (inner) | File Object (outer) | “Contained_Within” | |
A File and another File that it places on a system | File Object (dropper) | File Object (dropped file) | “Dropped” |
File Object (dropped file) | File Object (dropper) | “Dropped_By” | |
A File and the URL, Domain, or Hostname from which it was downloaded | File Object | URI Object | “Downloaded_From” |
URI Object | File Object | “Downloaded” | |
File Object | Domain Name Object | “Downloaded_From” | |
Domain Name Object | File Object | “Downloaded” | |
File Object | Hostname Object | “Downloaded_From” | |
Hostname Object | File Object | “Downloaded” |
Sometimes, a tool will capture properties about a CybOX object that aren’t in the schema for that object type. In some cases, this is because the schemas need to be expanded to cover that property, but in other cases this is because the tool is collecting derived information or other properties that are not generally represented for that object type.
In either case, those properties should be collected using the
Custom_Properties
element of the object properties. This is essentially a
simple list of key/value pairs:
<cybox:Properties xsi:type="FileObj:FileObjectType">
<cyboxCommon:Custom_Properties>
<cyboxCommon:Property name="Property Name">Property Value</cyboxCommon:Property>
</cyboxCommon:Custom_Properties>
<!-- Other properties from the FileObjectType schema -->
</cybox:Properties>
When capturing the output from a tool, the suggested practice is to set the
@name
attribute of the custom property to the exact field name used in the
tool. If possible, the @datatype
attribute should be set to the datatype that
will be output and the value formatted to fit that datatype’s formatting. If
that’s not possible, the exact value reported by the tool should be used and
the @datatype
attribute should be omitted.
The Bro tool captures the HTTP Transaction depth of an HTTP connection. In the
Bro output, this field is called trans_depth
and the value will be set to
some integer (whatever the depth is). So the @name
attribute should be set to
trans_depth
, the value should be set to the output from Bro, and the
@datatype
attribute should be set to int
(Integer). That would give you
something like:
<cyboxCommon:Custom_Properties>
<cyboxCommon:Property name="trans_depth" datatype="int">3</cyboxCommon:Property>
</cyboxCommon:Custom_Properties>
The release of CybOX 2.1 included the addition of two new objects: the Domain
Name
object
and the Hostname
object.
Although the terms “domain name” and “hostname” are often used interchangeably,
the terms have precise (and distinct) meanings in some contexts, and neither
term completely encompasses the other. This document hopes to clarify the
intent of these two objects and provide a set of suggested practices for their
use.
The concepts of a “domain” (in the context of DNS, not Windows Active
Directory domains) and a “host” (a generic term for a computing system) are
certainly distinct, but the names used to represent these entities are often
indistinguishable. Given the name www.example.com
, does that string
represent a domain? A host? Both? In this case, there is most likely a host
that responds to web requests at an IP address which a DNS query for that name
would respond with. However, there are some valid domain names that do not
correspond to hosts (e.g., top-level domains such as “org” or “co.uk”). There are
also host names (e.g., local names in a hosts
file) which may not correspond
to a name in any domain name system.
So, which type of object should you use?
In general, the Hostname
object should be used in “concrete” cases when you
know there is a host with a given name (for instance, when there is a network
connection between two machines). The Domain Name
object should be used in
more abstract scenarios when it is not clear if an actual connection is
occurring (DNS queries) or if there is the potential for more than one IP or
host to be involved (load balancer, etc.).
If you are looking to represent a “local hostname” (in other words, what a
system calls itself), there is a Hostname
property of the System
object
that should be used.
<SystemObj:System>
<SystemObj:Hostname>plato</SystemObj:Hostname>
</SystemObj:System>
There are two cases in which using the Hostname
object is used explicitly:
within the Socket Address
object
(which is used in the Network Connection
object),
and within a URL History Entry
component
of the URL History
object.
In each case, this represents an actual host involved in communication, so
this matches the general principle.
<URLHistoryObj:URL_History>
<URLHistoryObj:URL_History_Entry>
<URLHistoryObj:URL type="URL">
<URIObj:Value>http://www.example.com/index.html</URIObj:Value>
</URLHistoryObj:URL>
<URLHistoryObj:Hostname>
<HostnameObj:Hostname_Value>www.example.com</HostnameObj:Hostname_Value>
</URLHistoryObj:Hostname>
</URLHistoryObj:URL_History_Entry>
</URLHistoryObj:URL_History>
<NetworkConnectionObj:Network_Connection>
<NetworkConnectionObj:Layer7_Protocol>HTTP</NetworkConnectionObj:Layer7_Protocol>
<NetworkConnectionObj:Source_Socket_Address>
<SocketAddressObj:IP_Address>
<AddressObj:Address_Value>192.168.1.10</AddressObj:Address_Value>
</SocketAddressObj:IP_Address>
<SocketAddressObj:Port>
<PortObj:Port_Value>12345</PortObj:Port_Value>
<PortObj:Layer4_Protocol>TCP</PortObj:Layer4_Protocol>
</SocketAddressObj:Port>
</NetworkConnectionObj:Source_Socket_Address>
<NetworkConnectionObj:Destination_Socket_Address>
<SocketAddressObj:Hostname>www.example.com</SocketAddressObj:Hostname>
<SocketAddressObj:Port>
<PortObj:Port_Value>80</PortObj:Port_Value>
<PortObj:Layer4_Protocol>TCP</PortObj:Layer4_Protocol>
</SocketAddressObj:Port>
</NetworkConnectionObj:Destination_Socket_Address>
</NetworkConnectionObj:Network_Connection>
NOTE: In reality, TCP/IP network connections are not actual made based
on the hostname; rather, the hostname is used to look up an IP address,
which is then used for the connection. The Socket_Address
object supports
a Hostname
property for instances where the actual IP address is not
significant to what is being expressed. For example, in dynamic malware
sandboxes, DNS responses are frequently modified to return a different IP
address (often a private IP address). In these cases, the actual IP address
used for the connection is not important, and representing the hostname
that the malware uses for C2 as a direct property of the network connection
is desirable; it avoids the use of Related Object
s and the need to
include IP addresses that aren’t informative.
In the DNS Record
object,
the Domain Name
field uses the URI
object.
This is because the DNS Record
object predates the Domain Name
object.
This may be corrected in a future major release of CybOX, but for now, use a
URI
object with type="Domain Name"
(as this is the only schema-valid
type for this field).
<DNSRecordObj:DNS_Record>
<DNSRecordObj:Domain_Name type="Domain Name">
<URIObj:Value>www.example.com</URIObj:Value>
</DNSRecordObj:Domain_Name>
<DNSRecordObj:IP_Address category="ipv4-addr">
<AddressObj:Address_Value>192.168.1.42</AddressObj:Address_Value>
</DNSRecordObj:IP_Address>
<DNSRecordObj:Entry_Type>A</DNSRecordObj:Entry_Type>
</DNSRecordObj:DNS_Record>
If you don’t want to capture the entire DNS record, you can also use a
Domain Name
object, along with one or more related Address
objects,
using the Resolved_To
relationship.
<cybox:Object>
<cybox:Properties xsi:type="DomainNameObj:DomainNameObjectType">
<DomainNameObj:Value>www.google.com</DomainNameObj:Value>
</cybox:Properties>
<cybox:Related_Objects>
<cybox:Related_Object>
<cybox:Properties xsi:type="AddressObj:AddressObjectType" category="ipv4-addr">
<AddressObj:Address_Value>74.125.196.100</AddressObj:Address_Value>
</cybox:Properties>
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.1">Resolved_To</cybox:Relationship>
</cybox:Related_Object>
<cybox:Related_Object>
<cybox:Properties xsi:type="AddressObj:AddressObjectType" category="ipv4-addr">
<AddressObj:Address_Value>74.125.196.138</AddressObj:Address_Value>
</cybox:Properties>
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.1">Resolved_To</cybox:Relationship>
</cybox:Related_Object>
<cybox:Related_Object>
<cybox:Properties xsi:type="AddressObj:AddressObjectType" category="ipv4-addr">
<AddressObj:Address_Value>74.125.196.113</AddressObj:Address_Value>
</cybox:Properties>
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.1">Resolved_To</cybox:Relationship>
</cybox:Related_Object>
...
</cybox:Related_Objects>
</cybox:Object>
The is_domain_name
attribute on the Hostname
object can be used when it
is important to indicate whether or not the provided hostname is query-able
via DNS. However, if you aren’t sure whether a name actually corresponds to
a host, don’t use the Hostname
object with this attribute set to true
.
When capturing domain names as part of a “malicious domain watchlist” or
other list of domains, the Domain Name
object should be used.
The CybOX team is investigating ways to make the use of these objects even more clear in a future release. Suggestions and/or proposed changes are always welcome by subscribing and submitting comments to the CTI Users List or the CTI TC Public Comment List!
The FileObjectType
contains several fields for recording name and path
information about the file.
File_Name
File_Path
Device_Path
Full_Path
File_Extension
For File instance observables, the File_Name
and File_Path
are sufficient
for the vast majority of use cases. Given the file
C:\Users\ExampleUser\Documents\ProjectX\MeetingNotes_2014-08-01.txt
, the file
name and the path of the directory which contains the file should be separated
and stored in these two fields. Note the trailing \
in the File_Path
.
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Name>MeetingNotes_2014-08-01.txt</FileObj:File_Name>
<FileObj:File_Path>C:\Users\ExampleUser\Documents\ProjectX\</FileObj:File_Path>
</cybox:Properties>
If the file path is unknown, or you do not wish to include it, it can be omitted.
The Device_Path
field MAY be used to specify the path to the file system
partition on which the file resides. On Windows, Device_Path
could be a
path such as \Device\Harddisk0\Partition0
. On Unix-like systems, this could
be a path like /dev/sda1
. You should not use a path to a physical disk, such
as \\.\PhysicalDrive1
on Windows or /dev/sda
on Unix-like systems, since
file systems are generally tied to partitions rather than physical disks.
The Full_Path
field is used to specify a combination of Device_Path
plus
File_Path
. You SHOULD NOT use this field unless it is not possible to split
the Full_Path
into the Device_Path
and the File_Path
fields; it is
preferable to include this information separately under the component fields.
The File_Extension
field SHOULD NOT be used on instance data.
Representing file name and path data as CybOX patterns is more complex, as there is much more variation in what is being represented. A few examples are shown below, but this is far from an exhaustive list. Note that some examples can be combined to represent more complex conditions.
This is the time to use the File_Extension
field. Do not use a
condition="EndsWith"
on the File_Name
field.
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Extension condition="Equals">txt</FileObj:File_Extension>
</cybox:Properties>
Use the EndsWith
condition on the File_Path
field (or Equals
if you know
the full path to the directory).
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Path condition="EndsWith">ProjectX\</FileObj:File_Path>
</cybox:Properties>
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Path condition="Equals">C:\Users\ExampleUser\Documents\ProjectX\</FileObj:File_Path>
</cybox:Properties>
If you know a directory somewhere in the file path, but not necessarily the
directory which directly contains the file, you can use StartsWith
or
Contains
.
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Path condition="StartsWith">C:\Users\ExampleUser\Documents\</FileObj:File_Path>
</cybox:Properties>
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Path condition="Contains">Documents</FileObj:File_Path>
</cybox:Properties>