This post will cover how to bulk-export MSV Action details. The actions info could be useful in building a different categorization or understanding the actions coverage.
A possible use case is to pass the actions descriptions to an LLM to generate a different fine-tuned categorization, for example this is a snippet of categorizing Cloud Actions into finer categories by an LLM ;
Another use case is to use "verodin_tags" column to generate statistics about the different actions Vs MITRE tags (e.g. ATT&CK:T1082). This column has multiple tags categories like like Malware, APT, ..etc that could be leverage to build visualization matrices per threats.
The code snippet provided is expands the library descried in a previous post by adding the getActions() function to msvlib_simple.py snippet. The few extra lines provided will just parse the data into Pandas dataframe. The actions info will be fetched by ;
actions = getActions() : GET : manage_sims/actions : Empty Body
###main.py
from msvlib_simple import *
import pandas as pd
folderName='.'
configFileName='credentials.txt'
headers_msv=readConfig(configFileName = configFileName
, folderName = folderName
)
url_base = headers_msv['url_base']
payload=json.dumps("")
actionsList = getActions(headers_msv, url_base)
actionsPd = pd.DataFrame(actionsList)
###credentials.txt --Remove this line
[hdr]
Content-Type = application/json
Accept = application/json
Authorization = Bearer xxx=
Mandiant-Organization = UUID xxxx
url_base = https://app.validation.mandiant.com/
###msvlib_simple.py
import requests
import json
import configparser
import os
import urllib3
import time
def readConfig(configFileName='cre.txt',folderName='.'):
configFileName=os.path.join(folderName, configFileName)
config = configparser.ConfigParser()
config.read(configFileName)
keys=[key for key in config[config.sections()[0]]]
values=[config[config.sections()[0]][key] for key in keys]
headers={k:v for (k,v) in zip(keys,values)}
return (headers)
def runAPI(endpoint='topology/nodes', verb='GET'
, payload=json.dumps({}), headers_msv=json.dumps({})
,url_base = 'https://app.validation.mandiant.com/'
,params=None
, printing=False ):
url_msv=f"{url_base}{endpoint}"
successful = False
while not successful:
try:
res = requests.request(
method=verb
, url=url_msv
, params=params
, headers=headers_msv
, data=payload
, verify=False
, timeout=600
)
successful = True
except requests.exceptions.RequestException as e:
print (f"Error : {e}")
time.sleep(60)
if printing==True : print (res.url)
if printing==True : print (res.request)
if printing==True : print (res.text[:100])
if res.text!='':
return json.loads(res.text)
else :
return res.text
def getActions( headers_msv, url_base , filterPayload = {}):
#Returns a hash of sim_actions filtered by user provided tags
payload=json.dumps(filterPayload)
if filterPayload == {}:
##List actions
returnActionsList=runAPI(endpoint=f"manage_sims/actions"
, verb='GET'
, payload=payload
, headers_msv=headers_msv
, url_base=url_base
)
else:
returnActionsList=runAPI(endpoint=f"manage_sims/actions/filtered_actions"
, verb='GET'
, payload=payload
, headers_msv=headers_msv
, url_base=url_base
)
return returnActionsList