Skip to content

Instantly share code, notes, and snippets.

@blackfist
Last active July 21, 2018 04:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blackfist/b7a3e5bfbae571d8e024 to your computer and use it in GitHub Desktop.
Save blackfist/b7a3e5bfbae571d8e024 to your computer and use it in GitHub Desktop.
Creating VERIS incidents using python
{
"metadata": {
"name": "",
"signature": "sha256:be8501a2940fce195e5db05103c87f13e2dac07ac27e35cf5895ccad9045aace"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Manipulating VERIS Incidents in Python"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Last week FireEye released a blog post about a targeted campaign which they have dubbed **[Operation Poisoned Hurricane](http://www.fireeye.com/blog/technical/targeted-attack/2014/08/operation-poisoned-hurricane.html).** The article is an interesting read but like anyone else they have to protect the privacy of the victims (some of whom may be their clients). This presented an excellent opportunity to talk about some the features in VERIS that make it easier to model incomplete information and link multiple incidents together. This notebook will demonstrate constructing VERIS objects in python that make use of campaign_id, region codes, and the new secondary motive."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, some setup code. Here I am using a function that I use when I build an incident from scratch. It makes sure that I don't forget to put timestamps on the incident and that I don't forget to put my name on it. It also generates the incident_id and filename for me. These are just conveniences that I use in the **[VERIS Community Database](http://vcdb.org)** and are not required fields in all VERIS objects. I have also created a template incident that I'm going to use."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import json\n",
"import os\n",
"from datetime import datetime\n",
"from copy import deepcopy\n",
"import uuid\n",
"from glob import glob\n",
"\n",
"# putIncident(i, 'blackfist')\n",
"def putIncident(i, analyst=\"blackfist\"):\n",
" i['plus']['analyst'] = analyst\n",
" i['plus']['created'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')\n",
" identity = str(uuid.uuid4()).upper()\n",
" i['incident_id'] = identity\n",
" i['plus']['master_id'] = identity\n",
" outfile = open(identity + '.json','w')\n",
" outfile.write(json.dumps(i,sort_keys=True, indent=2,separators=(',', ': ')))\n",
" outfile.close()\n",
" \n",
"template = {'action':{}, \n",
" 'actor':{}, \n",
" 'asset':{}, \n",
" 'attribute':{}, \n",
" 'discovery_method':'Unknown',\n",
" 'plus':{'analysis_status':'First pass',\n",
" 'analyst':'blackfist',},\n",
" 'schema_version':'1.3.0',\n",
" 'security_incident':'Confirmed',\n",
" 'source_id':'vcdb',\n",
" 'timeline':{},\n",
" 'victim':{}}\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 31
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I'll probably use that code above in the future so I'm not going to make it super specific to this campaign. Instead I'm going to do that in a separate cell. That way I can just delete all the cells below that one next time I want to do something like this. In the cell below I'm modifying the template so that it models what we know about the campaign.\n",
"\n",
"One thing I've done is added **campaign_id** to the template. Every one of the incidents we create is going to have a common ID that we can use to find these incidents. For VERIS Community Database we use a GUID as our campaign ID.\n",
"\n",
"The FireEye artcle doesn't tell us much about the threat actor, but I think we can assume from the targets that espionage was the motive. I've seen some private discussions that have speculation about the threat actor, but VCDB has a strict rule about only including public knowledge. So we will model an unknown external attacker motivated by espionage."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# extra changes to the template for this specific campaign\n",
"template['campaign_id'] = \"104874B4-3EC7-4B09-95F1-930F007487B0\"\n",
"template['plus']['github'] = \"4130\"\n",
"template['reference'] = \"http://www.fireeye.com/blog/technical/targeted-attack/2014/08/operation-poisoned-hurricane.html\"\n",
"template['reference'] += \";http://blog.trendmicro.com/trendlabs-security-intelligence/unplugging-plugx-capabilities/\"\n",
"template['actor']['external'] = {'variety':['Unknown'], 'motive':['Espionage'], 'country':['Unknown']}\n",
"template['asset'] = {'assets':[{'variety':'Unknown'}]}\n",
"template['attribute'] = {'integrity':{'variety':['Software installation']}}\n",
"template['discovery_method'] = \"Ext - monitoring service\"\n",
"template['plus']['timeline'] = {'notification':{'day':6, 'month':8, 'year':2014}}\n",
"template['timeline']['incident'] = {'year':2014, }\n",
"template['notes'] = \"Operation Poisoned Hurricane\"\n",
"template['summary'] = \"Targeted malware campaign targeting Internet infrastructure providers, a media organization, a financial services company, and an Asian government organization.\""
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 32
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I could have put this next block of code up in the previous block but I didn't want it to get too cluttered and I was editing this more frequently as I put the notebook together."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Information about the malware\n",
"# Generic plugx information here: http://blog.trendmicro.com/trendlabs-security-intelligence/unplugging-plugx-capabilities/\n",
"template['action']['malware'] = {'name':'Kaba;PlugX;SOGU',\n",
" 'variety':['C2','Backdoor','Spyware/Keylogger','Scan network'],\n",
" 'vector':['Unknown']}"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 33
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"OK, I'm sure there is a better way to do this, so forgive me for coding the hard way. I've had this problem before when coding up multiple incidents and copying from a template. You can forget that python doesn't make real copies unless it has to or unless you tell it to. So if I copy that template to six incidents and start making changes, I'll actually affect all six of them. So I'll use **deepcopy** to make sure the incidents all stay unique.\n",
"\n",
"Then I fill in the victim demographic information that is known. For example, the article mentions one of the targets was an _Internet infrastrcture provider in Asia_, so I've created a victim with a NAICS code that could be just about any technology company, an unknown country, but a region that indicates Asia. For region codes, we use the **[United Nations Region Codes](http://unstats.un.org/unsd/methods/m49/m49regin.htm)** rather than reinventing our own numbering scheme."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Create each of the victim organizations and enter demographic info\n",
"he = deepcopy(template)\n",
"int1 = deepcopy(template)\n",
"int2 = deepcopy(template)\n",
"media = deepcopy(template)\n",
"finsvc = deepcopy(template)\n",
"asiagov = deepcopy(template)\n",
"\n",
"he['victim']['victim_id'] = \"Hurricane Electric llc\"\n",
"he['victim']['country'] = ['US']\n",
"he['victim']['region'] = ['019021']\n",
"he['victim']['employee_count'] = '11 to 100'\n",
"he['victim']['state'] = 'CA'\n",
"he['victim']['industry'] = '517911'\n",
"\n",
"# Internet infrastructure provider in the US\n",
"int1['victim']['industry'] = '517110'\n",
"int1['victim']['country'] = ['US']\n",
"int1['victim']['region'] = ['019021']\n",
"int1['victim']['employee_count'] = 'Unknown'\n",
"\n",
"# Internet infrastructure provider in Asia\n",
"int2['victim']['industry'] = '517110'\n",
"int2['victim']['region'] = ['142000']\n",
"int2['victim']['country'] = ['Unknown']\n",
"int2['victim']['employee_count'] = 'Unknown'\n",
"\n",
"# Media organization in US\n",
"media['victim']['country'] = ['US']\n",
"media['victim']['region'] = ['019021']\n",
"media['victim']['industry'] = '51'\n",
"media['victim']['employee_count'] = 'Unknown'\n",
"\n",
"# Financial services company in asia\n",
"finsvc['victim']['region'] = ['142000']\n",
"finsvc['victim']['country'] = ['Unknown']\n",
"finsvc['victim']['industry'] = '52'\n",
"finsvc['victim']['employee_count'] = 'Unknown'\n",
"\n",
"# Asian government\n",
"asiagov['victim']['region'] = ['142000']\n",
"asiagov['victim']['country'] = ['Unknown']\n",
"asiagov['victim']['industry'] = '92'\n",
"asiagov['victim']['employee_count'] = 'Unknown'"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 34
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All six of our victims are the same right now. Now we're going to make some changes to the Hurricane Electric incident to reflect the unique things about it. For example, there is no indication that there was malware at HE. There is only the abuse of functionality.\n",
"\n",
"The other thing I've done here is added an additional motive called **Secondary**. We use the secondary motive along with espionage to indicate that this victim was targeted by an espionage group and that the reason for their attack was espionage, but that they were not the primary target of the campaign."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Special consideration for HE\n",
"he['actor']['external']['motive'].append('Secondary')\n",
"he['action'] = {'hacking':{'variety':['Abuse of functionality'], 'vector':['Web application']}}\n",
"he['attribute'] = {'integrity':{'variety':['Modify configuration']}}"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 35
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# write the files\n",
"os.chdir('/tmp')\n",
"putIncident(he)\n",
"putIncident(int1)\n",
"putIncident(int2)\n",
"putIncident(media)\n",
"putIncident(finsvc)\n",
"putIncident(asiagov)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 36
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Is that all?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No it isn't! The FireEye article also included ip indicators, hashes, and domains. We could have included them in the VERIS record too if we had wanted to. That is not something we usually put in the VCDB however which is why I didn't do it here."
]
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Was that helpful?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Give me some feedback, tell me if I screwed up or anything. I'm **[@bifst](https://twitter.com/bfist)** on Twitter. And if this did help you, give me shout and follow me to find out what kind of cats I like."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment