diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 94fb44dd2..4069d4c34 100644 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -2045,11 +2045,19 @@ class EventsController extends AppController throw new MethodNotAllowedException(__('File upload failed or file does not have the expected extension (.xml / .json).')); } if (isset($this->data['Event']['submittedfile'])) { - if (Configure::read('MISP.take_ownership_xml_import') - && (isset($this->data['Event']['takeownership']) && $this->data['Event']['takeownership'] == 1)) { - $results = $this->_addMISPExportFile($ext, true, $this->data['Event']['publish']); - } else { - $results = $this->_addMISPExportFile($ext, false, $this->data['Event']['publish']); + $isXml = strtolower($ext) === 'xml'; + App::uses('FileAccessTool', 'Tools'); + $data = (new FileAccessTool())->readFromFile($this->data['Event']['submittedfile']['tmp_name'], $this->data['Event']['submittedfile']['size']); + $takeOwnership = Configure::read('MISP.take_ownership_xml_import') + && (isset($this->data['Event']['takeownership']) && $this->data['Event']['takeownership'] == 1); + + try { + $results = $this->Event->addMISPExportFile($this->Auth->user(), $data, $isXml, $takeOwnership, $this->data['Event']['publish']); + } catch (Exception $e) { + $filename = $this->data['Event']['submittedfile']['name']; + $this->log("Exception during processing MISP file import '$filename': {$e->getMessage()}"); + $this->Flash->error(__('Could not process MISP export file. Probably file content is invalid.')); + $this->redirect(['controller' => 'events', 'action' => 'add_misp_export']); } } } @@ -3120,66 +3128,6 @@ class EventsController extends AppController } } - private function _addMISPExportFile($ext, $take_ownership = false, $publish = false) - { - App::uses('FileAccessTool', 'Tools'); - $data = (new FileAccessTool())->readFromFile($this->data['Event']['submittedfile']['tmp_name'], $this->data['Event']['submittedfile']['size']); - - if ($ext == 'xml') { - App::uses('Xml', 'Utility'); - $dataArray = Xml::toArray(Xml::build($data)); - } else { - $dataArray = json_decode($data, true); - if (isset($dataArray['response'][0])) { - foreach ($dataArray['response'] as $k => $temp) { - $dataArray['Event'][] = $temp['Event']; - unset($dataArray['response'][$k]); - } - } - } - // In case we receive an event that is not encapsulated in a response. This should never happen (unless it's a copy+paste fail), - // but just in case, let's clean it up anyway. - if (isset($dataArray['Event'])) { - $dataArray['response']['Event'] = $dataArray['Event']; - unset($dataArray['Event']); - } - if (!isset($dataArray['response']) || !isset($dataArray['response']['Event'])) { - throw new Exception(__('This is not a valid MISP XML file.')); - } - $dataArray = $this->Event->updateXMLArray($dataArray); - $results = array(); - $validationIssues = array(); - if (isset($dataArray['response']['Event'][0])) { - foreach ($dataArray['response']['Event'] as $k => $event) { - $result = array('info' => $event['info']); - if ($take_ownership) { - $event['orgc_id'] = $this->Auth->user('org_id'); - unset($event['Orgc']); - } - $event = array('Event' => $event); - $created_id = 0; - $event['Event']['locked'] = 1; - $event['Event']['published'] = $publish; - $result['result'] = $this->Event->_add($event, true, $this->Auth->user(), '', null, false, null, $created_id, $validationIssues); - $result['id'] = $created_id; - $result['validationIssues'] = $validationIssues; - $results[] = $result; - } - } else { - $temp['Event'] = $dataArray['response']['Event']; - if ($take_ownership) { - $temp['Event']['orgc_id'] = $this->Auth->user('org_id'); - unset($temp['Event']['Orgc']); - } - $created_id = 0; - $temp['Event']['locked'] = 1; - $temp['Event']['published'] = $publish; - $result = $this->Event->_add($temp, true, $this->Auth->user(), '', null, false, null, $created_id, $validationIssues); - $results = array(0 => array('info' => $temp['Event']['info'], 'result' => $result, 'id' => $created_id, 'validationIssues' => $validationIssues)); - } - return $results; - } - public function downloadOpenIOCEvent($key, $eventid, $enforceWarninglist = false) { // return a downloadable text file called misp.openIOC..ioc for individual events diff --git a/app/Model/Event.php b/app/Model/Event.php index f29ac689b..cc6332e79 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -3522,6 +3522,82 @@ class Event extends AppModel return true; } + /** + * @param array $user + * @param string $data + * @param bool $isXml + * @param bool $takeOwnership + * @param bool $publish + * @return array[] + * @throws Exception + */ + public function addMISPExportFile(array $user, $data, $isXml = false, $takeOwnership = false, $publish = false) + { + if (empty($data)) { + throw new Exception("File is empty"); + } + + if ($isXml) { + App::uses('Xml', 'Utility'); + $dataArray = Xml::toArray(Xml::build($data)); + } else { + $dataArray = $this->jsonDecode($data); + if (isset($dataArray['response'][0])) { + foreach ($dataArray['response'] as $k => $temp) { + $dataArray['Event'][] = $temp['Event']; + unset($dataArray['response'][$k]); + } + } + } + // In case we receive an event that is not encapsulated in a response. This should never happen (unless it's a copy+paste fail), + // but just in case, let's clean it up anyway. + if (isset($dataArray['Event'])) { + $dataArray['response']['Event'] = $dataArray['Event']; + unset($dataArray['Event']); + } + if (!isset($dataArray['response']) || !isset($dataArray['response']['Event'])) { + $exception = $isXml ? __('This is not a valid MISP XML file.') : __('This is not a valid MISP JSON file.'); + throw new Exception($exception); + } + $dataArray = $this->updateXMLArray($dataArray); + $results = array(); + $validationIssues = array(); + if (isset($dataArray['response']['Event'][0])) { + foreach ($dataArray['response']['Event'] as $event) { + $result = array('info' => $event['info']); + if ($takeOwnership) { + $event['orgc_id'] = $user['org_id']; + unset($event['Orgc']); + } + $event = array('Event' => $event); + $created_id = 0; + $event['Event']['locked'] = 1; + $event['Event']['published'] = $publish; + $result['result'] = $this->_add($event, true, $user, '', null, false, null, $created_id, $validationIssues); + $result['id'] = $created_id; + $result['validationIssues'] = $validationIssues; + $results[] = $result; + } + } else { + $temp['Event'] = $dataArray['response']['Event']; + if ($takeOwnership) { + $temp['Event']['orgc_id'] = $user['org_id']; + unset($temp['Event']['Orgc']); + } + $created_id = 0; + $temp['Event']['locked'] = 1; + $temp['Event']['published'] = $publish; + $result = $this->_add($temp, true, $user, '', null, false, null, $created_id, $validationIssues); + $results = array(array( + 'info' => $temp['Event']['info'], + 'result' => $result, + 'id' => $created_id, + 'validationIssues' => $validationIssues, + )); + } + return $results; + } + // Low level function to add an Event based on an Event $data array public function _add(array &$data, $fromXml, array $user, $org_id = 0, $passAlong = null, $fromPull = false, $jobId = null, &$created_id = 0, &$validationErrors = array()) { @@ -3530,16 +3606,19 @@ class Event extends AppModel } if (Configure::read('MISP.enableEventBlocklisting') !== false && isset($data['Event']['uuid'])) { $this->EventBlocklist = ClassRegistry::init('EventBlocklist'); - $r = $this->EventBlocklist->find('first', array('conditions' => array('event_uuid' => $data['Event']['uuid']))); - if (!empty($r)) { + if ($this->EventBlocklist->isBlocked($data['Event']['uuid'])) { return 'Blocked by blocklist'; } } if (!$this->checkEventBlockRules($data)) { return 'Blocked by event block rules'; } + + if (!isset($this->Log)) { + $this->Log = ClassRegistry::init('Log'); // initialize Log class if not + } + if (empty($data['Event']['Attribute']) && empty($data['Event']['Object']) && !empty($data['Event']['published'])) { - $this->Log = ClassRegistry::init('Log'); $this->Log->create(); $validationErrors['Event'] = 'Received a published event that was empty. Event add process blocked.'; $this->Log->save(array( @@ -3654,7 +3733,6 @@ class Event extends AppModel } } if (!empty($failedCapture)) { - $this->Log = ClassRegistry::init('Log'); $this->Log->create(); $this->Log->save(array( 'org' => $user['Organisation']['name'], @@ -3705,7 +3783,6 @@ class Event extends AppModel 'ObjectRelation' => array() ); $saveResult = $this->save(array('Event' => $data['Event']), array('fieldList' => $fieldList['Event'])); - $this->Log = ClassRegistry::init('Log'); if ($saveResult) { if ($passAlong) { if ($server['Server']['publish_without_email'] == 0) { @@ -3823,8 +3900,7 @@ class Event extends AppModel if (empty($found)) { $this->EventTag->create(); if ($this->EventTag->save(array('event_id' => $this->id, 'tag_id' => $tag_id))) { - $log = ClassRegistry::init('Log'); - $log->createLogEntry($user, 'tag', 'Event', $this->id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to event (' . $this->id . ')', 'Event (' . $this->id . ') tagged as Tag (' . $tag_id . ')'); + $this->Log->createLogEntry($user, 'tag', 'Event', $this->id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to event (' . $this->id . ')', 'Event (' . $this->id . ') tagged as Tag (' . $tag_id . ')'); } } } diff --git a/app/Model/EventBlocklist.php b/app/Model/EventBlocklist.php index 401eb0fdc..15f33da3e 100644 --- a/app/Model/EventBlocklist.php +++ b/app/Model/EventBlocklist.php @@ -1,5 +1,6 @@ updateDatabase('addEventBlocklistsContext'); } - $date = date('Y-m-d H:i:s'); if (empty($this->data['EventBlocklist']['id'])) { - $this->data['EventBlocklist']['date_created'] = $date; + $this->data['EventBlocklist']['date_created'] = date('Y-m-d H:i:s'); } if (empty($this->data['EventBlocklist']['comment'])) { $this->data['EventBlocklist']['comment'] = ''; } return true; } + + /** + * @param string $eventUuid + * @return bool + */ + public function isBlocked($eventUuid) + { + $result = $this->find('first', [ + 'conditions' => ['event_uuid' => $eventUuid], + 'fields' => ['id'] + ]); + return !empty($result); + } } diff --git a/app/Model/Server.php b/app/Model/Server.php index 66a0a7f69..8ca65efc1 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -2464,8 +2464,7 @@ class Server extends AppModel { if (Configure::read('MISP.enableEventBlocklisting') !== false) { $this->EventBlocklist = ClassRegistry::init('EventBlocklist'); - $r = $this->EventBlocklist->find('first', array('conditions' => array('event_uuid' => $event['Event']['uuid']))); - if (!empty($r)) { + if ($this->EventBlocklist->isBlocked($event['Event']['uuid'])) { return true; } }