Compare commits

...

15 Commits

Author SHA1 Message Date
Alexandre Dulaunoy b5a87d228a
Merge branch 'main' 2024-03-13 16:42:47 +01:00
Alexandre Dulaunoy 6f141c736c
chg: [malware_classification] add `Stalkerware` from #275 2024-03-13 16:39:04 +01:00
Alexandre Dulaunoy 9f4f72c175
Merge pull request #275 from vxsh4d0w/patch-5
Update machinetag.json
2024-03-13 16:35:35 +01:00
V c5566e0d03
Update machinetag.json
Added Stalkerware, ad defined by Kaspersky "commercially available software that can be discreetly installed on smartphone devices, enabling a perpetrator to monitor an individual’s private life without their knowledge"
2024-03-13 13:56:28 +00:00
Alexandre Dulaunoy 5f580a3bb5
chg: [MANIFEST] updated 2024-03-04 10:10:41 +01:00
Alexandre Dulaunoy 5fc23d4795
chg: [tools] clean-up python script to generate the asciidoctor files 2024-03-04 10:06:48 +01:00
Alexandre Dulaunoy a62a3bdad7
Merge pull request #274 from JRC-T2/main
Dark-Web Ransomware support
2024-03-04 10:06:21 +01:00
Alexandre Dulaunoy 5e93071832
fix: [tools] Fix #273 in markdown generator 2024-03-04 09:57:26 +01:00
JRC-T2 08cab31a89
Update machinetag.json
Added darknet ransomware activity support
2024-03-04 09:46:03 +01:00
Alexandre Dulaunoy 8cd705ba62
chg: [exercise] updated 2024-02-16 16:18:09 +01:00
Alexandre Dulaunoy 6b593ea8c1
Merge pull request #272 from DCSO/courseofaction-nodiscover
Add 'course-of-action:passive=nodiscover'
2024-02-07 06:36:57 +01:00
Hendrik Baecker 41e8bdc4f3 Added 'course-of-action:passive=nodiscover' 2024-02-06 14:28:16 +01:00
Alexandre Dulaunoy 1472de2c10
Merge pull request #266 from vxsh4d0w/master
Update Cryptocurrency Threat Taxonomy
2023-07-23 08:27:36 +02:00
V 135f62cace
Update machinetag.json 2023-07-22 21:50:11 +00:00
V d44ef96000
Update machinetag.json 2023-07-22 21:49:39 +00:00
7 changed files with 272 additions and 91 deletions

View File

@ -121,7 +121,7 @@
{
"description": "A Course Of Action analysis considers six potential courses of action for the development of a cyber security capability.",
"name": "course-of-action",
"version": 2
"version": 3
},
{
"description": "Crowdsec IP address classifications and behaviors taxonomy.",
@ -176,7 +176,7 @@
{
"description": "Criminal motivation and content detection the dark web: A categorisation model for law enforcement. ref: Janis Dalins, Campbell Wilson, Mark Carman. Taxonomy updated by MISP Project and extended by the JRC (Joint Research Centre) of the European Commission.",
"name": "dark-web",
"version": 5
"version": 6
},
{
"description": "Data classification for data potentially at risk of exfiltration based on table 2.1 of Solving Cyber Risk book.",
@ -306,7 +306,7 @@
{
"description": "Exercise is a taxonomy to describe if the information is part of one or more cyber or crisis exercise.",
"name": "exercise",
"version": 10
"version": 11
},
{
"description": "Reasons why an event has been extended. This taxonomy must be used on the extended event. The competitive analysis aspect is from Psychology of Intelligence Analysis by Richard J. Heuer, Jr. ref:http://www.foo.be/docs/intelligence/PsychofIntelNew.pdf",
@ -755,5 +755,5 @@
}
],
"url": "https://raw.githubusercontent.com/MISP/misp-taxonomies/main/",
"version": "20231231"
"version": "20240304"
}

View File

@ -2,7 +2,7 @@
"namespace": "course-of-action",
"expanded": "Courses of Action",
"description": "A Course Of Action analysis considers six potential courses of action for the development of a cyber security capability.",
"version": 2,
"version": 3,
"predicates": [
{
"value": "passive",
@ -21,6 +21,10 @@
"value": "discover",
"expanded": "The discover action is a 'historical look at the data'. This action heavily relies on your capability to store logs for a reasonable amount of time and have them accessible for searching. Typically, this type of action is applied against security information and event management (SIEM) or stored network data. The goal is to determine whether you have seen a specific indicator in the past."
},
{
"value": "nodiscover",
"expanded": "The no-discover action is a negation of discover in case you want to explicit prohibit 'historical look at the data'. The goal is to exclude a specific indicator from searches of historical data."
},
{
"value": "detect",
"expanded": "The passive action is setting up detection rules of an indicator for future traffic. These actions are most often executed via an intrusion detection system (IDS) or a specific logging rule on your firewall or application. It can also be configured as an alert in a SIEM when a specific condition is triggered."

View File

@ -43,6 +43,10 @@
"value": "Crypto Robbing Ransomware",
"expanded": "Cyber-extortionists began distributing new malware that empties cryptocurrency wallets and steals private keys while holding user data hostage."
},
{
"value": "Rag Pull",
"expanded": "Crypto scam that occurs when a team pumps their projects token before disappearing with the funds, leaving their investors with a valueless asset."
},
{
"value": "Pig Butchering Scam",
"expanded": "Cryptocurrency investment fraud that lures individuals into investing their money in seemingly legitimate and profitable ventures."

View File

@ -2,7 +2,7 @@
"namespace": "dark-web",
"expanded": "Dark Web",
"description": "Criminal motivation and content detection the dark web: A categorisation model for law enforcement. ref: Janis Dalins, Campbell Wilson, Mark Carman. Taxonomy updated by MISP Project and extended by the JRC (Joint Research Centre) of the European Commission.",
"version": 5,
"version": 6,
"predicates": [
{
"value": "topic",
@ -359,6 +359,11 @@
"expanded": "videos",
"description": "Videos and streaming"
},
{
"value": "ransomware-post",
"expanded": "ransomwarePost",
"description": "Ransomware post published by a ransomware group"
},
{
"value": "unclear",
"expanded": "unclear",
@ -473,6 +478,31 @@
"value": "pgp-public-key-block",
"expanded": "pgpPublicKeyBlock",
"description": "PGP public key block identified in the dark-web site"
},
{
"value": "country",
"expanded": "country",
"description": "Associated country detected on the code of the dark-web site, following ISO 3166-1 alpha-2"
},
{
"value": "company-name",
"expanded": "companyName",
"description": "Company name identified in a dark-web site"
},
{
"value": "company-link",
"expanded": "companyLink",
"description": "Company link identified in a dark-web site"
},
{
"value": "victim-address",
"expanded": "victimAddress",
"description": "Business address identified in a dark-web site"
},
{
"value": "victim-TLD",
"expanded": "victimTLD",
"description": "Business Top Level Domain (TLD) of a company identified in a dark-web site"
}
]
}

View File

@ -45,6 +45,11 @@
{
"predicate": "cyber-europe",
"entry": [
{
"value": "2024",
"expanded": "2024",
"description": "7th pan European cyber crisis exercise: Cyber Europe 2024 (CE2024)"
},
{
"value": "2022",
"expanded": "2022",
@ -104,6 +109,16 @@
"value": "2022",
"expanded": "2022",
"description": "Locked Shields 2022"
},
{
"value": "2023",
"expanded": "2023",
"description": "Locked Shields 2023"
},
{
"value": "2024",
"expanded": "2024",
"description": "Locked Shields 2024"
}
]
},
@ -193,7 +208,7 @@
]
}
],
"version": 10,
"version": 11,
"description": "Exercise is a taxonomy to describe if the information is part of one or more cyber or crisis exercise.",
"expanded": "Exercise",
"namespace": "exercise"

View File

@ -1,7 +1,7 @@
{
"namespace": "malware_classification",
"description": "Classification based on different categories. Based on https://www.sans.org/reading-room/whitepapers/incident/malware-101-viruses-32848",
"version": 2,
"version": 3,
"predicates": [
{
"value": "malware-category",
@ -52,6 +52,10 @@
"value": "Adware",
"expanded": "Adware"
},
{
"value": "Stalkerware",
"expanded": "Stalkerware"
},
{
"value": "Spyware",
"expanded": "Spyware"

View File

@ -32,25 +32,35 @@ import argparse
import os
import sys
skip_list = ['death-possibilities', 'poison-taxonomy', 'doping-substances']
skip_list = ["death-possibilities", "poison-taxonomy", "doping-substances"]
taxonomies = []
# Get our current directory from file location
thisDir = os.path.dirname(__file__)
argParser = argparse.ArgumentParser(description='Dump Machine Tags (Triple Tags) from MISP taxonomies', epilog='Available taxonomies are {0}'.format(taxonomies))
argParser.add_argument('-e', action='store_true', help='Include expanded tags')
argParser.add_argument('-a', action='store_true', help='Generate asciidoctor document from MISP taxonomies')
argParser.add_argument('-v', action='store_true', help='Include descriptions')
argParser.add_argument('-n', default=False, help='Show only the specified namespace')
argParser.add_argument('--disable-skip-list', default=False, action='store_true', help='disable default skip list')
argParser = argparse.ArgumentParser(
description="Dump Machine Tags (Triple Tags) from MISP taxonomies",
epilog="Available taxonomies are {0}".format(taxonomies),
)
argParser.add_argument("-e", action="store_true", help="Include expanded tags")
argParser.add_argument(
"-a", action="store_true", help="Generate asciidoctor document from MISP taxonomies"
)
argParser.add_argument("-v", action="store_true", help="Include descriptions")
argParser.add_argument("-n", default=False, help="Show only the specified namespace")
argParser.add_argument(
"--disable-skip-list",
default=False,
action="store_true",
help="disable default skip list",
)
args = argParser.parse_args()
if args.disable_skip_list:
skip_list = ''
skip_list = ""
for folder in os.listdir(os.path.join(thisDir, '../')):
if os.path.isfile(os.path.join(thisDir, '../', folder, 'machinetag.json')):
for folder in os.listdir(os.path.join(thisDir, "../")):
if os.path.isfile(os.path.join(thisDir, "../", folder, "machinetag.json")):
if folder in skip_list:
continue
taxonomies.append(folder)
@ -58,23 +68,35 @@ for folder in os.listdir(os.path.join(thisDir, '../')):
taxonomies.sort()
doc = ''
doc = ""
if args.a:
dedication = "\n[dedication]\n== Funding and Support\nThe MISP project is financially and resource supported by https://www.circl.lu/[CIRCL Computer Incident Response Center Luxembourg ].\n\nimage:{images-misp}logo.png[CIRCL logo]\n\nA CEF (Connecting Europe Facility) funding under CEF-TC-2016-3 - Cyber Security has been granted from 1st September 2017 until 31th August 2019 as ***Improving MISP as building blocks for next-generation information sharing***.\n\nimage:{images-misp}en_cef.png[CEF funding]\n\nIf you are interested to co-fund projects around MISP, feel free to get in touch with us.\n\n"
doc = doc + ":toc: right\n"
doc = doc + ":toclevels: 1\n"
doc = doc + ":icons: font\n"
doc = doc + ":images-cdn: https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/logos/\n"
doc = (
doc
+ ":images-cdn: https://raw.githubusercontent.com/MISP/MISP/2.4/INSTALL/logos/\n"
)
doc = doc + ":images-misp: https://www.misp-project.org/assets/images/\n"
doc = doc + "= MISP taxonomies and classification as machine tags\n\n"
doc = doc + "= Introduction\n"
doc = doc + "\nimage::{images-cdn}misp-logo.png[MISP logo]\n"
doc = doc + "The MISP threat sharing platform is a free and open source software helping information sharing of threat intelligence including cyber security indicators, financial fraud or counter-terrorism information. The MISP project includes multiple sub-projects to support the operational requirements of analysts and improve the overall quality of information shared.\n\n"
doc = (
doc
+ "The MISP threat sharing platform is a free and open source software helping information sharing of threat intelligence including cyber security indicators, financial fraud or counter-terrorism information. The MISP project includes multiple sub-projects to support the operational requirements of analysts and improve the overall quality of information shared.\n\n"
)
doc = doc + ""
doc = "{} {} {} {}".format(doc, "\nTaxonomies that can be used in MISP (2.4) and other information sharing tool and expressed in Machine Tags (Triple Tags).",
"A machine tag is composed of a namespace (MUST), a predicate (MUST) and an (OPTIONAL) value.",
"Machine tags are often called triple tag due to their format.\n")
doc = doc + "The following document is generated from the machine-readable JSON describing the https://github.com/MISP/misp-taxonomies[MISP taxonomies]."
doc = "{} {} {} {}".format(
doc,
"\nTaxonomies that can be used in MISP (2.4) and other information sharing tool and expressed in Machine Tags (Triple Tags).",
"A machine tag is composed of a namespace (MUST), a predicate (MUST) and an (OPTIONAL) value.",
"Machine tags are often called triple tag due to their format.\n",
)
doc = (
doc
+ "The following document is generated from the machine-readable JSON describing the https://github.com/MISP/misp-taxonomies[MISP taxonomies]."
)
doc = doc + "\n\n"
doc = doc + "<<<\n"
doc = doc + dedication
@ -87,31 +109,37 @@ if args.n:
taxonomies.append(args.n)
def asciidoc(content=False, adoc=doc, t='title', toplevel=False):
def asciidoc(content=False, adoc=doc, t="title", toplevel=False):
if not args.a:
return False
adoc = adoc + "\n"
if t == 'title':
content = '==== ' + content
elif t == 'predicate':
content = '=== ' + content
elif t == 'namespace':
content = '== ' + content + '\n'
content = "{}\n{}{} {}{}{} {}".format(content, 'NOTE: ', namespace, 'namespace available in JSON format at https://github.com/MISP/misp-taxonomies/blob/main/',
namespace, '/machinetag.json[*this location*]. The JSON format can be freely reused in your application',
'or automatically enabled in https://www.github.com/MISP/MISP[MISP] taxonomy.')
elif t == 'description' and toplevel is True:
if t == "title":
content = "==== " + content
elif t == "predicate":
content = "=== " + content
elif t == "namespace":
content = "== " + content + "\n"
content = "{}\n{}{} {}{}{} {}".format(
content,
"NOTE: ",
namespace,
"namespace available in JSON format at https://github.com/MISP/misp-taxonomies/blob/main/",
namespace,
"/machinetag.json[*this location*]. The JSON format can be freely reused in your application",
"or automatically enabled in https://www.github.com/MISP/MISP[MISP] taxonomy.",
)
elif t == "description" and toplevel is True:
content = "\n{} \n".format(content)
elif t == 'description' and toplevel is False:
elif t == "description" and toplevel is False:
try:
(n, value) = content.split(":", 1)
content = "\n{} \n".format(value)
except:
content = "\n{} \n".format(content)
elif t == 'numerical_value':
elif t == "numerical_value":
(n, value) = content.split(":", 1)
content = "\nAssociated numerical value=\"{}\" \n".format(value)
elif t == 'exclusive':
content = '\nAssociated numerical value="{}" \n'.format(value)
elif t == "exclusive":
(n, value) = content.split(":", 1)
if n:
content = "\nIMPORTANT: Exclusive flag set which means the values or predicate below must be set exclusively.\n"
@ -124,9 +152,9 @@ def machineTag(namespace=False, predicate=False, value=None):
if namespace is False or predicate is False:
return None
if value is None:
return (u'{0}:{1}'.format(namespace, predicate))
return "{0}:{1}".format(namespace, predicate)
else:
return (u'{0}:{1}=\"{2}\"'.format(namespace, predicate, value))
return '{0}:{1}="{2}"'.format(namespace, predicate, value)
for taxonomy in taxonomies:
@ -136,70 +164,166 @@ for taxonomy in taxonomies:
filename = os.path.join(thisDir, "../", taxonomy, "machinetag.json")
with open(filename) as fp:
t = json.load(fp)
namespace = t['namespace']
if t.get('expanded'):
expanded_namespace = t['expanded']
namespace = t["namespace"]
if t.get("expanded"):
expanded_namespace = t["expanded"]
else:
expanded_namespace = namespace
if args.a:
doc = asciidoc(content=t['namespace'], adoc=doc, t='namespace')
doc = asciidoc(content=t['description'], adoc=doc, t='description', toplevel = True)
if t.get('exclusive'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=t['exclusive']), adoc=doc, t='exclusive')
doc = asciidoc(content=t["namespace"], adoc=doc, t="namespace")
doc = asciidoc(
content=t["description"], adoc=doc, t="description", toplevel=True
)
if t.get("exclusive"):
doc = asciidoc(
content=machineTag(namespace=namespace, predicate=t["exclusive"]),
adoc=doc,
t="exclusive",
)
if args.v:
print('{0}'.format(t['description']))
for predicate in t['predicates']:
print("{0}".format(t["description"]))
for predicate in t["predicates"]:
if args.a:
doc = asciidoc(content=predicate['value'], adoc=doc, t='predicate')
if predicate.get('description'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['description']), adoc=doc, t='description')
if predicate.get('exclusive'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['exclusive']), adoc=doc, t='exclusive')
doc = asciidoc(content=predicate["value"], adoc=doc, t="predicate")
if predicate.get("description"):
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["description"]
),
adoc=doc,
t="description",
)
if predicate.get("exclusive"):
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["exclusive"]
),
adoc=doc,
t="exclusive",
)
if t.get('values') is None:
if t.get("values") is None:
if args.a:
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['value']), adoc=doc)
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['expanded']), adoc=doc, t='description')
if predicate.get('description'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['description']), adoc=doc, t='description')
if predicate.get('numerical_value'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['numerical_value']), adoc=doc, t='description')
if predicate.get('exclusive'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=predicate['exclusive']), adoc=adoc, t='exclusive')
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["value"]
),
adoc=doc,
)
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["expanded"]
),
adoc=doc,
t="description",
)
if predicate.get("description"):
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["description"]
),
adoc=doc,
t="description",
)
if predicate.get("numerical_value"):
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["numerical_value"]
),
adoc=doc,
t="description",
)
if predicate.get("exclusive"):
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=predicate["exclusive"]
),
adoc=doc,
t="exclusive",
)
else:
print(machineTag(namespace=namespace, predicate=predicate['value']))
print(machineTag(namespace=namespace, predicate=predicate["value"]))
if args.e:
print("--> " + machineTag(namespace=expanded_namespace, predicate=predicate['expanded']))
if predicate.get('description'):
print("--> " + predicate['description'])
print(
"--> "
+ machineTag(
namespace=expanded_namespace, predicate=predicate["expanded"]
)
)
if predicate.get("description"):
print("--> " + predicate["description"])
else:
for e in t['values']:
if e['predicate'] == predicate['value']:
if 'expanded' in predicate:
expanded = predicate['expanded']
for v in e['entry']:
if args.a and 'expanded' in v:
doc = asciidoc(content=machineTag(namespace=namespace, predicate=e['predicate'], value=v['value']), adoc=doc)
doc = asciidoc(content=machineTag(namespace=namespace, predicate=v['expanded']), adoc=doc, t='description')
if 'description' in v:
doc = asciidoc(content=machineTag(namespace=namespace, predicate=v['description']), adoc=doc, t='description')
if v.get('numerical_value'):
doc = asciidoc(content=machineTag(namespace=namespace, predicate=v['numerical_value']), adoc=doc, t='numerical_value')
for e in t["values"]:
if e["predicate"] == predicate["value"]:
if "expanded" in predicate:
expanded = predicate["expanded"]
for v in e["entry"]:
if args.a and "expanded" in v:
doc = asciidoc(
content=machineTag(
namespace=namespace,
predicate=e["predicate"],
value=v["value"],
),
adoc=doc,
)
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=v["expanded"]
),
adoc=doc,
t="description",
)
if "description" in v:
doc = asciidoc(
content=machineTag(
namespace=namespace, predicate=v["description"]
),
adoc=doc,
t="description",
)
if v.get("numerical_value"):
doc = asciidoc(
content=machineTag(
namespace=namespace,
predicate=v["numerical_value"],
),
adoc=doc,
t="numerical_value",
)
else:
print(machineTag(namespace=namespace, predicate=e['predicate'], value=v['value']))
print(
machineTag(
namespace=namespace,
predicate=e["predicate"],
value=v["value"],
)
)
if args.e:
if'expanded' in v:
print("--> " + machineTag(namespace=namespace, predicate=expanded, value=v['expanded']))
if "expanded" in v:
print(
"--> "
+ machineTag(
namespace=namespace,
predicate=expanded,
value=v["expanded"],
)
)
with open('../mapping/mapping.json') as mapping:
with open("../mapping/mapping.json") as mapping:
m = json.load(mapping)
output = '\n= Mapping of taxonomies\n'
output = '{}{}'.format(output, 'Analysts relying on taxonomies don\'t always know the appropriate namespace to use but know which value to use for classification. The MISP mapping taxonomy allows to map a single classification into a series of machine-tag synonyms.\n')
output = "\n= Mapping of taxonomies\n"
output = "{}{}".format(
output,
"Analysts relying on taxonomies don't always know the appropriate namespace to use but know which value to use for classification. The MISP mapping taxonomy allows to map a single classification into a series of machine-tag synonyms.\n",
)
for value in sorted(m.keys()):
output = '{}{} **{}**{}{}\n'.format(output,'\n.Mapping table - ',value,'\n|===\n|',value)
for mapped in m[value]['values']:
output = '{}|{}\n'.format(output,mapped)
output = '{}|===\n'.format(output)
output = "{}{} **{}**{}{}\n".format(
output, "\n.Mapping table - ", value, "\n|===\n|", value
)
for mapped in m[value]["values"]:
output = "{}|{}\n".format(output, mapped)
output = "{}|===\n".format(output)
doc = doc + output
if args.a: