0
# Data Markings and Access Control
1
2
Comprehensive data marking system for applying access control, handling restrictions, and managing classification levels on STIX objects using both object-level and granular markings.
3
4
## Capabilities
5
6
### Marking Functions
7
8
Core functions for manipulating data markings on STIX objects.
9
10
```python { .api }
11
def add_markings(obj, marking, selectors=None):
12
"""
13
Add markings to STIX objects or properties.
14
15
Parameters:
16
- obj: STIX object to mark
17
- marking: Marking definition reference or object
18
- selectors (list): Property selectors for granular markings
19
20
Returns:
21
Modified STIX object with added markings
22
"""
23
24
def set_markings(obj, marking, selectors=None, marking_ref=True, lang=True):
25
"""
26
Set markings on STIX objects, replacing existing markings.
27
28
Parameters:
29
- obj: STIX object to mark
30
- marking: Marking definition reference or object
31
- selectors (list): Property selectors for granular markings
32
- marking_ref (bool): Include marking definition references
33
- lang (bool): Include language markings
34
35
Returns:
36
Modified STIX object with set markings
37
"""
38
39
def remove_markings(obj, marking, selectors=None):
40
"""
41
Remove markings from STIX objects or properties.
42
43
Parameters:
44
- obj: STIX object to modify
45
- marking: Marking definition reference or object to remove
46
- selectors (list): Property selectors for granular markings
47
48
Returns:
49
Modified STIX object with removed markings
50
"""
51
52
def clear_markings(obj, selectors=None, marking_ref=True, lang=True):
53
"""
54
Clear all markings from STIX objects or properties.
55
56
Parameters:
57
- obj: STIX object to modify
58
- selectors (list): Property selectors for granular markings
59
- marking_ref (bool): Clear marking definition references
60
- lang (bool): Clear language markings
61
62
Returns:
63
Modified STIX object with cleared markings
64
"""
65
66
def get_markings(obj, selectors=None, inherited=False, descendants=False, marking_ref=True, lang=True):
67
"""
68
Get markings from STIX objects or properties.
69
70
Parameters:
71
- obj: STIX object to examine
72
- selectors (list): Property selectors for granular markings
73
- inherited (bool): Include inherited markings from parent objects
74
- descendants (bool): Include markings from descendant properties
75
- marking_ref (bool): Include marking definition references
76
- lang (bool): Include language markings
77
78
Returns:
79
List of marking definition references and language tags
80
"""
81
82
def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=False):
83
"""
84
Check if STIX object or properties are marked.
85
86
Parameters:
87
- obj: STIX object to check
88
- marking: Specific marking to check for (optional)
89
- selectors (list): Property selectors for granular markings
90
- inherited (bool): Check inherited markings
91
- descendants (bool): Check descendant markings
92
93
Returns:
94
bool: True if marked, False otherwise
95
"""
96
```
97
98
### Object-Level Markings
99
100
Apply markings to entire STIX objects using the `object_marking_refs` property.
101
102
Usage examples:
103
104
```python
105
from stix2 import add_markings, get_markings, Indicator, TLP_RED, TLP_WHITE
106
107
# Create indicator without markings
108
indicator = Indicator(
109
name="Sensitive Indicator",
110
indicator_types=["malicious-activity"],
111
pattern_type="stix",
112
pattern="[file:hashes.MD5 = 'abc123']"
113
)
114
115
# Add TLP:RED marking to entire object
116
marked_indicator = add_markings(indicator, TLP_RED)
117
118
# Check what markings are applied
119
markings = get_markings(marked_indicator)
120
print(markings) # ['marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed']
121
122
# Check if object is marked with specific marking
123
is_tlp_red = is_marked(marked_indicator, TLP_RED)
124
print(is_tlp_red) # True
125
126
# Add additional marking
127
double_marked = add_markings(marked_indicator, TLP_WHITE)
128
129
# Set markings (replaces existing)
130
white_only = set_markings(marked_indicator, TLP_WHITE)
131
132
# Remove specific marking
133
unmarked = remove_markings(marked_indicator, TLP_RED)
134
135
# Clear all markings
136
clean_indicator = clear_markings(marked_indicator)
137
```
138
139
### Granular Markings
140
141
Apply markings to specific properties of STIX objects for fine-grained access control.
142
143
Usage examples:
144
145
```python
146
from stix2 import add_markings, get_markings, Malware, TLP_AMBER, TLP_GREEN
147
148
# Create malware object
149
malware = Malware(
150
name="Zeus Banking Trojan",
151
malware_types=["trojan"],
152
description="Advanced banking trojan targeting financial institutions",
153
aliases=["Zbot", "Zeus Bot"]
154
)
155
156
# Mark specific properties with different classification levels
157
# Mark name as TLP:GREEN (low sensitivity)
158
malware = add_markings(malware, TLP_GREEN, ["name"])
159
160
# Mark description as TLP:AMBER (moderate sensitivity)
161
malware = add_markings(malware, TLP_AMBER, ["description"])
162
163
# Mark aliases as TLP:RED (high sensitivity)
164
malware = add_markings(malware, TLP_RED, ["aliases"])
165
166
# Get markings for specific property
167
name_markings = get_markings(malware, ["name"])
168
print(name_markings) # ['marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da']
169
170
desc_markings = get_markings(malware, ["description"])
171
print(desc_markings) # ['marking-definition--f88d31f6-486f-44da-b317-01333bde0b82']
172
173
# Check if specific property is marked
174
is_name_marked = is_marked(malware, TLP_GREEN, ["name"])
175
print(is_name_marked) # True
176
177
# Remove marking from specific property
178
malware = remove_markings(malware, TLP_RED, ["aliases"])
179
180
# Clear markings from specific property
181
malware = clear_markings(malware, ["description"])
182
```
183
184
### Complex Property Selectors
185
186
Use advanced selectors for nested properties and list elements.
187
188
```python
189
from stix2 import NetworkTraffic, add_markings, TLP_AMBER
190
191
# Create network traffic with complex structure
192
traffic = NetworkTraffic(
193
protocols=["tcp", "http"],
194
extensions={
195
"http-request-ext": {
196
"request_method": "GET",
197
"request_value": "/admin/login",
198
"request_version": "1.1",
199
"request_header": {
200
"User-Agent": "Malicious-Bot/1.0",
201
"Host": "victim.com"
202
}
203
}
204
}
205
)
206
207
# Mark nested extension properties
208
traffic = add_markings(traffic, TLP_AMBER, ["extensions.http-request-ext.request_value"])
209
traffic = add_markings(traffic, TLP_RED, ["extensions.http-request-ext.request_header.User-Agent"])
210
211
# Mark list elements by index
212
traffic = add_markings(traffic, TLP_GREEN, ["protocols.[0]"]) # Mark first protocol
213
214
# Mark entire nested object
215
traffic = add_markings(traffic, TLP_AMBER, ["extensions.http-request-ext"])
216
217
# Get markings for nested properties
218
ua_markings = get_markings(traffic, ["extensions.http-request-ext.request_header.User-Agent"])
219
```
220
221
### Traffic Light Protocol (TLP) Markings
222
223
Built-in TLP marking definitions for standardized information sharing controls.
224
225
```python { .api }
226
# Pre-defined TLP marking constants
227
TLP_WHITE # marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9
228
TLP_GREEN # marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da
229
TLP_AMBER # marking-definition--f88d31f6-486f-44da-b317-01333bde0b82
230
TLP_RED # marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed
231
```
232
233
Usage examples:
234
235
```python
236
from stix2 import TLP_WHITE, TLP_GREEN, TLP_AMBER, TLP_RED, Indicator, add_markings
237
238
# Create indicators with different TLP classifications
239
public_indicator = Indicator(
240
name="Public IoC",
241
indicator_types=["malicious-activity"],
242
pattern_type="stix",
243
pattern="[domain-name:value = 'public-malware.com']",
244
object_marking_refs=[TLP_WHITE]
245
)
246
247
community_indicator = add_markings(Indicator(
248
name="Community IoC",
249
indicator_types=["malicious-activity"],
250
pattern_type="stix",
251
pattern="[ip-addr:value = '10.0.0.1']"
252
), TLP_GREEN)
253
254
limited_indicator = add_markings(Indicator(
255
name="Limited Distribution IoC",
256
indicator_types=["malicious-activity"],
257
pattern_type="stix",
258
pattern="[file:hashes.SHA-256 = 'abc123...']"
259
), TLP_AMBER)
260
261
restricted_indicator = add_markings(Indicator(
262
name="Highly Sensitive IoC",
263
indicator_types=["malicious-activity"],
264
pattern_type="stix",
265
pattern="[email-addr:value = 'attacker@evil.com']"
266
), TLP_RED)
267
```
268
269
### Custom Marking Definitions
270
271
Create custom marking definitions for organization-specific classification systems.
272
273
```python
274
from stix2 import MarkingDefinition, StatementMarking, add_markings
275
276
# Create custom statement marking
277
internal_only = MarkingDefinition(
278
definition_type="statement",
279
definition=StatementMarking(
280
statement="Internal Use Only - Do Not Share Outside Organization"
281
)
282
)
283
284
# Create custom TLP-like marking
285
custom_classification = MarkingDefinition(
286
definition_type="statement",
287
definition=StatementMarking(
288
statement="CONFIDENTIAL//NOFORN//PROPRIETARY"
289
)
290
)
291
292
# Apply custom markings
293
sensitive_report = add_markings(Report(
294
name="Internal Threat Assessment",
295
published="2021-04-23T10:30:00.000Z",
296
object_refs=[]
297
), internal_only)
298
299
classified_indicator = add_markings(Indicator(
300
name="Classified Indicator",
301
indicator_types=["malicious-activity"],
302
pattern_type="stix",
303
pattern="[ip-addr:value = '192.168.1.100']"
304
), custom_classification)
305
```
306
307
### Language Markings
308
309
Apply language tags for internationalization and content language identification.
310
311
```python
312
from stix2 import add_markings, ThreatActor
313
314
# Create threat actor with multiple language content
315
threat_actor = ThreatActor(
316
name="APT Example",
317
threat_actor_types=["nation-state"],
318
description="Advanced persistent threat group"
319
)
320
321
# Add language markings for specific properties
322
# Mark name as English
323
threat_actor = add_markings(threat_actor, "en", ["name"])
324
325
# Mark description as English
326
threat_actor = add_markings(threat_actor, "en", ["description"])
327
328
# For objects with translated content
329
multilingual_actor = ThreatActor(
330
name="APT Example",
331
threat_actor_types=["nation-state"]
332
)
333
334
# Add language-specific granular markings
335
multilingual_actor = add_markings(multilingual_actor, "en", ["name"])
336
337
# Get language markings
338
lang_markings = get_markings(multilingual_actor, ["name"], lang=True)
339
print(lang_markings) # ['en']
340
```
341
342
### Inheritance and Propagation
343
344
Understanding how markings are inherited and propagated through object hierarchies.
345
346
```python
347
from stix2 import Bundle, add_markings, get_markings, TLP_AMBER
348
349
# Create bundle with objects
350
bundle = Bundle(
351
threat_actor,
352
malware,
353
indicator
354
)
355
356
# Mark entire bundle
357
marked_bundle = add_markings(bundle, TLP_AMBER)
358
359
# Check inherited markings on contained objects
360
for obj_ref in marked_bundle.objects:
361
inherited_markings = get_markings(obj_ref, inherited=True)
362
print(f"{obj_ref.type}: {inherited_markings}")
363
364
# Descendant markings - check child properties
365
complex_object = ObservedData(
366
first_observed="2021-04-23T10:30:00.000Z",
367
last_observed="2021-04-23T10:30:00.000Z",
368
number_observed=1,
369
objects={
370
"0": {
371
"type": "file",
372
"name": "malware.exe",
373
"hashes": {"MD5": "abc123"}
374
}
375
}
376
)
377
378
# Mark parent property
379
marked_complex = add_markings(complex_object, TLP_RED, ["objects"])
380
381
# Check descendants
382
desc_markings = get_markings(marked_complex, ["objects.0.name"], descendants=True)
383
```
384
385
### Marking Validation
386
387
Validate and enforce marking policies on STIX objects.
388
389
```python
390
from stix2.exceptions import MarkingNotFoundError, TLPMarkingDefinitionError
391
392
def validate_tlp_compliance(obj):
393
"""Validate TLP marking compliance."""
394
markings = get_markings(obj)
395
396
# Check for conflicting TLP markings
397
tlp_markings = [m for m in markings if 'marking-definition--' in m and
398
m in [TLP_WHITE, TLP_GREEN, TLP_AMBER, TLP_RED]]
399
400
if len(tlp_markings) > 1:
401
raise TLPMarkingDefinitionError(
402
"Object has multiple conflicting TLP markings",
403
tlp_markings
404
)
405
406
return tlp_markings[0] if tlp_markings else None
407
408
def enforce_minimum_classification(obj, min_classification=TLP_AMBER):
409
"""Ensure object meets minimum classification level."""
410
current_tlp = validate_tlp_compliance(obj)
411
412
tlp_hierarchy = {
413
TLP_WHITE: 0,
414
TLP_GREEN: 1,
415
TLP_AMBER: 2,
416
TLP_RED: 3
417
}
418
419
if not current_tlp or tlp_hierarchy.get(current_tlp, 0) < tlp_hierarchy[min_classification]:
420
return add_markings(obj, min_classification)
421
422
return obj
423
424
# Apply validation
425
try:
426
compliant_indicator = enforce_minimum_classification(indicator, TLP_AMBER)
427
tlp_level = validate_tlp_compliance(compliant_indicator)
428
print(f"Indicator classified as: {tlp_level}")
429
except TLPMarkingDefinitionError as e:
430
print(f"TLP validation error: {e}")
431
```
432
433
### Marking Query and Filtering
434
435
Query and filter STIX objects based on their markings.
436
437
```python
438
from stix2 import MemoryStore, Filter
439
440
# Create store with marked objects
441
store = MemoryStore([
442
add_markings(indicator1, TLP_WHITE),
443
add_markings(indicator2, TLP_GREEN),
444
add_markings(indicator3, TLP_AMBER),
445
add_markings(malware1, TLP_RED)
446
])
447
448
# Filter by marking level - objects marked TLP:GREEN or lower
449
def filter_by_tlp_level(objects, max_level=TLP_GREEN):
450
tlp_hierarchy = {
451
TLP_WHITE: 0,
452
TLP_GREEN: 1,
453
TLP_AMBER: 2,
454
TLP_RED: 3
455
}
456
457
filtered = []
458
for obj in objects:
459
markings = get_markings(obj)
460
tlp_markings = [m for m in markings if m in tlp_hierarchy]
461
462
if not tlp_markings: # No TLP marking = assume WHITE
463
filtered.append(obj)
464
elif any(tlp_hierarchy[m] <= tlp_hierarchy[max_level] for m in tlp_markings):
465
filtered.append(obj)
466
467
return filtered
468
469
# Get all objects safe for community sharing (TLP:GREEN and below)
470
community_safe = filter_by_tlp_level(store.query(), TLP_GREEN)
471
472
# Custom filter for unmarked objects
473
unmarked_objects = [obj for obj in store.query()
474
if not get_markings(obj)]
475
476
# Filter objects by specific marking
477
tlp_amber_objects = [obj for obj in store.query()
478
if TLP_AMBER in get_markings(obj)]
479
```