2018-12-29 20:27:58 +01:00
|
|
|
% DO NOT COMPILE THIS FILE DIRECTLY!
|
|
|
|
% This is included by the other .tex files.
|
|
|
|
|
|
|
|
\lstdefinelanguage{json}{
|
|
|
|
basicstyle=\ttfamily\footnotesize,
|
|
|
|
numbers=left,
|
|
|
|
numberstyle=\ttfamily\footnotesize,
|
|
|
|
stepnumber=1,
|
|
|
|
numbersep=8pt,
|
|
|
|
showstringspaces=false,
|
|
|
|
breaklines=true,
|
|
|
|
frame=lines,
|
|
|
|
title=\lstname,
|
|
|
|
backgroundcolor=\color{background},
|
|
|
|
literate=
|
|
|
|
*{0}{{{\color{numb}0}}}{1}
|
|
|
|
{1}{{{\color{numb}1}}}{1}
|
|
|
|
{2}{{{\color{numb}2}}}{1}
|
|
|
|
{3}{{{\color{numb}3}}}{1}
|
|
|
|
{4}{{{\color{numb}4}}}{1}
|
|
|
|
{5}{{{\color{numb}5}}}{1}
|
|
|
|
{6}{{{\color{numb}6}}}{1}
|
|
|
|
{7}{{{\color{numb}7}}}{1}
|
|
|
|
{8}{{{\color{numb}8}}}{1}
|
|
|
|
{9}{{{\color{numb}9}}}{1}
|
|
|
|
{:}{{{\color{punct}{:}}}}{1}
|
|
|
|
{,}{{{\color{punct}{,}}}}{1}
|
|
|
|
{\{}{{{\color{delim}{\{}}}}{1}
|
|
|
|
{\}}{{{\color{delim}{\}}}}}{1}
|
|
|
|
{[}{{{\color{delim}{[}}}}{1}
|
|
|
|
{]}{{{\color{delim}{]}}}}{1},
|
|
|
|
}
|
|
|
|
|
|
|
|
\begin{frame}[t,plain]
|
|
|
|
\titlepage
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Why we want to go more modular...}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Ways to extend MISP before modules
|
|
|
|
\begin{itemize}
|
|
|
|
\item APIs (PyMISP, MISP API)
|
|
|
|
\begin{itemize}
|
|
|
|
\item Works really well
|
|
|
|
\item {\bf No integration with the UI}
|
|
|
|
\end{itemize}
|
|
|
|
\item Change the core code
|
|
|
|
\begin{itemize}
|
|
|
|
\item Have to change the core of MISP, diverge from upstream
|
|
|
|
\item Needs a deep understanding of MISP internals
|
|
|
|
\item Let's not beat around the bush: {\bf Everyone hates PHP}
|
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Goals for the module system}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Have a way to extend MISP without altering the core
|
|
|
|
\item Get started {\bf quickly} without a need to study the internals
|
|
|
|
\item Make the {\bf modules as light weight as possible}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Module developers should only have to worry about the data transformation
|
|
|
|
\item Modules should have a simple and clean skeleton
|
|
|
|
\end{itemize}
|
|
|
|
\item In a friendlier language - {\bf Python}
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}
|
|
|
|
\frametitle{MISP modules - extending MISP with Python scripts}
|
|
|
|
\begin{columns}[t]
|
|
|
|
\column{5.6cm}
|
|
|
|
\begin{figure}
|
|
|
|
\includegraphics[scale=0.70]{misp-expansion.pdf}
|
|
|
|
\end{figure}
|
|
|
|
\column{6.4cm}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Extending MISP with expansion modules with zero customization in MISP.
|
|
|
|
\item A simple ReST API between the modules and MISP allowing auto-discovery of new modules with their features.
|
|
|
|
\item Benefit from existing Python modules in Viper or any other tools.
|
|
|
|
\item MISP modules functionnality introduced in MISP 2.4.28.
|
|
|
|
\item MISP import/export modules introduced in MISP 2.4.50.
|
|
|
|
\end{itemize}
|
|
|
|
\end{columns}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{MISP modules - installation}
|
|
|
|
\begin{itemize}
|
|
|
|
\item MISP modules can be run on the same system or on a remote server.
|
|
|
|
\item Python 3 is required to run MISP modules.
|
|
|
|
\begin{itemize}
|
|
|
|
\item sudo apt-get install python3-dev python3-pip libpq5
|
|
|
|
\item cd /usr/local/src/
|
|
|
|
\item sudo git clone https://github.com/MISP/misp-modules.git
|
|
|
|
\item cd misp-modules
|
|
|
|
\item sudo pip3 install -I -r REQUIREMENTS
|
|
|
|
\item sudo pip3 install -I .
|
|
|
|
\item sudo vi /etc/rc.local, add this line: `sudo -u www-data misp-modules -s \&`
|
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}
|
|
|
|
\frametitle{MISP modules - Simple REST API mechanism}
|
|
|
|
\begin{itemize}
|
|
|
|
\item http://127.0.0.1:6666/modules - introspection interface to get {\bf all modules available}
|
|
|
|
\begin{itemize}
|
|
|
|
\item returns a JSON with a description of each module
|
|
|
|
\end{itemize}
|
|
|
|
\item http://127.0.0.1:6666/query - interface to {\bf query a specific module}
|
|
|
|
\begin{itemize}
|
|
|
|
\item to send a JSON to query the module
|
|
|
|
\end{itemize}
|
|
|
|
\item {\bf MISP autodiscovers} the available modules and the MISP site administrator can enable modules as they wish.
|
|
|
|
\item If a configuration is required for a module, {\bf MISP adds automatically the option} in the server settings.
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Finding available MISP modules}
|
|
|
|
\begin{itemize}
|
|
|
|
\item curl -s http://127.0.0.1:6666/modules
|
|
|
|
\end{itemize}
|
|
|
|
\begin{adjustbox}{width=\textwidth,height=6cm,keepaspectratio}
|
|
|
|
\begin{lstlisting}[language=json,firstnumber=1]
|
|
|
|
{
|
|
|
|
"type": "expansion",
|
|
|
|
"name": "dns",
|
|
|
|
"meta": {
|
|
|
|
"module-type": [
|
|
|
|
"expansion",
|
|
|
|
"hover"
|
|
|
|
],
|
|
|
|
"description": "Simple DNS expansion service to resolve IP address from MISP attributes",
|
|
|
|
"author": "Alexandre Dulaunoy",
|
|
|
|
"version": "0.1"
|
|
|
|
},
|
|
|
|
"mispattributes": {
|
|
|
|
"output": [
|
|
|
|
"ip-src",
|
|
|
|
"ip-dst"
|
|
|
|
],
|
|
|
|
"input": [
|
|
|
|
"hostname",
|
|
|
|
"domain"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
\end{lstlisting}
|
|
|
|
\end{adjustbox}
|
|
|
|
\end{frame}
|
|
|
|
|
2020-02-19 11:31:28 +01:00
|
|
|
\begin{frame}
|
|
|
|
\frametitle{MISP modules - configuration in the UI}
|
|
|
|
\includegraphics[scale=0.50]{modules-integration.png}
|
2018-12-29 20:27:58 +01:00
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}
|
|
|
|
\frametitle{MISP modules - How it's integrated in the UI?}
|
|
|
|
\includegraphics[scale=0.40]{screenshots/enrichment1.PNG}\\
|
|
|
|
\includegraphics[scale=0.38]{screenshots/enrichment2.PNG}\\
|
|
|
|
\includegraphics[scale=0.35]{screenshots/enrichment3.PNG}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}
|
|
|
|
\frametitle{MISP modules - main types of modules}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Expansion modules - enrich data that is in MISP
|
|
|
|
\begin{itemize}
|
|
|
|
\item Hover type - showing the expanded values directly on the attributes
|
|
|
|
\item Expansion type - showing and adding the expanded values via a proposal form
|
|
|
|
\end{itemize}
|
|
|
|
\item Import modules - import new data into MISP
|
|
|
|
\item Export modules - export existing data from MISP
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
2020-02-19 11:31:28 +01:00
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Expansion module (Skeleton)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% import json
|
|
|
|
% import dns.resolver
|
|
|
|
%
|
|
|
|
% misperrors = {'error' : 'Error'}
|
|
|
|
% mispattributes = {'input': [], 'output': []}
|
|
|
|
% moduleinfo = {'version': '', 'author': '',
|
|
|
|
% 'description': '', 'module-type': []}
|
|
|
|
%
|
|
|
|
% def handler(q=False):
|
|
|
|
% if q is False:
|
|
|
|
% return False
|
|
|
|
% request = json.loads(q)
|
|
|
|
% r = {'results': [{'types': [], 'values':[]}]}
|
|
|
|
% return r
|
|
|
|
% def introspection():
|
|
|
|
% return mispattributes
|
|
|
|
% def version():
|
|
|
|
% return moduleinfo
|
|
|
|
%
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Expansion module (metadata 1)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% misperrors = {'error' : 'Error'}
|
|
|
|
% mispattributes = {'input': ['hostname', 'domain'], 'output': ['ip-src', 'ip-dst']}
|
|
|
|
% moduleinfo = {'version': '', 'author': '',
|
|
|
|
% 'description': '', 'module-type': []}
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Expansion module (metadata 2)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=10cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python,showstringspaces=false]
|
|
|
|
% misperrors = {'error' : 'Error'}
|
|
|
|
% mispattributes = {'input': ['hostname', 'domain'], 'output': ['ip-src', 'ip-dst']}
|
|
|
|
% moduleinfo = {'version': '0.1', 'author': 'Alexandre Dulaunoy',
|
|
|
|
% 'description': 'Simple DNS expansion service to
|
|
|
|
% resolve IP address from MISP attributes', 'module-type': ['expansion','hover']}
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Expansion module (handler 1)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% def handler(q=False):
|
|
|
|
% if q is False:
|
|
|
|
% return False
|
|
|
|
% request = json.loads(q)
|
|
|
|
% # MAGIC
|
|
|
|
% # MORE MAGIC
|
|
|
|
% r = {'results': [
|
|
|
|
% {'types': output_types, 'values':values},
|
|
|
|
% {'types': output_types2, 'values':values2}
|
|
|
|
% ]}
|
|
|
|
% return r
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Expansion module (handler 2)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% if request.get('hostname'):
|
|
|
|
% toquery = request['hostname']
|
|
|
|
% elif request.get('domain'):
|
|
|
|
% toquery = request['domain']
|
|
|
|
% else:
|
|
|
|
% return False
|
|
|
|
% r = dns.resolver.Resolver()
|
|
|
|
% r.timeout = 2
|
|
|
|
% r.lifetime = 2
|
|
|
|
% r.nameservers = ['8.8.8.8']
|
|
|
|
% try:
|
|
|
|
% answer = r.query(toquery, 'A')
|
|
|
|
% except dns.resolver.NXDOMAIN:
|
|
|
|
% misperrors['error'] = "NXDOMAIN"
|
|
|
|
% return misperrors
|
|
|
|
% except dns.exception.Timeout:
|
|
|
|
% misperrors['error'] = "Timeout"
|
|
|
|
% return misperrors
|
|
|
|
% except:
|
|
|
|
% misperrors['error'] = "DNS resolving error"
|
|
|
|
% return misperrors
|
|
|
|
% r = {'results': [{'types': mispattributes['output'], 'values':[str(answer[0])]}]}
|
|
|
|
% return r
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
2018-12-29 20:27:58 +01:00
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
2020-02-19 11:31:28 +01:00
|
|
|
\frametitle{Querying a module}
|
|
|
|
\begin{itemize}
|
|
|
|
\item curl -s http://127.0.0.1:6666/query -H "Content-Type: application/json" --data @body.json -X POST
|
|
|
|
\end{itemize}
|
|
|
|
\begin{lstlisting}[language=json,firstnumber=1]{body.json}
|
|
|
|
{"module": "dns", "hostname": "www.circl.lu"}
|
|
|
|
\end{lstlisting}
|
|
|
|
\begin{itemize}
|
|
|
|
\item and the response of the dns module:
|
|
|
|
\end{itemize}
|
|
|
|
\begin{lstlisting}[language=json,firstnumber=1]
|
|
|
|
{"results": [{"values": ["149.13.33.14"],
|
|
|
|
"types": ["ip-src", "ip-dst"]}]}
|
2018-12-29 20:27:58 +01:00
|
|
|
\end{lstlisting}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
2020-02-19 11:31:28 +01:00
|
|
|
\frametitle{Creating your module - DNS module}
|
2018-12-29 20:27:58 +01:00
|
|
|
\begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
\begin{lstlisting}[language=python]
|
|
|
|
import json
|
|
|
|
import dns.resolver
|
|
|
|
misperrors = {'error' : 'Error'}
|
|
|
|
mispattributes = {'input': ['hostname', 'domain'], 'output': ['ip-src', 'ip-dst']}
|
|
|
|
moduleinfo = {'version': '0.1', 'author': 'Alexandre Dulaunoy',
|
|
|
|
'description': 'Simple DNS expansion service to resolve IP address from MISP attributes', 'module-type': ['expansion','hover']}
|
|
|
|
def handler(q=False):
|
|
|
|
if q is False:
|
|
|
|
return False
|
|
|
|
request = json.loads(q)
|
|
|
|
if request.get('hostname'):
|
|
|
|
toquery = request['hostname']
|
|
|
|
elif request.get('domain'):
|
|
|
|
toquery = request['domain']
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
r = dns.resolver.Resolver()
|
|
|
|
r.timeout = 2
|
|
|
|
r.lifetime = 2
|
|
|
|
r.nameservers = ['8.8.8.8']
|
|
|
|
try:
|
|
|
|
answer = r.query(toquery, 'A')
|
|
|
|
except dns.resolver.NXDOMAIN:
|
|
|
|
misperrors['error'] = "NXDOMAIN"
|
|
|
|
return misperrors
|
|
|
|
except dns.exception.Timeout:
|
|
|
|
misperrors['error'] = "Timeout"
|
|
|
|
return misperrors
|
|
|
|
except:
|
|
|
|
misperrors['error'] = "DNS resolving error"
|
|
|
|
return misperrors
|
|
|
|
r = {'results': [{'types': mispattributes['output'], 'values':[str(answer[0])]}]}
|
|
|
|
return r
|
|
|
|
|
|
|
|
def introspection():
|
|
|
|
return mispattributes
|
|
|
|
|
|
|
|
def version():
|
|
|
|
return moduleinfo
|
|
|
|
\end{lstlisting}
|
|
|
|
\end{adjustbox}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[t,fragile]
|
|
|
|
\frametitle{Testing your module}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Copy your module dns.py in modules/expansion/
|
|
|
|
\item Restart the server misp-modules.py
|
|
|
|
\end{itemize}
|
|
|
|
\begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
\begin{lstlisting}
|
|
|
|
[adulau:~/git/misp-modules/bin]$ python3 misp-modules.py
|
|
|
|
2016-03-20 19:25:43,748 - misp-modules - INFO - MISP modules passivetotal imported
|
|
|
|
2016-03-20 19:25:43,787 - misp-modules - INFO - MISP modules sourcecache imported
|
|
|
|
2016-03-20 19:25:43,789 - misp-modules - INFO - MISP modules cve imported
|
|
|
|
2016-03-20 19:25:43,790 - misp-modules - INFO - MISP modules dns imported
|
|
|
|
2016-03-20 19:25:43,797 - misp-modules - INFO - MISP modules server started on TCP port 6666
|
|
|
|
\end{lstlisting}
|
|
|
|
\end{adjustbox}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Check if your module is present in the introspection
|
|
|
|
\item curl -s http://127.0.0.1:6666/modules
|
|
|
|
\item If yes, test it directly with MISP or via curl
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Code samples (Configuration)}
|
|
|
|
\begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
\begin{lstlisting}[language=python]
|
|
|
|
# Configuration at the top
|
|
|
|
moduleconfig = ['username', 'password']
|
|
|
|
# Code block in the handler
|
|
|
|
if request.get('config'):
|
|
|
|
if (request['config'].get('username') is None) or (request['config'].get('password') is None):
|
|
|
|
misperrors['error'] = 'CIRCL Passive SSL authentication is missing'
|
|
|
|
return misperrors
|
|
|
|
-
|
|
|
|
x = pypssl.PyPSSL(basic_auth=(request['config']['username'], request['config']['password']))
|
|
|
|
|
|
|
|
\end{lstlisting}
|
|
|
|
\end{adjustbox}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Default expansion module set}
|
|
|
|
\begin{itemize}
|
|
|
|
\item asn history
|
|
|
|
\item CIRCL Passive DNS
|
|
|
|
\item CIRCL Passive SSL
|
|
|
|
\item Country code lookup
|
|
|
|
\item CVE information expansion
|
|
|
|
\item DNS resolver
|
|
|
|
\item DomainTools
|
|
|
|
\item eupi (checking url in phishing database)
|
|
|
|
\item IntelMQ (experimental)
|
|
|
|
\item ipasn
|
|
|
|
\item PassiveTotal - http://blog.passivetotal.org/misp-sharing-done-differently
|
|
|
|
\item sourcecache
|
|
|
|
\item Virustotal
|
|
|
|
\item Whois
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Import modules}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Similar to expansion modules
|
|
|
|
\item Input is a file upload or a text paste
|
|
|
|
\item Output is a list of parsed attributes to be editend and verified by the user
|
2019-06-17 17:27:44 +02:00
|
|
|
\item Some examples
|
2018-12-29 20:27:58 +01:00
|
|
|
\begin{itemize}
|
|
|
|
\item Cuckoo JSON import
|
|
|
|
\item email import
|
|
|
|
\item OCR module
|
2019-06-17 17:27:44 +02:00
|
|
|
\item Open IoC import
|
2018-12-29 20:27:58 +01:00
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
2020-02-19 11:31:28 +01:00
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Import module (Skeleton)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% import json
|
|
|
|
%
|
|
|
|
% misperrors = {'error' : 'Error'}
|
|
|
|
% userConfig = {
|
|
|
|
% 'number1': {
|
|
|
|
% 'type': 'Integer',
|
|
|
|
% 'regex': '/^[0-4]$/i',
|
|
|
|
% 'errorMessage': 'Expected a number in range [0-4]',
|
|
|
|
% 'message': 'Column number used for value'
|
|
|
|
% }
|
|
|
|
% };
|
|
|
|
% inputSource = ['file', 'paste']
|
|
|
|
% moduleinfo = {'version': '', 'author': '',
|
|
|
|
% 'description': '', 'module-type': ['import']}
|
|
|
|
% moduleconfig=[]
|
|
|
|
%
|
|
|
|
% def handler(q=False):
|
|
|
|
% if q is False:
|
|
|
|
% return False
|
|
|
|
% request = json.loads(q)
|
|
|
|
% request["data"] = base64.b64decode(request["data"])
|
|
|
|
% r = {'results': [{'categories': [], 'types': [], 'values':[]}]}
|
|
|
|
% return r
|
|
|
|
%
|
|
|
|
% def introspection():
|
|
|
|
% return {'userConfig': userConfig, 'inputSource': inputSource, 'moduleConfig': moduleConfig}
|
|
|
|
%
|
|
|
|
% def version():
|
|
|
|
% return moduleinfo
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your import module (userConfig and inputSource)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% userConfig = {
|
|
|
|
% 'number1': {
|
|
|
|
% 'type': 'Integer',
|
|
|
|
% 'regex': '/^[0-4]$/i',
|
|
|
|
% 'errorMessage': 'Expected a number in range [0-4]',
|
|
|
|
% 'message': 'Column number used for value'
|
|
|
|
% }
|
|
|
|
% };
|
|
|
|
% inputSource = ['file', 'paste']
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your import module (Handler)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% def handler(q=False):
|
|
|
|
% if q is False:
|
|
|
|
% return False
|
|
|
|
% request = json.loads(q)
|
|
|
|
% request["data"] = base64.b64decode(request["data"])
|
|
|
|
% r = {'results': [{'categories': [], 'types': [], 'values':[]}]}
|
|
|
|
% return r
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your import module (Introspection)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% def introspection():
|
|
|
|
% modulesetup = {}
|
|
|
|
% try:
|
|
|
|
% userConfig
|
|
|
|
% modulesetup['userConfig'] = userConfig
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% try:
|
|
|
|
% moduleConfig
|
|
|
|
% modulesetup['moduleConfig'] = moduleConfig
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% try:
|
|
|
|
% inputSource
|
|
|
|
% modulesetup['inputSource'] = inputSource
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% return modulesetup
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
2018-12-29 20:27:58 +01:00
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{Export modules}
|
|
|
|
\begin{itemize}
|
2020-02-19 11:31:28 +01:00
|
|
|
\item Not the preferred way to export data from MISP
|
|
|
|
\item Input is currently only a single event
|
|
|
|
\item Output is a file in the export format served back to the user
|
|
|
|
\item Will be moved / merged with MISP built-in export modules
|
|
|
|
\begin{itemize}
|
|
|
|
\item Allows export of event / attribute collections
|
|
|
|
\end{itemize}
|
2018-12-29 20:27:58 +01:00
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
2020-02-19 11:31:28 +01:00
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your Export module (Skeleton)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% import json
|
|
|
|
% inputSource = ['event']
|
|
|
|
% outputFileExtension = 'txt'
|
|
|
|
% responseType = 'application/txt'
|
|
|
|
% moduleinfo = {'version': '0.1', 'author': 'Andras Iklody',
|
|
|
|
% 'description': 'Skeleton export module',
|
|
|
|
% 'module-type': ['export']}
|
|
|
|
%
|
|
|
|
% def handler(q=False):
|
|
|
|
% if q is False:
|
|
|
|
% return False
|
|
|
|
% request = json.loads(q)
|
|
|
|
% # insert your magic here!
|
|
|
|
% output = my_magic(request["data"])
|
|
|
|
% r = {"data":base64.b64encode(output.encode('utf-8')).decode('utf-8')}
|
|
|
|
% return r
|
|
|
|
%
|
|
|
|
% def introspection():
|
|
|
|
% return {'userConfig': userConfig, 'inputSource': inputSource, 'moduleConfig': moduleConfig, 'outputFileExtension': outputFileExtension}
|
|
|
|
%
|
|
|
|
% def version():
|
|
|
|
% return moduleinfo
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your export module (settings)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% inputSource = ['event']
|
|
|
|
% outputFileExtension = 'txt'
|
|
|
|
% responseType = 'application/txt'
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your export module (handler)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% def handler(q=False):
|
|
|
|
% if q is False:
|
|
|
|
% return False
|
|
|
|
% request = json.loads(q)
|
|
|
|
% # insert your magic here!
|
|
|
|
% output = my_magic(request["data"])
|
|
|
|
% r = {"data":base64.b64encode(output.encode('utf-8')).decode('utf-8')}
|
|
|
|
% return r
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
|
|
|
%
|
|
|
|
% \begin{frame}[fragile]
|
|
|
|
% \frametitle{Creating your export module (introspection)}
|
|
|
|
% \begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
% \begin{lstlisting}[language=python]
|
|
|
|
% def introspection():
|
|
|
|
% modulesetup = {}
|
|
|
|
% try:
|
|
|
|
% responseType
|
|
|
|
% modulesetup['responseType'] = responseType
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% try:
|
|
|
|
% userConfig
|
|
|
|
% modulesetup['userConfig'] = userConfig
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% try:
|
|
|
|
% moduleConfig
|
|
|
|
% modulesetup['moduleConfig'] = moduleConfig
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% try:
|
|
|
|
% outputFileExtension
|
|
|
|
% modulesetup['outputFileExtension'] = outputFileExtension
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% try:
|
|
|
|
% inputSource
|
|
|
|
% modulesetup['inputSource'] = inputSource
|
|
|
|
% except NameError:
|
|
|
|
% pass
|
|
|
|
% return modulesetup
|
|
|
|
% \end{lstlisting}
|
|
|
|
% \end{adjustbox}
|
|
|
|
% \end{frame}
|
2018-12-29 20:27:58 +01:00
|
|
|
|
2019-06-17 17:27:44 +02:00
|
|
|
\begin{frame}[fragile]
|
|
|
|
\frametitle{New expansion \& import modules format}
|
|
|
|
\begin{itemize}
|
2019-06-18 08:14:31 +02:00
|
|
|
\item Backward compatible - an additional field to extend the format
|
2019-06-17 17:27:44 +02:00
|
|
|
\end{itemize}
|
|
|
|
\begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
\begin{lstlisting}[language=python]
|
|
|
|
misp_attributes = {'input': [...], 'output': [...],
|
|
|
|
'format': 'misp_standard'}
|
|
|
|
\end{lstlisting}
|
|
|
|
\end{adjustbox}
|
|
|
|
\begin{itemize}
|
|
|
|
\item Takes a standard MISP attribute as input
|
2020-02-19 11:31:28 +01:00
|
|
|
\item Returns MISP format
|
|
|
|
\begin{itemize}
|
|
|
|
\item Attributes
|
|
|
|
\item Objects (with their references)
|
|
|
|
\item Tags
|
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
\begin{adjustbox}{width=\textwidth,height=5cm,keepaspectratio}
|
|
|
|
\begin{lstlisting}[language=python]
|
|
|
|
results = {'Attribute': [...], 'Object': [...],
|
|
|
|
'Tag': [...]}
|
|
|
|
\end{lstlisting}
|
|
|
|
\end{adjustbox}
|
|
|
|
\begin{itemize}
|
2019-06-18 08:14:31 +02:00
|
|
|
\item First modules supporting this new export format
|
2019-06-17 17:27:44 +02:00
|
|
|
\begin{itemize}
|
|
|
|
\item urlhaus expansion module
|
2019-06-18 08:14:31 +02:00
|
|
|
\item Joe Sandbox import \& query module
|
2019-06-17 17:27:44 +02:00
|
|
|
\end{itemize}
|
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
2019-06-18 08:14:31 +02:00
|
|
|
\frametitle{New expansion \& import modules view (MISP 2.4.110}
|
2019-06-17 17:27:44 +02:00
|
|
|
\includegraphics[scale=0.2]{new_format_view.png}
|
|
|
|
\end{frame}
|
2018-12-29 20:27:58 +01:00
|
|
|
|
|
|
|
\begin{frame}[fragile]
|
2020-02-19 11:31:28 +01:00
|
|
|
\frametitle{Future of the modules system}
|
2018-12-29 20:27:58 +01:00
|
|
|
\begin{itemize}
|
2020-02-19 11:31:28 +01:00
|
|
|
\item Enrichment on full events
|
2018-12-29 20:27:58 +01:00
|
|
|
\item Move the modules to background processes with a messaging system
|
2020-02-19 11:31:28 +01:00
|
|
|
\item Have a way to skip the results preview
|
|
|
|
\begin{itemize}
|
|
|
|
\item Preview can be very heavy
|
|
|
|
\item Difficulty is dealing with uncertain results (without the user having final say)
|
|
|
|
\end{itemize}
|
2018-12-29 20:27:58 +01:00
|
|
|
\end{itemize}
|
|
|
|
\end{frame}
|
|
|
|
|
|
|
|
\begin{frame}[t,fragile] {Q\&A}
|
|
|
|
\includegraphics[scale=0.5]{misplogo.pdf}
|
|
|
|
\begin{itemize}
|
|
|
|
\item \url{https://github.com/MISP/misp-modules}
|
|
|
|
\item \url{https://github.com/MISP/}
|
|
|
|
\item We welcome new modules and pull requests.
|
|
|
|
\item MISP modules can be designed as standalone application.
|
|
|
|
\end{itemize}
|
|
|
|
|
|
|
|
\end{frame}
|