├── GenAI_Stix2_1_Generator.ipynb
└── README.md
/GenAI_Stix2_1_Generator.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "id": "view-in-github",
7 | "colab_type": "text"
8 | },
9 | "source": [
10 | "
"
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {
16 | "editable": true,
17 | "nteract": {
18 | "transient": {
19 | "deleting": false
20 | }
21 | },
22 | "run_control": {
23 | "frozen": false
24 | },
25 | "id": "124VCS5orni9"
26 | },
27 | "source": [
28 | "#GenAI STIX 2.1 Generator\n",
29 | "\n",
30 | "__Notebook Version:__ 0.1
\n",
31 | "__Notebook Author:__ [Antonio Formato](https://www.linkedin.com/in/antonioformato/)
\n",
32 | "\n",
33 | "\n",
34 | "__Python Version:__ >=Python 3.8
\n",
35 | "\n",
36 | "__Python Packages:__\n",
37 | "- requests\n",
38 | "- stix2\n",
39 | "- openai\n",
40 | "- dotenv\n",
41 | "\n",
42 | "## Table of Contents\n",
43 | "\n",
44 | "1. **Web Scraper** for Blog Post Data\n",
45 | "2. Definition of the necessary **functions**\n",
46 | "3. **STIX Domain Objects** - AI SDO Generator\n",
47 | "4. **STIX Domain Objects** - AI SCO Generator\n",
48 | "5. **STIX Domain Objects** - AI SRO Generator\n",
49 | "6. **STIX Bundle Generator**\n",
50 | "7. **STIX viewer**\n",
51 | "\n"
52 | ]
53 | },
54 | {
55 | "cell_type": "markdown",
56 | "metadata": {
57 | "nteract": {
58 | "transient": {
59 | "deleting": false
60 | }
61 | },
62 | "id": "rtLHNcEtrni_"
63 | },
64 | "source": [
65 | "**Initialization**\n",
66 | "\n",
67 | "Please install required python package listed in the description above (pip install packages)."
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "source": [
73 | "!pip3 install python-dotenv\n",
74 | "!pip3 install stix2\n",
75 | "!pip3 install httpx==0.27.2"
76 | ],
77 | "metadata": {
78 | "colab": {
79 | "base_uri": "https://localhost:8080/"
80 | },
81 | "id": "avGM2_xZtySu",
82 | "outputId": "a69bff5e-e9f8-430b-c72b-4f85341ecf57",
83 | "collapsed": true
84 | },
85 | "execution_count": 2,
86 | "outputs": [
87 | {
88 | "output_type": "stream",
89 | "name": "stdout",
90 | "text": [
91 | "Requirement already satisfied: python-dotenv in /usr/local/lib/python3.10/dist-packages (1.0.1)\n",
92 | "Requirement already satisfied: stix2 in /usr/local/lib/python3.10/dist-packages (3.0.1)\n",
93 | "Requirement already satisfied: pytz in /usr/local/lib/python3.10/dist-packages (from stix2) (2024.2)\n",
94 | "Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from stix2) (2.32.3)\n",
95 | "Requirement already satisfied: simplejson in /usr/local/lib/python3.10/dist-packages (from stix2) (3.19.3)\n",
96 | "Requirement already satisfied: stix2-patterns>=1.2.0 in /usr/local/lib/python3.10/dist-packages (from stix2) (2.0.0)\n",
97 | "Requirement already satisfied: antlr4-python3-runtime~=4.9.0 in /usr/local/lib/python3.10/dist-packages (from stix2-patterns>=1.2.0->stix2) (4.9.3)\n",
98 | "Requirement already satisfied: six in /usr/local/lib/python3.10/dist-packages (from stix2-patterns>=1.2.0->stix2) (1.16.0)\n",
99 | "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests->stix2) (3.4.0)\n",
100 | "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests->stix2) (3.10)\n",
101 | "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->stix2) (2.2.3)\n",
102 | "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests->stix2) (2024.8.30)\n",
103 | "Requirement already satisfied: httpx==0.27.2 in /usr/local/lib/python3.10/dist-packages (0.27.2)\n",
104 | "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx==0.27.2) (3.7.1)\n",
105 | "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx==0.27.2) (2024.8.30)\n",
106 | "Requirement already satisfied: httpcore==1.* in /usr/local/lib/python3.10/dist-packages (from httpx==0.27.2) (1.0.7)\n",
107 | "Requirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx==0.27.2) (3.10)\n",
108 | "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx==0.27.2) (1.3.1)\n",
109 | "Requirement already satisfied: h11<0.15,>=0.13 in /usr/local/lib/python3.10/dist-packages (from httpcore==1.*->httpx==0.27.2) (0.14.0)\n",
110 | "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx==0.27.2) (1.2.2)\n"
111 | ]
112 | }
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "metadata": {
118 | "editable": false,
119 | "nteract": {
120 | "transient": {
121 | "deleting": false
122 | }
123 | },
124 | "run_control": {
125 | "frozen": false
126 | },
127 | "id": "FL8V1Za9rnjA"
128 | },
129 | "source": [
130 | "## 1 **Extracting Insights** - Building a Web Scraper\n",
131 | "\n",
132 | "This section implements a web scraper to extract text content from a specified blog post URL (infosec writeup).\n",
133 | "\n",
134 | "Utilizing the requests library and BeautifulSoup (bs4), the code ensures successful retrieval of data before proceeding with the extraction.\n"
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": 3,
140 | "metadata": {
141 | "gather": {
142 | "logged": 1716730479306
143 | },
144 | "jupyter": {
145 | "outputs_hidden": false,
146 | "source_hidden": false
147 | },
148 | "nteract": {
149 | "transient": {
150 | "deleting": false
151 | }
152 | },
153 | "colab": {
154 | "base_uri": "https://localhost:8080/"
155 | },
156 | "id": "3K99_v6VrnjB",
157 | "outputId": "eb9f176e-9f18-4035-e901-a5a341571661"
158 | },
159 | "outputs": [
160 | {
161 | "name": "stdout",
162 | "output_type": "stream",
163 | "text": [
164 | "Enter blog post writeup url and press Enter\n",
165 | "https://cloud.google.com/blog/topics/threat-intelligence/untangling-iran-apt42-operations/\n"
166 | ]
167 | }
168 | ],
169 | "source": [
170 | " #Web scraper\n",
171 | " import requests\n",
172 | " from bs4 import BeautifulSoup\n",
173 | " import pandas as pd\n",
174 | "\n",
175 | " def scrape_text(url):\n",
176 | " # Add user-agent to avoid issue when scrapping most website\n",
177 | " headers = {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\"}\n",
178 | "\n",
179 | " # Send a GET request to the URL\n",
180 | " response = requests.get(url, headers=headers)\n",
181 | "\n",
182 | " # If the GET request is successful, the status code will be 200\n",
183 | " if response.status_code == 200:\n",
184 | " # Get the content of the response\n",
185 | " page_content = response.content\n",
186 | " # Create a BeautifulSoup object and specify the parser\n",
187 | " soup = BeautifulSoup(page_content, \"html.parser\")\n",
188 | " # Get the text of the soup object\n",
189 | " text = soup.get_text()\n",
190 | " # Return the text\n",
191 | " return text\n",
192 | " else:\n",
193 | " return \"Failed to scrape the website\"\n",
194 | "\n",
195 | " # Enter site\n",
196 | " print(\"Enter blog post writeup url and press Enter\")\n",
197 | " url = input()\n",
198 | "\n",
199 | " text = scrape_text(url)"
200 | ]
201 | },
202 | {
203 | "cell_type": "markdown",
204 | "metadata": {
205 | "editable": false,
206 | "nteract": {
207 | "transient": {
208 | "deleting": false
209 | }
210 | },
211 | "run_control": {
212 | "frozen": false
213 | },
214 | "id": "5AG-siCwrnjG"
215 | },
216 | "source": [
217 | "## 2 Definition of the necessary functions\n",
218 | "\n",
219 | "Below is the definition of the prerequisite functions for the notebook:\n",
220 | "\n",
221 | "\n",
222 | "* **add_uuid_to_ids** --> Add UUIDs in 'id' field in STIX object\n",
223 | "* **validate_stix_objects** --> Validate STIX objects against the STIX 2.1 standard\n",
224 | "\n",
225 | "\n"
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": 4,
231 | "metadata": {
232 | "gather": {
233 | "logged": 1716730481635
234 | },
235 | "jupyter": {
236 | "outputs_hidden": false,
237 | "source_hidden": false
238 | },
239 | "nteract": {
240 | "transient": {
241 | "deleting": false
242 | }
243 | },
244 | "id": "sMK_KjpHrnjH"
245 | },
246 | "outputs": [],
247 | "source": [
248 | "# Add UUIDs to 'id' fields in STIX objects, ensuring each object has a unique identifier.\n",
249 | "def add_uuid_to_ids(stix_data):\n",
250 | " \"\"\"\n",
251 | " Add UUIDs to 'id' fields in STIX objects.\n",
252 | " \"\"\"\n",
253 | " for item in stix_data:\n",
254 | " if 'id' in item:\n",
255 | " object_type = item['type']\n",
256 | " item['id'] = f\"{object_type}--{uuid.uuid4()}\"\n",
257 | " return stix_data\n",
258 | "\n",
259 | "#Validate a list of STIX objects against the STIX 2.1 standard, identifying any invalid objects.\n",
260 | "def validate_stix_objects(stix_objects):\n",
261 | " \"\"\"\n",
262 | " Validate STIX objects against the STIX 2.1 standard.\n",
263 | " \"\"\"\n",
264 | " all_valid = True\n",
265 | " invalid_objects = []\n",
266 | " for obj in stix_objects:\n",
267 | " try:\n",
268 | " # Parse the object to validate against the STIX 2.1 standard\n",
269 | " stix_obj = parse(json.dumps(obj), allow_custom=True)\n",
270 | " print(f\"Validation passed for object ID: {obj.get('id')}\")\n",
271 | " except exceptions.STIXError as se:\n",
272 | " print(f\"STIX parsing error for object ID {obj.get('id')}: {se}\")\n",
273 | " invalid_objects.append(obj)\n",
274 | " all_valid = False\n",
275 | " except json.JSONDecodeError as je:\n",
276 | " print(f\"JSON parsing error: {je}\")\n",
277 | " invalid_objects.append(obj)\n",
278 | " all_valid = False\n",
279 | " return all_valid, invalid_objects"
280 | ]
281 | },
282 | {
283 | "cell_type": "markdown",
284 | "source": [
285 | "**Environment variables**\n",
286 | "\n",
287 | "In this notebook is used Azure OpenAI istance.\n",
288 | "\n",
289 | "The notebook has been tested with **GPT-4o** in Azure OpenAI.\n"
290 | ],
291 | "metadata": {
292 | "id": "_kJ1_dJdSoU-"
293 | }
294 | },
295 | {
296 | "cell_type": "code",
297 | "source": [
298 | "# Setup Azure OpenAI environment\n",
299 | "import os\n",
300 | "from openai import AzureOpenAI\n",
301 | "from dotenv import load_dotenv\n",
302 | "from google.colab import userdata\n",
303 | "import json\n",
304 | "\n",
305 | "temperature = 0.7\n",
306 | "\n",
307 | "# Set up Azure OpenAI client\n",
308 | "# Store your env variables in Colab Secret configuration\n",
309 | "client = AzureOpenAI(\n",
310 | " azure_endpoint = userdata.get('AZURE_OPENAI_ENDPOINT'),\n",
311 | " api_key=userdata.get('AZURE_OPENAI_KEY'),\n",
312 | " api_version=\"2023-05-15\"\n",
313 | "\n",
314 | ")"
315 | ],
316 | "metadata": {
317 | "id": "1cJS1ZNOvxd7"
318 | },
319 | "execution_count": 6,
320 | "outputs": []
321 | },
322 | {
323 | "cell_type": "markdown",
324 | "source": [
325 | "## 3 STIX Domain Objects - **AI SDO Generator**\n",
326 | "\n",
327 | "STIX 2.1 Domain Objects (SDOs) genearator.\n",
328 | "\n",
329 | "Definition of the prompt for generating STIX 2.1 Domain Objects and **SDO generator**"
330 | ],
331 | "metadata": {
332 | "id": "eviORN1Z9no4"
333 | }
334 | },
335 | {
336 | "cell_type": "code",
337 | "execution_count": 7,
338 | "metadata": {
339 | "gather": {
340 | "logged": 1716730484793
341 | },
342 | "jupyter": {
343 | "outputs_hidden": false,
344 | "source_hidden": false
345 | },
346 | "nteract": {
347 | "transient": {
348 | "deleting": false
349 | }
350 | },
351 | "id": "AMUHMC0trnjI"
352 | },
353 | "outputs": [],
354 | "source": [
355 | "#STIX Domain Objects prompt\n",
356 | "system_prompt_sdo = (\n",
357 | " \"You are tasked with creating STIX 2.1 Domain Objects (SDOs) from the provided threat intelligence text.\"\n",
358 | " \"Possible SDOs include: Attack Pattern, Campaign, Course of Action, Identity, Indicator, Intrusion Set, Malware, Observed Data, Report, Threat Actor, Tool, Vulnerability, Infrastructure, Relationship, Sighting, Note, Opinion, Grouping, Incident, Location, Malware Analysis.\"\n",
359 | " \"Create relevant SDOs in JSON format, strictly adhering to the STIX 2.1 specification.\"\n",
360 | " \"Ensure the output is a valid JSON array ([...]) containing only SDOs identified with high confidence.\"\n",
361 | " \"The is_family field indicates whether the malware is a family (if true) or an instance (if false). The values true or false are always enclosed in quotes.\"\n",
362 | " \"For id property write just SDO_type-- following this example: \\\"id\\\": \\\"malware--\\\"\"\n",
363 | " \"Timestamp must be in ISO 8601 format.\"\n",
364 | " \"Don't use created_by_ref and source_ref\"\n",
365 | " \"The labels property in malware is used to categorize or tag the malware object with descriptive terms (e.g., \\\"trojan\\\", \\\"backdoor\\\", \\\"ransomware\\\"), Must contain at least one string.\"\n",
366 | " \"threat-actor labels property should be an array of strings representing categories or descriptive terms for the threat actor.\"\n",
367 | " \"Return only the JSON array, without any additional text, commentary, or code block delimiters (e.g., json).\"\n",
368 | ")\n",
369 | "\n",
370 | "user_prompt_stix = f\"Text: {text}\""
371 | ]
372 | },
373 | {
374 | "cell_type": "markdown",
375 | "metadata": {
376 | "editable": true,
377 | "nteract": {
378 | "transient": {
379 | "deleting": false
380 | }
381 | },
382 | "run_control": {
383 | "frozen": false
384 | },
385 | "id": "Tw_vCw6ZrnjJ"
386 | },
387 | "source": [
388 | "**STIX 2.1 SDO generator**"
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "source": [
394 | "# STIX 2.1 SDO Generator\n",
395 | "import uuid\n",
396 | "import json\n",
397 | "from stix2 import parse, exceptions\n",
398 | "\n",
399 | "# SDO Generator\n",
400 | "def sdo_stix(text):\n",
401 | " # Define the SYSTEM prompt\n",
402 | " response = client.chat.completions.create(\n",
403 | " model=userdata.get('DEPLOYMENT_NAME'),\n",
404 | " messages=[\n",
405 | " {\"role\": \"system\", \"content\": system_prompt_sdo},\n",
406 | " {\"role\": \"user\", \"content\": user_prompt_stix}\n",
407 | " ],\n",
408 | " temperature=temperature\n",
409 | " )\n",
410 | " return response.choices[0].message.content\n",
411 | "\n",
412 | "def correct_invalid_stix(text, invalid_objects, original_stix):\n",
413 | " \"\"\"\n",
414 | " Ask the LLM to correct invalid STIX output based on the original text and invalid objects.\n",
415 | " \"\"\"\n",
416 | " # Create a focused invalid output section\n",
417 | " invalid_output = json.dumps(invalid_objects, indent=4)\n",
418 | " response = client.chat.completions.create(\n",
419 | " model=userdata.get('DEPLOYMENT_NAME'),\n",
420 | " messages=[\n",
421 | " {\"role\": \"system\", \"content\": system_prompt_sdo},\n",
422 | " {\n",
423 | " \"role\": \"user\",\n",
424 | " \"content\": f\"\"\"\n",
425 | "Correct the following invalid STIX objects based on the original text and ensure consistency with the overall STIX data:\n",
426 | "\n",
427 | "Input text:\n",
428 | "{text}\n",
429 | "\n",
430 | "Invalid STIX objects:\n",
431 | "{invalid_output}\n",
432 | "\n",
433 | "Existing valid STIX data:\n",
434 | "{original_stix}\n",
435 | "\"\"\"\n",
436 | " }\n",
437 | " ],\n",
438 | " temperature=temperature\n",
439 | " )\n",
440 | " return response.choices[0].message.content\n",
441 | "\n",
442 | "# Generate STIX data and ensure valid output\n",
443 | "is_valid = False\n",
444 | "stix_sdo = \"\"\n",
445 | "\n",
446 | "while not is_valid:\n",
447 | " # Generate STIX SDO from the LLM\n",
448 | " stix_sdo = sdo_stix(text)\n",
449 | "\n",
450 | " try:\n",
451 | " # Parse STIX SDO string to a Python list\n",
452 | " stix_data = json.loads(stix_sdo)\n",
453 | " if not isinstance(stix_data, list):\n",
454 | " raise ValueError(\"Parsed STIX SDO must be a list of dictionaries.\")\n",
455 | "\n",
456 | " # Add UUIDs to IDs\n",
457 | " stix_data = add_uuid_to_ids(stix_data)\n",
458 | "\n",
459 | " # Print STIX data after UUIDs have been inserted\n",
460 | " print(\"\\nSTIX data after UUID insertion:\")\n",
461 | " print(json.dumps(stix_data, indent=4))\n",
462 | "\n",
463 | " # Validate STIX objects\n",
464 | " is_valid, invalid_objects = validate_stix_objects(stix_data)\n",
465 | "\n",
466 | " if not is_valid:\n",
467 | " print(\"Validation failed. Requesting correction from LLM...\")\n",
468 | " stix_sdo = correct_invalid_stix(text, invalid_objects, stix_sdo)\n",
469 | " else:\n",
470 | " print(\"Validation successful. All objects are valid.\")\n",
471 | "\n",
472 | " except json.JSONDecodeError as e:\n",
473 | " print(f\"Error parsing STIX SDO: {e}\")\n",
474 | " stix_sdo = correct_invalid_stix(text, [], stix_sdo)\n",
475 | " except ValueError as e:\n",
476 | " print(e)\n",
477 | " stix_sdo = correct_invalid_stix(text, [], stix_sdo)\n",
478 | "\n",
479 | "# Final validated STIX SDO as JSON string\n",
480 | "stix_sdo = json.dumps(stix_data, indent=4)\n",
481 | "print(stix_sdo)"
482 | ],
483 | "metadata": {
484 | "colab": {
485 | "base_uri": "https://localhost:8080/"
486 | },
487 | "id": "sfBqSXi1wAXl",
488 | "outputId": "c0ea28ec-c818-4562-ff6f-6c2bbc451004"
489 | },
490 | "execution_count": 9,
491 | "outputs": [
492 | {
493 | "output_type": "stream",
494 | "name": "stdout",
495 | "text": [
496 | "\n",
497 | "STIX data after UUID insertion:\n",
498 | "[\n",
499 | " {\n",
500 | " \"type\": \"threat-actor\",\n",
501 | " \"id\": \"threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\",\n",
502 | " \"name\": \"APT42\",\n",
503 | " \"description\": \"APT42 is an Iranian state-sponsored cyber espionage actor targeting Western and Middle Eastern NGOs, media organizations, academia, legal services, and activists. It operates on behalf of the Islamic Revolutionary Guard Corps Intelligence Organization (IRGC-IO).\",\n",
504 | " \"labels\": [\n",
505 | " \"state-sponsored\",\n",
506 | " \"cyber-espionage\",\n",
507 | " \"Iranian\"\n",
508 | " ],\n",
509 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
510 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
511 | " },\n",
512 | " {\n",
513 | " \"type\": \"intrusion-set\",\n",
514 | " \"id\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
515 | " \"name\": \"APT42 Operations\",\n",
516 | " \"description\": \"APT42 uses enhanced social engineering schemes to gain access to victim networks, including cloud environments, by harvesting credentials and using them to gain initial access. It exfiltrates data of strategic interest to Iran, using built-in features and open-source tools to avoid detection.\",\n",
517 | " \"labels\": [\n",
518 | " \"intrusion-set\",\n",
519 | " \"APT42\"\n",
520 | " ],\n",
521 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
522 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
523 | " },\n",
524 | " {\n",
525 | " \"type\": \"malware\",\n",
526 | " \"id\": \"malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\",\n",
527 | " \"name\": \"NICECURL\",\n",
528 | " \"description\": \"NICECURL is a backdoor written in VBScript that can download additional modules to be executed, including data mining and arbitrary command execution.\",\n",
529 | " \"is_family\": \"true\",\n",
530 | " \"labels\": [\n",
531 | " \"backdoor\",\n",
532 | " \"VBScript\"\n",
533 | " ],\n",
534 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
535 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
536 | " },\n",
537 | " {\n",
538 | " \"type\": \"malware\",\n",
539 | " \"id\": \"malware--00c9240a-4365-4101-8be4-66a0bc8f0530\",\n",
540 | " \"name\": \"TAMECAT\",\n",
541 | " \"description\": \"TAMECAT is a PowerShell toehold that can execute arbitrary PowerShell or C# content. It is used by APT42 to gain initial access to targets.\",\n",
542 | " \"is_family\": \"true\",\n",
543 | " \"labels\": [\n",
544 | " \"PowerShell\",\n",
545 | " \"backdoor\"\n",
546 | " ],\n",
547 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
548 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
549 | " },\n",
550 | " {\n",
551 | " \"type\": \"campaign\",\n",
552 | " \"id\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
553 | " \"name\": \"APT42 Credential Harvesting Operations\",\n",
554 | " \"description\": \"APT42 conducts extensive credential harvesting operations through spear-phishing campaigns and social engineering, targeting individuals and organizations in policy, government, media, and NGOs.\",\n",
555 | " \"labels\": [\n",
556 | " \"credential-harvesting\",\n",
557 | " \"spear-phishing\"\n",
558 | " ],\n",
559 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
560 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
561 | " }\n",
562 | "]\n",
563 | "Validation passed for object ID: threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\n",
564 | "Validation passed for object ID: intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\n",
565 | "Validation passed for object ID: malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\n",
566 | "Validation passed for object ID: malware--00c9240a-4365-4101-8be4-66a0bc8f0530\n",
567 | "Validation passed for object ID: campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\n",
568 | "Validation successful. All objects are valid.\n",
569 | "[\n",
570 | " {\n",
571 | " \"type\": \"threat-actor\",\n",
572 | " \"id\": \"threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\",\n",
573 | " \"name\": \"APT42\",\n",
574 | " \"description\": \"APT42 is an Iranian state-sponsored cyber espionage actor targeting Western and Middle Eastern NGOs, media organizations, academia, legal services, and activists. It operates on behalf of the Islamic Revolutionary Guard Corps Intelligence Organization (IRGC-IO).\",\n",
575 | " \"labels\": [\n",
576 | " \"state-sponsored\",\n",
577 | " \"cyber-espionage\",\n",
578 | " \"Iranian\"\n",
579 | " ],\n",
580 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
581 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
582 | " },\n",
583 | " {\n",
584 | " \"type\": \"intrusion-set\",\n",
585 | " \"id\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
586 | " \"name\": \"APT42 Operations\",\n",
587 | " \"description\": \"APT42 uses enhanced social engineering schemes to gain access to victim networks, including cloud environments, by harvesting credentials and using them to gain initial access. It exfiltrates data of strategic interest to Iran, using built-in features and open-source tools to avoid detection.\",\n",
588 | " \"labels\": [\n",
589 | " \"intrusion-set\",\n",
590 | " \"APT42\"\n",
591 | " ],\n",
592 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
593 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
594 | " },\n",
595 | " {\n",
596 | " \"type\": \"malware\",\n",
597 | " \"id\": \"malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\",\n",
598 | " \"name\": \"NICECURL\",\n",
599 | " \"description\": \"NICECURL is a backdoor written in VBScript that can download additional modules to be executed, including data mining and arbitrary command execution.\",\n",
600 | " \"is_family\": \"true\",\n",
601 | " \"labels\": [\n",
602 | " \"backdoor\",\n",
603 | " \"VBScript\"\n",
604 | " ],\n",
605 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
606 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
607 | " },\n",
608 | " {\n",
609 | " \"type\": \"malware\",\n",
610 | " \"id\": \"malware--00c9240a-4365-4101-8be4-66a0bc8f0530\",\n",
611 | " \"name\": \"TAMECAT\",\n",
612 | " \"description\": \"TAMECAT is a PowerShell toehold that can execute arbitrary PowerShell or C# content. It is used by APT42 to gain initial access to targets.\",\n",
613 | " \"is_family\": \"true\",\n",
614 | " \"labels\": [\n",
615 | " \"PowerShell\",\n",
616 | " \"backdoor\"\n",
617 | " ],\n",
618 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
619 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
620 | " },\n",
621 | " {\n",
622 | " \"type\": \"campaign\",\n",
623 | " \"id\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
624 | " \"name\": \"APT42 Credential Harvesting Operations\",\n",
625 | " \"description\": \"APT42 conducts extensive credential harvesting operations through spear-phishing campaigns and social engineering, targeting individuals and organizations in policy, government, media, and NGOs.\",\n",
626 | " \"labels\": [\n",
627 | " \"credential-harvesting\",\n",
628 | " \"spear-phishing\"\n",
629 | " ],\n",
630 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
631 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
632 | " }\n",
633 | "]\n"
634 | ]
635 | }
636 | ]
637 | },
638 | {
639 | "cell_type": "markdown",
640 | "source": [
641 | "## 4 STIX Cyber-Observable Objects - **AI SCO Generator**\n",
642 | "\n",
643 | "STIX 2.1 Cyber-Observable Objects (SCOs) generator.\n",
644 | "\n",
645 | "Definition of the prompt for generating STIX 2.1 Cyber-Observable Objects and **SCO generator**"
646 | ],
647 | "metadata": {
648 | "id": "CHDD1xc699Zi"
649 | }
650 | },
651 | {
652 | "cell_type": "code",
653 | "execution_count": 10,
654 | "metadata": {
655 | "gather": {
656 | "logged": 1716730662309
657 | },
658 | "jupyter": {
659 | "outputs_hidden": false,
660 | "source_hidden": false
661 | },
662 | "nteract": {
663 | "transient": {
664 | "deleting": false
665 | }
666 | },
667 | "id": "SQNaKU6mrnjM"
668 | },
669 | "outputs": [],
670 | "source": [
671 | "#STIX Cyber-observable Object prompt\n",
672 | "system_prompt_sco = (\n",
673 | " \"You are tasked with creating STIX 2.1 Cyber-observable Objects (SCOs) based on the provided threat intelligence write-up.\"\n",
674 | " \"SCOs include: Artifact, Autonomous System, Directory, Domain Name, Email Address, Email Message, File, IPv4 Address, IPv6 Address, MAC Address, Mutex, Network Traffic, Process, Software, URL, User Account, Windows Registry Key, X.509 Certificate, HTTP Request, ICMP, Socket Ext, TCP Ext, Archive Ext, Raster Image Ext, NTFS Ext, PDF Ext, UNIX Account Ext, Windows PE Binary Ext, Windows Process Ext, Windows Service Ext, Windows Registry Ext, JPEG File Ext, Email MIME Component, Email MIME Multipart Type, Email MIME Message Type, Email MIME Text Type.\"\n",
675 | " \"Create relevant STIX 2.1 SCOs in JSON format based on the information provided in the text.\"\n",
676 | " \"Strictly follow the STIX 2.1 specification, ensuring no properties are used that are not defined in the specification\"\n",
677 | " \"Ensure the JSON output is valid, starting with [ and closing with ].\"\n",
678 | " \"STIX SCO objects require at least type, id and value properties\"\n",
679 | " \"Only provide output if one or more SCOs can be identified with reasonable certainty from the text.\"\n",
680 | " \"Ensure the structure and format are fully compliant with STIX 2.1.\"\n",
681 | " \"id STIX identifier must match --\"\n",
682 | " \"Return only the JSON array, without any additional text, commentary, or code block delimiters (e.g., json).\"\n",
683 | " )"
684 | ]
685 | },
686 | {
687 | "cell_type": "markdown",
688 | "source": [
689 | "**STIX 2.1 SCO generator**"
690 | ],
691 | "metadata": {
692 | "id": "mQ02btal4z0C"
693 | }
694 | },
695 | {
696 | "cell_type": "code",
697 | "source": [
698 | "# STIX 2.1 SCO Generator\n",
699 | "import uuid\n",
700 | "import json\n",
701 | "from stix2 import parse, exceptions\n",
702 | "\n",
703 | "# SCO Generator\n",
704 | "def sco_stix(text):\n",
705 | " \"\"\"\n",
706 | " Generate STIX SCOs using the LLM.\n",
707 | " \"\"\"\n",
708 | " response = client.chat.completions.create(\n",
709 | " model=userdata.get('DEPLOYMENT_NAME'),\n",
710 | " messages=[\n",
711 | " {\"role\": \"system\", \"content\": system_prompt_sco},\n",
712 | " {\"role\": \"user\", \"content\": user_prompt_stix}\n",
713 | " ],\n",
714 | " temperature=temperature\n",
715 | " )\n",
716 | " return response.choices[0].message.content\n",
717 | "\n",
718 | "def correct_invalid_stix(text, invalid_objects, original_stix):\n",
719 | " \"\"\"\n",
720 | " Ask the LLM to correct invalid STIX output based on the original text and invalid objects.\n",
721 | " \"\"\"\n",
722 | " # Create a focused invalid output section\n",
723 | " invalid_output = json.dumps(invalid_objects, indent=4)\n",
724 | " response = client.chat.completions.create(\n",
725 | " model=userdata.get('DEPLOYMENT_NAME'),\n",
726 | " messages=[\n",
727 | " {\"role\": \"system\", \"content\": system_prompt_sco},\n",
728 | " {\n",
729 | " \"role\": \"user\",\n",
730 | " \"content\": f\"\"\"\n",
731 | "Correct the following invalid STIX objects based on the original text and ensure consistency with the overall STIX data:\n",
732 | "\n",
733 | "Input text:\n",
734 | "{text}\n",
735 | "\n",
736 | "Invalid STIX objects:\n",
737 | "{invalid_output}\n",
738 | "\n",
739 | "Existing valid STIX data:\n",
740 | "{original_stix}\n",
741 | "\"\"\"\n",
742 | " }\n",
743 | " ],\n",
744 | " temperature=temperature\n",
745 | " )\n",
746 | " return response.choices[0].message.content\n",
747 | "\n",
748 | "# Generate and validate STIX SCO\n",
749 | "is_valid = False\n",
750 | "stix_sco = \"\"\n",
751 | "\n",
752 | "while not is_valid:\n",
753 | " # Generate STIX SCO from the LLM\n",
754 | " stix_sco = sco_stix(text)\n",
755 | "\n",
756 | " try:\n",
757 | " # Parse STIX SCO string to a Python list\n",
758 | " stix_data = json.loads(stix_sco)\n",
759 | " if not isinstance(stix_data, list):\n",
760 | " raise ValueError(\"Parsed STIX SCO must be a list of dictionaries.\")\n",
761 | "\n",
762 | " # Add UUIDs to IDs\n",
763 | " stix_data = add_uuid_to_ids(stix_data)\n",
764 | "\n",
765 | " # Print STIX data after UUIDs have been inserted\n",
766 | " print(\"\\nSTIX SCO data after UUID insertion:\")\n",
767 | " print(json.dumps(stix_data, indent=4))\n",
768 | "\n",
769 | " # Validate STIX objects\n",
770 | " is_valid, invalid_objects = validate_stix_objects(stix_data)\n",
771 | "\n",
772 | " if not is_valid:\n",
773 | " print(\"Validation failed. Requesting correction from LLM...\")\n",
774 | " stix_sco = correct_invalid_stix(text, invalid_objects, stix_sco)\n",
775 | " else:\n",
776 | " print(\"Validation successful. All objects are valid.\")\n",
777 | "\n",
778 | " except json.JSONDecodeError as e:\n",
779 | " print(f\"Error parsing STIX SCO: {e}\")\n",
780 | " stix_sco = correct_invalid_stix(text, [], stix_sco)\n",
781 | " except ValueError as e:\n",
782 | " print(e)\n",
783 | " stix_sco = correct_invalid_stix(text, [], stix_sco)\n",
784 | "\n",
785 | "# Final validated STIX SCO as JSON string\n",
786 | "stix_sco = json.dumps(stix_data, indent=4)\n",
787 | "print(stix_sco)"
788 | ],
789 | "metadata": {
790 | "colab": {
791 | "base_uri": "https://localhost:8080/"
792 | },
793 | "id": "7AZa_Nxiqfxj",
794 | "outputId": "0ff9736e-f958-42c9-992b-e93c60c05dd1"
795 | },
796 | "execution_count": 11,
797 | "outputs": [
798 | {
799 | "output_type": "stream",
800 | "name": "stdout",
801 | "text": [
802 | "\n",
803 | "STIX SCO data after UUID insertion:\n",
804 | "[\n",
805 | " {\n",
806 | " \"type\": \"domain-name\",\n",
807 | " \"id\": \"domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\",\n",
808 | " \"value\": \"washinqtonpost.press\"\n",
809 | " },\n",
810 | " {\n",
811 | " \"type\": \"domain-name\",\n",
812 | " \"id\": \"domain-name--31e83530-c412-47f0-a636-f35293916b52\",\n",
813 | " \"value\": \"ksview.top\"\n",
814 | " },\n",
815 | " {\n",
816 | " \"type\": \"domain-name\",\n",
817 | " \"id\": \"domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\",\n",
818 | " \"value\": \"honest-halcyon-fresher.buzz\"\n",
819 | " },\n",
820 | " {\n",
821 | " \"type\": \"domain-name\",\n",
822 | " \"id\": \"domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\",\n",
823 | " \"value\": \"n9.cl\"\n",
824 | " },\n",
825 | " {\n",
826 | " \"type\": \"domain-name\",\n",
827 | " \"id\": \"domain-name--8fdd479b-587b-434c-95f5-499165203aac\",\n",
828 | " \"value\": \"review.modification-check.online\"\n",
829 | " },\n",
830 | " {\n",
831 | " \"type\": \"domain-name\",\n",
832 | " \"id\": \"domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\",\n",
833 | " \"value\": \"nterview.site\"\n",
834 | " },\n",
835 | " {\n",
836 | " \"type\": \"domain-name\",\n",
837 | " \"id\": \"domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\",\n",
838 | " \"value\": \"admin-stable-right.top\"\n",
839 | " },\n",
840 | " {\n",
841 | " \"type\": \"domain-name\",\n",
842 | " \"id\": \"domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\",\n",
843 | " \"value\": \"shortlinkview.live\"\n",
844 | " },\n",
845 | " {\n",
846 | " \"type\": \"domain-name\",\n",
847 | " \"id\": \"domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\",\n",
848 | " \"value\": \"reconsider.site\"\n",
849 | " },\n",
850 | " {\n",
851 | " \"type\": \"domain-name\",\n",
852 | " \"id\": \"domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\",\n",
853 | " \"value\": \"last-check-leave.buzz\"\n",
854 | " },\n",
855 | " {\n",
856 | " \"type\": \"domain-name\",\n",
857 | " \"id\": \"domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\",\n",
858 | " \"value\": \"email-daemon.online\"\n",
859 | " },\n",
860 | " {\n",
861 | " \"type\": \"domain-name\",\n",
862 | " \"id\": \"domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\",\n",
863 | " \"value\": \"onmicrosofl.com\"\n",
864 | " },\n",
865 | " {\n",
866 | " \"type\": \"domain-name\",\n",
867 | " \"id\": \"domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\",\n",
868 | " \"value\": \"bitly.org.il\"\n",
869 | " },\n",
870 | " {\n",
871 | " \"type\": \"domain-name\",\n",
872 | " \"id\": \"domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\",\n",
873 | " \"value\": \"youtransfer.live\"\n",
874 | " },\n",
875 | " {\n",
876 | " \"type\": \"domain-name\",\n",
877 | " \"id\": \"domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\",\n",
878 | " \"value\": \"drive-file-share.site\"\n",
879 | " },\n",
880 | " {\n",
881 | " \"type\": \"domain-name\",\n",
882 | " \"id\": \"domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\",\n",
883 | " \"value\": \"prism-west-candy.glitch.me\"\n",
884 | " },\n",
885 | " {\n",
886 | " \"type\": \"domain-name\",\n",
887 | " \"id\": \"domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\",\n",
888 | " \"value\": \"worried-eastern-salto.glitch.me\"\n",
889 | " },\n",
890 | " {\n",
891 | " \"type\": \"domain-name\",\n",
892 | " \"id\": \"domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\",\n",
893 | " \"value\": \"tnt200.mywire.org\"\n",
894 | " },\n",
895 | " {\n",
896 | " \"type\": \"domain-name\",\n",
897 | " \"id\": \"domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\",\n",
898 | " \"value\": \"accurate-sprout-porpoise.glitch.me\"\n",
899 | " }\n",
900 | "]\n",
901 | "Validation passed for object ID: domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\n",
902 | "Validation passed for object ID: domain-name--31e83530-c412-47f0-a636-f35293916b52\n",
903 | "Validation passed for object ID: domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\n",
904 | "Validation passed for object ID: domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\n",
905 | "Validation passed for object ID: domain-name--8fdd479b-587b-434c-95f5-499165203aac\n",
906 | "Validation passed for object ID: domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\n",
907 | "Validation passed for object ID: domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\n",
908 | "Validation passed for object ID: domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\n",
909 | "Validation passed for object ID: domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\n",
910 | "Validation passed for object ID: domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\n",
911 | "Validation passed for object ID: domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\n",
912 | "Validation passed for object ID: domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\n",
913 | "Validation passed for object ID: domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\n",
914 | "Validation passed for object ID: domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\n",
915 | "Validation passed for object ID: domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\n",
916 | "Validation passed for object ID: domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\n",
917 | "Validation passed for object ID: domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\n",
918 | "Validation passed for object ID: domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\n",
919 | "Validation passed for object ID: domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\n",
920 | "Validation successful. All objects are valid.\n",
921 | "[\n",
922 | " {\n",
923 | " \"type\": \"domain-name\",\n",
924 | " \"id\": \"domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\",\n",
925 | " \"value\": \"washinqtonpost.press\"\n",
926 | " },\n",
927 | " {\n",
928 | " \"type\": \"domain-name\",\n",
929 | " \"id\": \"domain-name--31e83530-c412-47f0-a636-f35293916b52\",\n",
930 | " \"value\": \"ksview.top\"\n",
931 | " },\n",
932 | " {\n",
933 | " \"type\": \"domain-name\",\n",
934 | " \"id\": \"domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\",\n",
935 | " \"value\": \"honest-halcyon-fresher.buzz\"\n",
936 | " },\n",
937 | " {\n",
938 | " \"type\": \"domain-name\",\n",
939 | " \"id\": \"domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\",\n",
940 | " \"value\": \"n9.cl\"\n",
941 | " },\n",
942 | " {\n",
943 | " \"type\": \"domain-name\",\n",
944 | " \"id\": \"domain-name--8fdd479b-587b-434c-95f5-499165203aac\",\n",
945 | " \"value\": \"review.modification-check.online\"\n",
946 | " },\n",
947 | " {\n",
948 | " \"type\": \"domain-name\",\n",
949 | " \"id\": \"domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\",\n",
950 | " \"value\": \"nterview.site\"\n",
951 | " },\n",
952 | " {\n",
953 | " \"type\": \"domain-name\",\n",
954 | " \"id\": \"domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\",\n",
955 | " \"value\": \"admin-stable-right.top\"\n",
956 | " },\n",
957 | " {\n",
958 | " \"type\": \"domain-name\",\n",
959 | " \"id\": \"domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\",\n",
960 | " \"value\": \"shortlinkview.live\"\n",
961 | " },\n",
962 | " {\n",
963 | " \"type\": \"domain-name\",\n",
964 | " \"id\": \"domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\",\n",
965 | " \"value\": \"reconsider.site\"\n",
966 | " },\n",
967 | " {\n",
968 | " \"type\": \"domain-name\",\n",
969 | " \"id\": \"domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\",\n",
970 | " \"value\": \"last-check-leave.buzz\"\n",
971 | " },\n",
972 | " {\n",
973 | " \"type\": \"domain-name\",\n",
974 | " \"id\": \"domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\",\n",
975 | " \"value\": \"email-daemon.online\"\n",
976 | " },\n",
977 | " {\n",
978 | " \"type\": \"domain-name\",\n",
979 | " \"id\": \"domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\",\n",
980 | " \"value\": \"onmicrosofl.com\"\n",
981 | " },\n",
982 | " {\n",
983 | " \"type\": \"domain-name\",\n",
984 | " \"id\": \"domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\",\n",
985 | " \"value\": \"bitly.org.il\"\n",
986 | " },\n",
987 | " {\n",
988 | " \"type\": \"domain-name\",\n",
989 | " \"id\": \"domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\",\n",
990 | " \"value\": \"youtransfer.live\"\n",
991 | " },\n",
992 | " {\n",
993 | " \"type\": \"domain-name\",\n",
994 | " \"id\": \"domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\",\n",
995 | " \"value\": \"drive-file-share.site\"\n",
996 | " },\n",
997 | " {\n",
998 | " \"type\": \"domain-name\",\n",
999 | " \"id\": \"domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\",\n",
1000 | " \"value\": \"prism-west-candy.glitch.me\"\n",
1001 | " },\n",
1002 | " {\n",
1003 | " \"type\": \"domain-name\",\n",
1004 | " \"id\": \"domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\",\n",
1005 | " \"value\": \"worried-eastern-salto.glitch.me\"\n",
1006 | " },\n",
1007 | " {\n",
1008 | " \"type\": \"domain-name\",\n",
1009 | " \"id\": \"domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\",\n",
1010 | " \"value\": \"tnt200.mywire.org\"\n",
1011 | " },\n",
1012 | " {\n",
1013 | " \"type\": \"domain-name\",\n",
1014 | " \"id\": \"domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\",\n",
1015 | " \"value\": \"accurate-sprout-porpoise.glitch.me\"\n",
1016 | " }\n",
1017 | "]\n"
1018 | ]
1019 | }
1020 | ]
1021 | },
1022 | {
1023 | "cell_type": "markdown",
1024 | "source": [
1025 | "## 5 STIX Relationship Objects - **AI SRO Generator**\n",
1026 | "\n",
1027 | "STIX 2.1 Relationship Objects (SROs) generator.\n",
1028 | "\n",
1029 | "Definition of the prompt for generating STIX 2.1 Relationship Objects and **SRO generator**\n"
1030 | ],
1031 | "metadata": {
1032 | "id": "4Mhp-pRj-F5L"
1033 | }
1034 | },
1035 | {
1036 | "cell_type": "code",
1037 | "execution_count": 12,
1038 | "metadata": {
1039 | "gather": {
1040 | "logged": 1716730845189
1041 | },
1042 | "jupyter": {
1043 | "outputs_hidden": false,
1044 | "source_hidden": false
1045 | },
1046 | "nteract": {
1047 | "transient": {
1048 | "deleting": false
1049 | }
1050 | },
1051 | "id": "t_RjRwIgrnjN"
1052 | },
1053 | "outputs": [],
1054 | "source": [
1055 | "#STIX Relationship Object prompt\n",
1056 | "system_prompt_sro = (\n",
1057 | " \"You are tasked with creating a STIX 2.1 Relationship Object (SRO) based on the provided writeup about threat intelligence text SDOs and SCOs\"\n",
1058 | " \"Remember a relationship is a link between STIX Domain Objects (SDOs), STIX Cyber-observable Objects (SCOs), or between an SDO and a SCO that describes the way in which the objects are related. Relationships can be represented using an external STIX Relationship Object (SRO) or, in some cases, through certain properties which store an identifier reference that comprises an embedded relationship, (for example the created_by_ref property).\"\n",
1059 | " \"Create STIX Objects, in json format.\"\n",
1060 | " \"Identify Relationships: For each entity (like intrusion-set, malware, infrastructure, domain-name, file, directory), identify how they relate to each other. For example, malware might use infrastructure for command and control, or an intrusion set might leverage certain domains\"\n",
1061 | " \"Use relationship Objects: Use relationship objects to connect entities. This object will specify the source and target entities and define the nature of the relationship (e.g., \\\"uses\\\", \\\"communicates with\\\")\"\n",
1062 | " \"Ensure Consistent Referencing: Make sure that every object you want to relate is referenced correctly using their id in the relationship objects.\"\n",
1063 | " \"Pay attention to properties, don't use properties not defined in STIX 2.1 specification\"\n",
1064 | " \"Start with [ and close with ] , no other content before [ and after ]\"\n",
1065 | " \"If you cannot identify a specific SCO from the provided text, simply do not do anything.\"\n",
1066 | " \"Provide output only if you can identify one or more SCOs with reasonable certainty.\"\n",
1067 | " \"Pay attention to provide valid json.\"\n",
1068 | " \"Pay attention to provide valid STIX 2.1 structure.\"\n",
1069 | " \"Return only the JSON array, without any additional text, commentary, or code block delimiters (e.g., json).\"\n",
1070 | " )\n",
1071 | "\n",
1072 | "user_stix_sdo_sco_text = f\"Text of writeup: {text}, {stix_sdo} , {stix_sco}\""
1073 | ]
1074 | },
1075 | {
1076 | "cell_type": "markdown",
1077 | "source": [
1078 | "**STIX 2.1 SRO generator**"
1079 | ],
1080 | "metadata": {
1081 | "id": "Ywv_9IRl49a_"
1082 | }
1083 | },
1084 | {
1085 | "cell_type": "code",
1086 | "source": [
1087 | "# STIX 2.1 SRO generator\n",
1088 | "import uuid\n",
1089 | "import json\n",
1090 | "from stix2 import parse, exceptions\n",
1091 | "\n",
1092 | "# SRO Generator\n",
1093 | "def sro_stix(text, stix_sdo, stix_sco):\n",
1094 | " \"\"\"\n",
1095 | " Generate STIX SROs using the LLM.\n",
1096 | " \"\"\"\n",
1097 | " response = client.chat.completions.create(\n",
1098 | " model=userdata.get('DEPLOYMENT_NAME'),\n",
1099 | " messages=[\n",
1100 | " {\"role\": \"system\", \"content\": system_prompt_sro},\n",
1101 | " {\n",
1102 | " \"role\": \"user\",\n",
1103 | " \"content\": f\"\"\"\n",
1104 | "Generate STIX 2.1 relationship objects (SROs) based on the following:\n",
1105 | "\n",
1106 | "Input text:\n",
1107 | "{text}\n",
1108 | "\n",
1109 | "SDO:\n",
1110 | "{stix_sdo}\n",
1111 | "\n",
1112 | "SCO:\n",
1113 | "{stix_sco}\n",
1114 | "\"\"\"\n",
1115 | " }\n",
1116 | " ],\n",
1117 | " temperature=temperature\n",
1118 | " )\n",
1119 | " return response.choices[0].message.content\n",
1120 | "\n",
1121 | "def correct_invalid_stix(text, invalid_objects, original_stix):\n",
1122 | " \"\"\"\n",
1123 | " Ask the LLM to correct invalid STIX output based on the original text and invalid objects.\n",
1124 | " \"\"\"\n",
1125 | " # Create a focused invalid output section\n",
1126 | " invalid_output = json.dumps(invalid_objects, indent=4)\n",
1127 | " response = client.chat.completions.create(\n",
1128 | " model=userdata.get('DEPLOYMENT_NAME'),\n",
1129 | " messages=[\n",
1130 | " {\"role\": \"system\", \"content\": system_prompt_sro},\n",
1131 | " {\n",
1132 | " \"role\": \"user\",\n",
1133 | " \"content\": f\"\"\"\n",
1134 | "Correct the following invalid STIX relationship objects (SROs) based on the original text and ensure consistency with the SDO and SCO data:\n",
1135 | "\n",
1136 | "Input text:\n",
1137 | "{text}\n",
1138 | "\n",
1139 | "Invalid SRO objects:\n",
1140 | "{invalid_output}\n",
1141 | "\n",
1142 | "SDO:\n",
1143 | "{stix_sdo}\n",
1144 | "\n",
1145 | "SCO:\n",
1146 | "{stix_sco}\n",
1147 | "\"\"\"\n",
1148 | " }\n",
1149 | " ],\n",
1150 | " temperature=temperature\n",
1151 | " )\n",
1152 | " return response.choices[0].message.content\n",
1153 | "\n",
1154 | "# Generate and validate STIX SRO\n",
1155 | "is_valid = False\n",
1156 | "stix_sro = \"\"\n",
1157 | "\n",
1158 | "while not is_valid:\n",
1159 | " # Generate STIX SRO from the LLM\n",
1160 | " stix_sro = sro_stix(text, stix_sdo, stix_sco)\n",
1161 | "\n",
1162 | " try:\n",
1163 | " # Parse STIX SRO string to a Python list\n",
1164 | " stix_data = json.loads(stix_sro)\n",
1165 | " if not isinstance(stix_data, list):\n",
1166 | " raise ValueError(\"Parsed STIX SRO must be a list of dictionaries.\")\n",
1167 | "\n",
1168 | " # Add UUIDs to IDs\n",
1169 | " stix_data = add_uuid_to_ids(stix_data)\n",
1170 | "\n",
1171 | " # Print STIX data after UUIDs have been inserted\n",
1172 | " print(\"\\nSTIX SRO data after UUID insertion:\")\n",
1173 | " print(json.dumps(stix_data, indent=4))\n",
1174 | "\n",
1175 | " # Validate STIX objects\n",
1176 | " is_valid, invalid_objects = validate_stix_objects(stix_data)\n",
1177 | "\n",
1178 | " if not is_valid:\n",
1179 | " print(\"Validation failed. Requesting correction from LLM...\")\n",
1180 | " stix_sro = correct_invalid_stix(text, invalid_objects, stix_sro)\n",
1181 | " else:\n",
1182 | " print(\"Validation successful. All objects are valid.\")\n",
1183 | "\n",
1184 | " except json.JSONDecodeError as e:\n",
1185 | " print(f\"Error parsing STIX SRO: {e}\")\n",
1186 | " stix_sro = correct_invalid_stix(text, [], stix_sro)\n",
1187 | " except ValueError as e:\n",
1188 | " print(e)\n",
1189 | " stix_sro = correct_invalid_stix(text, [], stix_sro)\n",
1190 | "\n",
1191 | "# Final validated STIX SRO as JSON string\n",
1192 | "stix_sro = json.dumps(stix_data, indent=4)\n",
1193 | "print(stix_sro)"
1194 | ],
1195 | "metadata": {
1196 | "colab": {
1197 | "base_uri": "https://localhost:8080/"
1198 | },
1199 | "id": "lWaIiaeTsCxp",
1200 | "outputId": "6e786162-208e-40d7-e331-cad0026fc6c0"
1201 | },
1202 | "execution_count": 13,
1203 | "outputs": [
1204 | {
1205 | "output_type": "stream",
1206 | "name": "stdout",
1207 | "text": [
1208 | "\n",
1209 | "STIX SRO data after UUID insertion:\n",
1210 | "[\n",
1211 | " {\n",
1212 | " \"type\": \"relationship\",\n",
1213 | " \"id\": \"relationship--8624e252-244b-43b2-828b-4860687979cd\",\n",
1214 | " \"relationship_type\": \"uses\",\n",
1215 | " \"source_ref\": \"threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\",\n",
1216 | " \"target_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1217 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1218 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1219 | " },\n",
1220 | " {\n",
1221 | " \"type\": \"relationship\",\n",
1222 | " \"id\": \"relationship--6a653878-988c-49fe-9463-7b5a91541d9e\",\n",
1223 | " \"relationship_type\": \"uses\",\n",
1224 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1225 | " \"target_ref\": \"malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\",\n",
1226 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1227 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1228 | " },\n",
1229 | " {\n",
1230 | " \"type\": \"relationship\",\n",
1231 | " \"id\": \"relationship--b0dd9712-f460-422a-92d7-9d229f645a03\",\n",
1232 | " \"relationship_type\": \"uses\",\n",
1233 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1234 | " \"target_ref\": \"malware--00c9240a-4365-4101-8be4-66a0bc8f0530\",\n",
1235 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1236 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1237 | " },\n",
1238 | " {\n",
1239 | " \"type\": \"relationship\",\n",
1240 | " \"id\": \"relationship--d6ef9860-6982-44c1-ad34-56e52fed4ad2\",\n",
1241 | " \"relationship_type\": \"uses\",\n",
1242 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1243 | " \"target_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1244 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1245 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1246 | " },\n",
1247 | " {\n",
1248 | " \"type\": \"relationship\",\n",
1249 | " \"id\": \"relationship--21e85f01-fbac-4568-a695-86fc30cdc2d4\",\n",
1250 | " \"relationship_type\": \"uses\",\n",
1251 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1252 | " \"target_ref\": \"domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\",\n",
1253 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1254 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1255 | " },\n",
1256 | " {\n",
1257 | " \"type\": \"relationship\",\n",
1258 | " \"id\": \"relationship--0dcf6c28-c5ab-489d-b086-de6b8e5dfb56\",\n",
1259 | " \"relationship_type\": \"uses\",\n",
1260 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1261 | " \"target_ref\": \"domain-name--31e83530-c412-47f0-a636-f35293916b52\",\n",
1262 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1263 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1264 | " },\n",
1265 | " {\n",
1266 | " \"type\": \"relationship\",\n",
1267 | " \"id\": \"relationship--41b7981b-9866-4b17-862a-7b614944ca0d\",\n",
1268 | " \"relationship_type\": \"uses\",\n",
1269 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1270 | " \"target_ref\": \"domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\",\n",
1271 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1272 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1273 | " },\n",
1274 | " {\n",
1275 | " \"type\": \"relationship\",\n",
1276 | " \"id\": \"relationship--f53ae137-d0bb-4752-b7fd-8e29efcecb0c\",\n",
1277 | " \"relationship_type\": \"uses\",\n",
1278 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1279 | " \"target_ref\": \"domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\",\n",
1280 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1281 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1282 | " },\n",
1283 | " {\n",
1284 | " \"type\": \"relationship\",\n",
1285 | " \"id\": \"relationship--146166ac-027a-419e-9059-dc6def3e4920\",\n",
1286 | " \"relationship_type\": \"uses\",\n",
1287 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1288 | " \"target_ref\": \"domain-name--8fdd479b-587b-434c-95f5-499165203aac\",\n",
1289 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1290 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1291 | " },\n",
1292 | " {\n",
1293 | " \"type\": \"relationship\",\n",
1294 | " \"id\": \"relationship--d00105ee-bcdf-4cba-9358-b0535cff30aa\",\n",
1295 | " \"relationship_type\": \"uses\",\n",
1296 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1297 | " \"target_ref\": \"domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\",\n",
1298 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1299 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1300 | " },\n",
1301 | " {\n",
1302 | " \"type\": \"relationship\",\n",
1303 | " \"id\": \"relationship--2749e554-2bcd-4d15-be2b-4f8808904eac\",\n",
1304 | " \"relationship_type\": \"uses\",\n",
1305 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1306 | " \"target_ref\": \"domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\",\n",
1307 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1308 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1309 | " },\n",
1310 | " {\n",
1311 | " \"type\": \"relationship\",\n",
1312 | " \"id\": \"relationship--10680e58-642e-4fa4-b2d5-cc9ef2bf514f\",\n",
1313 | " \"relationship_type\": \"uses\",\n",
1314 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1315 | " \"target_ref\": \"domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\",\n",
1316 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1317 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1318 | " },\n",
1319 | " {\n",
1320 | " \"type\": \"relationship\",\n",
1321 | " \"id\": \"relationship--305c3032-d16a-4eab-9bc8-7b6f5e6bc8e0\",\n",
1322 | " \"relationship_type\": \"uses\",\n",
1323 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1324 | " \"target_ref\": \"domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\",\n",
1325 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1326 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1327 | " },\n",
1328 | " {\n",
1329 | " \"type\": \"relationship\",\n",
1330 | " \"id\": \"relationship--028b6372-8be7-4dfe-8f19-67134e6fd36b\",\n",
1331 | " \"relationship_type\": \"uses\",\n",
1332 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1333 | " \"target_ref\": \"domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\",\n",
1334 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1335 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1336 | " },\n",
1337 | " {\n",
1338 | " \"type\": \"relationship\",\n",
1339 | " \"id\": \"relationship--02c76c2f-e181-47dd-bcb1-342c98955486\",\n",
1340 | " \"relationship_type\": \"uses\",\n",
1341 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1342 | " \"target_ref\": \"domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\",\n",
1343 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1344 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1345 | " },\n",
1346 | " {\n",
1347 | " \"type\": \"relationship\",\n",
1348 | " \"id\": \"relationship--86a5c7c4-b89c-4d19-92df-0a63b92f82cc\",\n",
1349 | " \"relationship_type\": \"uses\",\n",
1350 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1351 | " \"target_ref\": \"domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\",\n",
1352 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1353 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1354 | " },\n",
1355 | " {\n",
1356 | " \"type\": \"relationship\",\n",
1357 | " \"id\": \"relationship--f405c316-9378-4e24-8bd5-140195aead25\",\n",
1358 | " \"relationship_type\": \"uses\",\n",
1359 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1360 | " \"target_ref\": \"domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\",\n",
1361 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1362 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1363 | " },\n",
1364 | " {\n",
1365 | " \"type\": \"relationship\",\n",
1366 | " \"id\": \"relationship--0fd33c4d-94ee-4fc1-a06e-ca6280bc37ea\",\n",
1367 | " \"relationship_type\": \"uses\",\n",
1368 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1369 | " \"target_ref\": \"domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\",\n",
1370 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1371 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1372 | " },\n",
1373 | " {\n",
1374 | " \"type\": \"relationship\",\n",
1375 | " \"id\": \"relationship--7541ecee-82b5-42d9-ae8d-68dfb2c8f174\",\n",
1376 | " \"relationship_type\": \"uses\",\n",
1377 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1378 | " \"target_ref\": \"domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\",\n",
1379 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1380 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1381 | " },\n",
1382 | " {\n",
1383 | " \"type\": \"relationship\",\n",
1384 | " \"id\": \"relationship--d4e7e70f-da4b-4a49-be51-4f27addb0186\",\n",
1385 | " \"relationship_type\": \"uses\",\n",
1386 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1387 | " \"target_ref\": \"domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\",\n",
1388 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1389 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1390 | " },\n",
1391 | " {\n",
1392 | " \"type\": \"relationship\",\n",
1393 | " \"id\": \"relationship--b05b3459-c45f-415c-9e44-ebf7f8d75e13\",\n",
1394 | " \"relationship_type\": \"uses\",\n",
1395 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1396 | " \"target_ref\": \"domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\",\n",
1397 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1398 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1399 | " },\n",
1400 | " {\n",
1401 | " \"type\": \"relationship\",\n",
1402 | " \"id\": \"relationship--d52f8223-3ad3-4eec-a178-f470a9b41853\",\n",
1403 | " \"relationship_type\": \"uses\",\n",
1404 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1405 | " \"target_ref\": \"domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\",\n",
1406 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1407 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1408 | " },\n",
1409 | " {\n",
1410 | " \"type\": \"relationship\",\n",
1411 | " \"id\": \"relationship--7a0c1599-4212-40c8-8f38-bc3951402baa\",\n",
1412 | " \"relationship_type\": \"uses\",\n",
1413 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1414 | " \"target_ref\": \"domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\",\n",
1415 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1416 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1417 | " }\n",
1418 | "]\n",
1419 | "Validation passed for object ID: relationship--8624e252-244b-43b2-828b-4860687979cd\n",
1420 | "Validation passed for object ID: relationship--6a653878-988c-49fe-9463-7b5a91541d9e\n",
1421 | "Validation passed for object ID: relationship--b0dd9712-f460-422a-92d7-9d229f645a03\n",
1422 | "Validation passed for object ID: relationship--d6ef9860-6982-44c1-ad34-56e52fed4ad2\n",
1423 | "Validation passed for object ID: relationship--21e85f01-fbac-4568-a695-86fc30cdc2d4\n",
1424 | "Validation passed for object ID: relationship--0dcf6c28-c5ab-489d-b086-de6b8e5dfb56\n",
1425 | "Validation passed for object ID: relationship--41b7981b-9866-4b17-862a-7b614944ca0d\n",
1426 | "Validation passed for object ID: relationship--f53ae137-d0bb-4752-b7fd-8e29efcecb0c\n",
1427 | "Validation passed for object ID: relationship--146166ac-027a-419e-9059-dc6def3e4920\n",
1428 | "Validation passed for object ID: relationship--d00105ee-bcdf-4cba-9358-b0535cff30aa\n",
1429 | "Validation passed for object ID: relationship--2749e554-2bcd-4d15-be2b-4f8808904eac\n",
1430 | "Validation passed for object ID: relationship--10680e58-642e-4fa4-b2d5-cc9ef2bf514f\n",
1431 | "Validation passed for object ID: relationship--305c3032-d16a-4eab-9bc8-7b6f5e6bc8e0\n",
1432 | "Validation passed for object ID: relationship--028b6372-8be7-4dfe-8f19-67134e6fd36b\n",
1433 | "Validation passed for object ID: relationship--02c76c2f-e181-47dd-bcb1-342c98955486\n",
1434 | "Validation passed for object ID: relationship--86a5c7c4-b89c-4d19-92df-0a63b92f82cc\n",
1435 | "Validation passed for object ID: relationship--f405c316-9378-4e24-8bd5-140195aead25\n",
1436 | "Validation passed for object ID: relationship--0fd33c4d-94ee-4fc1-a06e-ca6280bc37ea\n",
1437 | "Validation passed for object ID: relationship--7541ecee-82b5-42d9-ae8d-68dfb2c8f174\n",
1438 | "Validation passed for object ID: relationship--d4e7e70f-da4b-4a49-be51-4f27addb0186\n",
1439 | "Validation passed for object ID: relationship--b05b3459-c45f-415c-9e44-ebf7f8d75e13\n",
1440 | "Validation passed for object ID: relationship--d52f8223-3ad3-4eec-a178-f470a9b41853\n",
1441 | "Validation passed for object ID: relationship--7a0c1599-4212-40c8-8f38-bc3951402baa\n",
1442 | "Validation successful. All objects are valid.\n",
1443 | "[\n",
1444 | " {\n",
1445 | " \"type\": \"relationship\",\n",
1446 | " \"id\": \"relationship--8624e252-244b-43b2-828b-4860687979cd\",\n",
1447 | " \"relationship_type\": \"uses\",\n",
1448 | " \"source_ref\": \"threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\",\n",
1449 | " \"target_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1450 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1451 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1452 | " },\n",
1453 | " {\n",
1454 | " \"type\": \"relationship\",\n",
1455 | " \"id\": \"relationship--6a653878-988c-49fe-9463-7b5a91541d9e\",\n",
1456 | " \"relationship_type\": \"uses\",\n",
1457 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1458 | " \"target_ref\": \"malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\",\n",
1459 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1460 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1461 | " },\n",
1462 | " {\n",
1463 | " \"type\": \"relationship\",\n",
1464 | " \"id\": \"relationship--b0dd9712-f460-422a-92d7-9d229f645a03\",\n",
1465 | " \"relationship_type\": \"uses\",\n",
1466 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1467 | " \"target_ref\": \"malware--00c9240a-4365-4101-8be4-66a0bc8f0530\",\n",
1468 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1469 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1470 | " },\n",
1471 | " {\n",
1472 | " \"type\": \"relationship\",\n",
1473 | " \"id\": \"relationship--d6ef9860-6982-44c1-ad34-56e52fed4ad2\",\n",
1474 | " \"relationship_type\": \"uses\",\n",
1475 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1476 | " \"target_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1477 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1478 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1479 | " },\n",
1480 | " {\n",
1481 | " \"type\": \"relationship\",\n",
1482 | " \"id\": \"relationship--21e85f01-fbac-4568-a695-86fc30cdc2d4\",\n",
1483 | " \"relationship_type\": \"uses\",\n",
1484 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1485 | " \"target_ref\": \"domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\",\n",
1486 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1487 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1488 | " },\n",
1489 | " {\n",
1490 | " \"type\": \"relationship\",\n",
1491 | " \"id\": \"relationship--0dcf6c28-c5ab-489d-b086-de6b8e5dfb56\",\n",
1492 | " \"relationship_type\": \"uses\",\n",
1493 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1494 | " \"target_ref\": \"domain-name--31e83530-c412-47f0-a636-f35293916b52\",\n",
1495 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1496 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1497 | " },\n",
1498 | " {\n",
1499 | " \"type\": \"relationship\",\n",
1500 | " \"id\": \"relationship--41b7981b-9866-4b17-862a-7b614944ca0d\",\n",
1501 | " \"relationship_type\": \"uses\",\n",
1502 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1503 | " \"target_ref\": \"domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\",\n",
1504 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1505 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1506 | " },\n",
1507 | " {\n",
1508 | " \"type\": \"relationship\",\n",
1509 | " \"id\": \"relationship--f53ae137-d0bb-4752-b7fd-8e29efcecb0c\",\n",
1510 | " \"relationship_type\": \"uses\",\n",
1511 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1512 | " \"target_ref\": \"domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\",\n",
1513 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1514 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1515 | " },\n",
1516 | " {\n",
1517 | " \"type\": \"relationship\",\n",
1518 | " \"id\": \"relationship--146166ac-027a-419e-9059-dc6def3e4920\",\n",
1519 | " \"relationship_type\": \"uses\",\n",
1520 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1521 | " \"target_ref\": \"domain-name--8fdd479b-587b-434c-95f5-499165203aac\",\n",
1522 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1523 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1524 | " },\n",
1525 | " {\n",
1526 | " \"type\": \"relationship\",\n",
1527 | " \"id\": \"relationship--d00105ee-bcdf-4cba-9358-b0535cff30aa\",\n",
1528 | " \"relationship_type\": \"uses\",\n",
1529 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1530 | " \"target_ref\": \"domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\",\n",
1531 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1532 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1533 | " },\n",
1534 | " {\n",
1535 | " \"type\": \"relationship\",\n",
1536 | " \"id\": \"relationship--2749e554-2bcd-4d15-be2b-4f8808904eac\",\n",
1537 | " \"relationship_type\": \"uses\",\n",
1538 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1539 | " \"target_ref\": \"domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\",\n",
1540 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1541 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1542 | " },\n",
1543 | " {\n",
1544 | " \"type\": \"relationship\",\n",
1545 | " \"id\": \"relationship--10680e58-642e-4fa4-b2d5-cc9ef2bf514f\",\n",
1546 | " \"relationship_type\": \"uses\",\n",
1547 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1548 | " \"target_ref\": \"domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\",\n",
1549 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1550 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1551 | " },\n",
1552 | " {\n",
1553 | " \"type\": \"relationship\",\n",
1554 | " \"id\": \"relationship--305c3032-d16a-4eab-9bc8-7b6f5e6bc8e0\",\n",
1555 | " \"relationship_type\": \"uses\",\n",
1556 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1557 | " \"target_ref\": \"domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\",\n",
1558 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1559 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1560 | " },\n",
1561 | " {\n",
1562 | " \"type\": \"relationship\",\n",
1563 | " \"id\": \"relationship--028b6372-8be7-4dfe-8f19-67134e6fd36b\",\n",
1564 | " \"relationship_type\": \"uses\",\n",
1565 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1566 | " \"target_ref\": \"domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\",\n",
1567 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1568 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1569 | " },\n",
1570 | " {\n",
1571 | " \"type\": \"relationship\",\n",
1572 | " \"id\": \"relationship--02c76c2f-e181-47dd-bcb1-342c98955486\",\n",
1573 | " \"relationship_type\": \"uses\",\n",
1574 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1575 | " \"target_ref\": \"domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\",\n",
1576 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1577 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1578 | " },\n",
1579 | " {\n",
1580 | " \"type\": \"relationship\",\n",
1581 | " \"id\": \"relationship--86a5c7c4-b89c-4d19-92df-0a63b92f82cc\",\n",
1582 | " \"relationship_type\": \"uses\",\n",
1583 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1584 | " \"target_ref\": \"domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\",\n",
1585 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1586 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1587 | " },\n",
1588 | " {\n",
1589 | " \"type\": \"relationship\",\n",
1590 | " \"id\": \"relationship--f405c316-9378-4e24-8bd5-140195aead25\",\n",
1591 | " \"relationship_type\": \"uses\",\n",
1592 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1593 | " \"target_ref\": \"domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\",\n",
1594 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1595 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1596 | " },\n",
1597 | " {\n",
1598 | " \"type\": \"relationship\",\n",
1599 | " \"id\": \"relationship--0fd33c4d-94ee-4fc1-a06e-ca6280bc37ea\",\n",
1600 | " \"relationship_type\": \"uses\",\n",
1601 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1602 | " \"target_ref\": \"domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\",\n",
1603 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1604 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1605 | " },\n",
1606 | " {\n",
1607 | " \"type\": \"relationship\",\n",
1608 | " \"id\": \"relationship--7541ecee-82b5-42d9-ae8d-68dfb2c8f174\",\n",
1609 | " \"relationship_type\": \"uses\",\n",
1610 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1611 | " \"target_ref\": \"domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\",\n",
1612 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1613 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1614 | " },\n",
1615 | " {\n",
1616 | " \"type\": \"relationship\",\n",
1617 | " \"id\": \"relationship--d4e7e70f-da4b-4a49-be51-4f27addb0186\",\n",
1618 | " \"relationship_type\": \"uses\",\n",
1619 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1620 | " \"target_ref\": \"domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\",\n",
1621 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1622 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1623 | " },\n",
1624 | " {\n",
1625 | " \"type\": \"relationship\",\n",
1626 | " \"id\": \"relationship--b05b3459-c45f-415c-9e44-ebf7f8d75e13\",\n",
1627 | " \"relationship_type\": \"uses\",\n",
1628 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1629 | " \"target_ref\": \"domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\",\n",
1630 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1631 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1632 | " },\n",
1633 | " {\n",
1634 | " \"type\": \"relationship\",\n",
1635 | " \"id\": \"relationship--d52f8223-3ad3-4eec-a178-f470a9b41853\",\n",
1636 | " \"relationship_type\": \"uses\",\n",
1637 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1638 | " \"target_ref\": \"domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\",\n",
1639 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1640 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1641 | " },\n",
1642 | " {\n",
1643 | " \"type\": \"relationship\",\n",
1644 | " \"id\": \"relationship--7a0c1599-4212-40c8-8f38-bc3951402baa\",\n",
1645 | " \"relationship_type\": \"uses\",\n",
1646 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1647 | " \"target_ref\": \"domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\",\n",
1648 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1649 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1650 | " }\n",
1651 | "]\n"
1652 | ]
1653 | }
1654 | ]
1655 | },
1656 | {
1657 | "cell_type": "markdown",
1658 | "source": [
1659 | "## 6 **STIX Bundle Generator**\n",
1660 | "\n",
1661 | "STIX 2.1 bundle genearator.\n",
1662 | "\n",
1663 | "Let's combine SDO, SCO, and SRO to generate the **STIX 2.1 bundle**."
1664 | ],
1665 | "metadata": {
1666 | "id": "KsmPtc3g-XxN"
1667 | }
1668 | },
1669 | {
1670 | "source": [
1671 | "#Create STIX 2.1 Bundle\n",
1672 | "import json\n",
1673 | "from stix2 import Bundle\n",
1674 | "import uuid\n",
1675 | "from datetime import datetime\n",
1676 | "\n",
1677 | "def remove_brackets(text):\n",
1678 | " \"\"\"\n",
1679 | " Remove leading '[' and trailing ']' and format inner objects into a valid JSON array.\n",
1680 | " \"\"\"\n",
1681 | " if not text.startswith('[') or not text.endswith(']'):\n",
1682 | " raise ValueError(\"Input text does not start with '[' or end with ']'\")\n",
1683 | "\n",
1684 | " # Remove brackets and split into individual JSON objects\n",
1685 | " objects_str = text[1:-1].strip() # Remove brackets and leading/trailing whitespace\n",
1686 | " objects_list = objects_str.split('}{')\n",
1687 | "\n",
1688 | " # Add back the missing curly braces and format into a valid JSON array\n",
1689 | " formatted_objects = \"[\" + \", \".join([\"{\" + obj + \"}\" if not obj.startswith(\"{\") and not obj.endswith(\"}\") else obj for obj in objects_list]) + \"]\"\n",
1690 | "\n",
1691 | " return formatted_objects\n",
1692 | "\n",
1693 | "def create_stix_bundle(sdo_data, sco_data, sro_data):\n",
1694 | " \"\"\"\n",
1695 | " Create a STIX 2.1 bundle from input SDO, SCO, and SRO data.\n",
1696 | "\n",
1697 | " Args:\n",
1698 | " sdo_data (list): List of valid SDO objects.\n",
1699 | " sco_data (list): List of valid SCO objects.\n",
1700 | " sro_data (list): List of valid SRO objects.\n",
1701 | "\n",
1702 | " Returns:\n",
1703 | " str: A STIX 2.1 bundle in JSON format.\n",
1704 | " \"\"\"\n",
1705 | " # Combine SDO, SCO, and SRO data\n",
1706 | " all_objects = sdo_data + sco_data + sro_data\n",
1707 | " #print(\"all_objects:\", all_objects)\n",
1708 | "\n",
1709 | " bundle = {\n",
1710 | " \"type\": \"bundle\",\n",
1711 | " \"id\": f\"bundle--{uuid.uuid4()}\",\n",
1712 | " \"objects\": all_objects\n",
1713 | " }\n",
1714 | "\n",
1715 | " # Return the serialized bundle\n",
1716 | " return json.dumps(bundle, indent=4)\n",
1717 | "\n",
1718 | "# Remove brackets and parse as JSON\n",
1719 | "stix_sdo_objects = json.loads(remove_brackets(stix_sdo))\n",
1720 | "stix_sco_objects = json.loads(remove_brackets(stix_sco))\n",
1721 | "stix_sro_objects = json.loads(remove_brackets(stix_sro))\n",
1722 | "\n",
1723 | "# Create STIX bundle\n",
1724 | "stix_bundle = create_stix_bundle(stix_sdo_objects, stix_sco_objects, stix_sro_objects)\n",
1725 | "\n",
1726 | "# Output the result\n",
1727 | "print(\"STIX Bundle:\")\n",
1728 | "print(stix_bundle)\n",
1729 | "# Generate the filename\n",
1730 | "filename = f\"bundle_{datetime.now().strftime('%Y_%m_%d_%H_%M')}.json\"\n",
1731 | "# Write the STIX bundle to the file\n",
1732 | "with open(filename, 'w') as file:\n",
1733 | " file.write(stix_bundle)\n",
1734 | "\n",
1735 | "print(f\"STIX bundle written to file: {filename}\")"
1736 | ],
1737 | "cell_type": "code",
1738 | "metadata": {
1739 | "colab": {
1740 | "base_uri": "https://localhost:8080/"
1741 | },
1742 | "id": "5Jm4pBXW4N2a",
1743 | "outputId": "a55af4f0-7c33-4181-8526-3f058d1548cb"
1744 | },
1745 | "execution_count": 14,
1746 | "outputs": [
1747 | {
1748 | "output_type": "stream",
1749 | "name": "stdout",
1750 | "text": [
1751 | "STIX Bundle:\n",
1752 | "{\n",
1753 | " \"type\": \"bundle\",\n",
1754 | " \"id\": \"bundle--00914181-1d69-4d79-9f94-e8e1b472505a\",\n",
1755 | " \"objects\": [\n",
1756 | " {\n",
1757 | " \"type\": \"threat-actor\",\n",
1758 | " \"id\": \"threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\",\n",
1759 | " \"name\": \"APT42\",\n",
1760 | " \"description\": \"APT42 is an Iranian state-sponsored cyber espionage actor targeting Western and Middle Eastern NGOs, media organizations, academia, legal services, and activists. It operates on behalf of the Islamic Revolutionary Guard Corps Intelligence Organization (IRGC-IO).\",\n",
1761 | " \"labels\": [\n",
1762 | " \"state-sponsored\",\n",
1763 | " \"cyber-espionage\",\n",
1764 | " \"Iranian\"\n",
1765 | " ],\n",
1766 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1767 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1768 | " },\n",
1769 | " {\n",
1770 | " \"type\": \"intrusion-set\",\n",
1771 | " \"id\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1772 | " \"name\": \"APT42 Operations\",\n",
1773 | " \"description\": \"APT42 uses enhanced social engineering schemes to gain access to victim networks, including cloud environments, by harvesting credentials and using them to gain initial access. It exfiltrates data of strategic interest to Iran, using built-in features and open-source tools to avoid detection.\",\n",
1774 | " \"labels\": [\n",
1775 | " \"intrusion-set\",\n",
1776 | " \"APT42\"\n",
1777 | " ],\n",
1778 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1779 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1780 | " },\n",
1781 | " {\n",
1782 | " \"type\": \"malware\",\n",
1783 | " \"id\": \"malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\",\n",
1784 | " \"name\": \"NICECURL\",\n",
1785 | " \"description\": \"NICECURL is a backdoor written in VBScript that can download additional modules to be executed, including data mining and arbitrary command execution.\",\n",
1786 | " \"is_family\": \"true\",\n",
1787 | " \"labels\": [\n",
1788 | " \"backdoor\",\n",
1789 | " \"VBScript\"\n",
1790 | " ],\n",
1791 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1792 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1793 | " },\n",
1794 | " {\n",
1795 | " \"type\": \"malware\",\n",
1796 | " \"id\": \"malware--00c9240a-4365-4101-8be4-66a0bc8f0530\",\n",
1797 | " \"name\": \"TAMECAT\",\n",
1798 | " \"description\": \"TAMECAT is a PowerShell toehold that can execute arbitrary PowerShell or C# content. It is used by APT42 to gain initial access to targets.\",\n",
1799 | " \"is_family\": \"true\",\n",
1800 | " \"labels\": [\n",
1801 | " \"PowerShell\",\n",
1802 | " \"backdoor\"\n",
1803 | " ],\n",
1804 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1805 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1806 | " },\n",
1807 | " {\n",
1808 | " \"type\": \"campaign\",\n",
1809 | " \"id\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1810 | " \"name\": \"APT42 Credential Harvesting Operations\",\n",
1811 | " \"description\": \"APT42 conducts extensive credential harvesting operations through spear-phishing campaigns and social engineering, targeting individuals and organizations in policy, government, media, and NGOs.\",\n",
1812 | " \"labels\": [\n",
1813 | " \"credential-harvesting\",\n",
1814 | " \"spear-phishing\"\n",
1815 | " ],\n",
1816 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1817 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1818 | " },\n",
1819 | " {\n",
1820 | " \"type\": \"domain-name\",\n",
1821 | " \"id\": \"domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\",\n",
1822 | " \"value\": \"washinqtonpost.press\"\n",
1823 | " },\n",
1824 | " {\n",
1825 | " \"type\": \"domain-name\",\n",
1826 | " \"id\": \"domain-name--31e83530-c412-47f0-a636-f35293916b52\",\n",
1827 | " \"value\": \"ksview.top\"\n",
1828 | " },\n",
1829 | " {\n",
1830 | " \"type\": \"domain-name\",\n",
1831 | " \"id\": \"domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\",\n",
1832 | " \"value\": \"honest-halcyon-fresher.buzz\"\n",
1833 | " },\n",
1834 | " {\n",
1835 | " \"type\": \"domain-name\",\n",
1836 | " \"id\": \"domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\",\n",
1837 | " \"value\": \"n9.cl\"\n",
1838 | " },\n",
1839 | " {\n",
1840 | " \"type\": \"domain-name\",\n",
1841 | " \"id\": \"domain-name--8fdd479b-587b-434c-95f5-499165203aac\",\n",
1842 | " \"value\": \"review.modification-check.online\"\n",
1843 | " },\n",
1844 | " {\n",
1845 | " \"type\": \"domain-name\",\n",
1846 | " \"id\": \"domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\",\n",
1847 | " \"value\": \"nterview.site\"\n",
1848 | " },\n",
1849 | " {\n",
1850 | " \"type\": \"domain-name\",\n",
1851 | " \"id\": \"domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\",\n",
1852 | " \"value\": \"admin-stable-right.top\"\n",
1853 | " },\n",
1854 | " {\n",
1855 | " \"type\": \"domain-name\",\n",
1856 | " \"id\": \"domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\",\n",
1857 | " \"value\": \"shortlinkview.live\"\n",
1858 | " },\n",
1859 | " {\n",
1860 | " \"type\": \"domain-name\",\n",
1861 | " \"id\": \"domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\",\n",
1862 | " \"value\": \"reconsider.site\"\n",
1863 | " },\n",
1864 | " {\n",
1865 | " \"type\": \"domain-name\",\n",
1866 | " \"id\": \"domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\",\n",
1867 | " \"value\": \"last-check-leave.buzz\"\n",
1868 | " },\n",
1869 | " {\n",
1870 | " \"type\": \"domain-name\",\n",
1871 | " \"id\": \"domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\",\n",
1872 | " \"value\": \"email-daemon.online\"\n",
1873 | " },\n",
1874 | " {\n",
1875 | " \"type\": \"domain-name\",\n",
1876 | " \"id\": \"domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\",\n",
1877 | " \"value\": \"onmicrosofl.com\"\n",
1878 | " },\n",
1879 | " {\n",
1880 | " \"type\": \"domain-name\",\n",
1881 | " \"id\": \"domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\",\n",
1882 | " \"value\": \"bitly.org.il\"\n",
1883 | " },\n",
1884 | " {\n",
1885 | " \"type\": \"domain-name\",\n",
1886 | " \"id\": \"domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\",\n",
1887 | " \"value\": \"youtransfer.live\"\n",
1888 | " },\n",
1889 | " {\n",
1890 | " \"type\": \"domain-name\",\n",
1891 | " \"id\": \"domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\",\n",
1892 | " \"value\": \"drive-file-share.site\"\n",
1893 | " },\n",
1894 | " {\n",
1895 | " \"type\": \"domain-name\",\n",
1896 | " \"id\": \"domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\",\n",
1897 | " \"value\": \"prism-west-candy.glitch.me\"\n",
1898 | " },\n",
1899 | " {\n",
1900 | " \"type\": \"domain-name\",\n",
1901 | " \"id\": \"domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\",\n",
1902 | " \"value\": \"worried-eastern-salto.glitch.me\"\n",
1903 | " },\n",
1904 | " {\n",
1905 | " \"type\": \"domain-name\",\n",
1906 | " \"id\": \"domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\",\n",
1907 | " \"value\": \"tnt200.mywire.org\"\n",
1908 | " },\n",
1909 | " {\n",
1910 | " \"type\": \"domain-name\",\n",
1911 | " \"id\": \"domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\",\n",
1912 | " \"value\": \"accurate-sprout-porpoise.glitch.me\"\n",
1913 | " },\n",
1914 | " {\n",
1915 | " \"type\": \"relationship\",\n",
1916 | " \"id\": \"relationship--8624e252-244b-43b2-828b-4860687979cd\",\n",
1917 | " \"relationship_type\": \"uses\",\n",
1918 | " \"source_ref\": \"threat-actor--a63b9ab7-7253-432d-98ea-5381207c74af\",\n",
1919 | " \"target_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1920 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1921 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1922 | " },\n",
1923 | " {\n",
1924 | " \"type\": \"relationship\",\n",
1925 | " \"id\": \"relationship--6a653878-988c-49fe-9463-7b5a91541d9e\",\n",
1926 | " \"relationship_type\": \"uses\",\n",
1927 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1928 | " \"target_ref\": \"malware--d10904bd-10b9-4045-b514-f6c5f7d1de50\",\n",
1929 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1930 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1931 | " },\n",
1932 | " {\n",
1933 | " \"type\": \"relationship\",\n",
1934 | " \"id\": \"relationship--b0dd9712-f460-422a-92d7-9d229f645a03\",\n",
1935 | " \"relationship_type\": \"uses\",\n",
1936 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1937 | " \"target_ref\": \"malware--00c9240a-4365-4101-8be4-66a0bc8f0530\",\n",
1938 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1939 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1940 | " },\n",
1941 | " {\n",
1942 | " \"type\": \"relationship\",\n",
1943 | " \"id\": \"relationship--d6ef9860-6982-44c1-ad34-56e52fed4ad2\",\n",
1944 | " \"relationship_type\": \"uses\",\n",
1945 | " \"source_ref\": \"intrusion-set--7e9242ea-dcab-49cf-8e6b-22919d2b361c\",\n",
1946 | " \"target_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1947 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1948 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1949 | " },\n",
1950 | " {\n",
1951 | " \"type\": \"relationship\",\n",
1952 | " \"id\": \"relationship--21e85f01-fbac-4568-a695-86fc30cdc2d4\",\n",
1953 | " \"relationship_type\": \"uses\",\n",
1954 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1955 | " \"target_ref\": \"domain-name--5f2730f5-a17a-4842-9744-73aacfcefcdb\",\n",
1956 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1957 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1958 | " },\n",
1959 | " {\n",
1960 | " \"type\": \"relationship\",\n",
1961 | " \"id\": \"relationship--0dcf6c28-c5ab-489d-b086-de6b8e5dfb56\",\n",
1962 | " \"relationship_type\": \"uses\",\n",
1963 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1964 | " \"target_ref\": \"domain-name--31e83530-c412-47f0-a636-f35293916b52\",\n",
1965 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1966 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1967 | " },\n",
1968 | " {\n",
1969 | " \"type\": \"relationship\",\n",
1970 | " \"id\": \"relationship--41b7981b-9866-4b17-862a-7b614944ca0d\",\n",
1971 | " \"relationship_type\": \"uses\",\n",
1972 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1973 | " \"target_ref\": \"domain-name--dde332d5-e63a-4796-965b-39e84bbf7f3a\",\n",
1974 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1975 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1976 | " },\n",
1977 | " {\n",
1978 | " \"type\": \"relationship\",\n",
1979 | " \"id\": \"relationship--f53ae137-d0bb-4752-b7fd-8e29efcecb0c\",\n",
1980 | " \"relationship_type\": \"uses\",\n",
1981 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1982 | " \"target_ref\": \"domain-name--ca21e8b0-0f63-4747-8039-5ebf7e9f17e1\",\n",
1983 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1984 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1985 | " },\n",
1986 | " {\n",
1987 | " \"type\": \"relationship\",\n",
1988 | " \"id\": \"relationship--146166ac-027a-419e-9059-dc6def3e4920\",\n",
1989 | " \"relationship_type\": \"uses\",\n",
1990 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
1991 | " \"target_ref\": \"domain-name--8fdd479b-587b-434c-95f5-499165203aac\",\n",
1992 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
1993 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
1994 | " },\n",
1995 | " {\n",
1996 | " \"type\": \"relationship\",\n",
1997 | " \"id\": \"relationship--d00105ee-bcdf-4cba-9358-b0535cff30aa\",\n",
1998 | " \"relationship_type\": \"uses\",\n",
1999 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2000 | " \"target_ref\": \"domain-name--1b837c95-98c9-4316-bd60-da67f956dfe9\",\n",
2001 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2002 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2003 | " },\n",
2004 | " {\n",
2005 | " \"type\": \"relationship\",\n",
2006 | " \"id\": \"relationship--2749e554-2bcd-4d15-be2b-4f8808904eac\",\n",
2007 | " \"relationship_type\": \"uses\",\n",
2008 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2009 | " \"target_ref\": \"domain-name--332b3542-2f73-4254-9c02-66d2e0123e32\",\n",
2010 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2011 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2012 | " },\n",
2013 | " {\n",
2014 | " \"type\": \"relationship\",\n",
2015 | " \"id\": \"relationship--10680e58-642e-4fa4-b2d5-cc9ef2bf514f\",\n",
2016 | " \"relationship_type\": \"uses\",\n",
2017 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2018 | " \"target_ref\": \"domain-name--17c8fe4c-9bb1-451c-8f2a-d3e5f54962be\",\n",
2019 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2020 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2021 | " },\n",
2022 | " {\n",
2023 | " \"type\": \"relationship\",\n",
2024 | " \"id\": \"relationship--305c3032-d16a-4eab-9bc8-7b6f5e6bc8e0\",\n",
2025 | " \"relationship_type\": \"uses\",\n",
2026 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2027 | " \"target_ref\": \"domain-name--8d9122d8-2bf6-4fe6-86da-d8e826e68331\",\n",
2028 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2029 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2030 | " },\n",
2031 | " {\n",
2032 | " \"type\": \"relationship\",\n",
2033 | " \"id\": \"relationship--028b6372-8be7-4dfe-8f19-67134e6fd36b\",\n",
2034 | " \"relationship_type\": \"uses\",\n",
2035 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2036 | " \"target_ref\": \"domain-name--07f5ca46-0260-4fbf-bf05-c4524c34d05c\",\n",
2037 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2038 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2039 | " },\n",
2040 | " {\n",
2041 | " \"type\": \"relationship\",\n",
2042 | " \"id\": \"relationship--02c76c2f-e181-47dd-bcb1-342c98955486\",\n",
2043 | " \"relationship_type\": \"uses\",\n",
2044 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2045 | " \"target_ref\": \"domain-name--9e628138-f801-4626-98cc-89fa5ce98ec0\",\n",
2046 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2047 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2048 | " },\n",
2049 | " {\n",
2050 | " \"type\": \"relationship\",\n",
2051 | " \"id\": \"relationship--86a5c7c4-b89c-4d19-92df-0a63b92f82cc\",\n",
2052 | " \"relationship_type\": \"uses\",\n",
2053 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2054 | " \"target_ref\": \"domain-name--9a66b85f-5847-43cb-b32e-36dbe52bcfa6\",\n",
2055 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2056 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2057 | " },\n",
2058 | " {\n",
2059 | " \"type\": \"relationship\",\n",
2060 | " \"id\": \"relationship--f405c316-9378-4e24-8bd5-140195aead25\",\n",
2061 | " \"relationship_type\": \"uses\",\n",
2062 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2063 | " \"target_ref\": \"domain-name--4eb73cd1-d832-4869-953c-b7bb8aee5ad4\",\n",
2064 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2065 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2066 | " },\n",
2067 | " {\n",
2068 | " \"type\": \"relationship\",\n",
2069 | " \"id\": \"relationship--0fd33c4d-94ee-4fc1-a06e-ca6280bc37ea\",\n",
2070 | " \"relationship_type\": \"uses\",\n",
2071 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2072 | " \"target_ref\": \"domain-name--26b853f7-ffb3-4437-b55b-e8e52e84dab8\",\n",
2073 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2074 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2075 | " },\n",
2076 | " {\n",
2077 | " \"type\": \"relationship\",\n",
2078 | " \"id\": \"relationship--7541ecee-82b5-42d9-ae8d-68dfb2c8f174\",\n",
2079 | " \"relationship_type\": \"uses\",\n",
2080 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2081 | " \"target_ref\": \"domain-name--76f78672-5ba5-457d-845b-918c2260ac5f\",\n",
2082 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2083 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2084 | " },\n",
2085 | " {\n",
2086 | " \"type\": \"relationship\",\n",
2087 | " \"id\": \"relationship--d4e7e70f-da4b-4a49-be51-4f27addb0186\",\n",
2088 | " \"relationship_type\": \"uses\",\n",
2089 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2090 | " \"target_ref\": \"domain-name--8023cb8e-39a6-45c9-bbf3-d8b35a4d6a9c\",\n",
2091 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2092 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2093 | " },\n",
2094 | " {\n",
2095 | " \"type\": \"relationship\",\n",
2096 | " \"id\": \"relationship--b05b3459-c45f-415c-9e44-ebf7f8d75e13\",\n",
2097 | " \"relationship_type\": \"uses\",\n",
2098 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2099 | " \"target_ref\": \"domain-name--7b14af40-0ee6-4afa-8962-c9b5c03090dc\",\n",
2100 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2101 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2102 | " },\n",
2103 | " {\n",
2104 | " \"type\": \"relationship\",\n",
2105 | " \"id\": \"relationship--d52f8223-3ad3-4eec-a178-f470a9b41853\",\n",
2106 | " \"relationship_type\": \"uses\",\n",
2107 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2108 | " \"target_ref\": \"domain-name--9453ccee-c8a6-4383-a7b8-76e0e8decf64\",\n",
2109 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2110 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2111 | " },\n",
2112 | " {\n",
2113 | " \"type\": \"relationship\",\n",
2114 | " \"id\": \"relationship--7a0c1599-4212-40c8-8f38-bc3951402baa\",\n",
2115 | " \"relationship_type\": \"uses\",\n",
2116 | " \"source_ref\": \"campaign--d00537dc-68aa-494b-b8fc-3e0ebf3204ce\",\n",
2117 | " \"target_ref\": \"domain-name--1b11e99a-ab73-4312-9838-fb0c9c85c2a1\",\n",
2118 | " \"created\": \"2024-05-01T00:00:00Z\",\n",
2119 | " \"modified\": \"2024-05-01T00:00:00Z\"\n",
2120 | " }\n",
2121 | " ]\n",
2122 | "}\n",
2123 | "STIX bundle written to file: bundle_2024_12_12_15_11.json\n"
2124 | ]
2125 | }
2126 | ]
2127 | },
2128 | {
2129 | "cell_type": "markdown",
2130 | "source": [
2131 | "## 7 **STIX Viewer**\n",
2132 | "\n",
2133 | "STIX 2.1 bundle Visualizer.\n",
2134 | "\n",
2135 | "To visualize the STIX bundle, we use the cti-stix-visualization project, inserted as an iFrame in the notebook.\n",
2136 | "\n",
2137 | "[STIX Visualizer](https://oasis-open.github.io/cti-stix-visualization/)\n"
2138 | ],
2139 | "metadata": {
2140 | "id": "Mfx1ULod6uH_"
2141 | }
2142 | },
2143 | {
2144 | "cell_type": "code",
2145 | "source": [
2146 | "# Visualize STIX Bundle\n",
2147 | "# cut & paste json file\n",
2148 | "from IPython.display import IFrame\n",
2149 | "\n",
2150 | "IFrame(src='https://oasis-open.github.io/cti-stix-visualization/', width=1200, height=1000)"
2151 | ],
2152 | "metadata": {
2153 | "colab": {
2154 | "base_uri": "https://localhost:8080/",
2155 | "height": 1000
2156 | },
2157 | "id": "mcYulPi3zzt-",
2158 | "outputId": "679fafbd-94c4-4141-daad-d0ecd224632b"
2159 | },
2160 | "execution_count": null,
2161 | "outputs": [
2162 | {
2163 | "output_type": "execute_result",
2164 | "data": {
2165 | "text/plain": [
2166 | ""
2167 | ],
2168 | "text/html": [
2169 | "\n",
2170 | " \n",
2178 | " "
2179 | ]
2180 | },
2181 | "metadata": {},
2182 | "execution_count": 8
2183 | }
2184 | ]
2185 | }
2186 | ],
2187 | "metadata": {
2188 | "kernel_info": {
2189 | "name": "python38-jupyter"
2190 | },
2191 | "kernelspec": {
2192 | "display_name": "jupyter-notebooks",
2193 | "language": "python",
2194 | "name": "python3"
2195 | },
2196 | "language_info": {
2197 | "codemirror_mode": {
2198 | "name": "ipython",
2199 | "version": 3
2200 | },
2201 | "file_extension": ".py",
2202 | "mimetype": "text/x-python",
2203 | "name": "python",
2204 | "nbconvert_exporter": "python",
2205 | "pygments_lexer": "ipython3",
2206 | "version": "3.11.9"
2207 | },
2208 | "microsoft": {
2209 | "host": {
2210 | "AzureML": {
2211 | "notebookHasBeenCompleted": true
2212 | }
2213 | },
2214 | "ms_spell_check": {
2215 | "ms_spell_check_language": "en"
2216 | }
2217 | },
2218 | "nteract": {
2219 | "version": "nteract-front-end@1.0.0"
2220 | },
2221 | "colab": {
2222 | "provenance": [],
2223 | "include_colab_link": true
2224 | }
2225 | },
2226 | "nbformat": 4,
2227 | "nbformat_minor": 0
2228 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GenAI-STIX2.1-Generator
2 | GenAI-STIX2.1-Generator is a tool that leverages Azure OpenAI capabilities to transform threat intelligence reports from unstructured web input into structured STIX 2.1 format.
3 |
4 | [Blog post](https://medium.com/@antonio.formato/from-unstructured-threat-intelligence-to-stix-2-1-bundles-with-generative-ai-1065ce399e63)
5 |
6 | # From Unstructured Threat Intelligence to STIX 2.1 Bundles with Generative AI
7 |
8 | ## Overview
9 |
10 | Cybersecurity relies on the rapid exchange of actionable intelligence. Yet, much of the threat intelligence shared today is unstructured, making it difficult to standardize and operationalize. This repository demonstrates how Generative AI can bridge this gap by automating the creation of STIX 2.1 bundles from unstructured threat reports.
11 |
12 | The Structured Threat Information Expression (STIX) 2.1 standard provides a machine-readable framework for sharing cyber threat intelligence. However, creating STIX bundles manually is time-consuming and prone to errors. This project leverages GPT-4 to automate the extraction, structuring, and validation of STIX Domain Objects (SDOs), Cyber Observables (SCOs), and Relationship Objects (SROs) from unstructured text.
13 |
14 | ## Key Features
15 |
16 | - **Automated Extraction**: Uses Generative AI to analyze unstructured threat reports and identify key indicators, relationships, and technical details.
17 | - **STIX-Compliant Output**: Ensures generated STIX objects adhere to the STIX 2.1 schema for interoperability and standardization.
18 | - **Flexible Configuration**: Supports Azure OpenAI GPT-4o by default but can be adapted for other LLMs.
19 | - **Visualization**: Includes tools to render and inspect generated STIX bundles for validation and analysis.
20 |
21 | ## Getting Started
22 |
23 | ### Prerequisites
24 |
25 | - Python 3.9 or higher
26 | - Access to Azure OpenAI GPT-4o or an equivalent LLM
27 | - Required Python packages:
28 | - `python-dotenv`
29 | - `stix2`
30 | - `httpx`
31 | - `BeautifulSoup`
32 |
33 | ## Usage
34 |
35 | ### Extracting STIX Bundles from Threat Reports
36 | This project automates the process of converting unstructured threat intelligence reports into STIX 2.1 bundles. Below is an example workflow demonstrating the usage of the tool:
37 |
38 | 1. **Input Threat Report**
39 | Provide the URL of a threat intelligence report. For instance, the [Midnight Blizzard campaign blog post](https://www.microsoft.com/en-us/security/blog/2024/10/29/midnight-blizzard-conducts-large-scale-spear-phishing-campaign-using-rdp-files/) by Microsoft Threat Intelligence.
40 |
41 | 2. **Run the Notebook**
42 | Use the provided Jupyter Notebook to execute the following steps:
43 | - Extract unstructured text from the provided URL using the web scraper.
44 | - Generate STIX Domain Objects (SDOs), Cyber Observables (SCOs), and Relationship Objects (SROs) using Generative AI.
45 | - Validate the generated STIX objects against the STIX 2.1 schema.
46 |
47 | 3. **Generate the STIX Bundle**
48 | The notebook combines SDOs, SCOs, and SROs into a complete STIX bundle in JSON format. The bundle is saved to a timestamped file and displayed in the console.
49 |
50 | 4. **Visualize the STIX Bundle**
51 | Utilize the STIX viewer to inspect the generated data visually. For example, use the [OASIS CTI-STIX Visualization tool](https://oasis-open.github.io/cti-stix-visualization/) to render the relationships and objects.
52 |
53 | ## Contributing
54 |
55 | We welcome contributions to enhance this project. Here's how you can help:
56 |
57 | - **Testing and Feedback**: Try the tool and share your insights to improve its performance and usability.
58 | - **Improving Prompts**: Help refine the AI prompts for better extraction and accuracy of STIX objects.
59 | - **Extending Functionality**: Add support for new STIX object types, build additional features, or improve existing workflows.
60 | - **Open Discussions**: Join the conversation to explore innovative use cases and share your ideas.
61 |
62 | Your contributions will help make this project more robust and impactful. Thank you for your support!
63 |
--------------------------------------------------------------------------------