fix: [security] Permission for tag collections

pull/8706/head
Jakub Onderka 2022-10-25 19:38:15 +02:00
parent 03327213f1
commit c4dcea7834
6 changed files with 120 additions and 106 deletions

View File

@ -954,6 +954,22 @@ class ACLComponent extends Component
return Configure::read('MISP.allow_disabling_correlation') && $this->canModifyEvent($user, $event);
}
/**
* @param array $user
* @param array $tagCollection
* @return bool
*/
public function canModifyTagCollection(array $user, array $tagCollection)
{
if (!isset($tagCollection['TagCollection'])) {
throw new InvalidArgumentException('Passed object does not contain a TagCollection.');
}
if (!empty($user['Role']['perm_site_admin'])) {
return true;
}
return $user['org_id'] == $tagCollection['TagCollection']['org_id'];
}
private function __checkLoggedActions($user, $controller, $action)
{
$loggedActions = array(

View File

@ -519,6 +519,10 @@ class GalaxiesController extends AppController
if (!$this->ACL->canModifyTag($user, $target, $local)) {
throw new ForbiddenException(__('No permission to attach this cluster to given target.'));
}
} else {
if (!$this->ACL->canModifyTagCollection($user, $target)) {
throw new ForbiddenException(__('No permission to attach this cluster to given target.'));
}
}
$result = $this->Galaxy->attachCluster($user, $target_type, $target_id, $cluster_id, $local);
@ -572,6 +576,10 @@ class GalaxiesController extends AppController
if (!$this->ACL->canModifyTag($user, $target, $local)) {
throw new ForbiddenException(__('No permission to attach this cluster to given target.'));
}
} else {
if (!$this->ACL->canModifyTagCollection($user, $target)) {
throw new ForbiddenException(__('No permission to attach this cluster to given target.'));
}
}
$result = $this->Galaxy->attachCluster($user, $target_type, $target, $cluster_id, $local);
if ($mirrorOnEventRequested) {

View File

@ -76,7 +76,7 @@ class TagCollectionsController extends AppController
{
if ($this->request->is('post')) {
if (isset($this->request->data['TagCollection']['json'])) {
$data = json_decode($this->request->data['TagCollection']['json'], true);
$data = $this->_jsonDecode($this->request->data['TagCollection']['json']);
} else {
$data = $this->request->data;
}
@ -108,32 +108,20 @@ class TagCollectionsController extends AppController
public function view($id)
{
$conditions = array();
if (!$this->_isSiteAdmin()) {
$conditions = array(
'OR' => array(
'TagCollection.all_orgs' => 1,
'TagCollection.org_id' => $this->Auth->user('org_id')
)
);
$this->paginate['conditions'] = $conditions;
}
$conditions = $this->TagCollection->createConditions($this->Auth->user());
$conditions['TagCollection.id'] = $id;
$params = array(
$collection = $this->TagCollection->find('first', array(
'recursive' => -1,
'contain' => array('TagCollectionTag' => array('Tag'), 'Organisation' => array('fields' => array('id', 'name', 'uuid')), 'User' => array('fields' => array('User.id', 'User.email')))
);
if (!empty($conditions)) {
$params['conditions'] = $conditions;
}
$collection = $this->TagCollection->find('first', $params);
'contain' => array('TagCollectionTag' => array('Tag'), 'Organisation' => array('fields' => array('id', 'name', 'uuid')), 'User' => array('fields' => array('User.id', 'User.email'))),
'conditions' => $conditions,
));
if (empty($collection)) {
throw new NotFoundException('Invalid Tag Collection');
}
$collection = $this->TagCollection->cullBlockedTags($this->Auth->user(), $collection);
$this->loadModel('Event');
$collection = $this->Event->massageTags($this->Auth->user(), $collection, 'TagCollection', false, true);
if (!$this->_isSiteAdmin() && $collection['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
if (!$this->ACL->canModifyTagCollection($this->Auth->user(), $collection)) {
unset($collection['User']);
unset($collection['TagCollection']['user_id']);
}
@ -151,15 +139,16 @@ class TagCollectionsController extends AppController
public function edit($id)
{
$this->TagCollection->id = $id;
if (!$this->TagCollection->exists()) {
throw new NotFoundException(__('Invalid Tag Collection'));
}
$conditions = $this->TagCollection->createConditions($this->Auth->user());
$conditions['TagCollection.id'] = $id;
$tagCollection = $this->TagCollection->find('first', array(
'conditions' => array('TagCollection.id' => $id),
'conditions' => $conditions,
'recursive' => -1
));
if (!$this->_isSiteAdmin() && $tagCollection['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
if (empty($tagCollection)) {
throw new NotFoundException(__('Invalid Tag Collection'));
}
if (!$this->ACL->canModifyTagCollection($this->Auth->user(), $tagCollection)) {
throw new MethodNotAllowedException(__('You don\'t have editing rights on this Tag Collection.'));
}
if ($this->request->is('post') || $this->request->is('put')) {
@ -203,7 +192,7 @@ class TagCollectionsController extends AppController
throw new NotFoundException(__('Invalid tag collection.'));
}
$tagCollection = $tagCollection[0];
if ($this->TagCollection->checkAccess($this->Auth->user(), $tagCollection, 'write')) {
if ($this->ACL->canModifyTagCollection($this->Auth->user(), $tagCollection)) {
$result = $this->TagCollection->delete($id);
if ($result) {
$message = __('Tag collection deleted.');
@ -258,10 +247,10 @@ class TagCollectionsController extends AppController
}
$tag_id = $this->request->data['tag'];
}
$conditions = array();
$tagConditions = array();
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
$tagConditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$tagConditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
}
if (!is_numeric($tag_id)) {
$tag_ids = json_decode($tag_id);
@ -277,7 +266,7 @@ class TagCollectionsController extends AppController
$tag_ids = $this->TagCollection->TagCollectionTag->Tag->find('list', array(
'conditions' => array(
'AND' => array(
$conditions,
$tagConditions,
$tag_lookups
)
),
@ -288,24 +277,27 @@ class TagCollectionsController extends AppController
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag(s).')), 'status'=>200, 'type' => 'json'));
}
} else {
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array('recursive' => -1, 'conditions' => $tagConditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
}
$conditions = $this->TagCollection->createConditions($this->Auth->user());
$conditions['TagCollection.id'] = $id;
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array('TagCollection.id' => $id)
'conditions' => $conditions,
));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid tag collection.')), 'status'=>200, 'type' => 'json'));
}
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $tagCollection['TagCollection']['org_id'])) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
if (!$this->ACL->canModifyTagCollection($this->Auth->user(), $tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid tag collection.')), 'status'=>200, 'type' => 'json'));
}
if (!$this->ACL->canModifyTagCollection($this->Auth->user(), $tagCollection) || !$this->userRole['perm_tagger']) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
$this->autoRender = false;
$success = false;
@ -314,13 +306,13 @@ class TagCollectionsController extends AppController
}
foreach ($tag_id_list as $tag_id) {
$conditions = ['Tag.id' => $tag_id];
$tagConditions = ['Tag.id' => $tag_id];
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
$tagConditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$tagConditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
}
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array(
'conditions' => $conditions,
'conditions' => $tagConditions,
'recursive' => -1,
'fields' => array('Tag.name')
));
@ -360,16 +352,21 @@ class TagCollectionsController extends AppController
public function removeTag($id = false, $tag_id = false)
{
$conditions = $this->TagCollection->createConditions($this->Auth->user());
$conditions['TagCollection.id'] = $id;
if (!$this->request->is('post')) {
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array(
'TagCollection.id' => $id
),
'conditions' => $conditions,
));
if (!$tagCollection) {
throw new NotFoundException(__('Invalid tag collection.'));
}
if ($this->ACL->canModifyTagCollection($this->Auth->user(), $tagCollection)) {
throw new ForbiddenException(__('You dont have a permission to do that'));
}
$tagCollectionTag = $this->TagCollection->TagCollectionTag->find('first', [
'recursive' => -1,
'conditions' => [
@ -407,9 +404,7 @@ class TagCollectionsController extends AppController
}
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array(
'TagCollection.id' => $id
),
'conditions' => $conditions,
'contain' => array(
'TagCollectionTag' => array(
'Tag'
@ -419,10 +414,10 @@ class TagCollectionsController extends AppController
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Invalid tag collection.'))), 'status' => 200, 'type' => 'json'));
}
$found = false;
if (!$this->_isSiteAdmin() && $this->Auth->user('org_id') !== $tagCollection['TagCollection']['org_id']) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Insufficient privileges to remove the tag from the collection.'))), 'status' => 200, 'type' => 'json'));
if ($this->ACL->canModifyTagCollection($this->Auth->user(), $tagCollection)) {
throw new ForbiddenException(__('You dont have a permission to do that'));
}
$found = false;
foreach ($tagCollection['TagCollectionTag'] as $TagCollectionTag) {
if ((is_numeric($tag_id) && $TagCollectionTag['Tag']['id'] == $tag_id) || $TagCollectionTag['Tag']['name'] === $tag_id) {
$found = true;
@ -446,16 +441,9 @@ class TagCollectionsController extends AppController
public function index()
{
$conditions = array();
if (!$this->_isSiteAdmin()) {
$conditions = array(
'OR' => array(
'TagCollection.all_orgs' => 1,
'TagCollection.org_id' => $this->Auth->user('org_id')
)
);
$this->paginate['conditions'] = $conditions;
}
$user = $this->Auth->user();
$conditions = $this->TagCollection->createConditions($user);
if ($this->_isRest()) {
$params = array(
'recursive' => -1,
@ -476,11 +464,9 @@ class TagCollectionsController extends AppController
'User.id'
)
)
)
),
'conditions' => $conditions,
);
if (!empty($conditions)) {
$params['conditions'] = $conditions;
}
$namedParams = array('limit', 'page');
foreach ($namedParams as $namedParam) {
if (!empty($this->params['named'][$namedParam])) {
@ -489,25 +475,27 @@ class TagCollectionsController extends AppController
}
$list = $this->TagCollection->find('all', $params);
} else {
$this->paginate['conditions'] = $conditions;
$list = $this->paginate();
}
$this->loadModel('Event');
foreach ($list as $k => $tag_collection) {
$list[$k] = $this->TagCollection->cullBlockedTags($this->Auth->user(), $tag_collection);
$list[$k] = $this->Event->massageTags($this->Auth->user(), $list[$k], 'TagCollection', false, true);
if (!$this->_isSiteAdmin() && $list[$k]['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
unset($list[$k]['User']);
unset($list[$k]['TagCollection']['user_id']);
$tag_collection = $this->TagCollection->cullBlockedTags($user, $tag_collection);
$tag_collection = $this->Event->massageTags($user, $tag_collection, 'TagCollection', false, true);
if (!$this->ACL->canModifyTagCollection($user, $tag_collection)) {
unset($tag_collection['User']);
unset($tag_collection['TagCollection']['user_id']);
}
if (!empty($list[$k]['TagCollectionTag'])) {
foreach ($list[$k]['TagCollectionTag'] as $k2 => $tct) {
$list[$k]['TagCollectionTag'][$k2]['Tag'] = array(
if (!empty($tag_collection['TagCollectionTag'])) {
foreach ($tag_collection['TagCollectionTag'] as $k2 => $tct) {
$tag_collection['TagCollectionTag'][$k2]['Tag'] = array(
'id' => $tct['Tag']['id'],
'name' => $tct['Tag']['name'],
'colour' => $tct['Tag']['colour']
);
}
}
$list[$k] = $tag_collection;
}
if ($this->_isRest()) {
return $this->RestResponse->viewData($list, $this->response->type());
@ -518,16 +506,17 @@ class TagCollectionsController extends AppController
public function getRow($id)
{
$params = array(
$conditions = $this->TagCollection->createConditions($this->Auth->user());
$conditions['TagCollection.id'] = $id;
$item = $this->TagCollection->find('first', array(
'recursive' => -1,
'contain' => array('TagCollectionTag' => array('Tag'), 'User', 'Organisation'),
'conditions' => array('TagCollection.id' => $id)
);
$item = $this->TagCollection->find('first', $params);
'conditions' => $conditions
));
if (empty($item)) {
throw new NotFoundException('Invalid tag collection.');
}
if (!$this->_isSiteAdmin() && $item['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
if (!$this->ACL->canModifyTagCollection($this->Auth->user(), $item)) {
unset($item['User']);
unset($item['TagCollection']['user_id']);
}

View File

@ -32,8 +32,6 @@ class TagCollection extends AppModel
)
);
public $allowedlistedItems = false;
public $validate = array(
'name' => array(
'valueNotEmpty' => array(
@ -67,12 +65,7 @@ class TagCollection extends AppModel
public function fetchTagCollection(array $user, $params = array())
{
if (empty($user['Role']['perm_site_admin'])) {
$params['conditions']['AND'][] = array(
'OR' => array(
'TagCollection.org_id' => $user['org_id'],
'TagCollection.all_orgs' => 1
)
);
$params['conditions']['AND'][] = $this->createConditions($user);
}
if (empty($params['contain'])) {
$params['contain'] = array(
@ -86,25 +79,6 @@ class TagCollection extends AppModel
return $tagCollections;
}
public function checkAccess($user, $tagCollection, $accessLevel = 'read')
{
if (isset($tagCollection['TagCollection'])) {
$tagCollection = $tagCollection['TagCollection'];
}
if (!empty($user['Role']['perm_site_admin'])) {
return true;
}
if (!$tagCollection['all_orgs'] && $user['org_id'] != $tagCollection['org_id']) {
return false;
}
if ($accessLevel === 'write') {
if ($tagCollection['org_id'] !== $user['org_id']) {
return false;
}
}
return true;
}
/**
* @param array $user
* @param array $tagCollections
@ -199,4 +173,20 @@ class TagCollection extends AppModel
}
return $results;
}
/**
* @param array $user
* @return array[]
*/
public function createConditions(array $user)
{
if ($user['Role']['perm_site_admin']) {
return [];
}
return ['OR' => [
'TagCollection.all_orgs' => 1,
'TagCollection.org_id' => $user['org_id'],
]];
}
}

View File

@ -1,3 +1,4 @@
<?php $canModify = $this->Acl->canModifyTagCollection($item) ?>
<tr data-row-id="<?php echo h($item['TagCollection']['id']); ?>">
<td class="short"><?php echo h($item['TagCollection']['id']);?></td>
<td class="short"><?php echo h($item['TagCollection']['uuid']);?></td>
@ -10,7 +11,7 @@
array(
'attributeId' => $item['TagCollection']['id'],
'attributeTags' => $item['TagCollectionTag'],
'tagAccess' => ($isSiteAdmin || $me['org_id'] == $item['TagCollection']['org_id']),
'tagAccess' => $canModify,
'context' => 'tagCollection',
'tagCollection' => $item
)
@ -21,7 +22,7 @@
<td class="shortish">
<?php
echo $this->element('galaxyQuickViewNew', array(
'tagAccess' => ($isSiteAdmin || $me['org_id'] == $item['TagCollection']['org_id']),
'tagAccess' => $canModify,
'localTagAccess' => false,
'data' => $item['Galaxy'],
'target_id' => h($item['TagCollection']['id']),
@ -40,7 +41,7 @@
<td><?php echo h($item['TagCollection']['description']);?></td>
<td class="short action-links">
<?php
if ($isSiteAdmin || $me['org_id'] == $item['TagCollection']['org_id']) {
if ($canModify) {
echo $this->Html->link('', array('action' => 'edit', $item['TagCollection']['id']), array('class' => 'fa fa-edit', 'title' => __('Edit')));
echo $this->Form->postLink('', array('action' => 'delete', $item['TagCollection']['id']), array('class' => 'fa fa-trash', 'title' => __('Delete')), __('Are you sure you want to delete "%s"?', $item['TagCollection']['name']));
}

View File

@ -63,4 +63,14 @@ class AclHelper extends Helper
$me = $this->_View->viewVars['me'];
return $this->ACL->canDisableCorrelation($me, $event);
}
/**
* @param array $tagCollection
* @return bool
*/
public function canModifyTagCollection(array $tagCollection)
{
$me = $this->_View->viewVars['me'];
return $this->ACL->canModifyTagCollection($me, $tagCollection);
}
}