diff --git a/INSTALL/MYSQL.sql b/INSTALL/MYSQL.sql index 738866c56..1449b0bd3 100644 --- a/INSTALL/MYSQL.sql +++ b/INSTALL/MYSQL.sql @@ -294,34 +294,36 @@ CREATE TABLE IF NOT EXISTS `whitelist` ( -- Default values for initial installation -- -INSERT INTO `regexp` - (`regexp`, `replacement`) -VALUES - ('/.:.ProgramData./i','%ALLUSERSPROFILE%\\\\'), - ('/.:.Documents and Settings.All Users./i','%ALLUSERSPROFILE%\\\\'), - ('/.:.Program Files.Common Files./i','%COMMONPROGRAMFILES%\\\\'), - ('/.:.Program Files \(x86\).Common Files./i','%COMMONPROGRAMFILES(x86)%\\\\'), - ('/.:.Users.(\\w+).AppData.Local.Temp./i','%TEMP%\\\\'), - ('/.:.ProgramData./i','%PROGRAMDATA%\\\\'), - ('/.:.Program Files./i','%PROGRAMFILES%\\\\'), - ('/.:.Program Files \(x86\)./i','%PROGRAMFILES(X86)%\\\\'), - ('/.:.Users.Public./i','%PUBLIC%\\\\'), - ('/.:.Documents and Settings.(\\w+).Local Settings.Temp./i','%TEMP%\\\\'), - ('/.:.Users.(\\w+).AppData.Local.Temp./i','%TEMP%\\\\'), - ('/.:.Users.(\\w+).AppData.Local./i','%LOCALAPPDATA%\\\\'), - ('/.:.Users.(\\w+).AppData.Roaming./i','%APPDATA%\\\\'), - ('/.:.Users.(\\w+).Application Data./i','%APPDATA%\\\\'), - ('/.:.Windows.(\\w+).Application Data./i','%APPDATA%\\\\'), - ('/.:.Users.(\\w+)./i','%USERPROFILE%\\\\'), - ('/.:.DOCUME~1.(\\w+)./i','%USERPROFILE%\\\\'), - ('/.:.Documents and Settings.(\\w+)./i','%USERPROFILE%\\\\'), - ('/.:.Windows./i','%WINDIR%\\\\'), - ('/.:.Windows./i','%WINDIR%\\\\'), - ('/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{9}){1}(-[0-9]{10}){1}-[0-9]{9}-[0-9]{4}/i','HKCU'), - ('/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{10}){2}-[0-9]{9}-[0-9]{4}/i','HKCU'), - ('/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{10}){3}-[0-9]{4}/i','HKCU'), - ('/.REGISTRY.MACHINE./i','HKLM\\\\'), - ('/.Registry.Machine./i','HKLM\\\\'); +INSERT INTO `regexp` (`id`, `regexp`, `replacement`, `type`) VALUES +(1, '/.:.ProgramData./i', '%ALLUSERSPROFILE%\\\\', 'ALL'), +(2, '/.:.Documents and Settings.All Users./i', '%ALLUSERSPROFILE%\\\\', 'ALL'), +(3, '/.:.Program Files.Common Files./i', '%COMMONPROGRAMFILES%\\\\', 'ALL'), +(4, '/.:.Program Files (x86).Common Files./i', '%COMMONPROGRAMFILES(x86)%\\\\', 'ALL'), +(5, '/.:.Users\\\\(.*?)\\\\AppData.Local.Temp./i', '%TEMP%\\\\', 'ALL'), +(6, '/.:.ProgramData./i', '%PROGRAMDATA%\\\\', 'ALL'), +(7, '/.:.Program Files./i', '%PROGRAMFILES%\\\\', 'ALL'), +(8, '/.:.Program Files (x86)./i', '%PROGRAMFILES(X86)%\\\\', 'ALL'), +(9, '/.:.Users.Public./i', '%PUBLIC%\\\\', 'ALL'), +(10, '/.:.Documents and Settings\\\\(.*?)\\\\Local Settings.Temp./i', '%TEMP%\\\\', 'ALL'), +(11, '/.:.Users\\\\(.*?)\\\\AppData.Local.Temp./i', '%TEMP%\\\\', 'ALL'), +(12, '/.:.Users\\\\(.*?)\\\\AppData.Local./i', '%LOCALAPPDATA%\\\\', 'ALL'), +(13, '/.:.Users\\\\(.*?)\\\\AppData.Roaming./i', '%APPDATA%\\\\', 'ALL'), +(14, '/.:.Users\\\\(.*?)\\\\Application Data./i', '%APPDATA%\\\\', 'ALL'), +(15, '/.:.Windows\\\\(.*?)\\\\Application Data./i', '%APPDATA%\\\\', 'ALL'), +(16, '/.:.Users\\\\(.*?)\\\\/i', '%USERPROFILE%\\\\', 'ALL'), +(17, '/.:.DOCUME~1.\\\\(.*?)\\\\/i', '%USERPROFILE%\\\\', 'ALL'), +(18, '/.:.Documents and Settings\\\\(.*?)\\\\/i', '%USERPROFILE%\\\\', 'ALL'), +(19, '/.:.Windows./i', '%WINDIR%\\\\', 'ALL'), +(20, '/.:.Windows./i', '%WINDIR%\\\\', 'ALL'), +(21, '/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{9}){1}(-[0-9]{10}){1}-[0-9]{9}-[0-9]{4}/i', 'HKCU', 'ALL'), +(22, '/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{10}){2}-[0-9]{9}-[0-9]{4}/i', 'HKCU', 'ALL'), +(23, '/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{10}){3}-[0-9]{4}/i', 'HKCU', 'ALL'), +(24, '/.REGISTRY.MACHINE./i', 'HKLM\\\\', 'ALL'), +(25, '/.Registry.Machine./i', 'HKLM\\\\', 'ALL'), +(26, '/%USERPROFILE%.Application Data.Microsoft.UProof/i', '', 'ALL'), +(27, '/%USERPROFILE%.Local Settings.History/i', '', 'ALL'), +(28, '/%APPDATA%.Microsoft.UProof/i ', '', 'ALL'), +(29, '/%LOCALAPPDATA%.Microsoft.Windows.Temporary Internet Files/i', '', 'ALL'); -- -------------------------------------------------------- @@ -360,4 +362,5 @@ VALUES (3,'Low','*low* means mass-malware','Mass-malware'), (4,'Undefined','*undefined* no risk','No risk'); --- -------------------------------------------------------- \ No newline at end of file +-- -------------------------------------------------------- + diff --git a/app/Controller/AttributesController.php b/app/Controller/AttributesController.php index 4baddbb8e..c5725a809 100755 --- a/app/Controller/AttributesController.php +++ b/app/Controller/AttributesController.php @@ -594,7 +594,7 @@ class AttributesController extends AppController { else $attribute['type'] = 'comment'; $attribute['value'] = $reference; - $attribute['distribution'] = 3; // 'All communities' + $attribute['distribution'] = '3'; // 'All communities' // add attribute to the array that will be saved $attributes[] = $attribute; } diff --git a/app/Controller/Component/IOCExportComponent.php b/app/Controller/Component/IOCExportComponent.php index 32de1f915..e1b09a329 100644 --- a/app/Controller/Component/IOCExportComponent.php +++ b/app/Controller/Component/IOCExportComponent.php @@ -7,8 +7,10 @@ class IOCExportComponent extends Component { public function buildAll($event, $isSiteAdmin, $isMyEvent) { $temp = array(); if (!$isSiteAdmin) { - if ($event['Event']['distribution'] == 1 && !$isMyEvent && !isSiteAdmin) { + if (!$isMyEvent) { + if ($event['Event']['distribution'] == 0) { throw new Exception('Nothing to see here (not authorised)'); + } } } $this->__buildTop($event); diff --git a/app/Controller/Component/NidsExportComponent.php b/app/Controller/Component/NidsExportComponent.php index 967cda5f2..4f881b57b 100755 --- a/app/Controller/Component/NidsExportComponent.php +++ b/app/Controller/Component/NidsExportComponent.php @@ -492,7 +492,7 @@ class NidsExportComponent extends Component { public function checkWhitelist($value) { foreach ($this->whitelist as $wlitem) { - if (preg_match($wlitem, $value)) { + if (preg_match("/".$wlitem."/", $value)) { return true; } } diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index 838f9a213..e1cb89a16 100755 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -1,6 +1,7 @@ 60, 'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page. 'order' => array( - 'Event.timestamp' => 'DESC' + 'Event.id' => 'DESC' ), ); @@ -45,7 +45,6 @@ class EventsController extends AppController { $this->Auth->allow('hids_sha1'); $this->Auth->allow('text'); $this->Auth->allow('dot'); - $this->Auth->allow('restSearch'); // TODO Audit, activate logable in a Controller if (count($this->uses) && $this->{$this->modelClass}->Behaviors->attached('SysLogLogable')) { @@ -150,11 +149,6 @@ class EventsController extends AppController { } } } - $this->paginate = array('contain' => array( - 'ThreatLevel' => array( - 'fields' => array( - 'ThreatLevel.name')) - )); $this->set('events', $this->paginate()); if (!$this->Auth->user('gpgkey')) { $this->Session->setFlash(__('No GPG key set in your profile. To receive emails, submit your public key in your profile.')); @@ -253,54 +247,6 @@ class EventsController extends AppController { $this->set('pivot', $pivot); $this->set('currentEvent', $id); } - $this->set('allPivots', $this->Session->read('pivot_thread')); - // Show the discussion - $this->loadModel('Thread'); - $params = array('conditions' => array('event_id' => $id), - 'recursive' => -1, - 'fields' => array('id', 'event_id', 'distribution', 'title') - ); - $thread = $this->Thread->find('first', $params); - if (empty($thread)) { - $newThread = array( - 'date_created' => date('Y/m/d H:i:s'), - 'date_modified' => date('Y/m/d H:i:s'), - 'user_id' => $this->Auth->user('id'), - 'event_id' => $id, - 'title' => 'Discussion about Event #' . $result['Event']['id'] . ' (' . $result['Event']['info'] . ')', - 'distribution' => $result['Event']['distribution'], - 'post_count' => 0, - 'org' => $result['Event']['orgc'] - ); - $this->Thread->save($newThread); - $thread = ($this->Thread->read()); - } else { - if ($thread['Thread']['distribution'] != $result['Event']['distribution']) { - $this->Thread->saveField('distribution', $result['Event']['distribution']); - } - } - $this->loadModel('Post'); - $this->paginate['Post'] = array( - 'limit' => 5, - 'conditions' => array('Post.thread_id' => $thread['Thread']['id']), - 'contain' => 'User' - ); - $posts = $this->paginate('Post'); - // Show the discussion - $this->set('posts', $posts); - $this->set('thread_id', $thread['Thread']['id']); - $this->set('myuserid', $this->Auth->user('id')); - $this->set('thread_title', $thread['Thread']['title']); - if ($this->request->is('ajax')) { - $this->disableCache(); - $this->layout = 'ajax'; - $this->render('/Elements/eventdiscussion'); - } - $pivot = $this->Session->read('pivot_thread'); - $this->__arrangePivotVertical($pivot); - $this->__setDeletable($pivot, $id, true); - $this->set('pivot', $pivot); - $this->set('currentEvent', $id); } private function __startPivoting($id, $info, $date){ @@ -317,7 +263,7 @@ class EventsController extends AppController { } $this->Session->write('pivot_thread', $pivot); } - + private function __insertPivot($pivot, $oldId, $newPivot, $depth) { $depth++; if ($pivot['id'] == $oldId) { @@ -330,7 +276,7 @@ class EventsController extends AppController { } return $pivot; } - + private function __checkForPivot($pivot, $id) { if ($id == $pivot['id']) return true; foreach ($pivot['children'] as $k => $v) { @@ -340,7 +286,7 @@ class EventsController extends AppController { } return false; } - + private function __arrangePivotVertical(&$pivot) { if (empty($pivot)) return null; $max = count($pivot['children']) - 1; @@ -354,7 +300,7 @@ class EventsController extends AppController { } return $temp; } - + public function removePivot($id, $eventId, $self = false) { $pivot = $this->Session->read('pivot_thread'); if ($pivot['id'] == $id) { @@ -368,7 +314,7 @@ class EventsController extends AppController { $pivot = $this->__arrangePivotVertical($pivot); $this->redirect(array('controller' => 'events', 'action' => 'view', $eventId, true, $eventId)); } - + private function __removeChildren(&$pivot, $id) { if ($pivot['id'] == $id) { $pivot['children'] = array(); @@ -378,7 +324,7 @@ class EventsController extends AppController { } } } - + private function __doRemove(&$pivot, $id) { foreach ($pivot['children'] as $k => $v) { if ($v['id'] == $id) { @@ -390,7 +336,7 @@ class EventsController extends AppController { } return $pivot; } - + private function __setDeletable(&$pivot, $id, $root=false) { if ($pivot['id'] == $id && !$root) { $pivot['deletable'] = false; @@ -403,7 +349,123 @@ class EventsController extends AppController { } return !$pivot['deletable']; } + + /* + public function view($id = null) { + // If the length of the id provided is 36 then it is most likely a Uuid - find the id of the event, change $id to it and proceed to read the event as if the ID was entered. + $perm_publish = $this->userRole['perm_publish']; + if (strlen($id) == 36) { + $this->Event->recursive = -1; + $temp = $this->Event->findByUuid($id); + if ($temp == null) throw new NotFoundException(__('Invalid event')); + $id = $temp['Event']['id']; + } + $isSiteAdmin = $this->_isSiteAdmin(); + $this->Event->id = $id; + if(!$this->Event->exists()) { + throw new NotFoundException(__('Invalid event, it already exists.')); + } + + $this->Event->recursive = 2; + $this->Event->contain('Attribute', 'ShadowAttribute', 'User.email'); + $this->Event->read(); + $myEvent = true; + if (!$isSiteAdmin) { + // check private + if (($this->Event->data['Event']['distribution'] == 0) && ($this->Event->data['Event']['org'] != $this->Auth->user('org'))) { + $this->Session->setFlash(__('Invalid event.')); + $this->redirect(array('controller' => 'events', 'action' => 'index')); + } + } + if ($this->Event->data['Event']['org'] != $this->Auth->user('org')) { + $myEvent = false; + } + + // Now that we're loaded the event and made sure that we can actually see it, let's do 2 thngs: + // run through each attribute and unset it if it's private and we're not an admin or from the owner org of the event + // if we didn't unset the attribute, rearrange the shadow attributes + foreach ($this->Event->data['Attribute'] as $key => &$attribute) { + if (!$isSiteAdmin && !$myEvent && ($attribute['distribution'] == 0)) { + unset($this->Event->data['Attribute'][$key]); + } else { + if (!isset($attribute['ShadowAttribute'])) $attribute['ShadowAttribute'] = array(); + foreach ($this->Event->data['ShadowAttribute'] as $k => &$sa) { + if ($sa['old_id'] == $attribute['id']) { + $this->Event->data['Attribute'][$key]['ShadowAttribute'][] = $sa; + unset($this->Event->data['ShadowAttribute'][$k]); + } + } + } + } + // since we unset some attributes and shadowattributes, let's reindex them. + $this->Event->data['ShadowAttribute'] = array_values($this->Event->data['ShadowAttribute']); + $this->Event->data['Attribute'] = array_values($this->Event->data['Attribute']); + + $this->set('analysisLevels', $this->Event->analysisLevels); + + $relatedEvents = $this->Event->getRelatedEvents($this->Auth->user()); + $relatedAttributes = $this->Event->getRelatedAttributes($this->Auth->user()); + $this->loadModel('Attribute'); + if ($this->_isRest()) { + foreach ($this->Event->data['Attribute'] as &$attribute) { + // for REST requests also add the encoded attachment + if ($this->Attribute->typeIsAttachment($attribute['type'])) { + // LATER check if this has a serious performance impact on XML conversion and memory usage + $encodedFile = $this->Attribute->base64EncodeAttachment($attribute); + $attribute['data'] = $encodedFile; + } + } + } + // set up the ShadowAttributes for the view - the only shadow attributes that should be passed to the view are the ones that the user is eligible to see + // This means: Proposals of other organisations to own events, if the user is a publisher + // Also: proposals made by the current user's organisation + if (!$this->_isRest()) { + foreach ($this->Event->data['Attribute'] as &$attribute) { + // if the user is of the same org as the event and has publishing rights, just show everything + if (($this->Auth->user('org') != $this->Event->data['Event']['org'] || !$perm_publish) && !$this->_isSiteAdmin()) { + $counter = 0; + foreach ($attribute['ShadowAttribute'] as &$shadow) { + if ($shadow['org'] != $this->Auth->user('org')) unset($attribute['ShadowAttribute'][$counter]); + $counter++; + } + } + } + } + // params for the jQuery RESTfull interface + $this->set('authkey', $this->Auth->user('authkey')); + $this->set('baseurl', Configure::read('CyDefSIG.baseurl')); + + $this->set('relatedAttributes', $relatedAttributes); + // passing decriptions for model fields + $this->set('eventDescriptions', $this->Event->fieldDescriptions); + $this->set('attrDescriptions', $this->Attribute->fieldDescriptions); + $this->set('event', $this->Event->data); + if(isset($this->Event->data['ShadowAttribute'])) { + $this->set('remaining', $this->Event->data['ShadowAttribute']); + } + $this->set('relatedEvents', $relatedEvents); + + $this->set('categories', $this->Attribute->validate['category']['rule'][1]); + + // passing type and category definitions (explanations) + $this->set('typeDefinitions', $this->Attribute->typeDefinitions); + $this->set('categoryDefinitions', $this->Attribute->categoryDefinitions); + + // combobox for analysis + $this->set('distributionDescriptions', $this->Event->distributionDescriptions); + $this->set('distributionLevels', $this->Event->distributionLevels); + + // combobox for analysis + $analysiss = $this->Event->validate['analysis']['rule'][1]; + $analysiss = $this->_arrayToValuesIndexArray($analysiss); + $this->set('analysiss', $analysiss); + // tooltip for analysis + $this->set('analysisDescriptions', $this->Event->analysisDescriptions); + $this->set('analysisLevels', $this->Event->analysisLevels); + } + + */ /** * add method @@ -468,9 +530,11 @@ class EventsController extends AppController { $this->set('distributionLevels', $this->Event->distributionLevels); // combobox for risks - $threat_levels = $this->Event->ThreatLevel->find('all'); - $this->set('threatLevels', Set::combine($threat_levels, '{n}.ThreatLevel.id', '{n}.ThreatLevel.name')); - $this->set('riskDescriptions', Set::combine($threat_levels, '{n}.ThreatLevel.id', '{n}.ThreatLevel.form_description')); + $risks = $this->Event->validate['risk']['rule'][1]; + $risks = $this->_arrayToValuesIndexArray($risks); + $this->set('risks',$risks); + // tooltip for risk + $this->set('riskDescriptions', $this->Event->riskDescriptions); // combobox for analysis $analysiss = $this->Event->validate['analysis']['rule'][1]; @@ -512,42 +576,38 @@ class EventsController extends AppController { } } } + // combobox for distribution + $distributions = array_keys($this->Event->distributionDescriptions); + $distributions = $this->_arrayToValuesIndexArray($distributions); + $this->set('distributions', $distributions); + // tooltip for distribution + $this->set('distributionDescriptions', $this->Event->distributionDescriptions); + $this->set('distributionLevels', $this->Event->distributionLevels); + + // combobox for risks + $risks = $this->Event->validate['risk']['rule'][1]; + $risks = $this->_arrayToValuesIndexArray($risks); + $this->set('risks',$risks); + // set the id $this->set('id', $id); // set whether it is published or not $this->set('published', $this->Event->data['Event']['published']); + + // tooltip for risk + $this->set('riskDescriptions', $this->Event->riskDescriptions); + + // combobox for analysis + $analysiss = $this->Event->validate['analysis']['rule'][1]; + $analysiss = $this->_arrayToValuesIndexArray($analysiss); + $this->set('analysiss',$analysiss); + // tooltip for analysis + $this->set('analysisDescriptions', $this->Event->analysisDescriptions); + $this->set('analysisLevels', $this->Event->analysisLevels); + + $this->set('eventDescriptions', $this->Event->fieldDescriptions); } - public function add_xml() { - if (!$this->userRole['perm_modify']) { - throw new UnauthorizedException('You do not have permission to do that.'); - } - if ($this->request->is('post')) { - if (!empty($this->data)) { - $ext = ''; - if (isset($this->data['Event']['submittedxml'])) { - App::uses('File', 'Utility'); - $file = new File($this->data['Event']['submittedxml']['name']); - $ext = $file->ext(); - } - if (isset($this->data['Event']['submittedxml']) && ($ext != 'xml') && $this->data['Event']['submittedxml']['size'] > 0 && - is_uploaded_file($this->data['Event']['submittedxml']['tmp_name'])) { - $this->Session->setFlash(__('You may only upload OpenIOC ioc files.')); - } - if (isset($this->data['Event']['submittedxml'])) $this->_addXMLFile(); - - // redirect to the view of the newly created event - if (!CakeSession::read('Message.flash')) { - $this->Session->setFlash(__('The event has been saved')); - } else { - $existingFlash = CakeSession::read('Message.flash'); - $this->Session->setFlash(__('The event has been saved. ' . $existingFlash['message'])); - } - } - } - } - - /** * Low level function to add an Event based on an Event $data array * @@ -574,6 +634,7 @@ class EventsController extends AppController { unset($this->Event->Attribute->validate['event_id']); unset($this->Event->Attribute->validate['value']['unique']); // otherwise gives bugs because event_id is not set } + unset ($data['Event']['id']); if (isset($data['Event']['uuid'])) { // check if the uuid already exists @@ -594,12 +655,10 @@ class EventsController extends AppController { } // FIXME chri: validatebut the necessity for all these fields...impact on security ! $fieldList = array( - 'Event' => array('org', 'orgc', 'date', 'threat_level_id', 'analysis', 'info', 'user_id', 'published', 'uuid', 'timestamp', 'distribution', 'locked'), + 'Event' => array('org', 'orgc', 'date', 'risk', 'analysis', 'info', 'user_id', 'published', 'uuid', 'timestamp', 'distribution', 'locked'), 'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'timestamp', 'distribution') ); - - $saveResult = $this->Event->saveAssociated($data, array('validate' => true, 'fieldList' => $fieldList, - 'atomic' => true)); + $saveResult = $this->Event->saveAssociated($data, array('validate' => true, 'fieldList' => $fieldList)); // FIXME chri: check if output of $saveResult is what we expect when data not valid, see issue #104 if ($saveResult) { if (!empty($data['Event']['published']) && 1 == $data['Event']['published']) { @@ -628,7 +687,7 @@ class EventsController extends AppController { return 'Event originated on this instance, any changes to it have to be done locally.'; } $fieldList = array( - 'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'), + 'Event' => array('date', 'risk', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'), 'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp') ); $data['Event']['id'] = $this->Event->data['Event']['id']; @@ -684,6 +743,7 @@ class EventsController extends AppController { $this->redirect(array('controller' => 'events', 'action' => 'index')); } } + if ($this->request->is('post') || $this->request->is('put')) { if ($this->_isRest()) { $saveEvent = false; @@ -719,7 +779,7 @@ class EventsController extends AppController { } } $fieldList = array( - 'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'), + 'Event' => array('date', 'risk', 'analysis', 'info', 'published', 'uuid', 'from', 'distribution', 'timestamp'), 'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp') ); @@ -772,7 +832,7 @@ class EventsController extends AppController { } } // say what fields are to be updated - $fieldList = array('date', 'threat_level_id', 'analysis', 'info', 'published', 'distribution', 'timestamp'); + $fieldList = array('date', 'risk', 'analysis', 'info', 'published', 'distribution', 'timestamp'); $this->Event->read(); // always force the org, but do not force it for admins @@ -805,9 +865,12 @@ class EventsController extends AppController { $this->set('distributionLevels', $this->Event->distributionLevels); // combobox for types - $threat_levels = $this->Event->ThreatLevel->find('all'); - $this->set('threatLevels', Set::combine($threat_levels, '{n}.ThreatLevel.id', '{n}.ThreatLevel.name')); - $this->set('riskDescriptions', Set::combine($threat_levels, '{n}.ThreatLevel.id', '{n}.ThreatLevel.form_description')); + $risks = $this->Event->validate['risk']['rule'][1]; + $risks = $this->_arrayToValuesIndexArray($risks); + $this->set('risks',$risks); + + // tooltip for risk + $this->set('riskDescriptions', $this->Event->riskDescriptions); // combobox for analysis $analysiss = $this->Event->validate['analysis']['rule'][1]; @@ -819,8 +882,6 @@ class EventsController extends AppController { $this->set('analysisLevels', $this->Event->analysisLevels); $this->set('eventDescriptions', $this->Event->fieldDescriptions); - - $this->set('event', $this->Event->data); } /** @@ -1058,11 +1119,11 @@ class EventsController extends AppController { if ('true' == Configure::read('CyDefSIG.showorg')) { $body .= 'Reported by : ' . $event['Event']['org'] . "\n"; } - $body .= 'Risk : ' . $event['ThreatLevel']['name'] . "\n"; + $body .= 'Risk : ' . $event['Event']['risk'] . "\n"; $body .= 'Analysis : ' . $this->Event->analysisLevels[$event['Event']['analysis']] . "\n"; $body .= 'Info : ' . "\n"; $body .= $event['Event']['info'] . "\n"; - $relatedEvents = $this->Event->getRelatedEvents($this->Auth->user(), $this->_isSiteAdmin()); + $relatedEvents = $this->Event->getRelatedEvents($this->Auth->user()); if (!empty($relatedEvents)) { $body .= '----------------------------------------------' . "\n"; $body .= 'Related to : '. "\n"; @@ -1120,7 +1181,7 @@ class EventsController extends AppController { // prepare the the unencrypted email $this->Email->from = Configure::read('CyDefSIG.email'); $this->Email->to = $user['User']['email']; - $this->Email->subject = "[" . Configure::read('CyDefSIG.org') . " " . Configure::read('CyDefSIG.name') . "] Event " . $id . " - " . $event['ThreatLevel']['name'] . " - TLP Amber"; + $this->Email->subject = "[" . Configure::read('CyDefSIG.org') . " " . Configure::read('CyDefSIG.name') . "] Event " . $id . " - " . $event['Event']['risk'] . " - TLP Amber"; $this->Email->template = 'body'; $this->Email->sendAs = 'text'; // both text or html $this->set('body', $bodySigned); @@ -1149,7 +1210,7 @@ class EventsController extends AppController { // send the email $this->Email->from = Configure::read('CyDefSIG.email'); $this->Email->to = $user['User']['email']; - $this->Email->subject = "[" . Configure::read('CyDefSIG.org') . " " . Configure::read('CyDefSIG.name') . "] Event " . $id . " - " . $event['ThreatLevel']['name'] . " - TLP Amber"; + $this->Email->subject = "[" . Configure::read('CyDefSIG.org') . " " . Configure::read('CyDefSIG.name') . "] Event " . $id . " - " . $event['Event']['risk'] . " - TLP Amber"; $this->Email->template = 'body'; $this->Email->sendAs = 'text'; // both text or html @@ -1275,9 +1336,9 @@ class EventsController extends AppController { if ('true' == Configure::read('CyDefSIG.showorg')) { $body .= 'Reported by : ' . $event['Event']['org'] . "\n"; } - $body .= 'Risk : ' . $event['ThreatLevel']['name'] . "\n"; + $body .= 'Risk : ' . $event['Event']['risk'] . "\n"; $body .= 'Analysis : ' . $event['Event']['analysis'] . "\n"; - $relatedEvents = $this->Event->getRelatedEvents($this->Auth->user(), $this->_isSiteAdmin()); + $relatedEvents = $this->Event->getRelatedEvents($this->Auth->user()); if (!empty($relatedEvents)) { foreach ($relatedEvents as &$relatedEvent) { $body .= 'Related to : ' . Configure::read('CyDefSIG.baseurl') . '/events/view/' . $relatedEvent['Event']['id'] . ' (' . $relatedEvent['Event']['date'] . ')' . "\n"; @@ -1389,7 +1450,7 @@ class EventsController extends AppController { } - public function xml($key, $eventid=null, $withAttachment = false) { + public function xml($key, $eventid=null) { if ($key != 'download') { // check if the key is valid -> search for users based on key $user = $this->checkAuthUser($key); @@ -1414,15 +1475,6 @@ class EventsController extends AppController { } } $results = $this->__fetchEvent($eventid); - if ($withAttachment) { - $this->loadModel('Attribute'); - foreach ($results[0]['Attribute'] as &$attribute) { - if ($this->Attribute->typeIsAttachment($attribute['type'])) { - $encodedFile = $this->Attribute->base64EncodeAttachment($attribute); - $attribute['data'] = $encodedFile; - } - } - } // Whitelist check $this->loadModel('Whitelist'); $results = $this->Whitelist->removeWhitelistedFromArray($results, false); @@ -1431,7 +1483,7 @@ class EventsController extends AppController { // Grab an event or a list of events for the event view or any of the XML exports. The returned object includes an array of events (or an array that only includes a single event if an ID was given) // Included with the event are the attached attributes, shadow attributes, related events, related attribute information for the event view and the creating user's email address where appropriate - private function __fetchEvent($eventid = null, $idList = null, $orgFromFetch = null, $isSiteAdmin = false) { + private function __fetchEvent($eventid = null, $idList = null) { if (isset($eventid)) { $this->Event->id = $eventid; if (!$this->Event->exists()) { @@ -1441,20 +1493,11 @@ class EventsController extends AppController { } else { $conditions = array(); } - // if we come from automation, we may not be logged in - instead we used an auth key in the URL. - if (!empty($orgFromFetch)) { - $org = $orgFromFetch; - } else { - $org = $this->_checkOrg(); - $isSiteAdmin = $this->_isSiteAdmin(); - } - $conditionsAttributes = array(); $conditionsShadowAttributes = array(); //restricting to non-private or same org if the user is not a site-admin. - if (!$isSiteAdmin) { - if (!empty($orgFromFetch)) $org = $orgFromFetch; - else $org = $this->_checkOrg(); + if (!$this->_isSiteAdmin()) { + $org = $this->_checkOrg(); $conditions['AND']['OR'] = array( 'Event.distribution >' => 0, 'Event.org LIKE' => $org @@ -1470,8 +1513,10 @@ class EventsController extends AppController { array('(SELECT events.org FROM events WHERE events.id = ShadowAttribute.event_id) LIKE' => $org), array('ShadowAttribute.org LIKE' => $org), ); - } + + } + if ($idList) { $conditions['AND'][] = array('Event.id' => $idList); } @@ -1482,17 +1527,14 @@ class EventsController extends AppController { // $conditions['AND'][] = array('Event.published =' => 1); // do not expose all the data ... - $fields = array('Event.id', 'Event.org', 'Event.date','Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.orgc', 'Event.user_id', 'Event.locked'); - $fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp', 'Attribute.comment'); + $fields = array('Event.id', 'Event.org', 'Event.date', 'Event.risk', 'Event.info', 'Event.published', 'Event.uuid', 'Event.attribute_count', 'Event.analysis', 'Event.timestamp', 'Event.distribution', 'Event.proposal_email_lock', 'Event.orgc', 'Event.user_id', 'Event.locked'); + $fieldsAtt = array('Attribute.id', 'Attribute.type', 'Attribute.category', 'Attribute.value', 'Attribute.to_ids', 'Attribute.uuid', 'Attribute.event_id', 'Attribute.distribution', 'Attribute.timestamp'); $fieldsShadowAtt = array('ShadowAttribute.id', 'ShadowAttribute.type', 'ShadowAttribute.category', 'ShadowAttribute.value', 'ShadowAttribute.to_ids', 'ShadowAttribute.uuid', 'ShadowAttribute.event_id', 'ShadowAttribute.old_id'); $params = array('conditions' => $conditions, 'recursive' => 0, 'fields' => $fields, 'contain' => array( - 'ThreatLevel' => array( - 'fields' => array('ThreatLevel.name') - ), 'Attribute' => array( 'fields' => $fieldsAtt, 'conditions' => $conditionsAttributes, @@ -1503,14 +1545,14 @@ class EventsController extends AppController { ), ) ); - if ($isSiteAdmin) $params['contain']['User'] = array('fields' => 'email'); + if ($this->_isAdmin()) $params['contain']['User'] = array('fields' => 'email'); $results = $this->Event->find('all', $params); // Do some refactoring with the event foreach ($results as $eventKey => &$event) { // Let's find all the related events and attach it to the event itself - $results[$eventKey]['RelatedEvent'] = $this->Event->getRelatedEvents($this->Auth->user(), $this->_isSiteAdmin(), $event['Event']['id']); + $results[$eventKey]['RelatedEvent'] = $this->Event->getRelatedEvents($this->Auth->user(), $event['Event']['id']); // Let's also find all the relations for the attributes - this won't be in the xml export though - $results[$eventKey]['RelatedAttribute'] = $this->Event->getRelatedAttributes($this->Auth->user(), $this->_isSiteAdmin(), $event['Event']['id']); + $results[$eventKey]['RelatedAttribute'] = $this->Event->getRelatedAttributes($this->Auth->user(), $event['Event']['id']); foreach ($event['Attribute'] as $key => &$attribute) { $attribute['ShadowAttribute'] = array(); // If a shadowattribute can be linked to an attribute, link it to it then remove it from the event @@ -1528,14 +1570,7 @@ class EventsController extends AppController { return $results; } - public function nids($format = 'suricata', $key = '') { - - // backwards compatibility, swap key and format - if ($format != 'snort' && $format != 'suricata') { - $key = $format; - $format = 'suricata'; // default format - } - + public function nids($key) { if ($key != 'download') { $this->response->type('txt'); // set the content type $this->header('Content-Disposition: inline; filename="misp.rules"'); @@ -1578,17 +1613,7 @@ class EventsController extends AppController { unset($this->Attribute->virtualFields['category_order']); // not needed for IDS export and speeds things up $items = $this->Attribute->find('all', $params); - // export depending of the requested type - switch ($format) { - case 'suricata': - $this->NidsExport = $this->Components->load('NidsSuricataExport'); - break; - case 'snort': - $this->NidsExport = $this->Components->load('NidsSnortExport'); - break; - } $rules = $this->NidsExport->export($items, $user['User']['nids_sid']); - $this->set('rules', $rules); } @@ -1925,7 +1950,7 @@ class EventsController extends AppController { $this->Event->read(null, $id); $saveEvent['Event'] = $this->Event->data['Event']; $saveEvent['Event']['published'] = false; - $dist = '3'; + $dist = 3; if (Configure::read('MISP.default_attribute_distribution') != null) { if (Configure::read('MISP.default_attribute_distribution') === 'event') { $dist = $this->Event->data['Event']['distribution']; @@ -1951,7 +1976,7 @@ class EventsController extends AppController { $fieldList = array( 'Event' => array('published', 'timestamp'), - 'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'distribution', 'timestamp', 'comment') + 'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'distribution', 'timestamp') ); // Save it all $saveResult = $this->Event->saveAssociated($saveEvent, array('validate' => true, 'fieldList' => $fieldList)); @@ -1968,46 +1993,24 @@ class EventsController extends AppController { } } - public function _addXMLFile() { - if (!empty($this->data) && $this->data['Event']['submittedxml']['size'] > 0 && - is_uploaded_file($this->data['Event']['submittedxml']['tmp_name'])) { - $xmlData = fread(fopen($this->data['Event']['submittedxml']['tmp_name'], "r"), - $this->data['Event']['submittedxml']['size']); - App::uses('Xml', 'Utility'); - $xmlArray = Xml::toArray(Xml::build($xmlData)); - - // 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($xmlArray['Event'])) { - $xmlArray['response']['Event'] = $xmlArray['Event']; - unset($xmlArray['Event']); - } - - if (!isset($xmlArray['response']) || !isset($xmlArray['response']['Event'])) { - throw new Exception('This is not a valid MISP XML file.'); - } - if (isset($xmlArray['response']['Event'][0])) { - foreach ($xmlArray['response']['Event'] as $event) { - $temp['Event'] = $event; - $this->_add($temp, true); - } - } else { - $temp['Event'] = $xmlArray['response']['Event']; - $this->_add($temp, true); - } - } - } - public function _readGfiXML($data, $id) { $this->loadModel('Attribute'); - + $this->Event->recursive = -1; + $this->Event->read(array('id', 'uuid', 'distribution'), $id); // import XML class App::uses('Xml', 'Utility'); // now parse it $parsedXml = Xml::build($data, array('return' => 'simplexml')); - // xpath.. + if (Configure::read('MISP.default_attribute_distribution') != null) { + if (Configure::read('MISP.default_attribute_distribution') === 'event') { + $dist = $this->Event->data['Event']['distribution']; + } else { + $dist = ''; + $dist .= Configure::read('MISP.default_attribute_distribution'); + } + } //Payload delivery -- malware-sample $results = $parsedXml->xpath('/analysis'); foreach ($results as $result) { @@ -2018,13 +2021,13 @@ class EventsController extends AppController { $realMalware = $realFileName; $rootDir = APP . "files" . DS . $id . DS; $malware = $rootDir . DS . 'sample'; - $this->Event->Attribute->uploadAttachment($malware, $realFileName, true, $id, null, '', '', true); + $this->Event->Attribute->uploadAttachment($malware, $realFileName, true, $id, null, '', $this->Event->data['Event']['uuid'] . '-sample', $dist, true); //Network activity -- .pcap $realFileName = 'analysis.pcap'; $rootDir = APP . "files" . DS . $id . DS; $malware = $rootDir . DS . 'Analysis' . DS . 'analysis.pcap'; - $this->Event->Attribute->uploadAttachment($malware, $realFileName, false, $id, 'Network activity', '', '', true); + $this->Event->Attribute->uploadAttachment($malware, $realFileName, false, $id, 'Network activity', '', $this->Event->data['Event']['uuid'] . '-analysis.pcap', $dist, true); //Artifacts dropped -- filename|md5 $files = array(); @@ -2073,11 +2076,10 @@ class EventsController extends AppController { $extraPath = 'Analysis' . DS . 'proc_' . $index . DS . 'modified_files' . DS; $file = new File($actualFile); if ($file->exists()) { // TODO put in array for test later - $this->Event->Attribute->uploadAttachment($actualFile, $realFileName, true, $id, null, $extraPath, $keyName, true); // TODO was false + $this->Event->Attribute->uploadAttachment($actualFile, $realFileName, true, $id, null, $extraPath, $keyName, $dist, true); // TODO was false } else { } } - //Network activity -- ip-dst $ips = array(); $hostnames = array(); @@ -2098,9 +2100,9 @@ class EventsController extends AppController { 'category' => 'Network activity', 'type' => 'ip-dst', 'value' => $ip, - 'to_ids' => false, + 'distribution' => $dist, 'comment' => 'GFI import', - )); + 'to_ids' => false)); } foreach ($hostnames as $hostname) { // add attribute.. @@ -2110,9 +2112,9 @@ class EventsController extends AppController { 'category' => 'Network activity', 'type' => 'hostname', 'value' => $hostname, - 'to_ids' => false, + 'distribution' => $dist, 'comment' => 'GFI import', - )); + 'to_ids' => false)); } // Persistence mechanism -- regkey|value $regs = array(); @@ -2132,29 +2134,17 @@ class EventsController extends AppController { foreach ($regs as $key => $val) { // add attribute.. $this->Attribute->create(); - if ($val == '[binary_data]') { - $itsCategory = 'Artifacts dropped'; - $itsType = 'regkey'; - $itsValue = $key; - } else { - if ($this->strposarray($val,$actualFileNameArray)) { - $itsCategory = 'Persistence mechanism'; - $itsType = 'regkey|value'; - $itsValue = $key . '|' . $val; - } else { - $itsCategory = 'Artifacts dropped'; // Persistence mechanism - $itsType = 'regkey|value'; - $itsValue = $key . '|' . $val; - } - } - $this->Attribute->save(array( + if ($this->strposarray($val,$actualFileNameArray)) { + $this->Attribute->save(array( 'event_id' => $id, - 'category' => $itsCategory, // 'Persistence mechanism' - 'type' => $itsType, - 'value' => $itsValue, - 'to_ids' => false, + 'category' => 'Persistence mechanism', // 'Persistence mechanism' + 'type' => 'regkey|value', + 'value' => $key . '|' . $val, + 'distribution' => $dist, 'comment' => 'GFI import', - )); + 'to_ids' => false + )); + } } } @@ -2184,96 +2174,7 @@ class EventsController extends AppController { $this->set('results', $results); $this->render('xml'); } - - // Use the rest interface to search for attributes or events. Usage: - // MISP-base-url/events/restSearch/[api-key]/[value]/[type]/[category]/[orgc] - // value, type, category, orgc are optional - // target can be either "event" or "attribute" - // the last 4 fields accept the following operators: - // && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two. - // ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't. - public function restSearch($key, $value=null, $type=null, $category=null, $org=null) { - $user = $this->checkAuthUser($key); - if (!$user) { - throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.'); - } - $value = str_replace('|', '/', $value); - $this->response->type('xml'); // set the content type - $this->layout = 'xml/default'; - $this->header('Content-Disposition: download; filename="misp.search.events.results.xml"'); - $conditions['AND'] = array(); - $subcondition = array(); - $this->loadModel('Attribute'); - // add the values as specified in the 2nd parameter to the conditions - $values = explode('&&', $value); - $parameters = array('value', 'type', 'category', 'org'); - - foreach ($parameters as $k => $param) { - if (isset(${$parameters[$k]})) { - $elements = explode('&&', ${$parameters[$k]}); - foreach($elements as $v) { - if (substr($v, 0, 1) == '!') { - if ($parameters[$k] === 'value' && preg_match('@^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$@', substr($v, 1))) { - $cidrresults = $this->Cidr->CIDR(substr($v, 1)); - foreach ($cidrresults as $result) { - $subcondition['AND'][] = array('Attribute.value NOT LIKE' => $result); - } - } else { - if ($parameters[$k] === 'org') { - $subcondition['AND'][] = array('Event.' . $parameters[$k] . ' NOT LIKE' => '%'.substr($v, 1).'%'); - } else { - $subcondition['AND'][] = array('Attribute.' . $parameters[$k] . ' NOT LIKE' => '%'.substr($v, 1).'%'); - } - } - } else { - if ($parameters[$k] === 'value' && preg_match('@^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$@', substr($v, 1))) { - $cidrresults = $this->Cidr->CIDR($v); - foreach ($cidrresults as $result) { - $subcondition['OR'][] = array('Attribute.value LIKE' => $result); - } - } else { - if ($parameters[$k] === 'org') { - $subcondition['OR'][] = array('Event.' . $parameters[$k] . ' LIKE' => '%'.$v.'%'); - } else { - $subcondition['OR'][] = array('Attribute.' . $parameters[$k] . ' LIKE' => '%'.$v.'%'); - } - } - } - } - array_push ($conditions['AND'], $subcondition); - $subcondition = array(); - } - } - - // If we are looking for an attribute, we want to retrieve some extra data about the event to be able to check for the permissions. - - if (!$user['User']['siteAdmin']) { - $temp = array(); - $temp['AND'] = array('Event.distribution >' => 0, 'Attribute.distribution >' => 0); - $subcondition['OR'][] = $temp; - $subcondition['OR'][] = array('Event.org' => $user['User']['org']); - array_push($conditions['AND'], $subcondition); - } - - $params = array( - 'conditions' => $conditions, - 'fields' => array('Attribute.event_id'), - ); - $attributes = $this->Attribute->find('all', $params); - $eventIds = array(); - foreach ($attributes as $attribute) { - if (!in_array($attribute['Attribute']['event_id'], $eventIds)) $eventIds[] = $attribute['Attribute']['event_id']; - } - if (!empty($eventIds)) { - $results = $this->__fetchEvent(null, $eventIds, $user['User']['org'], true); - } else { - throw new NotFoundException('No matches.'); - } - $this->loadModel('Whitelist'); - $results = $this->Whitelist->removeWhitelistedFromArray($results, true); - $this->set('results', $results); - } - + public function downloadOpenIOCEvent($eventid) { // return a downloadable text file called misp.openIOC..ioc for individual events @@ -2310,65 +2211,93 @@ class EventsController extends AppController { $final = $this->IOCExport->buildAll($event, $isMyEvent, $isSiteAdmin); $this->set('final', $final); } - - public function create_dummy_event() { + + public function _addXMLFile() { + if (!empty($this->data) && $this->data['Event']['submittedxml']['size'] > 0 && + is_uploaded_file($this->data['Event']['submittedxml']['tmp_name'])) { + $xmlData = fread(fopen($this->data['Event']['submittedxml']['tmp_name'], "r"), + $this->data['Event']['submittedxml']['size']); + App::uses('Xml', 'Utility'); + $xmlArray = Xml::toArray(Xml::build($xmlData)); + + // 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($xmlArray['Event'])) { + unset($xmlArray['Event']); + } + + if (!isset($xmlArray['response']) || !isset($xmlArray['response']['Event'])) { + throw new Exception('This is not a valid MISP XML file.'); + } + if (isset($xmlArray['response']['Event'][0])) { + foreach ($xmlArray['response']['Event'] as $event) { + $temp['Event'] = $event; + $this->_add($temp, true); + } + } else { + $temp['Event'] = $xmlArray['response']['Event']; + $this->_add($temp, true); + } + } + } + public function create_dummy_event() { if (!$this->_isSiteAdmin()) throw new MethodNotAllowedException('You don\'t have the privileges to access this.'); $date = new DateTime(); $data['Event']['info'] = 'Test event showing every category-type combination'; $data['Event']['date'] = '2013-10-09'; - $data['Event']['threat_level_id'] = 4; //'Undefined' + $data['Event']['threat_level_id'] = 4; //'Undefined' $data['Event']['analysis'] = '0'; $data['Event']['distribution'] = '0'; - $defaultValues = array( - 'md5' => '098f6bcd4621d373cade4e832627b4f6', - 'sha1' => 'a7645200866fd00bde529733ceac8506ab1f5518', - 'sha256' => '0f58957831a9cf0b768451ee6b236555f519c04f0da5a5ea87538fd0990b29d1', - 'filename' => 'test.exe', - 'filename|md5' => 'test.exe|8886be8e4e862189a68d27e8fc7a6144', - 'filename|sha1' => 'test.exe|a7645200866fd00bde529733ceac8506ab1f5518', - 'filename|sha256' => 'test.exe|0f58957831a9cf0b768451ee6b236555f519c04f0da5a5ea87538fd0990b29d1', - 'ip-src' => '1.1.1.1', - 'ip-dst' => '2.2.2.2', - 'hostname' => 'www.futuremark.com', - 'domain' => 'evildomain.org', - 'email-src' => 'bla@bla.com', - 'email-dst' => 'hmm@hmm.com', - 'email-subject' => 'Some made-up email subject', - 'email-attachment' => 'filename.exe', - 'url' => 'http://www.evilsite.com/test', - 'http-method' => 'POST', - 'user-agent' => 'Microsoft Internet Explorer', - 'regkey' => 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run\fishy', - 'regkey|value' => 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run\fishy|%ProgramFiles%\Malicios\malware.exe', - 'AS' => '45566', - 'snort' => 'alert ip 1.1.1.1 any -> $HOME_NET any (msg: "MISP e1 Incoming From IP: 1.1.1.1"; classtype:trojan-activity; sid:21; rev:1; priority:1; reference:url,http://localhost:8888/events/view/1;)', - 'pattern-in-file' => 'Somestringinfile', - 'pattern-in-traffic' => 'Somestringintraffic', - 'pattern-in-memory' => 'Somestringinmemory', - 'yara' => 'rule silent_banker : banker{meta:description = "This is just an example" thread_level = 3 in_the_wild = true strings: $a = {6A 40 68 00 30 00 00 6A 14 8D 91} $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9} $c = "UVODFRYSIHLNWPEJXQZAKCBGMT" condition:}', - 'vulnerability' => 'CVE-2011-0001', - 'attachment' => 'file.txt', - 'malware-sample' => 'test.exe|8886be8e4e862189a68d27e8fc7a6144', - 'link' => 'http://www.somesite.com/', - 'comment' => 'Comment', - 'text' => 'Any text', - 'other' => 'Could be anything', - 'named pipe' => '\\.\pipe\PipeName', - 'mutex' => 'mutexstring', - ); + $defaultValues = array( + 'md5' => '098f6bcd4621d373cade4e832627b4f6', + 'sha1' => 'a7645200866fd00bde529733ceac8506ab1f5518', + 'sha256' => '0f58957831a9cf0b768451ee6b236555f519c04f0da5a5ea87538fd0990b29d1', + 'filename' => 'test.exe', + 'filename|md5' => 'test.exe|8886be8e4e862189a68d27e8fc7a6144', + 'filename|sha1' => 'test.exe|a7645200866fd00bde529733ceac8506ab1f5518', + 'filename|sha256' => 'test.exe|0f58957831a9cf0b768451ee6b236555f519c04f0da5a5ea87538fd0990b29d1', + 'ip-src' => '1.1.1.1', + 'ip-dst' => '2.2.2.2', + 'hostname' => 'www.futuremark.com', + 'domain' => 'evildomain.org', + 'email-src' => 'bla@bla.com', + 'email-dst' => 'hmm@hmm.com', + 'email-subject' => 'Some made-up email subject', + 'email-attachment' => 'filename.exe', + 'url' => 'http://www.evilsite.com/test', + 'http-method' => 'POST', + 'user-agent' => 'Microsoft Internet Explorer', + 'regkey' => 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run\fishy', + 'regkey|value' => 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run\fishy|%ProgramFiles%\Malicios\malware.exe', + 'AS' => '45566', + 'snort' => 'alert ip 1.1.1.1 any -> $HOME_NET any (msg: "MISP e1 Incoming From IP: 1.1.1.1"; classtype:trojan-activity; sid:21; rev:1; priority:1; reference:url,http://localhost:8888/events/view/1;)', + 'pattern-in-file' => 'Somestringinfile', + 'pattern-in-traffic' => 'Somestringintraffic', + 'pattern-in-memory' => 'Somestringinmemory', + 'yara' => 'rule silent_banker : banker{meta:description = "This is just an example" thread_level = 3 in_the_wild = true strings: $a = {6A 40 68 00 30 00 00 6A 14 8D 91} $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9} $c = "UVODFRYSIHLNWPEJXQZAKCBGMT" condition:}', + 'vulnerability' => 'CVE-2011-0001', + 'attachment' => 'file.txt', + 'malware-sample' => 'test.exe|8886be8e4e862189a68d27e8fc7a6144', + 'link' => 'http://www.somesite.com/', + 'comment' => 'Comment', + 'text' => 'Any text', + 'other' => 'Could be anything', + 'named pipe' => '\\.\pipe\PipeName', + 'mutex' => 'mutexstring', + ); $this->loadModel('Attribute'); foreach ($this->Attribute->categoryDefinitions as $category => $v) { foreach ($v['types'] as $k => $type) { - $data['Attribute'][] = array( - 'category' => $category, - 'type' => $type, - 'value' => $defaultValues[$type], - 'to_ids' => '0', - 'distribution' => '0', + $data['Attribute'][] = array( + 'category' => $category, + 'type' => $type, + 'value' => $defaultValues[$type], + 'to_ids' => '0', + 'distribution' => '0', ); + } } - $this->_add($data, false); - } + } } diff --git a/app/Controller/UsersController.php b/app/Controller/UsersController.php index e5a38962d..f3a3bf7b0 100755 --- a/app/Controller/UsersController.php +++ b/app/Controller/UsersController.php @@ -464,7 +464,7 @@ class UsersController extends AppController { $params = array('recursive' => 0, 'fields' => $fields, 'group' => array('User.org'), - 'order' => array('User.org'), + 'order' => array('UPPER(User.org)'), ); $orgs = $this->User->find('all', $params); $this->set('orgs', $orgs); diff --git a/app/Model/Attribute.php b/app/Model/Attribute.php index ebb14796c..a6d06a9a5 100755 --- a/app/Model/Attribute.php +++ b/app/Model/Attribute.php @@ -795,7 +795,8 @@ class Attribute extends AppModel { * * @return void */ - public function uploadAttachment($fileP, $realFileName, $malware, $eventId = null, $category = null, $extraPath = '', $fullFileName = '', $fromGFI = false) { + public function uploadAttachment($fileP, $realFileName, $malware, $eventId = null, $category = null, $extraPath = '', $fullFileName = '', $dist, $fromGFI = false) { + // Check if there were problems with the file upload // only keep the last part of the filename, this should prevent directory attacks $filename = basename($fileP); @@ -804,13 +805,15 @@ class Attribute extends AppModel { // save the file-info in the database $this->create(); $this->data['Attribute']['event_id'] = $eventId; + $this->data['Attribute']['distribution'] = $dist; if ($malware) { $md5 = !$tmpfile->size() ? md5_file($fileP) : $tmpfile->md5(); $this->data['Attribute']['category'] = $category ? $category : "Payload delivery"; $this->data['Attribute']['type'] = "malware-sample"; $this->data['Attribute']['value'] = $fullFileName ? $fullFileName . '|' . $md5 : $filename . '|' . $md5; // TODO gives problems with bigger files - $this->data['Attribute']['to_ids'] = 1; // LATER let user choose to send this to IDS + $this->data['Attribute']['to_ids'] = 0; // LATER let user choose to send this to IDS if ($fromGFI) $this->data['Attribute']['comment'] = 'GFI import'; + $this->data['Attribute']['to_ids'] = 0; // LATER let user choose to send this to IDS } else { $this->data['Attribute']['category'] = $category ? $category : "Artifacts dropped"; $this->data['Attribute']['type'] = "attachment"; @@ -823,18 +826,13 @@ class Attribute extends AppModel { if ($this->save($this->data)) { // attribute saved correctly in the db } else { - // do some? + return; } // no errors in file upload, entry already in db, now move the file where needed and zip it if required. // no sanitization is required on the filename, path or type as we save // create directory structure - // ??? - if (PHP_OS == 'WINNT') { - $rootDir = APP . "files" . DS . $eventId; - } else { - $rootDir = APP . "files" . DS . $eventId; - } + $rootDir = APP . "files" . DS . $eventId; $dir = new Folder($rootDir, true); // move the file to the correct location $destpath = $rootDir . DS . $this->getId(); // id of the new attribute in the database diff --git a/app/Model/Whitelist.php b/app/Model/Whitelist.php index 5b1387545..da56672a7 100755 --- a/app/Model/Whitelist.php +++ b/app/Model/Whitelist.php @@ -67,7 +67,7 @@ class Whitelist extends AppModel { // regexp validation public function validateValue ($fields) { - if (preg_match($fields['name'], 'test') === false) return false; + if (preg_match("/".$fields['name']."/", 'test') === false) return false; return true; } @@ -104,7 +104,7 @@ class Whitelist extends AppModel { foreach ($data as $k => $attribute) { // loop through each whitelist item and run a preg match against the attribute value. If it matches, unset the attribute foreach ($whitelists as $wlitem) { - if (preg_match($wlitem, $attribute['Attribute']['value'])) { + if (preg_match("/".$wlitem."/", $attribute['Attribute']['value'])) { unset($data[$k]); } } @@ -116,7 +116,7 @@ class Whitelist extends AppModel { foreach ($event['Attribute'] as $k => $attribute) { // loop through each whitelist item and run a preg match against the attribute value. If it matches, unset the attribute foreach ($whitelists as $wlitem) { - if (preg_match($wlitem, $attribute['value'])) { + if (preg_match("/".$wlitem."/", $attribute['value'])) { unset($data[$ke]['Attribute'][$k]); } } diff --git a/app/View/Elements/global_menu.ctp b/app/View/Elements/global_menu.ctp index 604e40ad3..48223a5c5 100755 --- a/app/View/Elements/global_menu.ctp +++ b/app/View/Elements/global_menu.ctp @@ -4,7 +4,7 @@ - \ No newline at end of file + diff --git a/app/View/Users/login.ctp b/app/View/Users/login.ctp index 6b0e6ea8f..18471aad2 100755 --- a/app/View/Users/login.ctp +++ b/app/View/Users/login.ctp @@ -2,7 +2,7 @@ Session->flash('auth'); ?> - +
- +