Create an import script for MISP , step-by-step tutorial

By Pauline Bourmeau September 30, 2020

Create an import script for MISP in Python, step-by-step tutorial

Script description

Example add_github_user.py

Here the goal is to push to MISP information gathered on Github. The script add_github_user.py will be used as an example.

An import script, it’s different from a MISP module.

An import script is run from a terminal to push data into a MISP, but a MISP module runs into a MISP instance. For more information about MISP modules, see here

This script will add data from GitHub as object to an existing MISP event.

Tips: in early phase or for testing purpose, it’s better to start with an import script to test the code and results. If it’s conclusive you can code a MISP module.

PyMISP install

PyMISP is a Python library to access MISP with REST API. Install the PyMISP library on your machine.

To do so, clone the repository and install the library:

git clone https://github.com/MISP/PyMISP
cd PyMISP
pip3 install .

Fork

If you wish to contribute and push your code to the MISP community, you’ll need to fork the PyMISP library.

Meaningful naming

Where to put the files and what are their names?

The script will be in PyMISP/examples and has the name of the imported service. A short key word is a good practice to describe the script action:

PyMISP/examples/add_github_user.py

tips: before naming your script, consult the list of available scripts into the PyMISP/examples folder, in order to describe accurately what your import module does.

Keys management

For all scripts , you need to have a single key file keys.py. The file is not to be committed and contains the credentials for connecting to the MISP instance: API key, URL, SSH validations.

  • You create a file keys.py into the dir PyMISP/examples.

References to this file will be later set in the script:

from keys import misp_url, misp_key, misp_verifycert

Required libraries

  • PyMISP
  • request
  • sys
  • argparse

Usage block

We will go through the Python code and explain step-by-step each part.

It will be used by pyDoc, starts with """ and ends with “”". You will here describe the usage for the script.

"""
usage: add_github_user.py [-h] -e EVENT [-f] -u USERNAME
Fetch GitHub user details and add it in object in MISP
optional arguments:
-h, --help            show this help message and exit
-e EVENT, --event EVENT
		      Event ID to update
-f, --force-template-update
-u USERNAME, --username USERNAME
		      GitHub username to add
"""

Argument parser

The script needs to grab the event-id (-e), a force to update the template from the repository (-f), and here a user account (-u).

parser = argparse.ArgumentParser(description='Fetch GitHub user details and add it in object in MISP')
parser.add_argument("-e", "--event", required=True, help="Event ID to update")
parser.add_argument("-f", "--force-template-update", required=False, action="store_true")
parser.add_argument("-u", "--username", required=True, help="GitHub username to add")
args = parser.parse_args()

Request

NOTE: If the user doesn’t exist, the script is interrupted.

r = requests.get("https://api.github.com/users/{}".format(args.username))
if r.status_code != 200:
		sys.exit("HTTP return is {} and not 200 as expected".format(r.status_code))
if args.force_template_update:
		print("Updating MISP Object templates...")
		update_objects()
pymisp = PyMISP(misp_url, misp_key, misp_verifycert)

The PyMISP connection is instantiated with following parameters coming from the file keys.py : misp_url, misp_keys and misp_verifycert.

Object creation

We create a MISP object, the name is the object template name:

misp_object = MISPObject(name="github-user")

tips: you can find the object template name is the MISP object template repository.

contributing: if an object template is missing, you can propose your own.

User data

User data from the GitHub API are transformed into a JSON in order to be parsed by the following commands:

github_user = r.json()

Following HTTP GET requests to obtain the following and followers sections of the GitHub user.

rfollowers = requests.get(github_user['followers_url'])
followers = rfollowers.json()
rfollowing = requests.get("https://api.github.com/users/{}/following".format(args.username))
followings = rfollowing.json()

Same things for the SSH public keys attached to the GitHub user:

rkeys = requests.get("https://api.github.com/users/{}/keys".format(args.username))
keys = rkeys.json()

Then, filling of the object from the github_user json object:

misp_object.add_attributes("follower", *[follower['login'] for follower in followers])
misp_object.add_attributes("following", *[following['login'] for following in followings])
misp_object.add_attributes("ssh-public-key", *[sshkey['key'] for sshkey in keys])
misp_object.add_attribute('bio', github_user['bio'])
misp_object.add_attribute('link', github_user['html_url'])
misp_object.add_attribute('user-fullname', github_user['name'])
misp_object.add_attribute('username', github_user['login'])
misp_object.add_attribute('twitter_username', github_user['twitter_username'])
misp_object.add_attribute('location', github_user['location'])
misp_object.add_attribute('company', github_user['company'])
misp_object.add_attribute('public_gists', github_user['public_gists'])
misp_object.add_attribute('public_repos', github_user['public_repos'])
misp_object.add_attribute('blog', github_user['blog'])
misp_object.add_attribute('node_id', github_user['node_id'])

Finally, you add the new object created, then pushed to the specified event id, on your MISP instance:

retcode = pymisp.add_object(args.event, misp_object)

Now it’s your turn, to do a MISP import script.