fix: [security] Respect ACL when event edit

pull/6136/head
Jakub Onderka 2020-07-20 10:10:47 +02:00
parent 5d8f32a955
commit db626cf741
5 changed files with 212 additions and 376 deletions

View File

@ -1281,4 +1281,24 @@ class AppController extends Controller
return $this->RestResponse->viewData($final, $responseType, false, true, $filename, array('X-Result-Count' => $elementCounter, 'X-Export-Module-Used' => $returnFormat, 'X-Response-Format' => $responseType));
}
}
/**
* Returns true if user can modify given event.
*
* @param array $event
* @return bool
*/
protected function __canModifyEvent(array $event)
{
if ($this->userRole['perm_site_admin']) {
return true;
}
if ($this->userRole['perm_modify_org'] && $event['Event']['orgc_id'] == $this->Auth->user('org_id')) {
return true;
}
if ($this->userRole['perm_modify'] && $event['Event']['user_id'] == $this->Auth->user('id')) {
return true;
}
return false;
}
}

View File

@ -109,27 +109,15 @@ class AttributesController extends AppController
throw new MethodNotAllowedException(__('You do not have permissions to create attributes'));
}
$this->loadModel('Event');
if (Validation::uuid($eventId)) {
$temp = $this->Event->find('first', array('recursive' => -1, 'fields' => array('Event.id'), 'conditions' => array('Event.uuid' => $eventId)));
if (empty($temp)) {
throw new NotFoundException(__('Invalid event'));
}
$eventId = $temp['Event']['id'];
} elseif (!is_numeric($eventId)) {
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $eventId);
if (!$event) {
throw new NotFoundException(__('Invalid event'));
}
$this->Event->id = $eventId;
if (!$this->Event->exists()) {
throw new NotFoundException(__('Invalid event'));
}
// remove the published flag from the event
$this->Event->recursive = -1;
$this->Event->read(null, $eventId);
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc_id'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
if (!$this->_isRest()) {
$this->Event->insertLock($this->Auth->user(), $this->Event->data['Event']['id']);
$this->Event->insertLock($this->Auth->user(), $event['Event']['id']);
}
if ($this->request->is('ajax')) {
$this->set('ajax', true);
@ -141,7 +129,6 @@ class AttributesController extends AppController
if ($this->request->is('ajax')) {
$this->autoRender = false;
}
$date = new DateTime();
if (!isset($this->request->data['Attribute'])) {
$this->request->data = array('Attribute' => $this->request->data);
}
@ -173,7 +160,6 @@ class AttributesController extends AppController
if (!isset($attributes[0])) {
$attributes = array(0 => $attributes);
}
$uuids = array();
$this->Warninglist = ClassRegistry::init('Warninglist');
$fails = array();
$successes = 0;
@ -181,7 +167,7 @@ class AttributesController extends AppController
$inserted_ids = array();
foreach ($attributes as $k => $attribute) {
$validationErrors = array();
$this->Attribute->captureAttribute($attribute, $eventId, $this->Auth->user(), false, false, false, $validationErrors, $this->params['named']);
$this->Attribute->captureAttribute($attribute, $event['Event']['id'], $this->Auth->user(), false, false, false, $validationErrors, $this->params['named']);
if (empty($validationErrors)) {
$inserted_ids[] = $this->Attribute->id;
$successes +=1;
@ -190,7 +176,7 @@ class AttributesController extends AppController
}
}
if (!empty($successes)) {
$this->Event->unpublishEvent($eventId);
$this->Event->unpublishEvent($event['Event']['id']);
}
if ($this->_isRest()) {
if (!empty($successes)) {
@ -228,8 +214,6 @@ class AttributesController extends AppController
}
}
} else {
$message = '';
$redirect = '/events/view/' . $eventId;
if (empty($fails)) {
$message = 'Attributes saved.';
} else {
@ -281,7 +265,7 @@ class AttributesController extends AppController
}
} else {
if ($successes > 0) {
$this->redirect(array('controller' => 'events', 'action' => 'view', $eventId));
$this->redirect(array('controller' => 'events', 'action' => 'view', $event['Event']['id']));
}
}
}
@ -300,11 +284,9 @@ class AttributesController extends AppController
$categories = array_keys($this->Attribute->categoryDefinitions);
$categories = $this->_arrayToValuesIndexArray($categories);
$this->set('categories', $categories);
$this->loadModel('Event');
$events = $this->Event->findById($eventId);
$this->set('event_id', $events['Event']['id']);
$this->set('event_id', $event['Event']['id']);
// combobox for distribution
$this->set('currentDist', $events['Event']['distribution']);
$this->set('currentDist', $event['Event']['distribution']);
// tooltip for distribution
$this->loadModel('SharingGroup');
@ -337,19 +319,13 @@ class AttributesController extends AppController
$this->set('fieldDesc', $fieldDesc);
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
$this->set('published', $events['Event']['published']);
$this->set('published', $event['Event']['published']);
$this->set('action', $this->action);
}
public function download($id = null)
{
if (is_numeric($id)) {
$conditions = array('Attribute.id' => $id);
} elseif (Validation::uuid($id)) {
$conditions = array('Attribute.uuid' => $id);
} else {
throw new NotFoundException(__('Invalid attribute id.'));
}
$conditions = $this->__idToConditions($id);
$conditions['Attribute.type'] = array('attachment', 'malware-sample');
$attributes = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => $conditions, 'flatten' => true));
if (empty($attributes)) {
@ -410,16 +386,15 @@ class AttributesController extends AppController
public function add_attachment($eventId = null)
{
$event = $this->Attribute->Event->fetchSimpleEvent($this->Auth->user(), $eventId);
if (empty($event)) {
throw new NotFoundException(__('Invalid Event.'));
}
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
if ($this->request->is('post')) {
$this->Attribute->Event->id = $this->request->data['Attribute']['event_id'];
$this->Attribute->Event->recursive = -1;
$event = $this->Attribute->Event->read();
if (empty($event)) {
throw new NotFoundException(__('Invalid Event.'));
}
if (!$this->_isSiteAdmin() && ($this->Attribute->Event->data['Event']['orgc_id'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException(__('You do not have permission to do that.'));
}
$fails = array();
$success = 0;
@ -442,14 +417,14 @@ class AttributesController extends AppController
if ($this->request->data['Attribute']['malware']) {
if ($this->request->data['Attribute']['advanced']) {
$result = $this->Attribute->advancedAddMalwareSample(
$eventId,
$event['Event']['id'],
$this->request->data['Attribute'],
$filename,
$tmpfile
);
} else {
$result = $this->Attribute->simpleAddMalwareSample(
$eventId,
$event['Event']['id'],
$this->request->data['Attribute'],
$filename,
$tmpfile
@ -471,11 +446,11 @@ class AttributesController extends AppController
foreach ($object['Attribute'] as $ka => $attribute) {
$object['Attribute'][$ka]['distribution'] = 5;
}
$this->Attribute->Object->captureObject(array('Object' => $object), $eventId, $this->Auth->user());
$this->Attribute->Object->captureObject(array('Object' => $object), $event['Event']['id'], $this->Auth->user());
}
if (!empty($result['ObjectReference'])) {
foreach ($result['ObjectReference'] as $reference) {
$this->Attribute->Object->ObjectReference->smartSave($reference, $eventId);
$this->Attribute->Object->ObjectReference->smartSave($reference, $event['Event']['id']);
}
}
}
@ -485,7 +460,7 @@ class AttributesController extends AppController
'value' => $filename,
'category' => $this->request->data['Attribute']['category'],
'type' => 'attachment',
'event_id' => $this->request->data['Attribute']['event_id'],
'event_id' => $event['Event']['id'],
'data' => base64_encode($tmpfile->read()),
'comment' => $this->request->data['Attribute']['comment'],
'to_ids' => 0,
@ -511,8 +486,7 @@ class AttributesController extends AppController
$message = __('The attachment(s) could not be saved. Please contact your administrator.');
}
} else {
$this->Attribute->Event->id = $this->request->data['Attribute']['event_id'];
$this->Attribute->Event->saveField('published', 0);
$this->Attribute->Event->unpublishEvent($event['Event']['id']);
}
if (empty($success) && !empty($fails)) {
$this->Flash->error($message);
@ -520,21 +494,16 @@ class AttributesController extends AppController
$this->Flash->success($message);
}
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $eventId);
$this->Attribute->Event->insertLock($this->Auth->user(), $event['Event']['id']);
}
$this->redirect(array('controller' => 'events', 'action' => 'view', $eventId));
$this->redirect(array('controller' => 'events', 'action' => 'view', $event['Event']['id']));
} else {
// set the event_id in the form
$this->request->data['Attribute']['event_id'] = $eventId;
}
$event = $this->Attribute->Event->findById($eventId);
if (empty($event)) {
throw new NotFoundException(__('Invalid Event.'));
$this->request->data['Attribute']['event_id'] = $event['Event']['id'];
}
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $eventId);
$this->Attribute->Event->insertLock($this->Auth->user(), $event['Event']['id']);
}
// Filter categories that contains attachment type
@ -575,8 +544,8 @@ class AttributesController extends AppController
$this->Event->id = $eventId;
$this->Event->recursive = -1;
$this->Event->read();
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc_id'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException(__('You do not have permission to do that.'));
if (!$this->__canModifyEvent($this->Event->data)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
//
// File upload
@ -763,58 +732,25 @@ class AttributesController extends AppController
if ($this->request->is('get') && $this->_isRest()) {
return $this->RestResponse->describe('Attributes', 'edit', false, $this->response->type());
}
if (Validation::uuid($id)) {
$temp = $this->Attribute->find('first', array(
'recursive' => -1,
'fields' => array('Attribute.id', 'Attribute.uuid'),
'conditions' => array('Attribute.uuid' => $id)
));
if ($temp == null) {
throw new NotFoundException('Invalid attribute');
}
$id = $temp['Attribute']['id'];
} elseif (!is_numeric($id)) {
throw new NotFoundException(__('Invalid attribute'));
}
$this->Attribute->id = $id;
$date = new DateTime();
if (!$this->Attribute->exists()) {
throw new NotFoundException(__('Invalid attribute'));
}
$conditions = array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true, 'flatten' => true);
$conditions['includeAllTags'] = false;
$conditions['includeAttributeUuid'] = true;
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), $conditions);
$attribute = $this->__fetchAttribute($id);
if (empty($attribute)) {
throw new MethodNotAllowedException('Invalid attribute');
}
$this->Attribute->data = $attribute[0];
$event = $this->Attribute->Event->find('first', array(
'conditions' =>
array(
'Event.id' => $attribute[0]['Attribute']['event_id']
),
'recursive' => -1,
'fields' => array('Event.id', 'Event.user_id')
));
$this->Attribute->data = $attribute;
if ($this->Attribute->data['Attribute']['deleted']) {
throw new NotFoundException(__('Invalid attribute'));
}
if (!$this->_isSiteAdmin()) {
if ($this->Attribute->data['Event']['orgc_id'] == $this->Auth->user('org_id')
&& (($this->userRole['perm_modify'] && $event['Event']['user_id'] != $this->Auth->user('id'))
|| $this->userRole['perm_modify_org'])) {
// Allow the edit
$this->Attribute->id = $attribute['Attribute']['id'];
if (!$this->__canModifyEvent($attribute)) {
$message = __('You do not have permission to do that.');
if ($this->_isRest()) {
throw new ForbiddenException($message);
} else {
$message = __('You do not have permission to do that.');
if ($this->_isRest()) {
throw new ForbiddenException($message);
} else {
$this->Flash->error($message);
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
$this->Flash->error($message);
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
}
$date = new DateTime();
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $this->Attribute->data['Attribute']['event_id']);
}
@ -866,14 +802,6 @@ class AttributesController extends AppController
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
}
$this->loadModel('Event');
$event = $this->Attribute->Event->find('first', array(
'recursive' => -1,
'conditions' => array('Event.id' => $eventId)
));
if (empty($event)) {
throw new NotFoundException(__('Invalid Event.'));
}
if ($existingAttribute['Attribute']['object_id']) {
$result = $this->Attribute->save($this->request->data, array('fieldList' => $this->Attribute->editableFields));
if ($result) {
@ -897,7 +825,7 @@ class AttributesController extends AppController
if ($result) {
$this->Flash->success(__('The attribute has been saved'));
// remove the published flag from the event
$this->Event->unpublishEvent($eventId);
$this->Attribute->Event->unpublishEvent($eventId);
if (!empty($this->Attribute->data['Attribute']['object_id'])) {
$object = $this->Attribute->Object->find('first', array(
'recursive' => -1,
@ -948,11 +876,8 @@ class AttributesController extends AppController
$this->set('objectAttribute', false);
}
// enabling / disabling the distribution field in the edit view based on whether user's org == orgc in the event
$this->loadModel('Event');
$this->Event->id = $eventId;
$this->set('event_id', $eventId);
$this->Event->read();
$this->set('published', $this->Event->data['Event']['published']);
$this->set('event_id', $attribute['Event']['id']);
$this->set('published', $attribute['Event']['published']);
// needed for RBAC
// combobox for types
$types = array_keys($this->Attribute->typeDefinitions);
@ -964,7 +889,7 @@ class AttributesController extends AppController
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories
$this->set('currentDist', $this->Event->data['Event']['distribution']);
$this->set('currentDist', $attribute['Event']['distribution']);
$this->loadModel('SharingGroup');
$sgs = $this->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', 1);
@ -1016,44 +941,17 @@ class AttributesController extends AppController
// ajax edit - post a single edited field and this method will attempt to save it and return a json with the validation errors if they occur.
public function editField($id)
{
if (Validation::uuid($id)) {
$this->Attribute->recursive = -1;
$temp = $this->Attribute->findByUuid($id);
if ($temp == null) {
throw new NotFoundException(__('Invalid attribute'));
}
$id = $temp['Attribute']['id'];
} elseif (!is_numeric($id)) {
throw new NotFoundException(__('Invalid event id.'));
}
if ((!$this->request->is('post') && !$this->request->is('put'))) {
throw new MethodNotAllowedException();
}
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
return new CakeResponse(array('body'=> json_encode(array('fail' => false, 'errors' => 'Invalid attribute')), 'status'=>200, 'type' => 'json'));
}
$conditions = array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true, 'flatten' => true);
$conditions['includeAllTags'] = false;
$conditions['includeAttributeUuid'] = true;
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), $conditions);
$attribute = $this->__fetchAttribute($id);
if (empty($attribute)) {
throw new MethodNotAllowedException('Invalid attribute');
return new CakeResponse(array('body'=> json_encode(array('fail' => false, 'errors' => 'Invalid attribute')), 'status' => 200, 'type' => 'json'));
}
$attribute = $attribute[0];
$this->Attribute->data = $attribute;
if (!$this->_isSiteAdmin()) {
if ($this->Attribute->data['Event']['orgc_id'] == $this->Auth->user('org_id')
&& (($this->userRole['perm_modify'] && $this->Attribute->data['Event']['user_id'] != $this->Auth->user('id'))
|| $this->userRole['perm_modify_org'])) {
// Allow the edit
} else {
return new CakeResponse(array('body'=> json_encode(array('fail' => false, 'errors' => 'You do not have permission to do that')), 'status'=>200, 'type' => 'json'));
}
$this->Attribute->id = $attribute['Attribute']['id'];
if (!$this->__canModifyEvent($attribute)) {
return new CakeResponse(array('body' => json_encode(array('fail' => false, 'errors' => 'You do not have permission to do that')), 'status' => 200, 'type' => 'json'));
}
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $this->Attribute->data['Attribute']['event_id']);
$this->Attribute->Event->insertLock($this->Auth->user(), $attribute['Attribute']['event_id']);
}
$validFields = array('value', 'category', 'type', 'comment', 'to_ids', 'distribution', 'first_seen', 'last_seen');
$changed = false;
@ -1080,15 +978,8 @@ class AttributesController extends AppController
$date = new DateTime();
$attribute['Attribute']['timestamp'] = $date->getTimestamp();
if ($this->Attribute->save($attribute)) {
$event = $this->Attribute->Event->find('first', array(
'recursive' => -1,
'fields' => array('id', 'published', 'timestamp', 'info', 'uuid'),
'conditions' => array(
'id' => $attribute['Attribute']['event_id'],
)));
$event['Event']['timestamp'] = $date->getTimestamp();
$event['Event']['published'] = 0;
$this->Attribute->Event->save($event, array('fieldList' => array('published', 'timestamp', 'info')));
$this->Attribute->Event->unpublishEvent($attribute['Attribute']['event_id']);
if ($attribute['Attribute']['object_id'] != 0) {
$this->Attribute->Object->updateTimestamp($attribute['Attribute']['object_id'], $date->getTimestamp());
}
@ -1102,31 +993,10 @@ class AttributesController extends AppController
public function view($id)
{
if (Validation::uuid($id)) {
$temp = $this->Attribute->find('first', array(
'recursive' => -1,
'conditions' => array('Attribute.uuid' => $id),
'fields' => array('Attribute.id', 'Attribute.uuid')
));
if (empty($temp)) {
throw new NotFoundException(__('Invalid attribute'));
}
$id = $temp['Attribute']['id'];
} elseif (!is_numeric($id)) {
throw new NotFoundException(__('Invalid attribute id.'));
}
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
throw new NotFoundException('Invalid attribute');
}
$conditions = array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true, 'flatten' => true);
$conditions['includeAllTags'] = false;
$conditions['includeAttributeUuid'] = true;
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), $conditions);
$attribute = $this->__fetchAttribute($id);
if (empty($attribute)) {
throw new MethodNotAllowedException('Invalid attribute');
throw new MethodNotAllowedException(__('Invalid attribute'));
}
$attribute = $attribute[0];
if ($this->_isRest()) {
if (isset($attribute['AttributeTag'])) {
foreach ($attribute['AttributeTag'] as $k => $tag) {
@ -1144,14 +1014,7 @@ class AttributesController extends AppController
public function viewPicture($id, $thumbnail=false)
{
if (Validation::uuid($id)) {
$conditions = array('Attribute.uuid' => $id);
} elseif (is_numeric($id)) {
$conditions = array('Attribute.id' => $id);
} else {
throw new NotFoundException(__('Invalid attribute id.'));
}
$conditions = $this->__idToConditions($id);
$conditions['Attribute.type'] = 'attachment';
$options = array(
'conditions' => $conditions,
@ -1335,8 +1198,8 @@ class AttributesController extends AppController
'recursive' => -1,
'fields' => array('id', 'orgc_id', 'user_id')
));
if ($event['Event']['orgc_id'] != $this->Auth->user('org_id') || (!$this->userRole['perm_modify_org'] && !($this->userRole['perm_modify'] && $event['Event']['user_id'] == $this->Auth->user('id')))) {
throw new MethodNotAllowedException(__('Invalid Event.'));
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
}
if (empty($ids)) {
@ -1612,7 +1475,7 @@ class AttributesController extends AppController
}
if ($saveSuccess) {
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $id);
$this->Attribute->Event->insertLock($this->Auth->user(), $event['Event']['id']);
}
$event['Event']['timestamp'] = $date->getTimestamp();
$event['Event']['published'] = 0;
@ -1914,13 +1777,7 @@ class AttributesController extends AppController
if (!$user) {
throw new UnauthorizedException(__('This authentication key is not authorized to be used for exports. Contact your administrator.'));
}
if (is_numeric($id)) {
$conditions = array('Attribute.id' => $id);
} elseif (Validation::uuid($id)) {
$conditions = array('Attribute.uuid' => $id);
} else {
throw new NotFoundException(__('Invalid attribute id.'));
}
$conditions = $this->__idToConditions($id);
$conditions['Attribute.type'] = array('attachment', 'malware-sample');
$attributes = $this->Attribute->fetchAttributes($user, array('conditions' => $conditions, 'flatten' => true));
if (empty($attributes)) {
@ -2125,10 +1982,6 @@ class AttributesController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This function can only be accessed via AJAX.'));
}
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
throw new NotFoundException(__('Invalid attribute'));
}
$params = array(
'conditions' => array('Attribute.id' => $id),
'fields' => array('id', 'distribution', 'event_id', $field),
@ -2145,13 +1998,11 @@ class AttributesController extends AppController
}
$attribute = $attribute[0];
$result = $attribute['Attribute'][$field];
if ($field == 'distribution') {
$result=$this->Attribute->shortDist[$result];
}
if ($field == 'to_ids') {
if ($field === 'distribution') {
$result = $this->Attribute->shortDist[$result];
} elseif ($field === 'to_ids') {
$result = ($result == 0 ? 'No' : 'Yes');
}
if ($field == 'timestamp') {
} elseif ($field === 'timestamp') {
if (isset($result)) {
$result = date('Y-m-d', $result);
} else {
@ -2172,11 +2023,6 @@ class AttributesController extends AppController
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This function can only be accessed via AJAX.'));
}
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
throw new NotFoundException(__('Invalid attribute'));
}
$fields = array('id', 'distribution', 'event_id');
if ($field == 'category' || $field == 'type') {
$fields[] = 'type';
@ -2199,22 +2045,15 @@ class AttributesController extends AppController
throw new NotFoundException(__('Invalid attribute'));
}
$attribute = $attribute[0];
if (!$this->_isSiteAdmin()) {
if ($attribute['Event']['orgc_id'] == $this->Auth->user('org_id')
&& (($this->userRole['perm_modify'] && $attribute['Event']['user_id'] != $this->Auth->user('id'))
|| $this->userRole['perm_modify_org'])) {
// Allow the edit
} else {
throw new ForbiddenException(__('You do not have permission to do that'));
}
if (!$this->__canModifyEvent($attribute)) {
throw new ForbiddenException(__('You do not have permission to do that'));
}
$this->layout = 'ajax';
if ($field == 'distribution') {
if ($field === 'distribution') {
$distributionLevels = $this->Attribute->shortDist;
unset($distributionLevels[4]);
$this->set('distributionLevels', $distributionLevels);
}
if ($field == 'category') {
} elseif ($field === 'category') {
$typeCategory = array();
foreach ($this->Attribute->categoryDefinitions as $k => $category) {
foreach ($category['types'] as $type) {
@ -2222,8 +2061,7 @@ class AttributesController extends AppController
}
}
$this->set('typeCategory', $typeCategory);
}
if ($field == 'type') {
} elseif ($field === 'type') {
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
}
$this->set('object', $attribute['Attribute']);
@ -2235,14 +2073,14 @@ class AttributesController extends AppController
public function attributeReplace($id)
{
if (!$this->userRole['perm_add']) {
throw new MethodNotAllowedException(__('Event not found or you don\'t have permissions to create attributes'));
throw new ForbiddenException(__('Event not found or you don\'t have permissions to create attributes'));
}
$event = $this->Attribute->Event->find('first', array(
'conditions' => array('Event.id' => $id),
'fields' => array('id', 'orgc_id', 'distribution'),
'fields' => array('id', 'orgc_id', 'distribution', 'user_id'),
'recursive' => -1
));
if (empty($event) || (!$this->_isSiteAdmin() && ($event['Event']['orgc_id'] != $this->Auth->user('org_id') || !$this->userRole['perm_add']))) {
if (empty($event) || !$this->__canModifyEvent($event)) {
throw new MethodNotAllowedException(__('Event not found or you don\'t have permissions to create attributes'));
}
$this->set('event_id', $id);
@ -3083,30 +2921,16 @@ class AttributesController extends AppController
public function toggleCorrelation($id)
{
if (!$this->_isSiteAdmin() && !Configure::read('MISP.allow_disabling_correlation')) {
throw new MethodNotAllowedException(__('Disabling the correlation is not permitted on this instance.'));
}
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
throw new NotFoundException(__('Invalid Attribute.'));
}
if (!$this->Auth->user('Role')['perm_modify']) {
throw new MethodNotAllowedException(__('You do not have permission to do that.'));
}
$conditions = array('Attribute.id' => $id);
if (!$this->_isSiteAdmin()) {
$conditions['Event.orgc_id'] = $this->Auth->user('org_id');
}
$attribute = $this->Attribute->find('first', array(
'conditions' => $conditions,
'conditions' => array('Attribute.id' => $id),
'recursive' => -1,
'contain' => array('Event')
));
if (empty($attribute)) {
throw new NotFoundException(__('Invalid Attribute.'));
}
if (!$this->Auth->user('Role')['perm_modify_org'] && $this->Auth->user('id') != $attribute['Event']['user_id']) {
throw new MethodNotAllowedException(__('You do not have permission to do that.'));
if (!$this->__canModifyEvent($attribute)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
if (!$this->_isRest()) {
$this->Attribute->Event->insertLock($this->Auth->user(), $attribute['Event']['id']);
@ -3200,4 +3024,37 @@ class AttributesController extends AppController
}
return $info;
}
private function __fetchAttribute($id)
{
$options = array(
'conditions' => $this->__idToConditions($id),
'contain' => array(
'Event',
),
'withAttachments' => $this->_isRest(),
'flatten' => true,
'includeAllTags' => false,
'includeAttributeUuid' => true,
'limit' => 1,
);
$attributes = $this->Attribute->fetchAttributes($this->Auth->user(), $options);
if (!empty($attributes)) {
return $attributes[0];
} else {
return null;
}
}
private function __idToConditions($id)
{
if (is_numeric($id)) {
$conditions = array('Attribute.id' => $id);
} elseif (Validation::uuid($id)) {
$conditions = array('Attribute.uuid' => $id);
} else {
throw new NotFoundException(__('Invalid attribute ID.'));
}
return $conditions;
}
}

View File

@ -1889,7 +1889,7 @@ class EventsController extends AppController
public function add()
{
if (!$this->userRole['perm_add']) {
throw new MethodNotAllowedException(__('You don\'t have permissions to create events'));
throw new MethodNotAllowedException(__('You do not have permissions to create events.'));
}
$sgs = $this->Event->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', 1);
if ($this->request->is('post')) {
@ -2053,7 +2053,7 @@ class EventsController extends AppController
{
$this->Event->recursive = -1;
$this->Event->read(null, $id);
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc_id'] != $this->_checkOrg() || !$this->userRole['perm_modify'])) {
if (!$this->__canModifyEvent($this->Event->data)) {
throw new UnauthorizedException(__('You do not have permission to do that.'));
}
if ($this->request->is('post')) {
@ -2201,6 +2201,9 @@ class EventsController extends AppController
if (empty($target_event)) {
throw new NotFoundException(__('Invalid target event.'));
}
if (!$this->__canModifyEvent($target_event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
if ($this->request->is('post')) {
$source_id = $this->Toolbox->findIdByUuid($this->Event, $source_id);
$source_event = $this->Event->fetchEvent(
@ -2301,15 +2304,13 @@ class EventsController extends AppController
}
$this->Event->read(null, $id);
// check if private and user not authorised to edit
if (!$this->_isSiteAdmin() && !($this->userRole['perm_sync'] && $this->_isRest())) {
if (($this->Event->data['Event']['orgc_id'] != $this->_checkOrg()) || !($this->userRole['perm_modify'])) {
$message = __('You are not authorised to do that. Please consider using the \'propose attribute\' feature.');
if ($this->_isRest()) {
throw new MethodNotAllowedException($message);
} else {
$this->Flash->error($message);
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
if (!$this->__canModifyEvent($this->Event->data) && !($this->userRole['perm_sync'] && $this->_isRest())) {
$message = __('You are not authorised to do that.');
if ($this->_isRest()) {
throw new ForbiddenException($message);
} else {
$this->Flash->error($message);
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
}
if (!$this->_isRest()) {
@ -2456,17 +2457,15 @@ class EventsController extends AppController
}
$event = $this->Event->find('first', array(
'conditions' => array('Event.id' => $eid),
'fields' => array('Event.orgc_id', 'Event.id'),
'fields' => array('Event.orgc_id', 'Event.id', 'Event.user_id'),
'recursive' => -1
));
if (empty($event)) {
$fails[] = $eid;
} else {
if (!$this->_isSiteAdmin()) {
if ($event['Event']['orgc_id'] != $this->_checkOrg() || !$this->userRole['perm_modify']) {
$fails[] = $eid;
continue;
}
if (!$this->__canModifyEvent($event)) {
$fails[] = $eid;
continue;
}
$this->Event->insertLock($this->Auth->user(), $event['Event']['id']);
if ($this->Event->quickDelete($event)) {
@ -2523,10 +2522,8 @@ class EventsController extends AppController
$this->Event->id = $id;
$this->Event->recursive = -1;
$event = $this->Event->read(null, $id);
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_modify'] || $this->Auth->user('org_id') !== $this->Event->data['Event']['orgc_id']) {
throw new MethodNotAllowedException(__('You don\'t have the permission to do that.'));
}
if (!$this->__canModifyEvent($this->Event->data)) {
throw new ForbiddenException(__('You do not have the permission to do that.'));
}
$this->Event->insertLock($this->Auth->user(), $id);
if ($this->request->is('post') || $this->request->is('put')) {
@ -2626,7 +2623,7 @@ class EventsController extends AppController
$event = $this->Event->read(null, $id);
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_publish'] || $this->Auth->user('org_id') !== $this->Event->data['Event']['orgc_id']) {
throw new MethodNotAllowedException(__('You don\'t have the permission to do that.'));
throw new MethodNotAllowedException(__('You do not have the permission to do that.'));
}
}
$this->Event->insertLock($this->Auth->user(), $id);
@ -2697,7 +2694,7 @@ class EventsController extends AppController
$this->Event->read(null, $id);
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_publish'] || $this->Auth->user('org_id') !== $this->Event->data['Event']['orgc_id']) {
throw new MethodNotAllowedException(__('You don\'t have the permission to do that.'));
throw new MethodNotAllowedException(__('You do not have the permission to do that.'));
}
}
$errors = array();
@ -3630,15 +3627,14 @@ class EventsController extends AppController
if (!$this->userRole['perm_add']) {
throw new MethodNotAllowedException(__('Event not found or you don\'t have permissions to create attributes'));
}
$event = $this->Event->find('first', array(
'conditions' => array('Event.id' => $id),
'fields' => array('id', 'orgc_id'),
'recursive' => -1
));
$this->set('event_id', $id);
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new MethodNotAllowedException(__('Invalid event.'));
}
$this->set('event_id', $event['Event']['id']);
if ($this->request->is('get')) {
$this->layout = 'ajax';
$this->request->data['Attribute']['event_id'] = $id;
$this->request->data['Attribute']['event_id'] = $event['Event']['id'];
}
if ($this->request->is('post')) {
@ -3712,7 +3708,7 @@ class EventsController extends AppController
unset($distributions[4]);
}
$this->set('proposals', $event['Event']['orgc_id'] != $this->Auth->user('org_id') && !$this->_isSiteAdmin());
$this->set('proposals', !$this->__canModifyEvent($event));
$this->set('distributions', $distributions);
$this->set('sgs', $sgs);
$this->set('event', $event);
@ -3908,7 +3904,6 @@ class EventsController extends AppController
foreach ($this->request->data as $k => $sa) {
if (isset($event['ShadowAttribute'])) {
foreach ($event['ShadowAttribute'] as $oldk => $oldsa) {
$temp = json_encode($oldsa);
if ($sa['event_uuid'] == $oldsa['event_uuid'] && $sa['value'] == $oldsa['value'] && $sa['type'] == $oldsa['type'] && $sa['category'] == $oldsa['category'] && $sa['to_ids'] == $oldsa['to_ids']) {
if ($oldsa['timestamp'] < $sa['timestamp']) {
$this->Event->ShadowAttribute->delete($oldsa['id']);
@ -3958,11 +3953,10 @@ class EventsController extends AppController
if (!is_numeric($id)) {
throw new MethodNotAllowedException(__('Invalid ID'));
}
$event = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id));
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new NotFoundException(__('Event not found or you are not authorised to view it.'));
}
$event = $event[0];
// #TODO i18n
$exports = array(
'xml' => array(
@ -4099,11 +4093,10 @@ class EventsController extends AppController
if (!is_numeric($id)) {
throw new MethodNotAllowedException(__('Invalid ID'));
}
$event = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id));
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new NotFoundException(__('Event not found or you are not authorised to view it.'));
}
$event = $event[0];
$imports = array(
'freetext' => array(
'url' => '/events/freeTextImport/' . $id,
@ -5208,38 +5201,28 @@ class EventsController extends AppController
if (!$this->_isSiteAdmin() && !Configure::read('MISP.allow_disabling_correlation')) {
throw new MethodNotAllowedException(__('Disabling the correlation is not permitted on this instance.'));
}
if (!$this->Auth->user('Role')['perm_modify']) {
throw new MethodNotAllowedException(__('You don\'t have permission to do that.'));
}
$conditions = array('Event.id' => $id);
if (!$this->_isSiteAdmin()) {
$conditions['Event.orgc_id'] = $this->Auth->user('org_id');
}
$event = $this->Event->find('first', array(
'conditions' => $conditions,
'recursive' => -1
));
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new NotFoundException(__('Invalid Event.'));
throw new NotFoundException(__('Invalid event'));
}
if (!$this->Auth->user('Role')['perm_modify_org'] && $this->Auth->user('id') != $event['Event']['user_id']) {
throw new MethodNotAllowedException(__('You don\'t have permission to do that.'));
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You don\'t have permission to do that.'));
}
if ($this->request->is('post')) {
if ($event['Event']['disable_correlation']) {
$event['Event']['disable_correlation'] = 0;
$this->Event->save($event);
$this->Event->Attribute->generateCorrelation(false, 0, $id);
$this->Event->Attribute->generateCorrelation(false, 0, $event['Event']['id']);
} else {
$event['Event']['disable_correlation'] = 1;
$this->Event->save($event);
$this->Event->Attribute->purgeCorrelations($id);
$this->Event->Attribute->purgeCorrelations($event['Event']['id']);
}
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('events', 'toggleCorrelation', $id, false, 'Correlation ' . ($event['Event']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
return $this->RestResponse->saveSuccessResponse('events', 'toggleCorrelation', $event['Event']['id'], false, 'Correlation ' . ($event['Event']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
} else {
$this->Flash->success('Correlation ' . ($event['Event']['disable_correlation'] ? 'disabled' : 'enabled') . '.');
$this->redirect(array('controller' => 'events', 'action' => 'view', $id));
$this->redirect(array('controller' => 'events', 'action' => 'view', $event['Event']['id']));
}
} else {
$this->set('event', $event);
@ -5249,11 +5232,11 @@ class EventsController extends AppController
public function checkPublishedStatus($id)
{
$event = $this->Event->fetchEvent($this->Auth->user(), array('metadata' => 1, 'eventid' => $id));
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new NotFoundException(__('Invalid event'));
}
return new CakeResponse(array('body'=> h($event[0]['Event']['published']), 'status'=>200, 'type' => 'txt'));
return new CakeResponse(array('body' => $event['Event']['published'], 'status' => 200, 'type' => 'txt'));
}
// #TODO i18n
public function pushEventToZMQ($id)
@ -5365,15 +5348,13 @@ class EventsController extends AppController
public function enrichEvent($id)
{
if (Validation::uuid($id)) {
$conditions = array('Event.uuid' => $id);
} else {
$conditions = array('Event.id' => $id);
}
$event = $this->Event->find('first', array('conditions' => $conditions, 'recursive' => -1));
if (empty($event) || (!$this->_isSiteAdmin() && ($this->Auth->user('org_id') != $event['Event']['orgc_id'] || !$this->userRole['perm_modify']))) {
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $id);
if (empty($event)) {
throw new MethodNotAllowedException(__('Invalid Event'));
}
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
$this->Event->insertLock($this->Auth->user(), $event['Event']['id']);
if ($this->request->is('post')) {
$modules = array();

View File

@ -2,6 +2,9 @@
App::uses('AppController', 'Controller');
/**
* @property MispObject $MispObject
*/
class ObjectsController extends AppController
{
public $uses = 'MispObject';
@ -29,11 +32,6 @@ class ObjectsController extends AppController
throw new MethodNotAllowedException(__('This action can only be reached via POST requests'));
}
$this->request->data = $this->MispObject->attributeCleanup($this->request->data);
$eventFindParams = array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.uuid', 'Event.orgc_id'),
'conditions' => array('Event.id' => $event_id)
);
$template = $this->MispObject->ObjectTemplate->find('first', array(
'conditions' => array('ObjectTemplate.id' => $template_id),
'recursive' => -1,
@ -41,10 +39,13 @@ class ObjectsController extends AppController
'ObjectTemplateElement'
)
));
$event = $this->MispObject->Event->find('first', $eventFindParams);
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
$event = $this->MispObject->Event->fetchSimpleEvent($this->Auth->user(), $event_id);
if (empty($event)) {
throw new NotFoundException(__('Invalid event.'));
}
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
$sharing_groups = array();
if ($this->request->data['Object']['distribution'] == 4) {
$sharing_groups[$this->request->data['Object']['sharing_group_id']] = false;
@ -157,13 +158,8 @@ class ObjectsController extends AppController
public function add($eventId, $templateId = false, $version = false)
{
if (!$this->userRole['perm_modify']) {
throw new MethodNotAllowedException(__('You don\'t have permissions to create objects.'));
throw new ForbiddenException(__('You don\'t have permissions to create objects.'));
}
$eventFindParams = array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.uuid', 'Event.orgc_id'),
'conditions' => array()
);
if (!empty($templateId) && Validation::uuid($templateId)) {
$conditions = array('ObjectTemplate.uuid' => $templateId);
@ -189,16 +185,12 @@ class ObjectsController extends AppController
}
}
// Find the event that is to be updated
if (Validation::uuid($eventId)) {
$eventFindParams['conditions']['Event.uuid'] = $eventId;
} elseif (is_numeric($eventId)) {
$eventFindParams['conditions']['Event.id'] = $eventId;
} else {
$event = $this->MispObject->Event->fetchSimpleEvent($this->Auth->user(), $eventId);
if (empty($event)) {
throw new NotFoundException(__('Invalid event.'));
}
$event = $this->MispObject->Event->find('first', $eventFindParams);
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
throw new NotFoundException(__('Invalid event.'));
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
$eventId = $event['Event']['id'];
if (!$this->_isRest()) {
@ -380,10 +372,10 @@ class ObjectsController extends AppController
throw new NotFoundException(__('Invalid object.'));
}
$object = $object[0];
if ((!$this->_isSiteAdmin() && $object['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
throw new MethodNotAllowedException(__('Insufficient permissions to edit this object.'));
}
$event = $this->MispObject->Event->fetchEvent($this->Auth->user(), array('eventid' => $object['Event']['id'], 'metadata' => 1))[0];
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('Insufficient permissions to edit this object.'));
}
if (!$this->_isRest()) {
$this->MispObject->Event->insertLock($this->Auth->user(), $object['Event']['id']);
}
@ -536,7 +528,7 @@ class ObjectsController extends AppController
}
$id = $temp['Object']['id'];
} elseif (!is_numeric($id)) {
throw new NotFoundException(__('Invalid event id.'));
throw new NotFoundException(__('Invalid object id.'));
}
if ((!$this->request->is('post') && !$this->request->is('put'))) {
throw new MethodNotAllowedException(__('This function can only be accessed via POST or PUT'));
@ -549,14 +541,8 @@ class ObjectsController extends AppController
if (empty($object)) {
return $this->RestResponse->saveFailResponse('Objects', 'edit', false, 'Invalid object');
}
if (!$this->_isSiteAdmin()) {
if ($this->MispObject->data['Event']['orgc_id'] == $this->Auth->user('org_id')
&& (($this->userRole['perm_modify'] && $this->MispObject->data['Event']['user_id'] != $this->Auth->user('id'))
|| $this->userRole['perm_modify_org'])) {
// Allow the edit
} else {
return $this->RestResponse->saveFailResponse('Objects', 'edit', false, 'Invalid attribute');
}
if (!$this->__canModifyEvent($object)) {
return $this->RestResponse->saveFailResponse('Objects', 'edit', false, 'You do not have permission to do that.');
}
$validFields = array('comment', 'distribution', 'first_seen', 'last_seen');
$changed = false;
@ -665,14 +651,8 @@ class ObjectsController extends AppController
throw new NotFoundException(__('Invalid attribute'));
}
$object = $object[0];
if (!$this->_isSiteAdmin()) {
if ($object['Event']['orgc_id'] == $this->Auth->user('org_id')
&& (($this->userRole['perm_modify'] && $object['Event']['user_id'] != $this->Auth->user('id'))
|| $this->userRole['perm_modify_org'])) {
// Allow the edit
} else {
throw new NotFoundException(__('Invalid object'));
}
if (!$this->__canModifyEvent($object)) {
throw new NotFoundException(__('Invalid object'));
}
$this->layout = 'ajax';
if ($field == 'distribution') {
@ -686,15 +666,8 @@ class ObjectsController extends AppController
}
// Construct a template with valid object attributes to add to an object
public function quickFetchTemplateWithValidObjectAttributes($id) {
$this->MispObject->id = $id;
if (!$this->MispObject->exists()) {
if ($this->request->is('ajax')) {
return $this->RestResponse->saveFailResponse('Objects', 'add', false, 'Invalid object', $this->response->type());
} else {
throw new NotFoundException(__('Invalid object'));
}
}
public function quickFetchTemplateWithValidObjectAttributes($id)
{
$fields = array('template_uuid', 'template_version', 'id');
$params = array(
'conditions' => array('Object.id' => $id),
@ -771,20 +744,20 @@ class ObjectsController extends AppController
* GET: Returns a form allowing to add a valid object attribute to an object
* POST/PUT: Add the attribute to the object
*/
public function quickAddAttributeForm($id, $fieldName = null) {
public function quickAddAttributeForm($id, $fieldName = null)
{
if ($this->request->is('GET')) {
if (!isset($fieldName)) {
throw new MethodNotAllowedException('No field requested.');
}
$this->MispObject->id = $id;
if (!$this->MispObject->exists()) {
throw new NotFoundException(__('Invalid object'));
}
$fields = array('template_uuid', 'template_version', 'id', 'event_id');
$params = array(
'conditions' => array('Object.id' => $id),
'fields' => $fields,
'flatten' => 1,
'contain' => array(
'Event'
)
);
// fetchObjects restrict access based on user
$object = $this->MispObject->fetchObjects($this->Auth->user(), $params);
@ -793,6 +766,9 @@ class ObjectsController extends AppController
} else {
$object = $object[0];
}
if (!$this->__canModifyEvent($object)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
$template = $this->MispObject->ObjectTemplate->find('first', array(
'conditions' => array(
'ObjectTemplate.uuid' => $object['Object']['template_uuid'],
@ -807,7 +783,7 @@ class ObjectsController extends AppController
)
));
if (empty($template)) {
throw new NotFoundException(__('Invalid object'));
throw new NotFoundException(__('Invalid template'));
}
if (empty($template['ObjectTemplateElement'])) {
throw new NotFoundException(__('Invalid fields') . ' `' . h($fieldName) . '`');
@ -843,7 +819,7 @@ class ObjectsController extends AppController
{
$id = $this->Toolbox->findIdByUuid($this->MispObject, $id);
if (!$this->userRole['perm_modify']) {
throw new MethodNotAllowedException(__('You don\'t have permissions to delete objects.'));
throw new ForbiddenException(__('You don\'t have permissions to delete objects.'));
}
$object = $this->MispObject->find('first', array(
'recursive' => -1,
@ -854,12 +830,12 @@ class ObjectsController extends AppController
)
));
if (empty($object)) {
throw new NotFoundException(__('Invalid event.'));
throw new NotFoundException(__('Invalid object.'));
}
if (!$this->__canModifyEvent($object)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
$eventId = $object['Event']['id'];
if (!$this->_isSiteAdmin() && ($object['Event']['orgc_id'] != $this->Auth->user('org_id') || !$this->userRole['perm_modify'])) {
throw new UnauthorizedException(__('You do not have permission to do that.'));
}
if (!$this->_isRest()) {
$this->MispObject->Event->insertLock($this->Auth->user(), $eventId);
}
@ -1308,5 +1284,4 @@ class ObjectsController extends AppController
$this->set('object_references', $object_references);
}
}
}

View File

@ -2,6 +2,9 @@
App::uses('AppModel', 'Model');
App::uses('TmpFileTool', 'Tools');
/**
* @property Event $Event
*/
class MispObject extends AppModel
{
public $name = 'Object';