mirror of https://github.com/MISP/MISP
Merge branch '2.4' of github.com:MISP/MISP into 2.4
commit
f7a0b1916e
|
@ -238,6 +238,7 @@ class ObjectsController extends AppController
|
|||
$this->request->data['Attribute'] = $this->request->data['Object']['Attribute'];
|
||||
unset($this->request->data['Object']['Attribute']);
|
||||
}
|
||||
$breakOnDuplicate = !empty($this->request->data['Object']['breakOnDuplicate']) || !empty($this->params['named']['breakOnDuplicate']);
|
||||
$object = $this->MispObject->attributeCleanup($this->request->data);
|
||||
// we pre-validate the attributes before we create an object at this point
|
||||
// This allows us to stop the process and return an error (API) or return
|
||||
|
@ -283,7 +284,7 @@ class ObjectsController extends AppController
|
|||
}
|
||||
if (empty($error)) {
|
||||
unset($object['Object']['id']);
|
||||
$result = $this->MispObject->saveObject($object, $eventId, $template, $this->Auth->user(), $errorBehaviour = 'halt');
|
||||
$result = $this->MispObject->saveObject($object, $eventId, $template, $this->Auth->user(), 'halt', $breakOnDuplicate);
|
||||
if (is_numeric($result)) {
|
||||
$this->MispObject->Event->unpublishEvent($eventId);
|
||||
} else {
|
||||
|
|
|
@ -63,67 +63,32 @@ class ThreadsController extends AppController
|
|||
|
||||
private function __view($thread_id, $eventView, $post_id)
|
||||
{
|
||||
$conditions = array('id' => $thread_id);
|
||||
if ($eventView) {
|
||||
$id = $thread_id;
|
||||
// Show the discussion
|
||||
$this->Thread->Behaviors->unload('SysLogLogable.SysLogLogable');
|
||||
$params = array('conditions' => array('event_id' => $id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'event_id', 'distribution', 'title', 'sharing_group_id', 'org_id')
|
||||
);
|
||||
$thread = $this->Thread->find('first', $params);
|
||||
if (!empty($thread)) {
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if ($thread['Thread']['distribution'] == 0 && $thread['Thread']['org_id'] != $this->Auth->user('org_id')) {
|
||||
throw new MethodNotAllowedException('Invalid Thread.');
|
||||
}
|
||||
if ($thread['Thread']['distribution'] == 4) {
|
||||
if (!$this->Thread->SharingGroup->checkIfAuthorised($this->Auth->user(), $thread['Thread']['sharing_group_id'])) {
|
||||
new NotFoundException('Invalid thread.');
|
||||
}
|
||||
}
|
||||
}
|
||||
$thread_id = $thread['Thread']['id'];
|
||||
} else {
|
||||
$thread_id = 0;
|
||||
$event_id = $thread_id;
|
||||
if (!$this->request->is('ajax')) {
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $event_id));
|
||||
}
|
||||
$this->set('currentEvent', $id);
|
||||
$conditions = array('event_id' => $event_id);
|
||||
$this->set('currentEvent', $event_id);
|
||||
$this->set('event_id', $event_id);
|
||||
$this->set('context', 'event');
|
||||
} else {
|
||||
$this->Thread->recursive = -1;
|
||||
$this->Thread->id = $thread_id;
|
||||
|
||||
//If the thread doesn't exist, throw exception
|
||||
if (!$this->Thread->exists()) {
|
||||
$this->set('context', 'thread');
|
||||
}
|
||||
$this->set('myuserid', $this->Auth->user('id'));
|
||||
$thread = $this->Thread->find('first', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1
|
||||
));
|
||||
if (empty($thread)) {
|
||||
if (!$eventView) {
|
||||
throw new NotFoundException('Invalid thread.');
|
||||
}
|
||||
$thread = $this->Thread->read();
|
||||
|
||||
// If the thread belongs to an event, we have to make sure that the event's distribution level hasn't changed.
|
||||
// This is also a good time to update the thread's distribution level if that did happen.
|
||||
if (!empty($thread['Thread']['event_id'])) {
|
||||
$this->loadModel('Event');
|
||||
$this->Event->id = $thread['Thread']['event_id'];
|
||||
$this->Event->recursive = -1;
|
||||
$this->Event->read(array('id', 'distribution', 'org_id', 'sharing_group_id'));
|
||||
if ($this->Event->data['Event']['distribution'] != $thread['Thread']['distribution']) {
|
||||
$this->Thread->saveField('distribution', $this->Event->data['Event']['distribution']);
|
||||
}
|
||||
if ($this->Event->data['Event']['sharing_group_id'] != $thread['Thread']['sharing_group_id']) {
|
||||
$this->Thread->saveField('sharing_group_id', $this->Event->data['Event']['sharing_group_id']);
|
||||
}
|
||||
$this->set('event_id', $thread['Thread']['event_id']);
|
||||
}
|
||||
|
||||
// If the user shouldn't be allowed to see the event send him away.
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if ($thread['Thread']['distribution'] == 0 && $thread['Thread']['org_id'] != $this->Auth->user('org_id')) {
|
||||
throw new MethodNotAllowedException('Invalid Thread.');
|
||||
}
|
||||
if ($thread['Thread']['distribution'] == 4) {
|
||||
if (!$this->Thread->SharingGroup->checkIfAuthorised($this->Auth->user(), $thread['Thread']['sharing_group_id'])) {
|
||||
new NotFoundException('Invalid thread.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$thread_id = $thread['Thread']['id'];
|
||||
if (!$this->Thread->checkIfAuthorised($this->Auth->user(), $thread_id)) {
|
||||
throw new NotFoundException('Invalid thread.');
|
||||
}
|
||||
}
|
||||
if ($thread_id) {
|
||||
|
@ -166,15 +131,6 @@ class ThreadsController extends AppController
|
|||
$this->set('thread', $thread);
|
||||
}
|
||||
}
|
||||
if ($eventView) {
|
||||
$this->set('context', 'event');
|
||||
if (!$this->request->is('ajax')) {
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $id));
|
||||
}
|
||||
} else {
|
||||
$this->set('context', 'thread');
|
||||
}
|
||||
$this->set('myuserid', $this->Auth->user('id'));
|
||||
if ($this->request->is('ajax')) {
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/Elements/eventdiscussion');
|
||||
|
@ -185,7 +141,7 @@ class ThreadsController extends AppController
|
|||
{
|
||||
$this->loadModel('Posts');
|
||||
$this->loadModel('SharingGroup');
|
||||
$sgids = $this->SharingGroup->fetchAllAuthorised($this->Auth->user);
|
||||
$sgids = $this->SharingGroup->fetchAllAuthorised($this->Auth->user());
|
||||
$conditions = null;
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
$conditions['AND']['OR'] = array(
|
||||
|
@ -206,7 +162,7 @@ class ThreadsController extends AppController
|
|||
}
|
||||
$conditions['AND'][] = array('Thread.post_count >' => 0);
|
||||
$this->paginate = array(
|
||||
'conditions' => array($conditions),
|
||||
'conditions' => $conditions,
|
||||
'fields' => array('date_modified', 'date_created', 'org_id', 'distribution', 'title', 'post_count', 'sharing_group_id'),
|
||||
'contain' => array(
|
||||
'Post' =>array(
|
||||
|
|
|
@ -1066,6 +1066,7 @@ class UsersController extends AppController
|
|||
$this->Bruteforce = ClassRegistry::init('Bruteforce');
|
||||
if (!empty($this->request->data['User']['email'])) {
|
||||
if ($this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
|
||||
$expire = Configure::check('SecureAuth.expire') ? Configure::read('SecureAuth.expire') : 300;
|
||||
throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
|
||||
}
|
||||
}
|
||||
|
@ -1116,7 +1117,7 @@ class UsersController extends AppController
|
|||
$this->Session->delete('Message.auth');
|
||||
}
|
||||
// don't display "invalid user" before first login attempt
|
||||
if ($this->request->is('post')) {
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
$this->Flash->error(__('Invalid username or password, try again'));
|
||||
if (isset($this->request->data['User']['email'])) {
|
||||
$this->Bruteforce->insert($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email']);
|
||||
|
|
|
@ -9,17 +9,19 @@ class Bruteforce extends AppModel
|
|||
{
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$expire = time() + Configure::read('SecureAuth.expire');
|
||||
$expire = Configure::check('SecureAuth.expire') ? Configure::read('SecureAuth.expire') : 300;
|
||||
$amount = Configure::check('SecureAuth.amount') ? Configure::read('SecureAuth.amount') : 5;
|
||||
$expire = time() + $expire;
|
||||
$expire = date('Y-m-d H:i:s', $expire);
|
||||
$bruteforceEntry = array(
|
||||
'ip' => $ip,
|
||||
'username' => $username,
|
||||
'username' => trim(strtolower($username)),
|
||||
'expire' => $expire
|
||||
);
|
||||
$this->save($bruteforceEntry);
|
||||
$title = 'Failed login attempt using username ' . $username . ' from IP: ' . $_SERVER['REMOTE_ADDR'] . '.';
|
||||
if ($this->isBlacklisted($ip, $username)) {
|
||||
$title .= 'This has tripped the bruteforce protection after ' . Configure::read('SecureAuth.amount') . ' failed attempts. The user is now blacklisted for ' . Configure::read('SecureAuth.expire') . ' seconds.';
|
||||
$title .= 'This has tripped the bruteforce protection after ' . $amount . ' failed attempts. The user is now blacklisted for ' . $expire . ' seconds.';
|
||||
}
|
||||
$log = array(
|
||||
'org' => 'SYSTEM',
|
||||
|
@ -36,10 +38,11 @@ class Bruteforce extends AppModel
|
|||
{
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
$expire = date('Y-m-d H:i:s', time());
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'DELETE FROM bruteforces WHERE `expire` <= NOW();';
|
||||
$sql = 'DELETE FROM bruteforces WHERE `expire` <= "' . $expire . '";';
|
||||
} elseif ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'DELETE FROM bruteforces WHERE expire <= NOW();';
|
||||
$sql = 'DELETE FROM bruteforces WHERE expire <= "' . $expire . '";';
|
||||
}
|
||||
$this->query($sql);
|
||||
}
|
||||
|
@ -49,11 +52,14 @@ class Bruteforce extends AppModel
|
|||
// first remove old expired rows
|
||||
$this->clean();
|
||||
// count
|
||||
$params = array('conditions' => array(
|
||||
'Bruteforce.ip' => $ip,
|
||||
'Bruteforce.username' => $username),);
|
||||
$params = array(
|
||||
'conditions' => array(
|
||||
'Bruteforce.ip' => $ip,
|
||||
'LOWER(Bruteforce.username)' => trim(strtolower($username)))
|
||||
);
|
||||
$count = $this->find('count', $params);
|
||||
if ($count >= Configure::read('SecureAuth.amount')) {
|
||||
$amount = Configure::check('SecureAuth.amount') ? Configure::read('SecureAuth.amount') : 5;
|
||||
if ($count >= $amount) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -203,8 +203,49 @@ class MispObject extends AppModel
|
|||
}
|
||||
}
|
||||
|
||||
public function saveObject($object, $eventId, $template = false, $user, $errorBehaviour = 'drop')
|
||||
public function checkForDuplicateObjects($object, $eventId)
|
||||
{
|
||||
$newObjectAttributes = array();
|
||||
$existingObjectAttributes = array();
|
||||
foreach ($object['Attribute'] as $attribute) {
|
||||
$newObjectAttributes[] = hash('sha256', $attribute['object_relation'] . $attribute['category'] . $attribute['type'] . $attribute['value']);
|
||||
}
|
||||
$newObjectAttributeCount = count($newObjectAttributes);
|
||||
$existingObjects = $this->find('all', array(
|
||||
'recursive' => -1,
|
||||
'contain' => array(
|
||||
'Attribute' => array(
|
||||
'fields' => array('value', 'type', 'category', 'object_relation'),
|
||||
'conditions' => array('Attribute.deleted' => 0)
|
||||
)
|
||||
),
|
||||
'fields' => array('template_uuid'),
|
||||
'conditions' => array('template_uuid' => $object['Object']['template_uuid'], 'Object.deleted' => 0)
|
||||
));
|
||||
$oldObjects = array();
|
||||
foreach ($existingObjects as $k => $existingObject) {
|
||||
if (!empty($existingObject['Attribute']) && $newObjectAttributeCount == count($existingObject['Attribute'])) {
|
||||
foreach ($existingObject['Attribute'] as $existingAttribute) {
|
||||
$oldObjects[$k][] = hash('sha256',
|
||||
$attribute['object_relation'] . $existingAttribute['category'] . $existingAttribute['type'] . $existingAttribute['value']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($oldObjects as $k => $object) {
|
||||
if (empty(array_diff($object, $newObjectAttributes))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function saveObject($object, $eventId, $template = false, $user, $errorBehaviour = 'drop', $breakOnDuplicate = false)
|
||||
{
|
||||
if ($breakOnDuplicate) {
|
||||
$duplicate = $this->checkForDuplicateObjects($object, $eventId);
|
||||
return array('value' => array('Duplicate object found. Since breakOnDuplicate is set the object will not be added.'));
|
||||
}
|
||||
$this->create();
|
||||
$templateFields = array(
|
||||
'name' => 'name',
|
||||
|
|
|
@ -38,4 +38,51 @@ class Thread extends AppModel
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// convenience method to check whether a user can see an event
|
||||
public function checkIfAuthorised($user, $id)
|
||||
{
|
||||
if (!isset($user['id'])) {
|
||||
throw new MethodNotAllowedException('Invalid user.');
|
||||
}
|
||||
$this->id = $id;
|
||||
if (!$this->exists()) {
|
||||
return false;
|
||||
}
|
||||
$thread = $this->find('first', array(
|
||||
'conditions' => array('id' => $id),
|
||||
'recursive' => -1
|
||||
));
|
||||
if (!empty($thread['Thread']['event_id'])) {
|
||||
$event = $this->Event->fetchEvent($user, array(
|
||||
'eventid' => $thread['Thread']['event_id'],
|
||||
'metadata' => true
|
||||
));
|
||||
if (empty($event)) {
|
||||
return false;
|
||||
}
|
||||
$event = $event[0];
|
||||
// update the distribution if it diverged from the event
|
||||
if (
|
||||
$event['Event']['distribution'] != $thread['Thread']['distribution'] ||
|
||||
$event['Event']['sharing_group_id'] != $thread['Thread']['sharing_group_id']
|
||||
) {
|
||||
$this->Behaviors->unload('SysLogLogable.SysLogLogable');
|
||||
$thread['Thread']['distribution'] = $event['Event']['distribution'];
|
||||
$thread['Thread']['sharing_group_id'] = $event['Event']['sharing_group_id'];
|
||||
$this->save($thread);
|
||||
}
|
||||
return !empty($event);
|
||||
}
|
||||
if ($user['Role']['perm_site_admin']) {
|
||||
return true;
|
||||
}
|
||||
if ($thread['Thread']['org_id'] == $user['org_id'] || ($thread['Thread']['distribution'] > 0 && $thread['Thread']['distribution'] < 4)) {
|
||||
return true;
|
||||
}
|
||||
if ($thread['Thread']['distribution'] == 4 && $this->SharingGroup->checkIfAuthorised($user, $thread['Thread']['sharing_group_id'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue