mirror of https://github.com/infosecn1nja/HELK.git
74 lines
4.4 KiB
Python
74 lines
4.4 KiB
Python
#!/usr/bin/env python
|
|
|
|
# ATT&CK Client Main Script - Drill-down capabilities at the tactic / technique / platform / data source levels
|
|
# Author: Jose Rodriguez (@Cyb3rPandaH)
|
|
# License: GPL-3.0
|
|
# Reference:
|
|
# https://github.com/Cyb3rWard0g/ATTACK-Python-Client
|
|
# https://stackoverflow.com/questions/27263805/pandas-when-cell-contents-are-lists-create-a-row-for-each-element-in-the-list/27266225?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
|
|
# https://stackoverflow.com/questions/19913659/pandas-conditional-creation-of-a-series-dataframe-column?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
|
|
# http://pandas.pydata.org/pandas-docs/version/0.22/generated/pandas.Series.str.contains.html
|
|
# https://chrisalbon.com/python/data_wrangling/pandas_dropping_column_and_rows/
|
|
|
|
from pandas import *
|
|
from pandas.io.json import json_normalize
|
|
from pandas import Series,DataFrame
|
|
|
|
from attackcti import attack_client
|
|
|
|
mitre = attack_client()
|
|
|
|
db = mitre.get_all_attack()
|
|
|
|
# Removes '\n' inside of a list element of the 'system_requirements' property
|
|
db_fixed = db
|
|
for sr in db_fixed:
|
|
if 'system_requirements' in sr:
|
|
if sr['system_requirements']:
|
|
for idx, item in enumerate(sr['system_requirements']):
|
|
sr['system_requirements'][idx] = sr['system_requirements'][idx].replace('\n',' ')
|
|
|
|
df = json_normalize(db_fixed)
|
|
df = df[[
|
|
'matrix','tactic','technique','technique_id','technique_description',
|
|
'mitigation','mitigation_description','group','group_id','group_aliases',
|
|
'group_description','software','software_id','software_description','software_labels',
|
|
'relationship_description','platform','data_sources','detectable_by_common_defenses','detectable_explanation',
|
|
'difficulty_for_adversary','difficulty_explanation','effective_permissions','network_requirements','permissions_required',
|
|
'remote_support','system_requirements','contributors','url']]
|
|
|
|
#****** There are some columns that contain a list on their cells, we need to create a row per each value of the list
|
|
attributes = ['tactic','platform','data_sources','permissions_required']
|
|
# In attributes, we indicate the name of the columns that we need to distribute in rows by values of the list
|
|
|
|
for a in attributes:
|
|
s = df.apply(lambda x: pandas.Series(x[a]),axis=1).stack().reset_index(level=1, drop=True)
|
|
# "s" is going to be a column of a frame with every value of the list inside each cell of the column "a"
|
|
s.name = a
|
|
# We name "s" with the same name of "a".
|
|
df = df.drop(a, axis=1).join(s).reset_index(drop=True)
|
|
# We drop the column "a" from "df", and then join "df" with "s"
|
|
|
|
#****** Now we are going to create a new column to identify windows data sources in Linux and macOS platforms
|
|
conditions = [(df['platform']=='Linux')&(df['data_sources'].str.contains('windows',case=False)== True),
|
|
(df['platform']=='macOS')&(df['data_sources'].str.contains('windows',case=False)== True),
|
|
(df['platform']=='Linux')&(df['data_sources'].str.contains('powershell',case=False)== True),
|
|
(df['platform']=='macOS')&(df['data_sources'].str.contains('powershell',case=False)== True),
|
|
(df['platform']=='Linux')&(df['data_sources'].str.contains('wmi',case=False)== True),
|
|
(df['platform']=='macOS')&(df['data_sources'].str.contains('wmi',case=False)== True)]
|
|
# In conditions we indicate a logical test
|
|
|
|
choices = ['NO OK','NO OK','NO OK','NO OK','NO OK','NO OK']
|
|
# In choices, we indicate the result when the logical test is true
|
|
|
|
df['Validation'] = np.select(conditions,choices,default='OK')
|
|
# Finally, we add a column "Validation" to "df" with the result of the logical test. The default value is going to be "OK"
|
|
|
|
#****** Now we are going to create a new dataframe and filter the value "OK" in the column "Validation". We are going to replace some values in all the cells of the data frame
|
|
df_final = df[df.Validation == 'OK'].replace(['mitre-attack-mobile','Process monitoring','Application logs'],['mitre-mobile-attack','Process Monitoring','Application Logs'])
|
|
|
|
#****** Now we are going to delete the line breaks for all the cell of the dataframe. This action only applies for cells that contain a String value
|
|
df_final = df_final.replace('\n','',regex=True)
|
|
|
|
#****** Finally, we export the data frame to a CSV file
|
|
df_final.to_csv('mitre_attack.csv',index=False,encoding='utf-8') |