diff --git a/docs/tutorial/PyMISP Objects.ipynb b/docs/tutorial/FullOverview.ipynb similarity index 59% rename from docs/tutorial/PyMISP Objects.ipynb rename to docs/tutorial/FullOverview.ipynb index 2d39774..aed5528 100644 --- a/docs/tutorial/PyMISP Objects.ipynb +++ b/docs/tutorial/FullOverview.ipynb @@ -53,30 +53,6 @@ "```" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting the API key (automatically generated on the trainig VM)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pathlib import Path\n", - "\n", - "api_file = Path('apikey')\n", - "if api_file.exists():\n", - " misp_url = 'http://127.0.0.1'\n", - " misp_verifycert = False\n", - " with open(api_file) as f:\n", - " misp_key = f.read().strip()\n", - " print(misp_key)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -272,6 +248,15 @@ "print(attribute_second.to_json())" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(event.to_json())" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -312,6 +297,57 @@ "print(event.published)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## MISPAttribute" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "attr_type = 'ip-dst'\n", + "value = '1.1.1.1'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPAttribute\n", + "\n", + "# Attribute data already defined\n", + "attribute = MISPAttribute()\n", + "attribute.type = attr_type\n", + "attribute.value = value\n", + "print(attribute)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# An attribute can also be loaded directly from a JSON\n", + "json = '''{\n", + " \"type\": \"ip-dst\",\n", + " \"value\": \"127.0.0.1\",\n", + " \"category\": \"Network activity\",\n", + " \"to_ids\": false\n", + " }'''\n", + "\n", + "attribute = MISPAttribute()\n", + "attribute.from_json(json)\n", + "print(attribute)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -354,7 +390,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## One-liner to add an object to a MISPEvent\n", + "## Short version to add an object to a MISPEvent\n", "\n", "You can also add the object directly in a misp event this way" ] @@ -374,6 +410,10 @@ "misp_object.add_attribute('ip', value='149.13.33.14')\n", "misp_object.add_attribute('first-seen', value='2018-04-11')\n", "misp_object.add_attribute('last-seen', value='2018-06-11')\n", + "\n", + "misp_object.add_attributes('ip', {'value': '10.8.8.8', 'to_ids': False}, '10.9.8.8')\n", + "\n", + "\n", "misp_object.add_reference(obj_attr.uuid, 'related-to', 'Expanded with passive DNS entry')\n", "\n", "print(event.to_json())\n" @@ -383,7 +423,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Helpers for MISPObjects \n", + "# Helpers for MISPObjects \n", "\n", "For some objects, we have helpers in order to make your life easier. The most relevant example is the file object: when you have a file to push on MISP, there are plenty of indicators you can extract at once, and it is pretty simple to automate, so we made it a oneliner.\n", "\n", @@ -424,7 +464,74 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Generic helper\n", + "### Excel support \n", + "\n", + "(okay, CSV, but that's the same thing, right?)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bash \n", + "\n", + "cat ../../tests/csv_testfiles/valid_fieldnames.csv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bash \n", + "\n", + "cat ../../tests/csv_testfiles/invalid_fieldnames.csv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp.tools import CSVLoader\n", + "from pymisp import MISPEvent\n", + "from pathlib import Path\n", + "\n", + "csv1 = CSVLoader(template_name='file', csv_path=Path('../../tests/csv_testfiles/valid_fieldnames.csv'))\n", + "event = MISPEvent()\n", + "event.info = 'Test event from CSV loader'\n", + "for o in csv1.load():\n", + " event.add_object(**o)\n", + "\n", + "print(event.to_json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "event = MISPEvent()\n", + "event.info = 'Test event from CSV loader'\n", + "csv2 = CSVLoader(template_name='file', csv_path=Path('../../tests/csv_testfiles/invalid_fieldnames.csv'),\n", + " fieldnames=['SHA1', 'fileName', 'size-in-bytes'], has_fieldnames=True)\n", + "\n", + "for o in csv2.load():\n", + " event.add_object(**o)\n", + " \n", + "print(event.to_json())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generic helper\n", "\n", "This helper is meant to be used when you alreadu have a script that does the mapping between your own code, and the MISPObject template." ] @@ -449,6 +556,13 @@ "print(misp_object.to_json())" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## User defined objects" + ] + }, { "cell_type": "code", "execution_count": null, @@ -647,98 +761,6 @@ "print(existing_event.attributes[0].to_json())" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Full example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pymisp import MISPEvent, MISPObject\n", - "from pymisp import PyMISP\n", - "\n", - "event = MISPEvent()\n", - "event.info = 'This is my new MISP event' # Required\n", - "event.distribution = 0 # Optional, defaults to MISP.default_event_distribution in MISP config\n", - "event.threat_level_id = 2 # Optional, defaults to MISP.default_event_threat_level in MISP config\n", - "event.analysis = 1 # Optional, defaults to 0 (initial analysis)\n", - "\n", - "mispObject = MISPObject('file')\n", - "mispObject.add_attribute('filename', type='filename',\n", - " value='filename.exe',\n", - " Tag=[{'name': 'tlp:amber'}])\n", - "\n", - "event.add_object(mispObject)\n", - "\n", - "# The URL of the MISP instance to connect to\n", - "misp_url = 'http://127.0.0.1:8080'\n", - "# Can be found in the MISP web interface under \n", - "# http://+MISP_URL+/users/view/me -> Authkey\n", - "misp_key = 'xe5okWNY2OB3O9ljR6t2cJPNsv4u1VZB0C1mKwtB'\n", - "# Should PyMISP verify the MISP certificate\n", - "misp_verifycert = False\n", - "\n", - "misp = PyMISP(misp_url, misp_key, misp_verifycert)\n", - "res = misp.add_event(event)\n", - "existing_event = MISPEvent()\n", - "existing_event.load(res)\n", - "mispObject = MISPObject('file')\n", - "mispObject.add_attribute('filename', type='filename',\n", - " value='filename2.exe',\n", - " Tag=[{'name': 'tlp:white'}])\n", - "\n", - "existing_event.add_object(mispObject)\n", - "print(existing_event.to_json())\n", - "\n", - "res = misp.update(existing_event)\n", - "existing_event = MISPEvent()\n", - "existing_event.load(res)\n", - "print(existing_event.to_json())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from pymisp import MISPEvent, MISPObject\n", - "from pymisp import PyMISP\n", - "\n", - "event = MISPEvent()\n", - "\n", - "event.info = 'This is my new MISP event' # Required\n", - "event.distribution = 0 # Optional, defaults to MISP.default_event_distribution in MISP config\n", - "event.threat_level_id = 2 # Optional, defaults to MISP.default_event_threat_level in MISP config\n", - "event.analysis = 1 # Optional, defaults to 0 (initial analysis)\n", - "\n", - "mispObject = MISPObject('file')\n", - "mispObject.add_attribute('filename', type='filename',\n", - " value='filename.exe',\n", - " Tag=[{'name':'tlp:amber'}]) \n", - "event.add_object(mispObject)\n", - "\n", - "# The URL of the MISP instance to connect to\n", - "misp_url = 'http://127.0.0.1:8080'\n", - "# Can be found in the MISP web interface under \n", - "# http://+MISP_URL+/users/view/me -> Authkey\n", - "misp_key = 'yB8DMS8LkfYYpcVX8bN2v7xwDZDMp4bpW0sNqNGj'\n", - "# Should PyMISP verify the MISP certificate\n", - "misp_verifycert = False\n", - "\n", - "misp = PyMISP(misp_url, misp_key, misp_verifycert)\n", - "res = misp.add_event(event)\n", - "existing_event = MISPEvent()\n", - "existing_event.load(res)\n", - "print(existing_event.to_json())" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -769,6 +791,668 @@ "\n", "print(event.to_json())\n" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "***" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting the API key (automatically generated on the trainig VM)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "\n", + "api_file = Path('apikey')\n", + "if api_file.exists():\n", + " misp_url = 'http://127.0.0.1'\n", + " misp_verifycert = False\n", + " with open(api_file) as f:\n", + " misp_key = f.read().strip()\n", + " print(misp_key)\n", + "else:\n", + " print(\"Unable to find the api key\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize variables if you run the notebook locally" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The URL of the MISP instance to connect to\n", + "misp_url = 'http://127.0.0.1:8080/'\n", + "# Can be found in the MISP web interface under \n", + "# http://+MISP_URL+/users/view/me -> Authkey\n", + "misp_key = 'HRizIMmaxBOXAQSzKZ874rDWUsQEk4vGAGBoljQO'\n", + "# Should PyMISP verify the MISP certificate\n", + "misp_verifycert = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import ExpandedPyMISP, PyMISP\n", + "\n", + "misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)\n", + "misp_old = PyMISP(misp_url, misp_key, misp_verifycert)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Full example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## New API\n", + "\n", + "Returns MISPEvent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPEvent, MISPObject\n", + "\n", + "event = MISPEvent()\n", + "event.info = 'This is my new MISP event' # Required\n", + "event.distribution = 0 # Optional, defaults to MISP.default_event_distribution in MISP config\n", + "event.threat_level_id = 2 # Optional, defaults to MISP.default_event_threat_level in MISP config\n", + "event.analysis = 1 # Optional, defaults to 0 (initial analysis)\n", + "\n", + "mispObject = MISPObject('file')\n", + "mispObject.add_attribute('filename', type='filename',\n", + " value='filename.exe',\n", + " Tag=[{'name': 'tlp:amber'}])\n", + "\n", + "event.add_object(mispObject)\n", + "\n", + "print(misp)\n", + "existing_event = misp.add_event(event)\n", + "print(existing_event)\n", + "mispObject = MISPObject('file')\n", + "mispObject.add_attribute('filename', type='filename',\n", + " value='filename2.exe',\n", + " Tag=[{'name': 'tlp:white'}])\n", + "\n", + "existing_event.add_object(mispObject)\n", + "print(existing_event.to_json())\n", + "\n", + "res = misp.update(existing_event)\n", + "existing_event = MISPEvent()\n", + "existing_event.load(res)\n", + "print(existing_event.to_json())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Old API\n", + "\n", + "Returns plain JSON" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPEvent, MISPObject\n", + "\n", + "event = MISPEvent()\n", + "event.info = 'This is my new MISP event' # Required\n", + "event.distribution = 0 # Optional, defaults to MISP.default_event_distribution in MISP config\n", + "event.threat_level_id = 2 # Optional, defaults to MISP.default_event_threat_level in MISP config\n", + "event.analysis = 1 # Optional, defaults to 0 (initial analysis)\n", + "\n", + "mispObject = MISPObject('file')\n", + "mispObject.add_attribute('filename', type='filename',\n", + " value='filename.exe',\n", + " Tag=[{'name': 'tlp:amber'}])\n", + "\n", + "event.add_object(mispObject)\n", + "\n", + "print(misp)\n", + "res = misp.add_event(event)\n", + "print(res)\n", + "existing_event = MISPEvent()\n", + "existing_event.load(res)\n", + "mispObject = MISPObject('file')\n", + "mispObject.add_attribute('filename', type='filename',\n", + " value='filename2.exe',\n", + " Tag=[{'name': 'tlp:white'}])\n", + "\n", + "existing_event.add_object(mispObject)\n", + "print(existing_event.to_json())\n", + "\n", + "res = misp.update(existing_event)\n", + "existing_event = MISPEvent()\n", + "existing_event.load(res)\n", + "print(existing_event.to_json())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Interacting with a MISP instance" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating An Event" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Directly" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "event = misp.new_event(distribution=1,\n", + " threat_level_id=1,\n", + " analysis=1,\n", + " info=\"Event from notebook\")\n", + "print(\"Event id: %s\" % event.id)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "event = misp_old.new_event(distribution=1,\n", + " threat_level_id=1,\n", + " analysis=1,\n", + " info=\"Event from notebook\")\n", + "print(\"Event id: %s\" % event['Event']['id'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the MISPEvent constructor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPEvent\n", + "\n", + "event_obj = MISPEvent()\n", + "event_obj.distribution = 1\n", + "event_obj.threat_level_id = 1\n", + "event_obj.analysis = 1\n", + "event_obj.info = \"Event from notebook 2\"\n", + "event = misp.add_event(event_obj)\n", + "event_id = event.id\n", + "print(\"Event id: %s\" % event_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Fetching an event" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "event_id = 2752" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Fetch by ID\n", + "event = misp.get_event(event_id)\n", + "print(event)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Fetch by ID\n", + "event = misp_old.get_event(event_id)\n", + "print(event)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add an attribute to an event" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Directly" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "attr_type = \"ip-src\"\n", + "value = \"8.8.8.8\"\n", + "category = \"Network activity\"\n", + "to_ids = False" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Oldish API" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "proposal = False\n", + "updated_event = misp.add_named_attribute(event_id,\n", + " attr_type,\n", + " value,\n", + " category=category,\n", + " to_ids=to_ids,\n", + " proposal=proposal)\n", + "print(updated_event)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Cleaner way" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "value = \"9.8.8.8\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPAttribute\n", + "\n", + "# Attribute data already defined\n", + "attribute = MISPAttribute()\n", + "attribute.type = attr_type\n", + "attribute.value = value\n", + "attribute.category = category\n", + "attribute.to_ids = to_ids\n", + "\n", + "attribute_to_change = misp.add_attribute(event_id, attribute)\n", + "print(attribute_to_change.id, attribute_to_change)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Propose new Attribute" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPAttribute\n", + "\n", + "attr_type = \"ip-src\"\n", + "value = \"10.8.8.8\"\n", + "category = \"Network activity\"\n", + "to_ids = False\n", + "\n", + "# Attribute data already defined\n", + "attribute = MISPAttribute()\n", + "attribute.type = attr_type\n", + "attribute.value = value\n", + "attribute.category = category\n", + "attribute.to_ids = to_ids\n", + "\n", + "proposal = misp.add_attribute_proposal(event_id, attribute)\n", + "print(proposal.id, proposal)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Other things on proposals" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proposal = misp.get_attribute_proposal(21)\n", + "print(proposal.to_json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proposal = misp.accept_attribute_proposal(25)\n", + "print(proposal)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "proposal = misp.discard_attribute_proposal(27)\n", + "print(proposal)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Propose change to attribute" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPShadowAttribute\n", + "\n", + "proposal = MISPShadowAttribute()\n", + "proposal.type = 'ip-dst'\n", + "proposal.category = 'External analysis'\n", + "proposal.to_ids = False\n", + "\n", + "attribute = misp.update_attribute_proposal(attribute_to_change.id, proposal)\n", + "print(attribute.to_json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "attribute = misp.update_attribute_proposal(attribute_to_change.id, {'to_ids': False, 'comment': \"This is crap\"})\n", + "print(attribute.to_json())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Update existing event" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pymisp import MISPAttribute, MISPObject\n", + "\n", + "attr_type = \"ip-src\"\n", + "value = \"20.8.8.8\"\n", + "category = \"Network activity\"\n", + "to_ids = False\n", + "\n", + "# Attribute data already defined\n", + "attribute = MISPAttribute()\n", + "attribute.type = attr_type\n", + "attribute.value = value\n", + "attribute.category = category\n", + "attribute.to_ids = to_ids\n", + "\n", + "# New Python 3.6 API\n", + "event = misp.get(event_id)\n", + "\n", + "## Add the attribute to the event\n", + "event.add_attribute(**attribute)\n", + "event.add_attribute(type='domain', value='circl.lu', disable_correlation=True)\n", + "\n", + "mispObject = MISPObject('file')\n", + "mispObject.add_attribute('filename', type='filename',\n", + " value='filename2.exe',\n", + " Tag=[{'name': 'tlp:white'}])\n", + "\n", + "event.add_object(mispObject)\n", + "\n", + "## Push the updated event to MISP\n", + "event_dict = misp.update_event(event)\n", + "print(event_dict)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sightings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.sighting(value=event.attributes[1].value)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.sighting_list(event.attributes[1].id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Direct call, no validation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.direct_call('attributes/add/58', {'type': 'ip-dst', 'value': '8.11.8.8'})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.direct_call('events')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Admin Stuff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.get_sharing_groups()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## User" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.get_users_list()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.add_user('bar@foo.de', 1, 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Organisations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.get_organisations_list()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Roles" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.get_roles_list()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feeds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.get_feeds_list()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "misp.cache_feeds_all()" + ] } ], "metadata": { diff --git a/docs/tutorial/Search-NG.ipynb b/docs/tutorial/Search-FullOverview.ipynb similarity index 66% rename from docs/tutorial/Search-NG.ipynb rename to docs/tutorial/Search-FullOverview.ipynb index 0e02a01..1a883a2 100644 --- a/docs/tutorial/Search-NG.ipynb +++ b/docs/tutorial/Search-FullOverview.ipynb @@ -10,7 +10,7 @@ "misp_url = 'http://127.0.0.1:8080'\n", "# Can be found in the MISP web interface under ||\n", "# http://+MISP_URL+/users/view/me -> Authkey\n", - "misp_key = 'LBelWqKY9SQyG0huZzAMqiEBl6FODxpgRRXMsZFu'\n", + "misp_key = 'HRizIMmaxBOXAQSzKZ874rDWUsQEk4vGAGBoljQO'\n", "# Should PyMISP verify the MISP certificate\n", "misp_verifycert = False" ] @@ -70,7 +70,7 @@ "source": [ "## Search unpublished events\n", "\n", - "**WARNING**: By default, the search query will only return all the events listed on teh index page" + "**WARNING**: By default, the search query will only return all the events listed on the index page" ] }, { @@ -123,7 +123,7 @@ "metadata": {}, "outputs": [], "source": [ - "r = misp.search_index(tag='TODO:VT-ENRICHMENT', published=False)" + "print('No attributes are in the event', r[0].attributes)" ] }, { @@ -132,7 +132,16 @@ "metadata": {}, "outputs": [], "source": [ - "r = misp.search_index(tag=['!TODO:VT-ENRICHMENT', 'tlp:white'], published=False) # ! means \"not this tag\"" + "r = misp.search_index(tags='TODO:VT-ENRICHMENT', published=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = misp.search_index(tags=['!TODO:VT-ENRICHMENT', 'tlp:white'], published=False) # ! means \"not this tag\"" ] }, { @@ -227,6 +236,28 @@ "complex_query = misp.build_complex_query(or_parameters=['uibo.lembit@mail.ee', '103.195.185.222'])" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(complex_query)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "complex_query = misp.build_complex_query(or_parameters=['59.157.4.2', 'hotfixmsupload.com', '8.8.8.8'])\n", + "events = misp.search(value=complex_query, pythonify=True)\n", + "\n", + "for e in events:\n", + " print(e)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -318,6 +349,15 @@ "r = misp.search(value='8.8.8.8', withAttachments=True) # Return attachments" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(r)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -331,7 +371,7 @@ "metadata": {}, "outputs": [], "source": [ - "r = misp.search(controller='attributes', value='8.8.8.9')" + "r = misp.search(controller='attributes', value='8.8.8.8')" ] }, { @@ -349,14 +389,7 @@ "metadata": {}, "outputs": [], "source": [ - "r" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Because reason" + "print(r)" ] }, { @@ -365,22 +398,146 @@ "metadata": {}, "outputs": [], "source": [ - "tag_to_remove = 'foo'\n", + "# Search attributes (specified in controller) where the attribute type is 'ip-src'\n", + "# And the to_ids flag is set\n", + "attributes = misp.search(controller='attributes', type_attribute='ip-src', to_ids=0, pythonify=True)\n", "\n", - "events = misp.search(tags=tag_to_remove, pythonify=True)\n", + "event_ids = set()\n", + "for attr in attributes:\n", + " event_ids.add(event_id)\n", "\n", - "for event in events:\n", - " for tag in event.tags:\n", - " if tag.name == tag_to_remove:\n", - " print(f'Got {tag_to_remove} in {event.info}')\n", - " misp.untag(event.uuid, tag_to_remove)\n", - " break\n", - " for attribute in event.attributes:\n", - " for tag in attribute.tags:\n", - " if tag.name == tag_to_remove:\n", - " print(f'Got {tag_to_remove} in {attribute.value}')\n", - " misp.untag(attribute.uuid, tag_to_remove)\n", - " break" + "# Fetch all related events\n", + "for event_id in event_ids:\n", + " event = misp.get_event(event_id)\n", + " print(event.info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Last *published* attributes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "attributes = misp.search(controller='attributes', publish_timestamp='1d', pythonify=True)\n", + "\n", + "for attribute in attributes:\n", + " print(attribute.event_id, attribute)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "attributes = misp.search(controller='attributes', publish_timestamp=['2d', '1h'], pythonify=True)\n", + "\n", + "for a in attributes:\n", + " print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Last *updated* attributes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "from datetime import datetime\n", + "\n", + "ts = int(datetime.now().timestamp())\n", + "\n", + "attributes = misp.search(controller='attributes', timestamp=ts - 36000, pythonify=True)\n", + "\n", + "for a in attributes:\n", + " print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Orther output formats\n", + "\n", + "**Warning**: For that to work, the matching event has to be published" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = misp.search(controller='attributes', value='8.8.8.8', return_format='csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = misp.search(controller='events', value='9.8.8.8', return_format='snort')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = misp.search(controller='events', value='9.8.8.8', return_format='suricata')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = misp.search(controller='events', value='9.8.8.8', return_format='stix')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = misp.search(controller='events', value='9.8.8.8', return_format='stix2')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(r)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Search in logs" ] }, { @@ -404,23 +561,6 @@ "for l in logs:\n", " print(l.title)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "log = misp.search_logs(model='Tag', title=tag_to_remove)[0]\n", - "roles = misp.get_roles_list()\n", - "for r in roles:\n", - " if r['Role']['name'] == 'User':\n", - " new_role = r['Role']['id']\n", - " break\n", - "user = misp.get_user(log['Log']['user_id'])\n", - "user['User']['role_id'] = new_role\n", - "misp.edit_user(user['User']['id'], **user['User'])" - ] } ], "metadata": {