or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-storage.mdequivalence.mdindex.mdmarkings.mdobject-creation.mdpattern-matching.mdrelationships.mdstix-domain-objects.mdstix-observables.mdutilities.mdversioning.md

relationships.mddocs/

0

# Relationships and Object Links

1

2

STIX Relationship Objects and utilities for creating and managing connections between STIX objects, including relationships, sightings, and reference resolution across multiple data sources.

3

4

## Capabilities

5

6

### Relationship Objects

7

8

Connect STIX Domain Objects with typed relationships describing how they relate to each other.

9

10

```python { .api }

11

class Relationship:

12

"""

13

Relationship objects describe connections between STIX Domain Objects.

14

15

Required Properties:

16

- relationship_type (str): Type of relationship

17

- source_ref (str): ID of source STIX object

18

- target_ref (str): ID of target STIX object

19

20

Optional Properties:

21

- description (str): Description of the relationship

22

- start_time (timestamp): When relationship started

23

- stop_time (timestamp): When relationship ended

24

"""

25

```

26

27

Usage examples:

28

29

```python

30

from stix2 import Relationship, ThreatActor, Malware, AttackPattern

31

32

# Create objects to relate

33

threat_actor = ThreatActor(

34

name="APT1",

35

threat_actor_types=["nation-state"]

36

)

37

38

malware = Malware(

39

name="Poison Ivy",

40

malware_types=["remote-access-trojan"]

41

)

42

43

attack_pattern = AttackPattern(

44

name="Spear Phishing"

45

)

46

47

# Create relationships

48

uses_malware = Relationship(

49

relationship_type="uses",

50

source_ref=threat_actor.id,

51

target_ref=malware.id,

52

description="APT1 commonly uses Poison Ivy RAT in their operations"

53

)

54

55

uses_technique = Relationship(

56

relationship_type="uses",

57

source_ref=threat_actor.id,

58

target_ref=attack_pattern.id,

59

description="APT1 uses spear phishing for initial access"

60

)

61

62

implements_pattern = Relationship(

63

relationship_type="implements",

64

source_ref=malware.id,

65

target_ref=attack_pattern.id,

66

description="Poison Ivy is delivered via spear phishing attacks"

67

)

68

69

# Time-bounded relationship

70

active_relationship = Relationship(

71

relationship_type="targets",

72

source_ref=threat_actor.id,

73

target_ref="identity--target-organization-uuid",

74

start_time="2020-01-01T00:00:00.000Z",

75

stop_time="2020-12-31T23:59:59.000Z",

76

description="APT1 actively targeted this organization during 2020"

77

)

78

```

79

80

### Common Relationship Types

81

82

STIX defines standard relationship types for connecting different object types:

83

84

```python

85

# Threat Actor relationships

86

actor_uses_malware = Relationship(

87

relationship_type="uses", # ThreatActor -> Malware

88

source_ref=threat_actor.id,

89

target_ref=malware.id

90

)

91

92

actor_targets_identity = Relationship(

93

relationship_type="targets", # ThreatActor -> Identity

94

source_ref=threat_actor.id,

95

target_ref=identity.id

96

)

97

98

actor_attributed_to = Relationship(

99

relationship_type="attributed-to", # ThreatActor -> Identity

100

source_ref=threat_actor.id,

101

target_ref=sponsor_identity.id

102

)

103

104

actor_impersonates = Relationship(

105

relationship_type="impersonates", # ThreatActor -> Identity

106

source_ref=threat_actor.id,

107

target_ref=impersonated_identity.id

108

)

109

110

# Malware relationships

111

malware_targets_identity = Relationship(

112

relationship_type="targets", # Malware -> Identity

113

source_ref=malware.id,

114

target_ref=victim_identity.id

115

)

116

117

malware_uses_tool = Relationship(

118

relationship_type="uses", # Malware -> Tool

119

source_ref=malware.id,

120

target_ref=tool.id

121

)

122

123

malware_variant_of = Relationship(

124

relationship_type="variant-of", # Malware -> Malware

125

source_ref=malware_variant.id,

126

target_ref=malware_family.id

127

)

128

129

# Indicator relationships

130

indicator_indicates = Relationship(

131

relationship_type="indicates", # Indicator -> ThreatActor/Malware/AttackPattern

132

source_ref=indicator.id,

133

target_ref=malware.id

134

)

135

136

# Campaign relationships

137

campaign_uses_malware = Relationship(

138

relationship_type="uses", # Campaign -> Malware

139

source_ref=campaign.id,

140

target_ref=malware.id

141

)

142

143

campaign_attributed_to = Relationship(

144

relationship_type="attributed-to", # Campaign -> ThreatActor

145

source_ref=campaign.id,

146

target_ref=threat_actor.id

147

)

148

149

# Attack Pattern relationships

150

pattern_mitigated_by = Relationship(

151

relationship_type="mitigated-by", # AttackPattern -> CourseOfAction

152

source_ref=attack_pattern.id,

153

target_ref=course_of_action.id

154

)

155

156

# Course of Action relationships

157

coa_mitigates = Relationship(

158

relationship_type="mitigates", # CourseOfAction -> AttackPattern/Malware

159

source_ref=course_of_action.id,

160

target_ref=attack_pattern.id

161

)

162

163

# Vulnerability relationships

164

vuln_targets = Relationship(

165

relationship_type="targets", # Vulnerability -> Identity/Software

166

source_ref=vulnerability.id,

167

target_ref=software.id

168

)

169

170

# Tool relationships

171

tool_targets = Relationship(

172

relationship_type="targets", # Tool -> Identity/Infrastructure

173

source_ref=tool.id,

174

target_ref=infrastructure.id

175

)

176

177

# Infrastructure relationships

178

infra_communicates_with = Relationship(

179

relationship_type="communicates-with", # Infrastructure -> Infrastructure

180

source_ref=infrastructure1.id,

181

target_ref=infrastructure2.id

182

)

183

184

infra_consists_of = Relationship(

185

relationship_type="consists-of", # Infrastructure -> Infrastructure/Software

186

source_ref=infrastructure.id,

187

target_ref=component.id

188

)

189

190

infra_controls = Relationship(

191

relationship_type="controls", # Infrastructure -> Infrastructure/Malware

192

source_ref=c2_server.id,

193

target_ref=malware.id

194

)

195

196

infra_delivers = Relationship(

197

relationship_type="delivers", # Infrastructure -> Malware

198

source_ref=infrastructure.id,

199

target_ref=malware.id

200

)

201

202

infra_hosts = Relationship(

203

relationship_type="hosts", # Infrastructure -> Tool/Malware

204

source_ref=infrastructure.id,

205

target_ref=malware.id

206

)

207

208

infra_owns = Relationship(

209

relationship_type="owns", # Infrastructure -> Infrastructure

210

source_ref=infrastructure.id,

211

target_ref=owned_infrastructure.id

212

)

213

214

# Report relationships

215

report_object_refs = [ # Report -> any SDO/SRO (via object_refs property)

216

threat_actor.id,

217

malware.id,

218

indicator.id,

219

uses_malware.id

220

]

221

222

report = Report(

223

name="APT1 Analysis Report",

224

published="2021-04-23T10:30:00.000Z",

225

object_refs=report_object_refs

226

)

227

```

228

229

### Sighting Objects

230

231

Represent observations or encounters with STIX objects in the real world.

232

233

```python { .api }

234

class Sighting:

235

"""

236

Sighting objects represent observations of STIX objects.

237

238

Required Properties:

239

- sighting_of_ref (str): ID of sighted STIX object

240

241

Optional Properties:

242

- count (int): Number of times sighted

243

- first_seen (timestamp): First sighting time

244

- last_seen (timestamp): Last sighting time

245

- where_sighted_refs (list): References to identities that sighted

246

- observed_data_refs (list): References to observed data

247

- summary (bool): Whether this is a summary sighting

248

- description (str): Description of the sighting

249

"""

250

```

251

252

Usage examples:

253

254

```python

255

from stix2 import Sighting, Indicator, Identity

256

257

# Create indicator and observer identity

258

indicator = Indicator(

259

name="Malicious Domain",

260

indicator_types=["malicious-activity"],

261

pattern_type="stix",

262

pattern="[domain-name:value = 'evil.com']"

263

)

264

265

security_org = Identity(

266

name="ACME Security Team",

267

identity_class="organization"

268

)

269

270

# Create sighting of indicator

271

sighting = Sighting(

272

sighting_of_ref=indicator.id,

273

count=5,

274

first_seen="2021-04-23T10:30:00.000Z",

275

last_seen="2021-04-23T11:45:00.000Z",

276

where_sighted_refs=[security_org.id],

277

description="Domain observed in network traffic attempting C2 communication"

278

)

279

280

# Sighting with observed data

281

from stix2 import ObservedData

282

283

observed_data = ObservedData(

284

first_observed="2021-04-23T10:30:00.000Z",

285

last_observed="2021-04-23T10:30:00.000Z",

286

number_observed=1,

287

objects={

288

"0": {

289

"type": "domain-name",

290

"value": "evil.com"

291

}

292

}

293

)

294

295

detailed_sighting = Sighting(

296

sighting_of_ref=indicator.id,

297

count=1,

298

first_seen="2021-04-23T10:30:00.000Z",

299

where_sighted_refs=[security_org.id],

300

observed_data_refs=[observed_data.id],

301

description="Domain observed in DNS logs"

302

)

303

304

# Summary sighting (aggregated data)

305

summary_sighting = Sighting(

306

sighting_of_ref=indicator.id,

307

count=127,

308

first_seen="2021-04-01T00:00:00.000Z",

309

last_seen="2021-04-30T23:59:59.000Z",

310

where_sighted_refs=[security_org.id],

311

summary=True,

312

description="Monthly summary: domain seen 127 times across network"

313

)

314

```

315

316

### Reference Resolution

317

318

Utilities for resolving object references across data sources.

319

320

```python

321

from stix2 import MemoryStore, CompositeDataSource

322

323

# Store related objects

324

store = MemoryStore([

325

threat_actor,

326

malware,

327

uses_malware,

328

indicator,

329

sighting

330

])

331

332

# Resolve relationship targets

333

relationship = store.get(uses_malware.id)

334

source_object = store.get(relationship.source_ref) # ThreatActor

335

target_object = store.get(relationship.target_ref) # Malware

336

337

print(f"{source_object.name} uses {target_object.name}")

338

339

# Find all relationships involving an object

340

threat_actor_relationships = store.query([

341

Filter('type', '=', 'relationship'),

342

Filter('source_ref', '=', threat_actor.id)

343

])

344

345

# Find sightings of an indicator

346

indicator_sightings = store.query([

347

Filter('type', '=', 'sighting'),

348

Filter('sighting_of_ref', '=', indicator.id)

349

])

350

351

# Composite data source for cross-store resolution

352

composite = CompositeDataSource([

353

memory_store,

354

filesystem_store,

355

taxii_store

356

])

357

358

# Resolve references across multiple stores

359

resolved_relationship = composite.get(relationship_id)

360

resolved_source = composite.get(resolved_relationship.source_ref)

361

```

362

363

### Relationship Patterns

364

365

Common patterns for modeling threat intelligence relationships:

366

367

```python

368

# Attribution chain: Campaign -> ThreatActor -> Identity

369

campaign_attribution = Relationship(

370

relationship_type="attributed-to",

371

source_ref=campaign.id,

372

target_ref=threat_actor.id

373

)

374

375

actor_attribution = Relationship(

376

relationship_type="attributed-to",

377

source_ref=threat_actor.id,

378

target_ref=nation_state_identity.id

379

)

380

381

# Attack chain: ThreatActor -> AttackPattern -> Vulnerability -> Software

382

actor_uses_pattern = Relationship(

383

relationship_type="uses",

384

source_ref=threat_actor.id,

385

target_ref=attack_pattern.id

386

)

387

388

pattern_targets_vuln = Relationship(

389

relationship_type="targets",

390

source_ref=attack_pattern.id,

391

target_ref=vulnerability.id

392

)

393

394

vuln_in_software = Relationship(

395

relationship_type="targets",

396

source_ref=vulnerability.id,

397

target_ref=software.id

398

)

399

400

# Infrastructure relationships: C2 -> Malware <- ThreatActor

401

c2_hosts_malware = Relationship(

402

relationship_type="hosts",

403

source_ref=c2_infrastructure.id,

404

target_ref=malware.id

405

)

406

407

actor_uses_c2 = Relationship(

408

relationship_type="uses",

409

source_ref=threat_actor.id,

410

target_ref=c2_infrastructure.id

411

)

412

413

# Mitigation relationships: CourseOfAction -> AttackPattern/Malware

414

mitigation_blocks_pattern = Relationship(

415

relationship_type="mitigates",

416

source_ref=course_of_action.id,

417

target_ref=attack_pattern.id

418

)

419

420

# Indicator relationships: Indicator -> ThreatActor/Malware/Campaign

421

indicator_indicates_actor = Relationship(

422

relationship_type="indicates",

423

source_ref=indicator.id,

424

target_ref=threat_actor.id

425

)

426

427

# Version relationships: Malware -> Malware (variant-of)

428

new_version_relationship = Relationship(

429

relationship_type="variant-of",

430

source_ref=malware_v2.id,

431

target_ref=malware_v1.id,

432

description="Version 2 of the malware family"

433

)

434

```

435

436

### Querying Relationships

437

438

Find and analyze relationships between objects:

439

440

```python

441

# Find all objects a threat actor uses

442

threat_actor_uses = store.query([

443

Filter('type', '=', 'relationship'),

444

Filter('relationship_type', '=', 'uses'),

445

Filter('source_ref', '=', threat_actor.id)

446

])

447

448

for rel in threat_actor_uses:

449

target = store.get(rel.target_ref)

450

print(f"ThreatActor uses {target.type}: {target.name}")

451

452

# Find all indicators that indicate a specific malware

453

malware_indicators = store.query([

454

Filter('type', '=', 'relationship'),

455

Filter('relationship_type', '=', 'indicates'),

456

Filter('target_ref', '=', malware.id)

457

])

458

459

for rel in malware_indicators:

460

indicator = store.get(rel.source_ref)

461

print(f"Indicator: {indicator.name}")

462

463

# Find all sightings by a specific organization

464

org_sightings = store.query([

465

Filter('type', '=', 'sighting'),

466

Filter('where_sighted_refs', 'contains', security_org.id)

467

])

468

469

# Complex relationship queries

470

# Find all malware used by threat actors targeting a specific sector

471

financial_targets = store.query([

472

Filter('type', '=', 'identity'),

473

Filter('sectors', 'contains', 'financial-services')

474

])

475

476

for target in financial_targets:

477

# Find threat actors targeting this identity

478

targeting_rels = store.query([

479

Filter('type', '=', 'relationship'),

480

Filter('relationship_type', '=', 'targets'),

481

Filter('target_ref', '=', target.id)

482

])

483

484

for targeting_rel in targeting_rels:

485

actor = store.get(targeting_rel.source_ref)

486

if actor and actor.type == 'threat-actor':

487

# Find malware used by this actor

488

malware_rels = store.query([

489

Filter('type', '=', 'relationship'),

490

Filter('relationship_type', '=', 'uses'),

491

Filter('source_ref', '=', actor.id)

492

])

493

494

for malware_rel in malware_rels:

495

malware = store.get(malware_rel.target_ref)

496

if malware and malware.type == 'malware':

497

print(f"{actor.name} uses {malware.name} against {target.name}")

498

```