Merge pull request #6344 from JakubOnderka/misp-file-import

Misp file import error message
pull/6350/head
Jakub Onderka 2020-09-26 19:34:55 +02:00 committed by GitHub
commit 03b5af1f78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 76 deletions

View File

@ -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.<eventId>.ioc for individual events

View File

@ -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 . ')');
}
}
}

View File

@ -1,5 +1,6 @@
<?php
App::uses('AppModel', 'Model');
class EventBlocklist extends AppModel
{
public $useTable = 'event_blocklists';
@ -38,13 +39,25 @@ class EventBlocklist extends AppModel
if (!isset($schema['event_info'])) {
$this->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);
}
}

View File

@ -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;
}
}