Merge branch '2.4' of github.com:MISP/MISP into 2.4

pull/3725/head
iglocska 2018-09-28 09:24:40 +02:00
commit 46cb19df2d
19 changed files with 631 additions and 336 deletions

View File

@ -4,7 +4,7 @@ INSTALLATION INSTRUCTIONS
1/ Minimal Ubuntu install
-------------------------
# Install a minimal Ubuntu 16.04-server system with the software:
# Install a minimal Ubuntu 18.04-server system with the software:
- OpenSSH server
# Make sure your system is up2date:
@ -68,10 +68,13 @@ sudo apt-get install python3-dev python3-pip libxml2-dev libxslt1-dev zlib1g-dev
cd /var/www/MISP/app/files/scripts
sudo -u www-data git clone https://github.com/CybOXProject/python-cybox.git
sudo -u www-data git clone https://github.com/STIXProject/python-stix.git
sudo -u www-data git clone https://github.com/MAECProject/python-maec.git
cd /var/www/MISP/app/files/scripts/python-cybox
sudo python3 setup.py install
cd /var/www/MISP/app/files/scripts/python-stix
sudo python3 setup.py install
cd /var/www/MISP/app/files/scripts/python-maec
sudo python3 setup.py install
# install mixbox to accomodate the new STIX dependencies:
cd /var/www/MISP/app/files/scripts/

2
PyMISP

@ -1 +1 @@
Subproject commit 50a5a86ca69e5510a71955d319c026cca242297e
Subproject commit ba02c6c7663b65109b9878539e6efe66b2ffa5c6

View File

@ -516,4 +516,23 @@ class EventShell extends AppShell
);
$result = $this->Event->enrichment($options);
}
public function processfreetext() {
$inputFile = $this->args[0];
$tempdir = new Folder(APP . 'tmp/cache/ingest', true, 0750);
$tempFile = new File(APP . 'tmp/cache/ingest' . DS . $inputFile);
$inputData = $tempFile->read();
$inputData = json_decode($inputData, true);
$tempFile->delete();
$this->Event->processFreeTextData(
$inputData['user'],
$inputData['attributes'],
$inputData['id'],
$inputData['default_comment'],
$inputData['force'],
$inputData['adhereToWarninglists'],
$inputData['jobId']
);
return true;
}
}

View File

@ -210,9 +210,8 @@ class RestResponseComponent extends Component
),
'Warninglist' => array(
'toggleEnable' => array(
'description' => "POST a json object with a single or a list of warninglist IDs to toggle whether they're enabled or disabled. Specify the optional enabled boolean flag if you would like to enforce the outcome state. Not setting this flag will just toggle the current state.",
'mandatory' => array('id'),
'optional' => array('enabled')
'description' => "POST a json object with a single or a list of warninglist IDsIDs, or alternatively a (list of) substring(s) that match the names of warninglist(s) to toggle whether they're enabled or disabled. Specify the optional enabled boolean flag if you would like to enforce the outcome state. Not setting this flag will just toggle the current state.",'mandatory' => array('id'),
'optional' => array('id', 'name', 'enabled')
)
)
);

View File

@ -1058,10 +1058,12 @@ class EventsController extends AppController
$this->loadModel('GalaxyCluster');
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.tag_name', 'GalaxyCluster.id')));
foreach ($event['Object'] as $k => $object) {
foreach ($object['Attribute'] as $k2 => $attribute) {
foreach ($attribute['AttributeTag'] as $k3 => $attributeTag) {
if (in_array($attributeTag['Tag']['name'], $cluster_names)) {
unset($event['Object'][$k]['Attribute'][$k2]['AttributeTag'][$k3]);
if (isset($object['Attribute'])) {
foreach ($object['Attribute'] as $k2 => $attribute) {
foreach ($attribute['AttributeTag'] as $k3 => $attributeTag) {
if (in_array($attributeTag['Tag']['name'], $cluster_names)) {
unset($event['Object'][$k]['Attribute'][$k2]['AttributeTag'][$k3]);
}
}
}
}
@ -3641,142 +3643,12 @@ class EventsController extends AppController
$attributes[$k] = $attribute;
}
// actually save the attribute now
$this->__processFreeTextData($attributes, $id, '', false, $adhereToWarninglists);
$this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, '', false, $adhereToWarninglists);
// FIXME $attributes does not contain the onteflyattributes
$attributes = array_values($attributes);
return $this->RestResponse->viewData($attributes, $this->response->type());
}
private function __processFreeTextData($attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false)
{
$event = $this->Event->find('first', array(
'conditions' => array('id' => $id),
'recursive' => -1,
'fields' => array('orgc_id', 'id', 'distribution', 'published', 'uuid'),
));
if (!$this->_isSiteAdmin() && !empty($event) && $event['Event']['orgc_id'] != $this->Auth->user('org_id')) {
$objectType = 'ShadowAttribute';
} elseif ($this->_isSiteAdmin() && isset($force) && $force) {
$objectType = 'ShadowAttribute';
} else {
$objectType = 'Attribute';
}
if ($adhereToWarninglists) {
$this->Warninglist = ClassRegistry::init('Warninglist');
$warninglists = $this->Warninglist->fetchForEventView();
}
$saved = 0;
$failed = 0;
$attributeSources = array('attributes', 'ontheflyattributes');
$ontheflyattributes = array();
foreach ($attributeSources as $source) {
foreach (${$source} as $k => $attribute) {
if ($attribute['type'] == 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
} elseif ($attribute['type'] == 'ip-src|port/ip-dst|port') {
$types = array('ip-src|port', 'ip-dst|port');
} elseif ($attribute['type'] == 'malware-sample') {
if (!isset($attribute['data_is_handled']) || !$attribute['data_is_handled']) {
$result = $this->Event->Attribute->handleMaliciousBase64($id, $attribute['value'], $attribute['data'], array('md5', 'sha1', 'sha256'), $objectType == 'ShadowAttribute' ? true : false);
if (!$result['success']) {
$failed++;
continue;
}
$attribute['data'] = $result['data'];
$shortValue = $attribute['value'];
$attribute['value'] = $shortValue . '|' . $result['md5'];
$additionalHashes = array('sha1', 'sha256');
foreach ($additionalHashes as $hash) {
$temp = $attribute;
$temp['type'] = 'filename|' . $hash;
$temp['value'] = $shortValue . '|' . $result[$hash];
unset($temp['data']);
$ontheflyattributes[] = $temp;
}
}
$types = array($attribute['type']);
} else {
$types = array($attribute['type']);
}
foreach ($types as $type) {
$this->Event->$objectType->create();
$attribute['type'] = $type;
if (empty($attribute['comment'])) {
$attribute['comment'] = $default_comment;
}
$attribute['event_id'] = $id;
if ($objectType == 'ShadowAttribute') {
$attribute['org_id'] = $this->Auth->user('org_id');
$attribute['event_org_id'] = $event['Event']['orgc_id'];
$attribute['email'] = $this->Auth->user('email');
$attribute['event_uuid'] = $event['Event']['uuid'];
}
// adhere to the warninglist
if ($adhereToWarninglists) {
if (!$this->Warninglist->filterWarninglistAttributes($warninglists, $attribute)) {
if ($adhereToWarninglists == 'soft') {
$attribute['to_ids'] = 0;
} else {
// just ignore the attribute
continue;
}
}
}
$AttributSave = $this->Event->$objectType->save($attribute);
if ($AttributSave) {
// If Tags, attache each tags to attribut
if (!empty($attribute['tags'])) {
foreach (explode(",", $attribute['tags']) as $tagName) {
$this->loadModel('Tag');
$TagId = $this->Tag->captureTag(array('name' => $tagName), array('Role' => $this->userRole));
$this->loadModel('AttributeTag');
if (!$this->AttributeTag->attachTagToAttribute($AttributSave['Attribute']['id'], $id, $TagId)) {
throw new MethodNotAllowedException(__('Could not add tags.'));
}
}
}
$saved++;
} else {
$lastError = $this->Event->$objectType->validationErrors;
$failed++;
}
}
}
}
$emailResult = '';
$messageScope = $objectType == 'ShadowAttribute' ? 'proposals' : 'attributes';
if ($saved > 0) {
if ($objectType != 'ShadowAttribute') {
$event = $this->Event->find('first', array(
'conditions' => array('Event.id' => $id),
'recursive' => -1
));
if ($event['Event']['published'] == 1) {
$event['Event']['published'] = 0;
}
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
} else {
if (!$this->Event->ShadowAttribute->sendProposalAlertEmail($id)) {
$emailResult = " but sending out the alert e-mails has failed for at least one recipient";
}
}
}
if ($failed > 0) {
if ($failed == 1) {
$flashMessage = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. Reason for the failure: ' . json_encode($lastError);
} else {
$flashMessage = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. This may be due to attributes with similar values already existing.';
}
} else {
$flashMessage = $saved . ' ' . $messageScope . ' created' . $emailResult . '.';
}
return $flashMessage;
}
public function saveFreeText($id)
{
if (!$this->userRole['perm_add']) {
@ -3790,17 +3662,15 @@ class EventsController extends AppController
$attributes = json_decode($this->request->data['Attribute']['JsonObject'], true);
$default_comment = $this->request->data['Attribute']['default_comment'];
$force = $this->request->data['Attribute']['force'];
$flashMessage = $this->__processFreeTextData($attributes, $id, $default_comment, $force);
$flashMessage = $this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, $default_comment, $force);
$this->Flash->info($flashMessage);
$this->redirect(array('controller' => 'events', 'action' => 'view', $id));
} else {
throw new MethodNotAllowedException();
throw new MethodNotAllowedException('This endpoint requires a POST request.');
}
}
public function stix2($key, $id)
public function stix2($key, $id = false, $withAttachments = false, $tags = false, $from = false, $to = false, $last = false)
{
if ($key != 'download') {
// check if the key is valid -> search for users based on key
@ -3813,9 +3683,54 @@ class EventsController extends AppController
throw new UnauthorizedException(__('You have to be logged in to do that.'));
}
}
$result = $this->Event->stix2($id, $this->Auth->user());
$this->header('Content-Disposition: download; filename="misp.stix2.event' . $id . '.json"');
return $this->RestResponse->viewData($result, 'application/json', false, true, "misp.stix2.event" . $id . ".json");
if ($this->request->is('post')) {
if (empty($this->request->data)) {
throw new BadRequestException(__('Either specify the search terms in the url, or POST an xml (with the root element being "request".'));
} else {
$data = $this->request->data;
}
$paramArray = array('id', 'withAttachment', 'tags', 'from', 'to', 'last');
foreach ($paramArray as $p) {
if (isset($data['request'][$p])) {
${$p} = $data['request'][$p];
} else {
${$p} = null;
}
}
}
$simpleFalse = array('id', 'withAttachments', 'tags', 'from', 'to', 'last');
foreach ($simpleFalse as $sF) {
if (!is_array(${$sF}) && (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false')) {
${$sF} = false;
}
}
if ($from) {
$from = $this->Event->dateFieldCheck($from);
}
if ($to) {
$to = $this->Event->dateFieldCheck($to);
}
if ($last) {
$last = $this->Event->resolveTimeDelta($last);
}
// set null if a null string is passed
$numeric = false;
if (is_numeric($id)) {
$numeric = true;
}
$result = $this->Event->stix2($id, $tags, $withAttachments, $this->Auth->user(), 'json', $from, $to, $last);
if ($result['success'] == 1) {
if ($numeric) {
$filename = 'misp.stix2.event' . $id . '.json';
} else {
$filename = 'misp.stix2.event.collection.json';
}
$this->header('Content-Disposition: download; filename="' . $filename . '"');
return $this->RestResponse->viewData($result['data'], 'application/json', false, true, $filename);
} else {
throw new Exception(h($result['message']));
}
}
public function stix($key, $id = false, $withAttachments = false, $tags = false, $from = false, $to = false, $last = false)
@ -4888,6 +4803,11 @@ class EventsController extends AppController
$modulePayload['config'][$conf] = Configure::read('Plugin.Import_' . $moduleName . '_' . $conf);
}
}
if ($moduleName === 'csvimport') {
if (empty($this->request->data['Event']['config']['header']) && $this->request->data['Event']['config']['has_header'] === '1') {
$this->request->data['Event']['config']['header'] = ' ';
}
}
foreach ($module['mispattributes']['userConfig'] as $configName => $config) {
if (!$fail) {
if (isset($config['validation'])) {
@ -5169,6 +5089,9 @@ class EventsController extends AppController
$this->Event->insertLock($this->Auth->user(), $event['Event']['id']);
if ($this->request->is('post')) {
$modules = array();
if (!isset($this->request->data['Event'])) {
$this->request->data = array('Event' => $this->request->data);
}
foreach ($this->request->data['Event'] as $module => $enabled) {
if ($enabled) {
$modules[] = $module;

View File

@ -123,6 +123,8 @@ class WarninglistsController extends AppController
* To control what state the warninglists should have after execution instead of just blindly toggling them, simply pass the enabled flag
* Example:
* {"id": [5, 8], "enabled": 1}
* Alternatively search by a substring in the warninglist's named, such as:
* {"name": ["%alexa%", "%iana%"], "enabled": 1}
*/
public function toggleEnable()
{
@ -132,7 +134,24 @@ class WarninglistsController extends AppController
if (isset($this->request->data['Warninglist']['data'])) {
$id = $this->request->data['Warninglist']['data'];
} else {
$id = $this->request->data['id'];
if (!empty($this->request->data['id'])) {
$id = $this->request->data['id'];
} else if (!empty($this->request->data['name'])) {
if (!is_array($this->request->data['name'])) {
$names = array($this->request->data['name']);
} else {
$names = $this->request->data['name'];
}
$conditions = array();
foreach ($names as $k => $name) {
$conditions['OR'][] = array('LOWER(Warninglist.name) LIKE' => strtolower($name));
}
$id = $this->Warninglist->find('list', array(
'conditions' => $conditions,
'recursive' => -1,
'fields' => array('Warninglist.id', 'Warninglist.id')
));
}
}
if (isset($this->request->data['enabled'])) {
$enabled = $this->request->data['enabled'];

View File

@ -228,7 +228,7 @@ class ComplexTypeTool
);
// algorithms to run through in order
private $__checks = array('Hashes', 'Email', 'IP', 'DomainOrFilename', 'SimpleRegex');
private $__checks = array('Hashes', 'Email', 'IP', 'DomainOrFilename', 'SimpleRegex', 'AS');
private function __resolveType($raw_input)
{
@ -258,6 +258,14 @@ class ComplexTypeTool
return false;
}
private function __checkForAS($input)
{
if (preg_match('#^as[0-9]+$#i', $input['raw'])) {
$input['raw'] = strtoupper($input['raw']);
return array('types' => array('AS'), 'to_ids' => false, 'default_type' => 'AS', 'value' => $input['raw']);
}
}
private function __checkForHashes($input)
{
// handle prepared composite values with the filename|hash format
@ -313,6 +321,13 @@ class ComplexTypeTool
$input['refanged'] = preg_replace($regex, $replacement, $input['refanged']);
}
$input['refanged'] = rtrim($input['refanged'], ".");
$input['refanged'] = preg_replace_callback(
'/\[.\]/',
function ($matches) {
return trim($matches[0], '[]');
},
$input['refanged']
);
return $input;
}

View File

@ -3780,33 +3780,85 @@ class Event extends AppModel
}
}
public function stix2($id, $user)
public function stix2($id, $tags, $attachments, $user, $returnType = 'json', $from = false, $to = false, $last = false, $jobId = false, $returnFile = false)
{
$event = $this->fetchEvent($user, array('eventid' => $id, 'includeAttachments' => 1));
App::uses('JSONConverterTool', 'Tools');
$converter = new JSONConverterTool();
$event = $converter->convert($event[0]);
$randomFileName = $this->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts" . DS . "tmp";
$tempFile = new File($tmpDir . DS . $randomFileName, true, 0644);
$tempFile->write($event);
$scriptFile = APP . "files" . DS . "scripts" . DS . "stix2" . DS . "misp2stix2.py";
$result = shell_exec('python3 ' . $scriptFile . ' ' . $tempFile->path . ' json ' . escapeshellarg(Configure::read('MISP.baseurl')) . ' ' . escapeshellarg(Configure::read('MISP.org')) . ' 2>' . APP . 'tmp/logs/exec-errors.log');
$tempFile->delete();
$resultFile = new File($tmpDir . DS . $randomFileName . ".stix2");
$resultFile->write("{\"type\": \"bundle\", \"spec_version\": \"2.0\", \"id\": \"bundle--" . CakeText::uuid() . "\", \"objects\": [");
if (trim($result) == 1) {
$file = new File($tmpDir . DS . $randomFileName . '.out', true, 0644);
$result = substr($file->read(), 1, -1);
$file->delete();
$resultFile->append($result);
} else {
return false;
$eventIDs = $this->Attribute->dissectArgs($id);
$tagIDs = $this->Attribute->dissectArgs($tags);
$idList = $this->getAccessibleEventIds($eventIDs[0], $eventIDs[1], $tagIDs[0], $tagIDs[1]);
if (!empty($idList)) {
$event_ids = $this->fetchEventIds($user, $from, $to, $last, true);
$event_ids = array_intersect($event_ids, $idList);
}
$resultFile->append("]}\n");
$data2return = $resultFile->read();
$resultFile->delete();
return $data2return;
$randomFileName = $this->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts";
$stix2_framing_cmd = 'python3 ' . $tmpDir . DS . 'misp_framing.py stix2 ' . escapeshellarg(CakeText::uuid()) . ' 2>' . APP . 'tmp/logs/exec-errors.log';
$stix2_framing = json_decode(shell_exec($stix2_framing_cmd), true);
if (empty($stix2_framing)) {
return array('success' => 0, 'message' => 'There was an issue generating the STIX 2.0 export.');
}
$separator = $stix2_framing['separator'];
$tmpDir = $tmpDir . DS . "tmp";
$stixFile = new File($tmpDir . DS . $randomFileName . ".stix");
$stixFile->write($stix2_framing['header']);
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
$this->Job->id = $jobId;
if (!$this->Job->exists()) {
$jobId = false;
}
}
$i = 0;
$eventCount = count($event_ids);
$ORGs = ' ';
if ($event_ids) {
foreach ($event_ids as $event_id) {
$tempFile = new File($tmpDir . DS . $randomFileName, true, 0644);
$event = $this->fetchEvent($user, array('eventid' => $event_id, 'includeAttachments' => 1));
if (empty($event)) {
continue;
}
$event[0]['Tag'] = array();
foreach ($event[0]['EventTag'] as $tag) {
$event[0]['Tag'][] = $tag['Tag'];
}
App::uses('JSONConverterTool', 'Tools');
$converter = new JSONConverterTool();
$event = $converter->convert($event[0]);
$tempFile->write($event);
unset($event);
$scriptFile = APP . "files" . DS . "scripts" . DS . "stix2" . DS . "misp2stix2.py";
$result = shell_exec('python3 ' . $scriptFile . ' ' . $tempFile->path . $ORGs . '2>' . APP . 'tmp/logs/exec-errors.log');
$decoded = json_decode($result, true);
if (isset($decoded['success']) && $decoded['success'] == 1) {
if (isset($decoded['org'])) {
$ORGs = $ORGs . $decoded['org'] . ' ';
}
$file = new File($tmpDir . DS . $randomFileName . '.out', true, 0644);
$result = substr($file->read(), 1, -1);
$file->delete();
$stixFile->append($result . (($i + 1) != $eventCount ? $separator : ''));
} else {
return false;
}
$i++;
if ($jobId) {
$this->Job->saveField('message', 'Event ' . $i . '/' . $eventCount);
if ($i % 10 == 0) {
$this->Job->saveField('progress', $i * 80 / $eventCount);
}
}
$tempFile->close();
}
}
$stixFile->append($stix2_framing['footer']);
if ($tempFile) {
$tempFile->delete();
}
if (!$returnFile) {
$data2return = $stixFile->read();
$stixFile->delete();
}
return array('success' => 1, 'data' => $returnFile ? $stixFile->path : $data2return);
}
public function stix($id, $tags, $attachments, $user, $returnType = 'xml', $from = false, $to = false, $last = false, $jobId = false, $returnFile = false)
@ -3819,17 +3871,16 @@ class Event extends AppModel
$event_ids = array_intersect($event_ids, $idList);
}
$randomFileName = $this->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts" . DS . "tmp";
$stixFile = new File($tmpDir . DS . $randomFileName . ".stix");
$stix_framing = shell_exec('python3 ' . APP . "files" . DS . "scripts" . DS . 'misp2stix_framing.py ' . escapeshellarg(Configure::read('MISP.baseurl')) . ' ' . escapeshellarg(Configure::read('MISP.org')) . ' ' . escapeshellarg($returnType) . ' 2>' . APP . 'tmp/logs/exec-errors.log');
$tmpDir = APP . "files" . DS . "scripts";
$stix_framing_cmd = 'python3 ' . $tmpDir . DS . 'misp_framing.py stix ' . escapeshellarg(Configure::read('MISP.baseurl')) . ' ' . escapeshellarg(Configure::read('MISP.org')) . ' ' . escapeshellarg($returnType) . ' 2>' . APP . 'tmp/logs/exec-errors.log';
$stix_framing = json_decode(shell_exec($stix_framing_cmd), true);
if (empty($stix_framing)) {
$stixFile->delete();
return array('success' => 0, 'message' => 'There was an issue generating the STIX export.');
}
$stixFile->write(substr($stix_framing, 0, -1));
if ($returnType === 'xml') {
$stixFile->append(" <stix:Related_Packages>\n");
}
$separator = $stix_framing['separator'];
$tmpDir = $tmpDir . DS . "tmp";
$stixFile = new File($tmpDir . DS . $randomFileName . ".stix");
$stixFile->write($stix_framing['header']);
$result = array();
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
@ -3882,9 +3933,11 @@ class Event extends AppModel
$stix_event[count($stix_event)-1] = str_replace("STIX_Package", "Package", $stix_event[count($stix_event)-1]);
$stix_event = implode("\n", $stix_event);
$stix_event = str_replace("\n", "\n ", $stix_event) . "\n";
$stix_event = " <stix:Related_Package>\n" . $stix_event . " </stix:Related_Package>\n";
} else {
$stix_event = $file->read() . (($i + 1) != $eventCount ? ',' : '');
$stix_event = $file->read();
}
if (($i + 1) != $eventCount) {
$stix_event .= $separator;
}
$stixFile->append($stix_event);
$file->close();
@ -3899,11 +3952,7 @@ class Event extends AppModel
$tempFile->close();
}
}
if ($returnType == 'xml') {
$stixFile->append(" </stix:Related_Packages>\n</stix:STIX_Package>\n\n");
} else {
$stixFile->append("]}\n");
}
$stixFile->append($stix_framing['footer']);
if ($tempFile) {
$tempFile->delete();
}
@ -5013,4 +5062,201 @@ class Event extends AppModel
));
return false;
}
public function processFreeTextData($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false, $jobId = false)
{
$event = $this->find('first', array(
'conditions' => array('id' => $id),
'recursive' => -1,
'fields' => array('orgc_id', 'id', 'distribution', 'published', 'uuid'),
));
if (!$user['Role']['perm_site_admin'] && !empty($event) && $event['Event']['orgc_id'] != $user['org_id']) {
$objectType = 'ShadowAttribute';
} elseif ($user['Role']['perm_site_admin'] && isset($force) && $force) {
$objectType = 'ShadowAttribute';
} else {
$objectType = 'Attribute';
}
if ($adhereToWarninglists) {
$this->Warninglist = ClassRegistry::init('Warninglist');
$warninglists = $this->Warninglist->fetchForEventView();
}
$saved = 0;
$failed = 0;
$attributeSources = array('attributes', 'ontheflyattributes');
$ontheflyattributes = array();
$i = 0;
$total = count($attributeSources);
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
$this->Job->id = $jobId;
}
foreach ($attributeSources as $sourceKey => $source) {
foreach (${$source} as $k => $attribute) {
if ($attribute['type'] == 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
} elseif ($attribute['type'] == 'ip-src|port/ip-dst|port') {
$types = array('ip-src|port', 'ip-dst|port');
} elseif ($attribute['type'] == 'malware-sample') {
if (!isset($attribute['data_is_handled']) || !$attribute['data_is_handled']) {
$result = $this->Attribute->handleMaliciousBase64($id, $attribute['value'], $attribute['data'], array('md5', 'sha1', 'sha256'), $objectType == 'ShadowAttribute' ? true : false);
if (!$result['success']) {
$failed++;
continue;
}
$attribute['data'] = $result['data'];
$shortValue = $attribute['value'];
$attribute['value'] = $shortValue . '|' . $result['md5'];
$additionalHashes = array('sha1', 'sha256');
foreach ($additionalHashes as $hash) {
$temp = $attribute;
$temp['type'] = 'filename|' . $hash;
$temp['value'] = $shortValue . '|' . $result[$hash];
unset($temp['data']);
$ontheflyattributes[] = $temp;
}
}
$types = array($attribute['type']);
} else {
$types = array($attribute['type']);
}
foreach ($types as $type) {
$this->$objectType->create();
$attribute['type'] = $type;
if (empty($attribute['comment'])) {
$attribute['comment'] = $default_comment;
}
$attribute['event_id'] = $id;
if ($objectType == 'ShadowAttribute') {
$attribute['org_id'] = $user['Role']['org_id'];
$attribute['event_org_id'] = $event['Event']['orgc_id'];
$attribute['email'] = $user['Role']['email'];
$attribute['event_uuid'] = $event['Event']['uuid'];
}
// adhere to the warninglist
if ($adhereToWarninglists) {
if (!$this->Warninglist->filterWarninglistAttributes($warninglists, $attribute)) {
if ($adhereToWarninglists == 'soft') {
$attribute['to_ids'] = 0;
} else {
// just ignore the attribute
continue;
}
}
}
$AttributSave = $this->$objectType->save($attribute);
if ($AttributSave) {
// If Tags, attache each tags to attribut
if (!empty($attribute['tags'])) {
foreach (explode(",", $attribute['tags']) as $tagName) {
$this->loadModel('Tag');
$TagId = $this->Tag->captureTag(array('name' => $tagName), array('Role' => $user['Role']));
$this->loadModel('AttributeTag');
if (!$this->AttributeTag->attachTagToAttribute($AttributSave['Attribute']['id'], $id, $TagId)) {
throw new MethodNotAllowedException(__('Could not add tags.'));
}
}
}
$saved++;
} else {
$lastError = $this->$objectType->validationErrors;
$failed++;
}
}
if ($jobId) {
if ($i % 20 == 0) {
$this->Job->saveField('message', 'Attribute ' . $i . '/' . $total);
$this->Job->saveField('progress', $i * 80 / $total);
}
}
}
}
$emailResult = '';
$messageScope = $objectType == 'ShadowAttribute' ? 'proposals' : 'attributes';
if ($saved > 0) {
if ($objectType != 'ShadowAttribute') {
$event = $this->find('first', array(
'conditions' => array('Event.id' => $id),
'recursive' => -1
));
if ($event['Event']['published'] == 1) {
$event['Event']['published'] = 0;
}
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->save($event);
} else {
if (!$this->ShadowAttribute->sendProposalAlertEmail($id)) {
$emailResult = " but sending out the alert e-mails has failed for at least one recipient";
}
}
}
if ($failed > 0) {
if ($failed == 1) {
$message = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. Reason for the failure: ' . json_encode($lastError);
} else {
$message = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. This may be due to attributes with similar values already existing.';
}
} else {
$message = $saved . ' ' . $messageScope . ' created' . $emailResult . '.';
}
if ($jobId) {
if ($i % 20 == 0) {
$this->Job->saveField('message', 'Processing complete. ' . $message);
$this->Job->saveField('progress', 100);
}
}
return $message;
}
public function processFreeTextDataRouter($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false)
{
if (Configure::read('MISP.background_jobs')) {
$job = ClassRegistry::init('Job');
$job->create();
$data = array(
'worker' => 'default',
'job_type' => 'process_freetext_data',
'job_input' => 'Event: ' . $id,
'status' => 0,
'retries' => 0,
'org_id' => $user['org_id'],
'org' => $user['Organisation']['name'],
'message' => 'Processing...',
);
$job->save($data);
$randomFileName = $this->generateRandomFileName() . '.json';
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');
$tempdir = new Folder(APP . 'tmp/cache/ingest', true, 0755);
$tempFile = new File(APP . 'tmp/cache/ingest' . DS . $randomFileName, true, 0644);
$tempData = array(
'user' => $user,
'attributes' => $attributes,
'id' => $id,
'default_comment' => $default_comment,
'force' => $force,
'adhereToWarninglists' => $adhereToWarninglists,
'jobId' => $job->id
);
$writeResult = $tempFile->write(json_encode($tempData));
if (!$writeResult) {
return ($this->processFreeTextData($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false));
}
$tempFile->close();
$jobId = $job->id;
$process_id = CakeResque::enqueue(
'prio',
'EventShell',
array('processfreetext', $randomFileName),
true
);
$job->saveField('process_id', $process_id);
return 'Freetext ingestion queued for background processing. Attributes will be added to the event as they are being processed.';
} else {
return ($this->processFreeTextData($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false));
}
}
}

View File

@ -11,8 +11,10 @@
foreach ($galaxy['GalaxyCluster'] as $cluster):
?>
<div style="margin-left:8px;">
<span class="bold blue expandContainer useCursorPointer">
<span class="collapse-status" style="font-size: 16px;">+</span>
<span class="bold blue expandContainer">
<span class="collapse-status-container useCursorPointer">
<span class="collapse-status" style="font-size: 16px;">+</span>
</span>
<span><?php echo h($cluster['value']); ?></span>
<a href="<?php echo $baseurl; ?>/galaxy_clusters/view/<?php echo h($cluster['id']); ?>" class="icon-search" title="<?php echo __('View details about this cluster');?>"></a>&nbsp;
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($cluster['tag_id']); ?>" class="icon-th-list" title="<?php echo __('View all events containing this cluster.');?>"></a>
@ -100,12 +102,12 @@
<script type="text/javascript">
$(document).ready(function () {
$('.expandContainer').click(function() {
$(this).children('.galaxy_data').toggle();
if ($(this).children('.collapse-status').html() == '+') {
$(this).children('.collapse-status').html('-');
$('.collapse-status-container').click(function() {
$(this).parent().children('.galaxy_data').toggle();
if ($(this).parent().children('.collapse-status-container').children('.collapse-status').html() == '+') {
$(this).parent().children('.collapse-status-container').children('.collapse-status').html('-');
} else {
$(this).children('.collapse-status').html('+');
$(this).parent().children('.collapse-status-container').children('.collapse-status').html('+');
}
});
$('.delete-cluster').click(function() {

View File

@ -133,6 +133,36 @@
<p><?php echo __('The same search could be accomplished using the following POSTed XML object (note that ampersands need to be escaped, or alternatively separate id and tag elements can be used)');?>: </p>
<code>&lt;request&gt;&lt;id&gt;!51&lt;/id&gt;&lt;id&gt;!62&lt;/id&gt;&lt;tags&gt;APT1&lt;/tags&gt;&lt;tags&gt;!OSINT&lt;/tags&gt;&lt;from&gt;2015-02-15&lt;/from&gt;&lt;/request&gt;</code>
<h3><?php echo __('STIX 2.0 export');?></h3>
<p><?php echo __('You can export MISP events in STIX 2.0 format (to read more about STIX, click <a href="https://stix2.readthedocs.io/">here</a>). ');?>:</p>
<pre><?php echo $baseurl;?>/events/stix2/download.json</pre>
<p><?php echo __('Search parameters can be passed to the function via URL parameters or by POSTing a JSON object. The following parameters can be passed to the STIX 2.0 export tool: <code>id</code>, <code>withAttachments</code>, <code>tags</code>. Both <code>id</code> and <code>tags</code> can use the <code>&amp;&amp;</code> (and) and <code>!</code> (not) operators to build queries. Using the URL parameters, the syntax is as follows');?>:</p>
<pre><?php echo $baseurl;?>/events/stix2/download/[id]/[withAttachments]/[tags]/[from]/[to]/[last]</pre>
<p>
<b>id</b>: <?php echo __('The event\'s ID');?><br />
<b>withAttachments</b>: <?php echo __('Encode attachments where applicable');?><br />
<b>tags</b>: <?php echo __('To include a tag in the results just write its names into this parameter. To exclude a tag prepend it with a \'!\'.
You can also chain several tag commands together with the \'&amp;&amp;\' operator. Please be aware the colons (:) cannot be used in the tag search.
Use semicolons instead (the search will automatically search for colons instead). For example, to include tag1 and tag2 but exclude tag3 you would use');?>:<br />
</p>
<pre><?php echo $baseurl;?>/events/stix2/download/false/true/tag1&amp;&amp;tag2&amp;&amp;!tag3</pre>
<p>
<b>from</b>: <?php echo __('Events with the date set to a date after the one specified in the from field (format: 2015-02-15). This filter will use the date of the event.');?><br />
<b>to</b>: <?php echo __('Events with the date set to a date before the one specified in the to field (format: 2015-02-15). This filter will use the date of the event.');?><br />
<b>last</b>: <?php echo __('Events published within the last x amount of time, where x can be defined in days, hours, minutes (for example 5d or 12h or 30m). This filter will use the published timestamp of the event.');?><br />
</p>
<p><?php echo __('You can post a JSON object containing additional parameters in the following formats');?>:</p>
<p>JSON:</p>
<pre><?php echo $baseurl;?>/events/stix2/download.json</pre>
<code>{"request": {"id":["!51","!62"],"withAttachment":false,"tags":["APT1","!OSINT"],"from":false,"to":"2015-02-15"}}</code><br /><br />
<h4><?php echo __('Various ways to narrow down the search results of the STIX 2.0 export');?></h4>
<p><?php echo __('For example, to retrieve all events tagged "APT1" but excluding events tagged "OSINT" and excluding events #51 and #62 without any attachments');?>:
<pre><?php echo $baseurl;?>/events/stix2/download/!51&amp;&amp;!62/false/APT1&amp;&amp;!OSINT/2015-02-15</pre>
<p><?php echo __('To export the same events using a POST request use');?>:</p>
<pre><?php echo $baseurl;?>/events/stix2/download.json</pre>
<p><?php echo __('Together with this JSON object in the POST message');?>:</p>
<code>{"request": {"id":["!51","!62"],"tags":["APT1","!OSINT"],"from":"2015-02-15"}}</code><br /><br />
<h3><?php echo __('RPZ export');?></h3>
<p<?php echo __('>You can export RPZ zone files for DNS level firewalling by using the RPZ export functionality of MISP. The file generated will include all of the IDS flagged domain, hostname and IP-src/IP-dst attribute values that you have access to.');?></p>
<p><?php echo __('It is possible to further restrict the exported values using the following filters');?>:</p>

View File

@ -18,7 +18,7 @@
<span class="btn btn-inverse" id="btnRight">&gt;&gt;</span>
</td>
<td style="width:285px;">
<p><?php echo __('Added Organisations');?></p>
<p><?php echo __('Added Instances');?></p>
<select id="rightValues" size="5" multiple style="width:285px;"></select>
</td>
</tr>

View File

@ -8,6 +8,13 @@
foreach ($value as $k => $v) {
$value[$k] = h($v);
}
if (isset($value['OR']) || isset($value['AND']) || isset($value['NOT'])) {
$temp = array();
foreach ($value as $k => $v) {
$temp[] = $k . ': ' . implode(', ', $v);
}
$value = $temp;
}
$value = implode('<br />', $value);
} else {
$value = h($value);

@ -1 +1 @@
Subproject commit 6105522453dec9a86adce2c1ba08530aca9b9f09
Subproject commit 6d58e288b657a941ef314aac2fef8ae6725254dd

@ -1 +1 @@
Subproject commit 4d6e0d7580b6239e33ed268031b7a1297a6ad686
Subproject commit d1b2f6d5fb8c2fcff19757a5b13eab11011d594a

View File

@ -1,127 +0,0 @@
#!/usr/bin/env python3
import sys, datetime, re
from stix.core import STIXPackage, STIXHeader
from cybox.utils import Namespace
# As python3 is forced anyway, mixbox is used and we don't need to try to import idgen from stix.utils
from mixbox import idgen
from stix import __version__ as STIXVER
NS_DICT = {
"http://cybox.mitre.org/common-2" : 'cyboxCommon',
"http://cybox.mitre.org/cybox-2" : 'cybox',
"http://cybox.mitre.org/default_vocabularies-2" : 'cyboxVocabs',
"http://cybox.mitre.org/objects#AccountObject-2" : 'AccountObj',
"http://cybox.mitre.org/objects#ASObject-1" : 'ASObj',
"http://cybox.mitre.org/objects#AddressObject-2" : 'AddressObj',
"http://cybox.mitre.org/objects#PortObject-2" : 'PortObj',
"http://cybox.mitre.org/objects#DomainNameObject-1" : 'DomainNameObj',
"http://cybox.mitre.org/objects#EmailMessageObject-2" : 'EmailMessageObj',
"http://cybox.mitre.org/objects#FileObject-2" : 'FileObj',
"http://cybox.mitre.org/objects#HTTPSessionObject-2" : 'HTTPSessionObj',
"http://cybox.mitre.org/objects#HostnameObject-1" : 'HostnameObj',
"http://cybox.mitre.org/objects#MutexObject-2" : 'MutexObj',
"http://cybox.mitre.org/objects#PipeObject-2" : 'PipeObj',
"http://cybox.mitre.org/objects#URIObject-2" : 'URIObj',
"http://cybox.mitre.org/objects#WinRegistryKeyObject-2" : 'WinRegistryKeyObj',
'http://cybox.mitre.org/objects#WinServiceObject-2' : 'WinServiceObj',
"http://cybox.mitre.org/objects#NetworkConnectionObject-2" : 'NetworkConnectionObj',
"http://cybox.mitre.org/objects#NetworkSocketObject-2" : 'NetworkSocketObj',
"http://cybox.mitre.org/objects#SocketAddressObject-1" : 'SocketAddressObj',
"http://cybox.mitre.org/objects#SystemObject-2" : 'SystemObj',
"http://cybox.mitre.org/objects#ProcessObject-2" : 'ProcessObj',
"http://cybox.mitre.org/objects#X509CertificateObject-2" : 'X509CertificateObj',
"http://cybox.mitre.org/objects#WhoisObject-2" : 'WhoisObj',
"http://cybox.mitre.org/objects#WinExecutableFileObject-2" : 'WinExecutableFileObj',
"http://data-marking.mitre.org/Marking-1" : 'marking',
"http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1" : 'tlpMarking',
"http://stix.mitre.org/ExploitTarget-1" : 'et',
"http://stix.mitre.org/Incident-1" : 'incident',
"http://stix.mitre.org/Indicator-2" : 'indicator',
"http://stix.mitre.org/TTP-1" : 'ttp',
"http://stix.mitre.org/ThreatActor-1" : 'ta',
"http://stix.mitre.org/common-1" : 'stixCommon',
"http://stix.mitre.org/default_vocabularies-1" : 'stixVocabs',
"http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1" : 'ciqIdentity',
"http://stix.mitre.org/extensions/TestMechanism#Snort-1" : 'snortTM',
"http://stix.mitre.org/stix-1" : 'stix',
"http://www.w3.org/2001/XMLSchema-instance" : 'xsi',
"urn:oasis:names:tc:ciq:xal:3" : 'xal',
"urn:oasis:names:tc:ciq:xnl:3" : 'xnl',
"urn:oasis:names:tc:ciq:xpil:3" : 'xpil',
}
SCHEMALOC_DICT = {
'http://cybox.mitre.org/common-2': 'http://cybox.mitre.org/XMLSchema/common/2.1/cybox_common.xsd',
'http://cybox.mitre.org/cybox-2': 'http://cybox.mitre.org/XMLSchema/core/2.1/cybox_core.xsd',
'http://cybox.mitre.org/default_vocabularies-2': 'http://cybox.mitre.org/XMLSchema/default_vocabularies/2.1/cybox_default_vocabularies.xsd',
'http://cybox.mitre.org/objects#AccountObject-2': ' http://cybox.mitre.org/XMLSchema/objects/Account/2.1/Account_Object.xsd',
'http://cybox.mitre.org/objects#ASObject-1': 'http://cybox.mitre.org/XMLSchema/objects/AS/1.0/AS_Object.xsd',
'http://cybox.mitre.org/objects#AddressObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Address/2.1/Address_Object.xsd',
'http://cybox.mitre.org/objects#PortObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Port/2.1/Port_Object.xsd',
'http://cybox.mitre.org/objects#DomainNameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Domain_Name/1.0/Domain_Name_Object.xsd',
'http://cybox.mitre.org/objects#EmailMessageObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Email_Message/2.1/Email_Message_Object.xsd',
'http://cybox.mitre.org/objects#FileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/File/2.1/File_Object.xsd',
'http://cybox.mitre.org/objects#HTTPSessionObject-2': 'http://cybox.mitre.org/XMLSchema/objects/HTTP_Session/2.1/HTTP_Session_Object.xsd',
'http://cybox.mitre.org/objects#HostnameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Hostname/1.0/Hostname_Object.xsd',
'http://cybox.mitre.org/objects#MutexObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Mutex/2.1/Mutex_Object.xsd',
'http://cybox.mitre.org/objects#PipeObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Pipe/2.1/Pipe_Object.xsd',
'http://cybox.mitre.org/objects#URIObject-2': 'http://cybox.mitre.org/XMLSchema/objects/URI/2.1/URI_Object.xsd',
'http://cybox.mitre.org/objects#WinServiceObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Service/2.1/Win_Service_Object.xsd',
'http://cybox.mitre.org/objects#WinRegistryKeyObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Registry_Key/2.1/Win_Registry_Key_Object.xsd',
'http://cybox.mitre.org/objects#NetworkConnectionObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Network_Connection/2.0.1/Network_Connection_Object.xsd',
'http://cybox.mitre.org/objects#NetworkSocketObject-2': 'https://cybox.mitre.org/XMLSchema/objects/Network_Socket/2.1/Network_Socket_Object.xsd',
'http://cybox.mitre.org/objects#SystemObject-2': 'http://cybox.mitre.org/XMLSchema/objects/System/2.1/System_Object.xsd',
'http://cybox.mitre.org/objects#SocketAddressObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Socket_Address/1.1/Socket_Address_Object.xsd',
'http://cybox.mitre.org/objects#ProcessObject-2': 'https://cybox.mitre.org/XMLSchema/objects/Process/2.1/Process_Object.xsd',
'http://cybox.mitre.org/objects#X509CertificateObject-2': 'http://cybox.mitre.org/XMLSchema/objects/X509_Certificate/2.1/X509_Certificate_Object.xsd',
'http://cybox.mitre.org/objects#WhoisObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Whois/2.1/Whois_Object.xsd',
'http://cybox.mitre.org/objects#WinExecutableFileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Executable_File/2.1/Win_Executable_File_Object.xsd',
'http://data-marking.mitre.org/Marking-1': 'http://stix.mitre.org/XMLSchema/data_marking/1.1.1/data_marking.xsd',
'http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1': 'http://stix.mitre.org/XMLSchema/extensions/marking/tlp/1.1.1/tlp_marking.xsd',
'http://stix.mitre.org/ExploitTarget-1': 'http://stix.mitre.org/XMLSchema/exploit_target/1.1.1/exploit_target.xsd',
'http://stix.mitre.org/Incident-1': 'http://stix.mitre.org/XMLSchema/incident/1.1.1/incident.xsd',
'http://stix.mitre.org/Indicator-2': 'http://stix.mitre.org/XMLSchema/indicator/2.1.1/indicator.xsd',
'http://stix.mitre.org/TTP-1': 'http://stix.mitre.org/XMLSchema/ttp/1.1.1/ttp.xsd',
'http://stix.mitre.org/ThreatActor-1': 'http://stix.mitre.org/XMLSchema/threat_actor/1.1.1/threat_actor.xsd',
'http://stix.mitre.org/common-1': 'http://stix.mitre.org/XMLSchema/common/1.1.1/stix_common.xsd',
'http://stix.mitre.org/default_vocabularies-1': 'http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd',
'http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1': 'http://stix.mitre.org/XMLSchema/extensions/identity/ciq_3.0/1.1.1/ciq_3.0_identity.xsd',
'http://stix.mitre.org/extensions/TestMechanism#Snort-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/snort/1.1.1/snort_test_mechanism.xsd',
'http://stix.mitre.org/stix-1': 'http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd',
'urn:oasis:names:tc:ciq:xal:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xAL.xsd',
'urn:oasis:names:tc:ciq:xnl:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xNL.xsd',
'urn:oasis:names:tc:ciq:xpil:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xPIL.xsd',
}
def main(args):
if len(args) < 4:
sys.exit("Invalid parameters")
baseURL = args[1]
if not baseURL:
baseURL = 'https://www.misp-project.org'
orgname = args[2]
orgname = re.sub('[\W]+', '', orgname.replace(" ", "_"))
NS_DICT[baseURL] = orgname
try:
idgen.set_id_namespace(Namespace(baseURL, orgname))
except TypeError:
idgen.set_id_namespace(Namespace(baseURL, orgname, "MISP"))
stix_package = STIXPackage()
stix_header = STIXHeader()
stix_header.title="Export from {} MISP".format(args[2])
stix_header.package_intents="Threat Report"
stix_package.stix_header = stix_header
stix_package.version = "1.1.1"
stix_package.timestamp = datetime.datetime.now()
if args[3] == 'json':
stix_string = stix_package.to_json()[:-1]
stix_string += ', "related_packages": ['
else:
stix_string = stix_package.to_xml(auto_namespace=False, ns_dict=NS_DICT, schemaloc_dict=SCHEMALOC_DICT)
stix_string = stix_string.decode().replace("</stix:STIX_Package>\n", "");
print(stix_string)
if __name__ == "__main__":
main(sys.argv)

View File

@ -0,0 +1,150 @@
#!/usr/bin/env python3
import sys, json
n_args = {'stix': 4, 'stix2': 2}
json_footer = "]}\n"
keys_to_return = ['header', 'separator', 'footer']
def stix_framing(*args):
import datetime, re
from stix.core import STIXPackage, STIXHeader
from cybox.utils import Namespace
# As python3 is forced anyway, mixbox is used and we don't need to try to import idgen from stix.utils
from mixbox import idgen
from stix import __version__ as STIXVER
NS_DICT = {
"http://cybox.mitre.org/common-2" : 'cyboxCommon',
"http://cybox.mitre.org/cybox-2" : 'cybox',
"http://cybox.mitre.org/default_vocabularies-2" : 'cyboxVocabs',
"http://cybox.mitre.org/objects#AccountObject-2" : 'AccountObj',
"http://cybox.mitre.org/objects#ASObject-1" : 'ASObj',
"http://cybox.mitre.org/objects#AddressObject-2" : 'AddressObj',
"http://cybox.mitre.org/objects#PortObject-2" : 'PortObj',
"http://cybox.mitre.org/objects#DomainNameObject-1" : 'DomainNameObj',
"http://cybox.mitre.org/objects#EmailMessageObject-2" : 'EmailMessageObj',
"http://cybox.mitre.org/objects#FileObject-2" : 'FileObj',
"http://cybox.mitre.org/objects#HTTPSessionObject-2" : 'HTTPSessionObj',
"http://cybox.mitre.org/objects#HostnameObject-1" : 'HostnameObj',
"http://cybox.mitre.org/objects#MutexObject-2" : 'MutexObj',
"http://cybox.mitre.org/objects#PipeObject-2" : 'PipeObj',
"http://cybox.mitre.org/objects#URIObject-2" : 'URIObj',
"http://cybox.mitre.org/objects#WinRegistryKeyObject-2" : 'WinRegistryKeyObj',
'http://cybox.mitre.org/objects#WinServiceObject-2' : 'WinServiceObj',
"http://cybox.mitre.org/objects#NetworkConnectionObject-2" : 'NetworkConnectionObj',
"http://cybox.mitre.org/objects#NetworkSocketObject-2" : 'NetworkSocketObj',
"http://cybox.mitre.org/objects#SocketAddressObject-1" : 'SocketAddressObj',
"http://cybox.mitre.org/objects#SystemObject-2" : 'SystemObj',
"http://cybox.mitre.org/objects#ProcessObject-2" : 'ProcessObj',
"http://cybox.mitre.org/objects#X509CertificateObject-2" : 'X509CertificateObj',
"http://cybox.mitre.org/objects#WhoisObject-2" : 'WhoisObj',
"http://cybox.mitre.org/objects#WinExecutableFileObject-2" : 'WinExecutableFileObj',
"http://data-marking.mitre.org/Marking-1" : 'marking',
"http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1" : 'tlpMarking',
"http://stix.mitre.org/ExploitTarget-1" : 'et',
"http://stix.mitre.org/Incident-1" : 'incident',
"http://stix.mitre.org/Indicator-2" : 'indicator',
"http://stix.mitre.org/TTP-1" : 'ttp',
"http://stix.mitre.org/ThreatActor-1" : 'ta',
"http://stix.mitre.org/common-1" : 'stixCommon',
"http://stix.mitre.org/default_vocabularies-1" : 'stixVocabs',
"http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1" : 'ciqIdentity',
"http://stix.mitre.org/extensions/TestMechanism#Snort-1" : 'snortTM',
"http://stix.mitre.org/stix-1" : 'stix',
"http://www.w3.org/2001/XMLSchema-instance" : 'xsi',
"urn:oasis:names:tc:ciq:xal:3" : 'xal',
"urn:oasis:names:tc:ciq:xnl:3" : 'xnl',
"urn:oasis:names:tc:ciq:xpil:3" : 'xpil',
}
SCHEMALOC_DICT = {
'http://cybox.mitre.org/common-2': 'http://cybox.mitre.org/XMLSchema/common/2.1/cybox_common.xsd',
'http://cybox.mitre.org/cybox-2': 'http://cybox.mitre.org/XMLSchema/core/2.1/cybox_core.xsd',
'http://cybox.mitre.org/default_vocabularies-2': 'http://cybox.mitre.org/XMLSchema/default_vocabularies/2.1/cybox_default_vocabularies.xsd',
'http://cybox.mitre.org/objects#AccountObject-2': ' http://cybox.mitre.org/XMLSchema/objects/Account/2.1/Account_Object.xsd',
'http://cybox.mitre.org/objects#ASObject-1': 'http://cybox.mitre.org/XMLSchema/objects/AS/1.0/AS_Object.xsd',
'http://cybox.mitre.org/objects#AddressObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Address/2.1/Address_Object.xsd',
'http://cybox.mitre.org/objects#PortObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Port/2.1/Port_Object.xsd',
'http://cybox.mitre.org/objects#DomainNameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Domain_Name/1.0/Domain_Name_Object.xsd',
'http://cybox.mitre.org/objects#EmailMessageObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Email_Message/2.1/Email_Message_Object.xsd',
'http://cybox.mitre.org/objects#FileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/File/2.1/File_Object.xsd',
'http://cybox.mitre.org/objects#HTTPSessionObject-2': 'http://cybox.mitre.org/XMLSchema/objects/HTTP_Session/2.1/HTTP_Session_Object.xsd',
'http://cybox.mitre.org/objects#HostnameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Hostname/1.0/Hostname_Object.xsd',
'http://cybox.mitre.org/objects#MutexObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Mutex/2.1/Mutex_Object.xsd',
'http://cybox.mitre.org/objects#PipeObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Pipe/2.1/Pipe_Object.xsd',
'http://cybox.mitre.org/objects#URIObject-2': 'http://cybox.mitre.org/XMLSchema/objects/URI/2.1/URI_Object.xsd',
'http://cybox.mitre.org/objects#WinServiceObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Service/2.1/Win_Service_Object.xsd',
'http://cybox.mitre.org/objects#WinRegistryKeyObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Registry_Key/2.1/Win_Registry_Key_Object.xsd',
'http://cybox.mitre.org/objects#NetworkConnectionObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Network_Connection/2.0.1/Network_Connection_Object.xsd',
'http://cybox.mitre.org/objects#NetworkSocketObject-2': 'https://cybox.mitre.org/XMLSchema/objects/Network_Socket/2.1/Network_Socket_Object.xsd',
'http://cybox.mitre.org/objects#SystemObject-2': 'http://cybox.mitre.org/XMLSchema/objects/System/2.1/System_Object.xsd',
'http://cybox.mitre.org/objects#SocketAddressObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Socket_Address/1.1/Socket_Address_Object.xsd',
'http://cybox.mitre.org/objects#ProcessObject-2': 'https://cybox.mitre.org/XMLSchema/objects/Process/2.1/Process_Object.xsd',
'http://cybox.mitre.org/objects#X509CertificateObject-2': 'http://cybox.mitre.org/XMLSchema/objects/X509_Certificate/2.1/X509_Certificate_Object.xsd',
'http://cybox.mitre.org/objects#WhoisObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Whois/2.1/Whois_Object.xsd',
'http://cybox.mitre.org/objects#WinExecutableFileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Executable_File/2.1/Win_Executable_File_Object.xsd',
'http://data-marking.mitre.org/Marking-1': 'http://stix.mitre.org/XMLSchema/data_marking/1.1.1/data_marking.xsd',
'http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1': 'http://stix.mitre.org/XMLSchema/extensions/marking/tlp/1.1.1/tlp_marking.xsd',
'http://stix.mitre.org/ExploitTarget-1': 'http://stix.mitre.org/XMLSchema/exploit_target/1.1.1/exploit_target.xsd',
'http://stix.mitre.org/Incident-1': 'http://stix.mitre.org/XMLSchema/incident/1.1.1/incident.xsd',
'http://stix.mitre.org/Indicator-2': 'http://stix.mitre.org/XMLSchema/indicator/2.1.1/indicator.xsd',
'http://stix.mitre.org/TTP-1': 'http://stix.mitre.org/XMLSchema/ttp/1.1.1/ttp.xsd',
'http://stix.mitre.org/ThreatActor-1': 'http://stix.mitre.org/XMLSchema/threat_actor/1.1.1/threat_actor.xsd',
'http://stix.mitre.org/common-1': 'http://stix.mitre.org/XMLSchema/common/1.1.1/stix_common.xsd',
'http://stix.mitre.org/default_vocabularies-1': 'http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd',
'http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1': 'http://stix.mitre.org/XMLSchema/extensions/identity/ciq_3.0/1.1.1/ciq_3.0_identity.xsd',
'http://stix.mitre.org/extensions/TestMechanism#Snort-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/snort/1.1.1/snort_test_mechanism.xsd',
'http://stix.mitre.org/stix-1': 'http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd',
'urn:oasis:names:tc:ciq:xal:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xAL.xsd',
'urn:oasis:names:tc:ciq:xnl:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xNL.xsd',
'urn:oasis:names:tc:ciq:xpil:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xPIL.xsd',
}
baseurl, orgname, return_type = args
if not baseurl:
baseurl = 'https://www.misp-project.org'
real_orgname = args[1]
orgname = re.sub('[\W]+', '', orgname.replace(" ", "_"))
NS_DICT[baseurl] = orgname
try:
idgen.set_id_namespace(Namespace(baseurl, orgname))
except TypeError:
idgen.set_id_namespace(Namespace(baseurl, orgname, "MISP"))
stix_package = STIXPackage()
stix_header = STIXHeader()
stix_header.title="Export from {} MISP".format(real_orgname)
stix_header.package_intents="Threat Report"
stix_package.stix_header = stix_header
stix_package.version = "1.1.1"
stix_package.timestamp = datetime.datetime.now()
return stix_json_framing(stix_package) if return_type == 'json' else stix_xml_framing(stix_package, NS_DICT, SCHEMALOC_DICT)
def stix_json_framing(stix_package):
header = '{}, "related_packages": ['.format(stix_package.to_json()[:-1])
return header, ',', json_footer
def stix_xml_framing(stix_package, ns, schema):
s_stix_package = "</stix:STIX_Package>\n"
s_related_package = "stix:RelatedPackage"
header = stix_package.to_xml(auto_namespace=False, ns_dict=ns, schemaloc_dict=schema)
header = header.decode()
header = "{0} <{1}s>\n <{1}>\n".format(header, s_related_package).replace(s_stix_package, "")
footer = " </{0}>\n </{0}s>\n{1}".format(s_related_package, s_stix_package)
separator = " </{0}>\n <{0}>\n".format(s_related_package)
return header, separator, footer
def stix2_framing(*args):
return '{"type": "bundle", "spec_version": "2.0", "id": "bundle--%s", "objects": [' % args[0], ',', json_footer
framing_mapping = {'stix': stix_framing, 'stix2': stix2_framing}
def main(args):
framing_type = args[1]
n = n_args[framing_type]
if len(args) < n:
sys.exit("Invalid parameters")
args = args[2:]
values_to_return = framing_mapping[framing_type](*args)
print(json.dumps({keys: values for keys, values in zip(keys_to_return, values_to_return)}))
if __name__ == "__main__":
main(sys.argv)

View File

@ -46,19 +46,21 @@ class StixBuilder():
self.external_refs = []
self.galaxies = []
self.relationships = defaultdict(list)
self.to_return = {}
def loadEvent(self, args):
pathname = os.path.dirname(args[0])
filename = os.path.join(pathname, args[1])
self.orgs = [org for org in args[2:]] if len(args) > 2 else []
self.misp_event.load_file(filename)
self.filename = filename
self.report_id = "report--{}".format(self.misp_event.uuid)
def buildEvent(self):
self.__set_identity()
i = self.__set_identity()
self.read_attributes()
report = self.eventReport()
self.SDOs.insert(1, report)
self.SDOs.insert(i, report)
def eventReport(self):
report_args = {'type': 'report', 'id': self.report_id, 'name': self.misp_event.info,
@ -82,14 +84,21 @@ class StixBuilder():
outputfile = "{}.out".format(self.filename)
with open(outputfile, 'w') as f:
f.write(json.dumps(self.SDOs, cls=base.STIXJSONEncoder))
self.to_return['success'] = 1
print(json.dumps(self.to_return))
def __set_identity(self):
org = self.misp_event.Orgc
identity_id = 'identity--{}'.format(org['uuid'])
identity = Identity(type="identity", id=identity_id,
name=org["name"], identity_class="organization")
self.SDOs.append(identity)
org_uuid = org['uuid']
identity_id = 'identity--{}'.format(org_uuid)
self.identity_id = identity_id
if org_uuid not in self.orgs:
identity = Identity(type="identity", id=identity_id,
name=org["name"], identity_class="organization")
self.SDOs.append(identity)
self.to_return['org'] = org_uuid
return 1
return 0
def misp_types(self):
describe_types_filename = os.path.join(pymisp.__path__[0], 'data/describeTypes.json')
@ -532,7 +541,7 @@ class StixBuilder():
class Custom(object):
def __init__(self, **kwargs):
return
custom_object = Custom(**custom_object_args, )
custom_object = Custom(**custom_object_args)
self.append_object(custom_object, custom_object_id)
def add_object_indicator(self, misp_object, pattern_arg=None):
@ -1203,7 +1212,6 @@ def main(args):
stix_builder.loadEvent(args)
stix_builder.buildEvent()
stix_builder.saveFile()
print(1)
if __name__ == "__main__":
main(sys.argv)

@ -1 +1 @@
Subproject commit 7f36c65c549c456e902413d266c93917a4d6b8d9
Subproject commit f67d13ae654e19065e98a9810098aed1c48bffe1

1
app/tmp/cache/ingest/empty vendored Normal file
View File

@ -0,0 +1 @@