In [ ]:
import struct, socket
import numpy as np
import csv, json
import os
import urllib2
import datetime
import operator
import itertools
try:
import ipywidgets as widgets # For jupyter/ipython >= 1.4
except ImportError:
from IPython.html import widgets
from IPython.display import display, HTML, clear_output, Javascript
path = os.getcwd().split("/")
t_date = path[len(path)-1]
anchor = ''
anchor_type = ''
top_results = 20
details_limit = 1000
query_comments = {}
In [ ]:
# Widget styles and initialization
topBox = widgets.Box()
bottomBox = widgets.Box()
mainBoxes_css = (
(None, 'width', '90%'),
(None, 'margin', '0 auto'),
)
topBox._css = mainBoxes_css
bottomBox._css = mainBoxes_css
threatBox = widgets.HBox(width='100%', height='auto')
threat_title = widgets.HTML(height='25px', width='100%')
threat_list_container = widgets.Box(width='80%', height='100%')
threat_button_container = widgets.Box(width='20%', height='100%')
susp_select = widgets.Select(height='100%', width='99%')
search_btn = widgets.Button(description='Search',height='100%', width='65px')
search_btn.button_style = 'primary'
susp_select._css = (
(None, 'height', '90%'),
(None, 'width', '95%'),
('select', 'overflow-x', 'auto'),
('select', 'margin', 0)
)
resultSummaryBox = widgets.Box()
result_title = widgets.HTML(width='100%')
result_summary_box = widgets.HBox(width='100%')
result_summary_container = widgets.Box(width='80%')
result_button_container = widgets.Box(width='20%')
result_summary_box.children = [result_title, result_summary_container, result_button_container]
resultTableBox = widgets.Box()
result_html_title = widgets.HTML(height='25px', width='100%')
result_html_box = widgets.Box() #this one has the scroll
result_html = widgets.HTML(width='100%')
result_box_css = (
(None, 'overflow', 'hidden'),
(None, 'width', '100%'),
)
resultSummaryBox._css = result_box_css
resultTableBox._css = result_box_css
result_html_box._css = (
(None, 'overflow','auto'),
(None, 'max-height', '300px'),
)
threat_button_container._css = (
(None, 'padding-top', '30px'),
)
topBox.children = [threatBox]
bottomBox.children = [resultSummaryBox,resultTableBox]
threat_list_container.children = [threat_title,susp_select]
threat_button_container.children = [search_btn]
threatBox.children = [threat_list_container, threat_button_container]
Interface
In [ ]:
yy = t_date[0:4]
mm = t_date[4:6]
dd = t_date[6:8]
def fill_list(list_control,source):
susp_select.options = list_control
susp_select.selected_label = list_control[0][0]
def data_loader():
ips_query = {}
ip_sev={}
dns_sev={}
global query_comments
response = GraphQLClient.request(
query="""query($date:SpotDateType!) {
dns{
threats{
list(date:$date) {
dnsScore
clientIpScore
clientIp
dnsQuery
}
}
}
}""",
variables={
'date': datetime.datetime.strptime(t_date, '%Y%m%d').strftime('%Y-%m-%d')
}
)
query_comments = GraphQLClient.request(
query="""query($date:SpotDateType!) {
dns{
threats{
comments(date:$date) {
title
text
... on DnsQueryCommentType {
dnsQuery
}
... on DnsClientIpCommentType {
clientIp
}
}
}
}
}""",
variables={
'date': datetime.datetime.strptime(t_date, '%Y%m%d').strftime('%Y-%m-%d')
}
)
query_comments = query_comments['data']['dns']['threats']['comments']
if not 'errors' in response:
for row in response['data']['dns']['threats']['list']:
if row['clientIp'] not in ips_query and row['clientIpScore'] == 1:
ips_query[row['clientIp']]='i'
if row['dnsQuery'] not in ips_query and row['dnsScore'] == 1:
ips_query[row['dnsQuery']]='q'
if row['clientIp'] not in ip_sev:
ip_sev[row['clientIp']] = row['clientIpScore']
if row['dnsQuery'] not in dns_sev:
dns_sev[row['dnsQuery']] =row['dnsScore']
else:
print "An error ocurred: " + response["errors"][0]["message"]
threat_title.value ="<h4>Suspicious DNS</h4>"
if len(ips_query) == 0:
display(Javascript("$('.widget-area > .widget-subarea > *').remove();"))
display(widgets.HTML(value="There are not high risk results.", width='90%'),)
else:
sorted_dict = sorted(ips_query.items(), key=operator.itemgetter(0))
fill_list(sorted_dict,susp_select)
def start_investigation():
display(Javascript("$('.widget-area > .widget-subarea > *').remove();"))
data_loader()
if susp_select.options:
display_controls()
def display_controls():
susp_select
display(topBox)
def search_ip(b):
global anchor
global anchor_type
global expanded_results
anchor = ''
anchor_type = ''
anchor = susp_select.selected_label
anchor_type = susp_select.value
removeWidget(2)
removeWidget(1)
clear_output()
expanded_results = GraphQLClient.request(
query="""query($date:SpotDateType,$dnsQuery:String, $clientIp:SpotIpType){
dns{
threat{details(date:$date,dnsQuery:$dnsQuery,clientIp:$clientIp){
total
clientIp
dnsQuery
}}
}
}""",
variables={
'date': datetime.datetime.strptime(t_date, '%Y%m%d').strftime('%Y-%m-%d'),
'dnsQuery': anchor if anchor_type == 'q' else None,
'clientIp': anchor if anchor_type == 'i' else None
}
)
clear_output()
if not 'errors' in expanded_results:
table = "<table><th>IP</th><th>QUERY</th><th>TOTAL</th>"
for row in expanded_results["data"]["dns"]["threat"]["details"]:
table += "<tr><td class='spot-text-wrapper' data-toggle='tooltip'>"+row["clientIp"]+"</td>\
<td class='spot-text-wrapper' data-toggle='tooltip'>"+row["dnsQuery"]+"</td>\
<td align='center'>"+str(row["total"])+"</td></tr>"
table += "</table>"
result_html_title.value='<h4>Displaying top {0} search results</h4>'.format(top_results)
else:
print "An error ocurred: " + response["errors"][0]["message"]
result_html.value=table
result_html_box.children = [result_html]
display_threat_box(anchor,anchor_type)
resultTableBox.children = [result_html_title, result_html_box]
display(bottomBox)
search_btn.on_click(search_ip)
def display_threat_box(ip,anchor_type):
global query_comments
title =""
text = ""
data_filter = ""
data_filter = "dnsQuery" if anchor_type == 'q' else "clientIp"
title = next((item['title'] for item in query_comments if item.get(data_filter) == ip), "")
text = next((item['text'] for item in query_comments if item.get(data_filter) == ip), "")
result_title.value="<h4 class='spot-text-wrapper spot-text-xlg' data-toggle='tooltip'>Threat summary for " + anchor +"</h4>"
tc_txt_title = widgets.Text(value=title, placeholder='Threat Title', width='100%')
tc_txa_summary = widgets.Textarea(value=text, height=100, width='95%')
tc_btn_save = widgets.Button(description='Save', width='65px', layout='width:100%')
tc_btn_save.button_style = 'primary'
tc_txt_title._css = (
(None, 'width', '95%'),
)
result_summary_container.children = [tc_txt_title, tc_txa_summary]
result_button_container.children=[tc_btn_save]
result_summary_box.children = [result_summary_container, result_button_container]
resultSummaryBox.children = [result_title,result_summary_box]
def save_threat_summary(b):
global anchor
anchor_ip =''
anchor_dns =''
if anchor_type == 'i':
anchor_ip = anchor
elif anchor_type == 'q':
anchor_dns = anchor
if anchor != '':
mutation="""mutation(
$date: SpotDateType,
$dnsQuery:String,
$clientIp:SpotIpType,
$text: String!,
$title: String!,
$threatDetails: [DnsThreatDetailsInputType!]!)
{
dns{
createStoryboard(input:{
threatDetails: $threatDetails,
date: $date,
dnsQuery: $dnsQuery,
clientIp: $clientIp,
title: $title,
text: $text
})
{success}
}
}"""
variables={
'date': datetime.datetime.strptime(t_date, '%Y%m%d').strftime('%Y-%m-%d'),
'dnsQuery': anchor_dns if anchor_type == 'q' else None,
'clientIp': anchor_ip if anchor_type == 'i' else None,
'title': tc_txt_title.value,
'text': tc_txa_summary.value.replace('\n', '\\n'),
'threatDetails': expanded_results['data']['dns']['threat']['details']
}
response = GraphQLClient.request(mutation, variables)
display(Javascript("$('.widget-area > .widget-subarea > .widget-box:gt(0)').remove();"))
response = "Summary successfully saved"
else:
response = "No data selected"
susp_select.selected_label = susp_select.options[0][0]
display(widgets.Box((widgets.HTML(value=response, width='100%'),)))
data_loader()
tc_btn_save.on_click(save_threat_summary)
def file_is_empty(path):
return os.stat(path).st_size==0
def removeWidget(index):
js_command = "$('.widget-area > .widget-subarea > .widget-box:eq({0})').remove();".format(index)
display(Javascript(js_command))
In [ ]:
start_investigation()