| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #!/usr/bin/env python
- # coding: utf-8
-
- # In[1]:
-
-
- import pandas as pd
- import numpy as np
- from mlxtend.preprocessing import TransactionEncoder
- from mlxtend.frequent_patterns import association_rules, fpgrowth
- from prefixspan import PrefixSpan
-
-
-
- df = pd.read_csv("ts_data_accident-2020_sample.csv", low_memory=False, encoding='ISO-8859-1')
- pd.set_option('display.max_columns',None)
- df=df[['RISK_V2','INST_NM','DRULE_ATT_TYPE_CODE1','TW_ATT_IP','TW_ATT_PORT','TW_DMG_IP','TW_DMG_PORT','ACCD_DMG_PROTO_NM','TW_ATT_CT_NM','ACCD_FIND_MTD_CODE','DRULE_NM']].dropna()
- len(df)
- ##################### NTM section #####################
- NTM_df=df[df['ACCD_FIND_MTD_CODE']==1]
- NTM_df
-
- # Pick out it in order to get the asset, risk, intent, black IP out
- RISK_V2=NTM_df['RISK_V2']
- RISK_V2_FILTERED=RISK_V2.dropna()
- ## 결측값 제거.
-
- import json
- from pandas import json_normalize
-
- # modified
- def get_asset_desc(asset_field):
- if asset_field == 'ASSETS_VAL_1':
- return '공인-전체IP대역(유선)'
- elif asset_field == 'ASSETS_VAL_2':
- return '공인-전체IP대역(무선)'
- elif asset_field == 'ASSETS_VAL_3':
- return '공인-WEB서버'
- elif asset_field == 'ASSETS_VAL_4':
- return '공인-내부응용서버'
- elif asset_field == 'ASSETS_VAL_5':
- return '공인-DB서버'
- elif asset_field == 'ASSETS_VAL_6':
- return '공인-패치서버'
- elif asset_field == 'ASSETS_VAL_7':
- return '공인-네트워크'
- elif asset_field == 'ASSETS_VAL_8':
- return '공인-보안'
- elif asset_field == 'ASSETS_VAL_9':
- return '공인-업무용PC'
- elif asset_field == 'ASSETS_VAL_10':
- return '공인-비업무용PC'
- elif asset_field == 'ASSETS_VAL_11':
- return '공인-기타'
- elif asset_field == 'ASSETS_VAL_12':
- return '사설-전체IP대역(유선)'
- elif asset_field == 'ASSETS_VAL_13':
- return '사설-전체IP대역(무선)'
- elif asset_field == 'ASSETS_VAL_14':
- return '사설-WEB서버'
- elif asset_field == 'ASSETS_VAL_15':
- return '사설-내부응용서버'
- elif asset_field == 'ASSETS_VAL_16':
- return '사설-DB서버'
- elif asset_field == 'ASSETS_VAL_17':
- return '사설-패치서버'
- elif asset_field == 'ASSETS_VAL_18':
- return '사설-네트워크'
- elif asset_field == 'ASSETS_VAL_19':
- return '사설-보안'
- elif asset_field == 'ASSETS_VAL_20':
- return '사설-업무용PC'
- elif asset_field == 'ASSETS_VAL_21':
- return '사설-비업무용PC'
- elif asset_field == 'ASSETS_VAL_22':
- return '사설-기타'
- else:
- return ''
-
- def get_intent_desc(intent_field):
- if intent_field == 'INTENT_VAL_1':
- return '파괴'
- elif intent_field == 'INTENT_VAL_2':
- return '유출'
- elif intent_field == 'INTENT_VAL_3':
- return '지연'
- elif intent_field == 'INTENT_VAL_4':
- return '잠복'
- elif intent_field == 'INTENT_VAL_5':
- return '단순침입'
- elif intent_field == 'INTENT_VAL_6':
- return 'MD5'
- elif intent_field == 'INTENT_VAL_0':
- return 'Default'
- else:
- return ''
-
- def get_source_desc(source_field):
- if source_field=='SOURCE_VAL_1':
- return '북한IP'
- if source_field=='SOURCE_VAL_3':
- return 'ECSC Black IP'
- else:
- return ''
- # New assets column
-
- ## ASSETS_VAL을 아예 JSON항목으로 만들어서 새로운 데이터프레임으로 생성.
- risk_df = pd.DataFrame()
- for risk in RISK_V2_FILTERED:
- risk = risk.replace("'", "\"") #json으로 만들려고.
- json_string = json.loads(risk)
- json_df = json_normalize(json_string)
- risk_df = pd.concat([risk_df,json_df],ignore_index=True) #DataFrame 합쳐주기. ignore_index = True를 해야 index가 재구성 된다.
- risk_df_column_names = risk_df.columns
-
- assets_df = []
- intents_df = []
- sources_df = []
- def filter_all(risk):
- for i in range(0,len(risk)):
- risks=[]
- intents=[]
- sources=[]
- for column in risk_df_column_names:
- # filter_asset
- if 'ASSETS_VAL_' in column and risk.iloc[i][column]:
- risk_key_desc = 'RISK_V2.' + column + '=' + get_asset_desc(column)
- risks.append(risk_key_desc)
-
- # filter_intent
- if 'INTENT_VAL_' in column and risk.iloc[i][column]:
- intent_key_desc = 'RISK_V2.' + column + '=' + get_intent_desc(column)
- intents.append(intent_key_desc)
-
- if 'SOURCE_VAL_' in column and risk.iloc[i][column]:
- source_key_desc='RISK_V2.' + column + '=' + get_source_desc(column)
- sources.append(source_key_desc)
-
- assets_df.append(risks)
- intents_df.append(intents)
- sources_df.append(sources)
-
- filter_all(risk_df)
- ## 여기까지 내가 만든 것.
-
- ## ASSETS_VAL 확인
- NTM_df['ASSETS_VAL'] = assets_df
- NTM_df['ASSETS_VAL'] = NTM_df['ASSETS_VAL'].astype(str)
- NTM_df['ASSETS_VAL'] = NTM_df['ASSETS_VAL'].str.replace('[','',regex=True)
- NTM_df['ASSETS_VAL'] = NTM_df['ASSETS_VAL'].str.replace(']','',regex=True)
- # NTM_df['ASSETS_VAL']
-
- NTM_df['INTENT_VAL'] = intents_df
- NTM_df['INTENT_VAL'] = NTM_df['INTENT_VAL'].astype(str)
- NTM_df['INTENT_VAL'] = NTM_df['INTENT_VAL'].str.replace('[','',regex=True)
- NTM_df['INTENT_VAL'] = NTM_df['INTENT_VAL'].str.replace(']','',regex=True)
- # NTM_df['INTENT_VAL']
-
- NTM_df['SOURCE_VAL'] = sources_df
- NTM_df['SOURCE_VAL'] = NTM_df['SOURCE_VAL'].astype(str)
- NTM_df['SOURCE_VAL'] = NTM_df['SOURCE_VAL'].str.replace('[','',regex=True)
- NTM_df['SOURCE_VAL'] = NTM_df['SOURCE_VAL'].str.replace(']','',regex=True)
- # NTM_df['SOURCE_VAL']
-
- NTM_df.drop(columns=['RISK_V2'], inplace=True)
-
- ##################### 여기서부터 진행하시면 됩니다. #####################
- ##################### 아래 12개 아이템(12. 장비 ACCD_FIND_MTD_CODE 제외)에 대해서 모든 아이템 조합에 알고리즘 적용하기#####################
-
- # It should be 13 columns in total
-
- # 1. 기관 INST_NM
- # 2. 공격 DRULE_ATT_TYPE_CODE1
- # 3. 자산 ASSETS_VAL
- # 4. 위협공격ip TW_ATT_IP
- # 5. 위협공격port TW_ATT_PORT
- # 6. 위협피해ip TW_DMG_IP
- # 7. 위협피해port TW_DMG_PORT
- # 8. 위협피해프로토콜 ACCD_DMG_PROTO_NM
- # 9. 공격국가 TW_ATT_CT_NM
- # 10. 의도(7개) INTENT_VAL
- # 11. IP/URL 가중치 SOURCE_VAL
- # 12. 장비 ACCD_FIND_MTD_CODE
- # 13. 탐지규칙명 DRULE_NM
-
- NTM_df.isna().sum()
-
- # Change the Nan to zero
- NTM_df['ACCD_DMG_PROTO_NM']=NTM_df['ACCD_DMG_PROTO_NM'].replace(np.nan,'')
- NTM_df['INST_NM']=NTM_df['INST_NM'].replace(np.nan,'')
- NTM_df['DRULE_ATT_TYPE_CODE1']=NTM_df['DRULE_ATT_TYPE_CODE1'].replace(np.nan,'')
- NTM_df['TW_ATT_IP']=NTM_df['TW_ATT_IP'].replace(np.nan,0)
- NTM_df['TW_ATT_PORT']=NTM_df['TW_ATT_PORT'].replace(np.nan,0)
- NTM_df['TW_DMG_IP']=NTM_df['TW_DMG_IP'].replace(np.nan,0)
- NTM_df['TW_DMG_PORT']=NTM_df['TW_DMG_PORT'].replace(np.nan,0)
- NTM_df['TW_ATT_CT_NM']=NTM_df['TW_ATT_CT_NM'].replace(np.nan,'')
- NTM_df['ASSETS_VAL']=NTM_df['ASSETS_VAL'].replace(np.nan,0)
- NTM_df['INTENT_VAL']=NTM_df['INTENT_VAL'].replace(np.nan,0)
- NTM_df['SOURCE_VAL']=NTM_df['SOURCE_VAL'].replace(np.nan,0)
- NTM_df['DRULE_NM']=NTM_df['DRULE_NM'].replace(np.nan,'')
-
- # Check NaN out again
- NTM_df.isna().sum()
-
- # # Merge all
-
- # # Make one string from all of elements
- NTM_df['Combined']=NTM_df['INST_NM'].astype(str)+' '+NTM_df['TW_ATT_IP'].astype(str)+' '+NTM_df['TW_ATT_PORT'].astype(str)+' '+NTM_df['TW_DMG_IP'].astype(str)+' '+NTM_df['TW_DMG_PORT'].astype(str) +' '+NTM_df['ACCD_DMG_PROTO_NM'].astype(str)+' '+NTM_df['TW_ATT_CT_NM']+' '+NTM_df['ASSETS_VAL']+' '+NTM_df['INTENT_VAL']+' '+NTM_df['SOURCE_VAL']+' '+NTM_df['DRULE_ATT_TYPE_CODE1']+' '+NTM_df['DRULE_NM']
-
- NTM_com=NTM_df['Combined']
- ## 내가 만든 컴바인
- ## 모든 조합을 돌릴거면, [1,2,3,4,5] 처럼 배열의 원소로 만들어서 넣는게 가장 베스트 아닌가.
- ## 그런데 순서를 다 바꿔줘야 하는데, 그건 어떻게 할 것인지 내일 물어보자.
-
- data_len = len(NTM_df)
- hwan_list = []
- for i in range(0,data_len):
- accd_dmg_proto_nm = NTM_df.loc[i]['ACCD_DMG_PROTO_NM']
- inst_nm = NTM_df.loc[i]['INST_NM']
- drule_att_type_code1 = NTM_df.loc[i]['DRULE_ATT_TYPE_CODE1']
- tw_att_ip = NTM_df.loc[i]['TW_ATT_IP']
- tw_att_port = NTM_df.loc[i]['TW_ATT_PORT']
- tw_dmg_ip = NTM_df.loc[i]['TW_DMG_IP']
- tw_dmg_port = NTM_df.loc[i]['TW_DMG_PORT']
- tw_att_ct_nm = NTM_df.loc[i]['TW_ATT_CT_NM']
- assets_val = NTM_df.loc[i]['ASSETS_VAL']
- intent_val = NTM_df.loc[i]['INTENT_VAL']
- source_val = NTM_df.loc[i]['SOURCE_VAL']
- drule_nm = NTM_df.loc[i]['DRULE_NM']
- null_check_list = [accd_dmg_proto_nm, inst_nm, drule_att_type_code1, tw_att_ip, tw_att_port,
- tw_dmg_ip, tw_dmg_port, tw_att_ct_nm, assets_val, intent_val, source_val, drule_nm]
- not_null_arr = []
- ## 리스트안에 빈 값을 빼버리자.
- for item in null_check_list:
- if item and item != '[]':
- not_null_arr.append(item)
- hwan_list.append(not_null_arr)
-
- new_ps = PrefixSpan(hwan_list)
- # new_ps : hwan_list안에 순서대로 null값을 제외한 모든값들이 [1,2,3,4,5,6] 이런식으로 들어가 있는데,
- # 이 값을 PrefixSpan 수행한 코드.
-
- ## 여기도 내 코드
- test_ntm = new_ps.frequent(1)
- test_ntm_df = pd.DataFrame(test_ntm)
- test_ntm_df.rename(columns={0:'Frequency', 1:'Cause'}, inplace=True)
- print(test_ntm_df)
- test_sort_values = test_ntm_df.sort_values(by=['Frequency'],ascending=False,ignore_index=True)
- # test_sort_values : PrefixSpan을 수행하여 Frequency가 나온 값. Frequency 를 기준으로 정렬했는데, 2900만가지나 된다.
-
-
- # Effect Rule Name Case 1.
- prefix_NTM_df = test_sort_values
- for i in range(0,len(prefix_NTM_df)):
- drules=['Attack','DDOS','HACK','MAIL','Malwr','WEB']
- for drule in drules:
- if drule in prefix_NTM_df.Cause[i]:
- prefix_NTM_df.Effect[i] = drule
- elif prefix_NTM_df.Cause[i] == NaN:
- prefix_NTM_df.Effect[i] = ''
-
- # Effect Rule Name Case 2.
- prefix_NTM_df = test_sort_values
-
- for i in range(0,len(prefix_NTM_df)):
- drules=['Attack','DDOS','HACK','MAIL','Malwr','WEB']
- for drule in drules:
- iloc_value = prefix_NTM_df.iloc[i]['Cause']
- if drule in iloc_value:
- prefix_NTM_df.Cause[i] = drule
-
- # Case 1을 20분동안 돌렸는데도 결과가 나오질 않아서 iloc으로 바꾸어 Case2로 돌려보았다. 이것도 오래걸리는 중..
-
- # Rule Name 적용한 코드는 prefix_NTM_df 에 적용.
|