Merge branch '2.4' into issues_1643

pull/1809/head
devnull- 2017-02-16 21:49:45 +01:00 committed by GitHub
commit f24682f86a
104 changed files with 3257 additions and 980 deletions

4
.gitignore vendored
View File

@ -1,6 +1,9 @@
/vendors
/app/Vendor
/app/composer*
!/app/composer.phar
!/app/composer.license
/app/composer.json
/lib
/.project
/.settings
@ -9,7 +12,6 @@
.DS_Store
/.htaccess
/app/Vendor
/app/composer*
/README
/app/tmp/GPG*
/app/tmp/sessions/sess_*

View File

@ -9,10 +9,11 @@ Contributors
Aaron Kaplan
Airbus Group CERT (AiG CERT)
Alexander J
Alexander Jaeger
Alexandre Dulaunoy
Alexandru Ciobanu
Andras Iklody
Andreas Ziegler
Andrzej Dereszowski
Bâkır Emre
Chris Clark
@ -34,6 +35,7 @@ Copyright (C) 2012 Belgian Defence
Copyright (C) 2012 NATO / NCIRC
Copyright (C) 2013-2016 Andras Iklody
Copyright (C) 2015-2016 CIRCL - Computer Incident Response Center Luxembourg
Copyright (C) 2016 Andreas Ziegler
MISP is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE version 3.

View File

@ -76,7 +76,6 @@ git submodule update
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
cd /var/www/MISP/app
curl -s https://getcomposer.org/installer | php
php composer.phar require kamisama/cake-resque:4.1.2
php composer.phar config vendor-dir Vendor
php composer.phar install
@ -138,8 +137,14 @@ service apache2 reload
# We seriously recommend using only SSL !
# Check out the /var/www/MISP/INSTALL/apache.misp.ssl file for an example
8/ Log rotation
---------------
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
# To rotate these logs install the supplied logrotate script:
8/ MISP configuration
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
9/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config

View File

@ -42,7 +42,7 @@ sudo a2dissite 000-default
sudo a2ensite default-ssl
# Install PHP and dependencies
sudo apt-get install libapache2-mod-php5 php5 php5-cli php-crypt-gpg php5-dev php5-json php5-mysql php5-readline php5-redis
sudo apt-get install libapache2-mod-php5 php5 php5-cli php-crypt-gpg php5-dev php5-json php5-xml php5-mysql php5-readline php5-redis
# Apply all changes
sudo systemctl restart apache2
@ -86,7 +86,6 @@ sudo -u www-data git submodule update
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
cd /var/www/MISP/app
sudo -u www-data wget https://getcomposer.org/download/1.2.1/composer.phar -O composer.phar
sudo -u www-data php composer.phar require kamisama/cake-resque:4.1.2
sudo -u www-data php composer.phar config vendor-dir Vendor
sudo -u www-data php composer.phar install
@ -184,8 +183,14 @@ sudo a2ensite misp-ssl
# Restart apache
sudo systemctl restart apache2
8/ Log rotation
---------------
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
# To rotate these logs install the supplied logrotate script:
8/ MISP configuration
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
9/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php

View File

@ -27,7 +27,7 @@ Once the system is installed you can perform the following steps as root:
apt-get install vim
# Install the dependencies:
apt-get install gcc zip php-pear git redis-server make python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev php5-dev libapache2-mod-php5 php5-mysql php5-json php5-redis curl gnupg-agent
apt-get install gcc zip php-pear git redis-server make python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev php5-dev php5-xml libapache2-mod-php5 php5-mysql php5-json php5-redis curl gnupg-agent
pear install Crypt_GPG # we need version >1.3.0
3/ MISP code
@ -67,7 +67,6 @@ git submodule update
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
cd /var/www/MISP/app
curl -s https://getcomposer.org/installer | php
php composer.phar require kamisama/cake-resque:4.1.2
php composer.phar config vendor-dir Vendor
php composer.phar install
@ -129,8 +128,14 @@ service apache2 reload
# We seriously recommend using only SSL !
# Check out the apache.misp.ssl file for an example
8/ Log rotation
---------------
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
# To rotate these logs install the supplied logrotate script:
8/ MISP configuration
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
9/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config

View File

@ -43,7 +43,7 @@ sudo a2dissite 000-default
sudo a2ensite default-ssl
# Install PHP and dependencies
sudo apt-get install libapache2-mod-php php php-cli php-crypt-gpg php-dev php-json php-mysql php-opcache php-readline php-redis
sudo apt-get install libapache2-mod-php php php-cli php-crypt-gpg php-dev php-json php-mysql php-opcache php-readline php-redis php-xml
# Apply all changes
sudo systemctl restart apache2
@ -87,7 +87,6 @@ sudo -u www-data git submodule update
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
cd /var/www/MISP/app
sudo -u www-data wget https://getcomposer.org/download/1.2.1/composer.phar -O composer.phar
sudo -u www-data php composer.phar require kamisama/cake-resque:4.1.2
sudo -u www-data php composer.phar config vendor-dir Vendor
sudo -u www-data php composer.phar install
@ -185,8 +184,14 @@ sudo a2ensite misp-ssl
# Restart apache
sudo systemctl restart apache2
8/ Log rotation
---------------
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
# To rotate these logs install the supplied logrotate script:
8/ MISP configuration
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
9/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php

View File

@ -39,6 +39,23 @@ CREATE TABLE IF NOT EXISTS `attributes` (
UNIQUE INDEX `uuid` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- -------------------------------------------------------
--
-- Table structure for table `attribute_tags`
--
CREATE TABLE IF NOT EXISTS `attribute_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attribute_id` int(11) NOT NULL,
`event_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `attribute_id` (`attribute_id`),
INDEX `event_id` (`event_id`),
INDEX `tag_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--

View File

@ -39,6 +39,23 @@ CREATE INDEX idx_attributes_sharing_group_id ON attributes (sharing_group_id);
CREATE INDEX idx_attributes_value1 ON attributes (value1);
CREATE INDEX idx_attributes_value2 ON attributes (value2);
-- -------------------------------------------------------
--
-- Table structure for table attribute_tags
--
CREATE TABLE IF NOT EXISTS attribute_tags (
id bigserial NOT NULL,
attribute_id bigint NOT NULL,
event_id bigint NOT NULL,
tag_id bigint NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_attribute_tags_attribute_id ON attribute_tags (attribute_id);
CREATE INDEX idx_attribute_tags_event_id ON attribute_tags (event_id);
CREATE INDEX idx_attribute_tags_tag_id ON attribute_tags (tag_id);
-- --------------------------------------------------------
--

9
INSTALL/misp.logrotate Normal file
View File

@ -0,0 +1,9 @@
/var/www/MISP/app/tmp/logs/resque-*-error.log {
rotate 30
dateext
missingok
notifempty
compress
weekly
copytruncate
}

8
INSTALL/misplogrotate.te Normal file
View File

@ -0,0 +1,8 @@
module misplogrotate 1.0;
require {
type logrotate_t;
type httpd_sys_content_t;
class dir { ioctl read getattr lock search open };
}
#============= logrotate_t ==============
allow logrotate_t httpd_sys_content_t:dir { ioctl read getattr lock search open };

View File

@ -33,7 +33,7 @@ yum install vim
yum install gcc git httpd zip redis mysql-server python-devel python-pip libxslt-devel zlib-devel
# Install PHP 5.6 from SCL, see https://www.softwarecollections.org/en/scls/rhscl/rh-php56/
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-bcmath
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-php-xml rh-php56-bcmath
# rh-php56-php only provided mod_php for httpd24-httpd from SCL
# if we want to use httpd from CentOS base we can use rh-php56-php-fpm instead
@ -99,7 +99,6 @@ git submodule update
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
cd /var/www/MISP/app
curl -s https://getcomposer.org/installer | php
php composer.phar require kamisama/cake-resque:4.1.2
php composer.phar config vendor-dir Vendor
php composer.phar install
@ -177,8 +176,14 @@ service iptables save
# We seriously recommend using only SSL !
# Check out the apache.misp.ssl file for an example
8/ Log rotation
---------------
# MISP saves the stdout and stderr of its workers in /var/www/MISP/app/tmp/logs
# To rotate these logs install the supplied logrotate script:
8/ MISP configuration
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
9/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config

View File

@ -31,7 +31,7 @@ yum install centos-release-scl
yum install gcc git httpd zip redis mariadb mariadb-server python-devel python-pip libxslt-devel zlib-devel
# Install PHP 5.6 from SCL, see https://www.softwarecollections.org/en/scls/rhscl/rh-php56/
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-bcmath
yum install rh-php56 rh-php56-php-fpm rh-php56-php-devel rh-php56-php-mysqlnd rh-php56-php-mbstring rh-php56-php-xml rh-php56-php-bcmath
# rh-php56-php only provided mod_php for httpd24-httpd from SCL
# if we want to use httpd from CentOS base we can use rh-php56-php-fpm instead
@ -102,7 +102,6 @@ git submodule update
# Once done, install CakeResque along with its dependencies if you intend to use the built in background jobs:
cd /var/www/MISP/app
curl -s https://getcomposer.org/installer | php
php composer.phar require kamisama/cake-resque:4.1.2
php composer.phar config vendor-dir Vendor
php composer.phar install
@ -194,8 +193,24 @@ firewall-cmd --reload
# Add SSL support by running: yum install mod_ssl
# Check out the apache.misp.ssl file for an example
8/ Log rotation
---------------
# MISP saves the stdout and stderr of it's workers in /var/www/MISP/app/tmp/logs
# To rotate these logs install the supplied logrotate script:
8/ MISP configuration
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
# Now make logrotate work under SELinux as well
# Allow logrotate to modify the log files
semanage fcontext -a -t httpd_log_t "/var/www/MISP/app/tmp/logs(/.*)?"
chcon -R -t httpd_log_t /var/www/MISP/app/tmp/logs
# Allow logrotate to read /var/www
checkmodule -M -m -o /tmp/misplogrotate.mod INSTALL/misplogrotate.te
semodule_package -o /tmp/misplogrotate.pp -m /tmp/misplogrotate.mod
semodule -i /tmp/misplogrotate.pp
9/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config
@ -206,7 +221,7 @@ cp -a config.default.php config.php
# Configure the fields in the newly created files:
# config.php : baseurl (example: 'baseurl' => 'http://misp',) - don't use "localhost" it causes issues when browsing externally
# config.php : Uncomment and set the timezone: `// date_default_timezone_set('UTC');`
# core.php : Uncomment and set the timezone: `// date_default_timezone_set('UTC');`
# database.php : login, port, password, database
# Important! Change the salt key in /var/www/MISP/app/Config/config.php

2
PyMISP

@ -1 +1 @@
Subproject commit 0511bd44867f5f7f74cb54d61b0df7d99b719118
Subproject commit 26a8f4c66230c0df10b2f9637e53ee1542a26f40

View File

@ -1,12 +1,36 @@
[![Build Status](https://travis-ci.org/MISP/MISP.svg?branch=2.4)](https://travis-ci.org/MISP/MISP)
MISP - Malware Information Sharing Platform and Threat Sharing
--------------------------------------------------------------
[![Join the chat at https://gitter.im/MISP/MISP](https://badges.gitter.im/MISP/MISP.svg)](https://gitter.im/MISP/MISP?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![logo](./INSTALL/logos/misp-logo.png?raw=true "MISP")
<table>
<tr>
<td>Latest Release</td>
<td><a href="https://badge.fury.io/gh/MISP%2FMISP"><img src="https://badge.fury.io/gh/MISP%2FMISP.svg" alt="GitHub version" height="18"></a></td>
</tr>
<tr>
<td>Travis</td>
<td><a href="https://travis-ci.org/MISP/MISP.svg?branch=2.4"><img src="https://img.shields.io/travis/MISP/MISP/2.4.svg" /></td>
</tr>
<tr>
<td>Gitter</td>
<td><a href="https://gitter.im/MISP/MISP?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img src="https://badges.gitter.im/MISP/MISP.svg" /></a></td>
</tr>
<tr>
<td>Twitter</td>
<td><a href="https://twitter.com/MISPProject"><img src="https://img.shields.io/twitter/follow/MISPProject.svg?style=social&label=Follow" /></a></td>
</tr>
<tr>
<td>Contributors</td>
<td><img src="https://img.shields.io/github/contributors/MISP/MISP.svg" /></td>
</tr>
<tr>
<td>License</td>
<td><img src="https://img.shields.io/github/license/MISP/MISP.svg" /></td>
</tr>
</table>
MISP, Malware Information Sharing Platform and Threat Sharing, is an open source software solution for collecting, storing, distributing and sharing cyber security indicators and threat about cyber security incidents analysis and malware analysis. MISP is designed by and for incident analysts, security and ICT professionals or malware reverser to support their day-to-day operations to share structured informations efficiently.
The objective of MISP is to foster the sharing of structured information within the security community and abroad. MISP provides functionalities to support the exchange of information but also the consumption of the information by Network Detection Intrusion System (NIDS), LIDS but also log analysis tools, SIEMs.
@ -56,6 +80,8 @@ For installation guide see [INSTALL](https://github.com/MISP/MISP/tree/2.4/INSTA
Contributing
------------
Please see our [Code of conduct](code_of_conduct.md).
Feel free to fork the code, play with it, make some patches and send us the pull requests via the [issues](https://github.com/MISP/MISP/issues).
Feel free to contact us, create [issues](https://github.com/MISP/MISP/issues), if you have questions, remarks or bug reports.
@ -84,7 +110,8 @@ This software is licensed under [GNU Affero General Public License version 3](ht
* Copyright (C) 2012 Christophe Vandeplas
* Copyright (C) 2012 Belgian Defence
* Copyright (C) 2012 NATO / NCIRC
* Copyright (C) 2013-2016 Andras Iklody
* Copyright (C) 2015-2016 CIRCL - Computer Incident Response Center Luxembourg
* Copyright (C) 2013-2017 Andras Iklody
* Copyright (C) 2015-2017 CIRCL - Computer Incident Response Center Luxembourg
* Copyright (C) 2016 Andreas Ziegler
For more information, [the list of authors and contributors](AUTHORS) is available.

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":59}
{"major":2, "minor":4, "hotfix":65}

View File

@ -30,6 +30,8 @@ $config = array(
'default_attribute_distribution' => 'event',
'tagging' => true,
'full_tags_on_event_index' => true,
'attribute_tagging' => true,
'full_tags_on_attribute_index' => true,
'footer_logo' => '',
'take_ownership_xml_import' => false,
'unpublishedprivate' => false,

View File

@ -177,7 +177,7 @@ define('LOG_ERROR', LOG_ERR);
*/
Configure::write('Session', array(
'timeout' => 60, // Session timeout, default is 1 hour
'defaults' => 'database',
'defaults' => 'php',
'autoRegenerate' => true
));

View File

@ -70,6 +70,6 @@ class DATABASE_CONFIG {
'password' => 'db password',
'database' => 'misp',
'prefix' => '',
//'encoding' => 'utf8',
'encoding' => 'utf8',
);
}

View File

@ -2,7 +2,7 @@
App::uses('AppShell', 'Console/Command');
class AdminShell extends AppShell
{
public $uses = array('Event');
public $uses = array('Event', 'Post', 'Attribute', 'Job', 'User', 'Task', 'Whitelist', 'Server', 'Organisation');
public function jobGenerateCorrelation() {
$jobId = $this->args[0];
@ -45,4 +45,17 @@ class AdminShell extends AppShell
$this->Job->saveField('message', 'Job done.');
$this->Job->saveField('status', 4);
}
public function prune_update_logs() {
$jobId = $this->args[0];
$user_id = $this->args[1];
$user = $this->User->getAuthUser($user_id);
$this->loadModel('Job');
$this->Job->id = $jobId;
$this->loadModel('Log');
$this->Log->pruneUpdateLogs($jobId, $user);
$this->Job->saveField('progress', 100);
$this->Job->saveField('message', 'Job done.');
$this->Job->saveField('status', 4);
}
}

View File

@ -347,6 +347,7 @@ class EventShell extends AppShell
$file = new File($dir->pwd() . DS . 'misp.bro.' . $user['Organisation']['name'] . '.intel');
}
$file->write('');
foreach ($types as $k => $type) {
$final = $this->Attribute->bro($user, $type);
foreach ($final as $attribute) {

View File

@ -39,11 +39,13 @@ class UserInitShell extends AppShell {
}
if ($this->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
$date = date('Y-m-d H:i:s');
$org = array('Organisation' => array(
'id' => 1,
'name' => !empty(Configure::read('MISP.org')) ? Configure::read('MISP.org') : 'ADMIN',
'description' => 'Automatically generated admin organisation',
'type' => 'ADMIN',
'date_created' => $date,
'uuid' => CakeText::uuid(),
'local' => 1
));

View File

@ -46,9 +46,10 @@ class AppController extends Controller {
public $helpers = array('Utility');
private $__jsVersion = '2.4.58';
private $__jsVersion = '2.4.62';
public $pyMispVersion = '2.4.65';
public $phpmin = '5.5.9';
public $phprec = '5.6.0';
public $phprec = '7.0.0';
// Used for _isAutomation(), a check that returns true if the controller & action combo matches an action that is a non-xml and non-json automation method
// This is used to allow authentication via headers for methods not covered by _isRest() - as that only checks for JSON and XML formats
@ -81,6 +82,11 @@ class AppController extends Controller {
public function beforeFilter() {
// check for a supported datasource configuration
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
if (!isset($dataSourceConfig['encoding'])) {
$db = ConnectionManager::getDataSource('default');
$db->setConfig(array('encoding' => 'utf8'));
ConnectionManager::create('default', $db->config);
}
$dataSource = $dataSourceConfig['datasource'];
if ($dataSource != 'Database/Mysql' && $dataSource != 'Database/Postgres') {
throw new Exception('datasource not supported: ' . $dataSource);

View File

@ -63,6 +63,9 @@ class AttributesController extends AppController {
'Orgc' => array('fields' => array('id', 'name'))
)
);
if (!$this->_isRest()) {
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
}
$this->set('isSearch', 0);
$this->set('attributes', $this->paginate());
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
@ -235,7 +238,7 @@ class AttributesController extends AppController {
$message .= '[' . $k . ']: ' . $v[0] . PHP_EOL;
}
throw new NotFoundException('Could not save the attribute. ' . $message);
} else if ($this->request->is('ajax')) {
} else if ($this->request->is('ajax')) {
$this->autoRender = false;
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $this->Attribute->validationErrors)),'status'=>200));
} else {
@ -252,6 +255,11 @@ class AttributesController extends AppController {
// combobox for types
$types = array_keys($this->Attribute->typeDefinitions);
foreach ($types as $key => $value) {
if (in_array($value, array('malware-sample', 'attachment'))) {
unset($types[$key]);
}
}
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories
@ -714,7 +722,7 @@ class AttributesController extends AppController {
$saved_attribute = $this->Attribute->find('first', array(
'conditions' => array('id' => $this->Attribute->id),
'recursive' => -1,
'fields' => array('id', 'type', 'to_ids', 'category', 'uuid', 'event_id', 'distribution', 'timestamp', 'comment', 'value'),
'fields' => array('id', 'type', 'to_ids', 'category', 'uuid', 'event_id', 'distribution', 'timestamp', 'comment', 'value', 'disable_correlation'),
));
$response = array('response' => array('Attribute' => $saved_attribute['Attribute']));
$this->set('response', $response);
@ -744,6 +752,11 @@ class AttributesController extends AppController {
// needed for RBAC
// combobox for types
$types = array_keys($this->Attribute->typeDefinitions);
foreach ($types as $key => $value) {
if (in_array($value, array('malware-sample', 'attachment'))) {
unset($types[$key]);
}
}
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories
@ -851,9 +864,16 @@ class AttributesController extends AppController {
throw new NotFoundException('Invalid attribute');
}
if ($this->_isRest()) {
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true));
$conditions = array('conditions' => array('Attribute.id' => $id), 'withAttachments' => true);
$conditions['includeAllTags'] = false;
$attribute = $this->Attribute->fetchAttributes($this->Auth->user(), $conditions);
if (empty($attribute)) throw new MethodNotAllowedException('Invalid attribute');
$attribute = $attribute[0];
if (isset($attribute['AttributeTag'])) {
foreach ($attribute['AttributeTag'] as $k => $tag) {
$attribute['Attribute']['Tag'][$k] = $tag['Tag'];
}
}
$this->set('Attribute', $attribute['Attribute']);
$this->set('_serialize', array('Attribute'));
} else {
@ -972,7 +992,14 @@ class AttributesController extends AppController {
if ($hard) {
$save = $this->Attribute->delete($id);
} else {
$result['Attribute']['deleted'] = true;
if (Configure::read('Security.sanitise_attribute_on_delete')) {
$result['Attribute']['category'] = 'Other';
$result['Attribute']['type'] = 'comment';
$result['Attribute']['value'] = 'deleted';
$result['Attribute']['comment'] = '';
$result['Attribute']['to_ids'] = 0;
}
$result['Attribute']['deleted'] = 1;
$result['Attribute']['timestamp'] = $date->getTimestamp();
$save = $this->Attribute->save($result);
}
@ -1130,214 +1157,362 @@ class AttributesController extends AppController {
}
public function search() {
$fullAddress = '/attributes/search';
if ($this->request->here == $fullAddress) {
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
// reset the paginate_conditions
$this->Session->write('paginate_conditions',array());
if ($this->request->is('post')) {
$keyword = $this->request->data['Attribute']['keyword'];
$keyword2 = $this->request->data['Attribute']['keyword2'];
$tags = $this->request->data['Attribute']['tags'];
$org = $this->request->data['Attribute']['org'];
$type = $this->request->data['Attribute']['type'];
$ioc = $this->request->data['Attribute']['ioc'];
$this->set('ioc', $ioc);
$category = $this->request->data['Attribute']['category'];
$this->set('keywordSearch', $keyword);
$this->set('tags', $tags);
$keyWordText = null;
$keyWordText2 = null;
$keyWordText3 = null;
$this->set('typeSearch', $type);
$this->set('isSearch', 1);
$this->set('categorySearch', $category);
// search the db
$conditions = array();
if ($ioc) {
$conditions['AND'][] = array('Attribute.to_ids =' => 1);
$conditions['AND'][] = array('Event.published =' => 1);
}
// search on the value field
if (isset($keyword)) {
$keywordArray = explode("\n", $keyword);
$this->set('keywordArray', $keywordArray);
$i = 1;
$temp = array();
$temp2 = array();
foreach ($keywordArray as $keywordArrayElement) {
$saveWord = trim(strtolower($keywordArrayElement));
if ($saveWord != '') {
$toInclude = true;
if ($saveWord[0] == '!') {
$toInclude = false;
$saveWord = substr($saveWord, 1);
}
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($this->Cidr->checkCIDR($saveWord, 4)) {
$cidrresults = $this->Cidr->CIDR($saveWord);
foreach ($cidrresults as $result) {
$result = strtolower($result);
if (strpos($result, '|')) {
$resultParts = explode('|', $result);
$fullAddress = '/attributes/search';
// if no search is given, show the search form
if ($this->request->here == $fullAddress && !$this->request->is('post')) {
// adding filtering by category and type
// combobox for types
$types = array('' => array('ALL' => 'ALL'), 'types' => array());
$types['types'] = array_merge($types['types'], $this->_arrayToValuesIndexArray(array_keys($this->Attribute->typeDefinitions)));
ksort($types['types']);
$this->set('types', $types);
// combobox for categories
$categories['categories'] = array_merge(array('ALL' => 'ALL'), $this->_arrayToValuesIndexArray(array_keys($this->Attribute->categoryDefinitions)));
$this->set('categories', $categories);
} else {
$this->set('isSearch', 1);
$attributeTagQuery = '/attributetag';
// check if the request is a GET request for attributes with a specific tag (usually after clicking on an attributetag)
if (substr($this->request->here, strlen($fullAddress), strlen($attributeTagQuery)) == $attributeTagQuery) {
$attributeTagId = substr($this->request->here, (strlen($fullAddress) + strlen($attributeTagQuery) + 1));
if (!is_numeric($attributeTagId)) {
// either pagination active or no correct id
unset($attributeTagId);
}
}
// if this is no new search, get parameters from session
if ($this->request->here != $fullAddress && !isset($attributeTagId)) {
$keyword = $this->Session->read('paginate_conditions_keyword');
$keyword2 = $this->Session->read('paginate_conditions_keyword2');
$attributeTags = $this->Session->read('paginate_conditions_attributetags');
$org = $this->Session->read('paginate_conditions_org');
$type = $this->Session->read('paginate_conditions_type');
$category = $this->Session->read('paginate_conditions_category');
$tags = $this->Session->read('paginate_conditions_tags');
$this->set('keywordSearch', $keyword);
$this->set('keywordSearch2', $keyword2);
if (isset($attributeTags)) {
$this->set('attributeTags', $attributeTags);
}
$this->set('orgSearch', $org);
$this->set('typeSearch', $type);
$this->set('tags', $tags);
$this->set('categorySearch', $category);
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
// re-get pagination
$this->Attribute->recursive = 0;
$this->paginate = $this->Session->read('paginate_conditions');
$this->set('attributes', $this->paginate());
// set the same view as the index page
$this->render('index');
} else {
// reset the paginate_conditions
$this->Session->write('paginate_conditions', array());
$conditions = array();
$alternateSearch = false;
if (isset($attributeTagId)) {
$this->loadModel('Tag');
$this->Tag->id = $attributeTagId;
if (!$this->Tag->exists()) {
throw new NotFoundException(__('Invalid tag'));
}
$attributeTags = $this->Tag->find('first', array(
'recursive' => -1,
'conditions' => array(
'id' => $attributeTagId
)
));
$attributeTags = $attributeTags['Tag']['name'];
$conditions['AND'][] = array('OR' => array('Attribute.id' => $this->Tag->findAttributeIdsByAttributeTagNames(array($attributeTags))));
$keyword = null;
$keyword2 = null;
$org = null;
$type = 'ALL';
$tags = null;
$category = 'ALL';
$ioc = false;
$this->set('keywordSearch', $keyword);
$this->set('keywordSearch2', $keyword2);
}
if ($this->request->is('post')) {
$keyword = $this->request->data['Attribute']['keyword'];
$keyword2 = $this->request->data['Attribute']['keyword2'];
$attributeTags = $this->request->data['Attribute']['attributetags'];
$tags = $this->request->data['Attribute']['tags'];
$org = $this->request->data['Attribute']['org'];
$type = $this->request->data['Attribute']['type'];
$ioc = $this->request->data['Attribute']['ioc'];
$this->set('ioc', $ioc);
$category = $this->request->data['Attribute']['category'];
$keyWordText = null;
$keyWordText2 = null;
$keyWordText3 = null;
// search the db
if ($ioc) {
$conditions['AND'][] = array('Attribute.to_ids =' => 1);
$conditions['AND'][] = array('Event.published =' => 1);
}
// search on the value field
if (isset($keyword)) {
$keywordArray = explode("\n", $keyword);
$this->set('keywordArray', $keywordArray);
$i = 1;
$temp = array();
$temp2 = array();
foreach ($keywordArray as $keywordArrayElement) {
$saveWord = trim(strtolower($keywordArrayElement));
if ($saveWord != '') {
$toInclude = true;
if ($saveWord[0] == '!') {
$toInclude = false;
$saveWord = substr($saveWord, 1);
}
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($this->Cidr->checkCIDR($saveWord, 4)) {
$cidrresults = $this->Cidr->CIDR($saveWord);
foreach ($cidrresults as $result) {
$result = strtolower($result);
if (strpos($result, '|')) {
$resultParts = explode('|', $result);
if (!$toInclude) {
$temp2[] = array(
'AND' => array(
'LOWER(Attribute.value1) NOT LIKE' => $resultParts[0],
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1],
));
} else {
$temp[] = array(
'AND' => array(
'LOWER(Attribute.value1)' => $resultParts[0],
'LOWER(Attribute.value2)' => $resultParts[1],
));
}
} else {
if (!$toInclude) {
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => $result));
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => $result));
} else {
array_push($temp, array('LOWER(Attribute.value1) LIKE' => $result));
array_push($temp, array('LOWER(Attribute.value2) LIKE' => $result));
}
}
}
} else {
if (strpos($saveWord, '|')) {
$resultParts = explode('|', $saveWord);
if (!$toInclude) {
$temp2[] = array(
'AND' => array(
'LOWER(Attribute.value1) NOT LIKE' => $resultParts[0],
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1],
));
'LOWER(Attribute.value1) NOT LIKE' => '%' . $resultParts[0],
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1] . '%',
));
} else {
$temp[] = array(
$temp2[] = array(
'AND' => array(
'LOWER(Attribute.value1)' => $resultParts[0],
'LOWER(Attribute.value2)' => $resultParts[1],
));
'LOWER(Attribute.value1)' => '%' . $resultParts[0],
'LOWER(Attribute.value2)' => $resultParts[1] . '%',
));
}
} else {
if (!$toInclude) {
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => $result));
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => $result));
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => '%' . $saveWord . '%'));
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => '%' . $saveWord . '%'));
} else {
array_push($temp, array('LOWER(Attribute.value1) LIKE' => $result));
array_push($temp, array('LOWER(Attribute.value2) LIKE' => $result));
array_push($temp, array('LOWER(Attribute.value1) LIKE' => '%' . $saveWord . '%'));
array_push($temp, array('LOWER(Attribute.value2) LIKE' => '%' . $saveWord . '%'));
}
}
}
} else {
if (strpos($saveWord, '|')) {
$resultParts = explode('|', $saveWord);
if (!$toInclude) {
$temp2[] = array(
'AND' => array(
'LOWER(Attribute.value1) NOT LIKE' => '%' . $resultParts[0],
'LOWER(Attribute.value2) NOT LIKE' => $resultParts[1] . '%',
));
} else {
$temp2[] = array(
'AND' => array(
'LOWER(Attribute.value1)' => '%' . $resultParts[0],
'LOWER(Attribute.value2)' => $resultParts[1] . '%',
));
}
if ($toInclude) {
array_push($temp, array('LOWER(Attribute.comment) LIKE' => '%' . $saveWord . '%'));
} else {
if (!$toInclude) {
array_push($temp2, array('LOWER(Attribute.value1) NOT LIKE' => '%' . $saveWord . '%'));
array_push($temp2, array('LOWER(Attribute.value2) NOT LIKE' => '%' . $saveWord . '%'));
} else {
array_push($temp, array('LOWER(Attribute.value1) LIKE' => '%' . $saveWord . '%'));
array_push($temp, array('LOWER(Attribute.value2) LIKE' => '%' . $saveWord . '%'));
}
array_push($temp2, array('LOWER(Attribute.comment) NOT LIKE' => '%' . $saveWord . '%'));
}
}
if ($toInclude) {
array_push($temp, array('LOWER(Attribute.comment) LIKE' => '%' . $saveWord . '%'));
} else {
array_push($temp2, array('LOWER(Attribute.comment) NOT LIKE' => '%' . $saveWord . '%'));
if ($i == 1 && $saveWord != '') {
$keyWordText = $saveWord;
} else if (($i > 1 && $i < 10) && $saveWord != '') {
$keyWordText = $keyWordText . ', ' . $saveWord;
} else if ($i == 10 && $saveWord != '') {
$keyWordText = $keyWordText . ' and several other keywords';
}
$i++;
}
if ($i == 1 && $saveWord != '') $keyWordText = $saveWord;
else if (($i > 1 && $i < 10) && $saveWord != '') $keyWordText = $keyWordText . ', ' . $saveWord;
else if ($i == 10 && $saveWord != '') $keyWordText = $keyWordText . ' and several other keywords';
$i++;
}
$this->set('keywordSearch', $keyWordText);
if (!empty($temp)) {
$conditions['AND']['OR'] = $temp;
}
if (!empty($temp2)) {
$conditions['AND'][] = $temp2;
$this->set('keywordSearch', $keyWordText);
if (!empty($temp)) {
$conditions['AND']['OR'] = $temp;
}
if (!empty($temp2)) {
$conditions['AND'][] = $temp2;
}
}
}
// event IDs to be excluded
if (isset($keyword2)) {
$keywordArray2 = explode("\n", $keyword2);
$i = 1;
$temp = array();
foreach ($keywordArray2 as $keywordArrayElement) {
$saveWord = trim($keywordArrayElement);
if (empty($saveWord)) continue;
if ($saveWord[0] == '!') {
if (strlen(substr($saveWord, 1)) == 36) {
$temp[] = array('Event.uuid !=' => substr($saveWord, 1));
$temp[] = array('Attribute.uuid !=' => substr($saveWord, 1));
} else {
$temp[] = array('Attribute.event_id !=' => substr($saveWord, 1));
// event IDs to be excluded
if (isset($keyword2)) {
$keywordArray2 = explode("\n", $keyword2);
$i = 1;
$temp = array();
foreach ($keywordArray2 as $keywordArrayElement) {
$saveWord = trim($keywordArrayElement);
if (empty($saveWord)) {
continue;
}
} else {
if (strlen($saveWord) == 36) {
$temp['OR'][] = array('Event.uuid =' => $saveWord);
$temp['OR'][] = array('Attribute.uuid' => $saveWord);
if ($saveWord[0] == '!') {
if (strlen(substr($saveWord, 1)) == 36) {
$temp[] = array('Event.uuid !=' => substr($saveWord, 1));
$temp[] = array('Attribute.uuid !=' => substr($saveWord, 1));
} else {
$temp[] = array('Attribute.event_id !=' => substr($saveWord, 1));
}
} else {
$temp['OR'][] = array('Attribute.event_id =' => $saveWord);
if (strlen($saveWord) == 36) {
$temp['OR'][] = array('Event.uuid =' => $saveWord);
$temp['OR'][] = array('Attribute.uuid' => $saveWord);
} else {
$temp['OR'][] = array('Attribute.event_id =' => $saveWord);
}
}
if ($i == 1 && $saveWord != '') {
$keyWordText2 = $saveWord;
} else if (($i > 1 && $i < 10) && $saveWord != '') {
$keyWordText2 = $keyWordText2 . ', ' . $saveWord;
} else if ($i == 10 && $saveWord != '') {
$keyWordText2 = $keyWordText2 . ' and several other events';
}
$i++;
}
$this->set('keywordSearch2', $keyWordText2);
if (!empty($temp)) {
$conditions['AND'][] = $temp;
}
}
if (!empty($attributeTags) || !empty($tags)) {
$this->loadModel('Tag');
}
if (!empty($attributeTags)) {
$includeAttributeTags = array();
$excludeAttributeTags = array();
$attributeTagsKeywordArray = explode("\n", $attributeTags);
foreach ($attributeTagsKeywordArray as $tagName) {
$tagName = trim($tagName);
if (empty($tagName)) {
continue;
}
if (substr($tagName, 0, 1) === '!') {
$excludeAttributeTags[] = substr($tagName, 1);
} else {
$includeAttributeTags[] = $tagName;
}
}
if ($i == 1 && $saveWord != '') $keyWordText2 = $saveWord;
else if (($i > 1 && $i < 10) && $saveWord != '') $keyWordText2 = $keyWordText2 . ', ' . $saveWord;
else if ($i == 10 && $saveWord != '') $keyWordText2 = $keyWordText2 . ' and several other events';
$i++;
if (!empty($includeAttributeTags)) {
$conditions['AND'][] = array('OR' => array('Attribute.id' => $this->Tag->findAttributeIdsByAttributeTagNames($includeAttributeTags)));
}
if (!empty($excludeAttributeTags)) {
$conditions['AND'][] = array('Attribute.id !=' => $this->Tag->findAttributeIdsByAttributeTagNames($excludeAttributeTags));
}
}
$this->set('keywordSearch2', $keyWordText2);
if (!empty($temp)) {
$conditions['AND'][] = $temp;
if (!empty($tags)) {
$include = array();
$exclude = array();
$keywordArray = explode("\n", $tags);
foreach ($keywordArray as $tagname) {
$tagname = trim($tagname);
if (empty($tagname)) {
continue;
}
if (substr($tagname, 0, 1) === '!') {
$exclude[] = substr($tagname, 1);
} else {
$include[] = $tagname;
}
}
if (!empty($include)) {
$conditions['AND'][] = array('OR' => array('Attribute.event_id' => $this->Tag->findEventIdsByTagNames($include)));
}
if (!empty($exclude)) {
$conditions['AND'][] = array('Attribute.event_id !=' => $this->Tag->findEventIdsByTagNames($exclude));
}
}
}
if (!empty($tags)) {
$include = array();
$exclude = array();
$keywordArray = explode("\n", $tags);
foreach ($keywordArray as $tagname) {
$tagname = trim($tagname);
if (empty($tagname)) continue;
if (substr($tagname, 0, 1) === '!') $exclude[] = substr($tagname, 1);
else $include[] = $tagname;
if ($type != 'ALL') {
$conditions['Attribute.type ='] = $type;
}
$this->loadModel('Tag');
if (!empty($include)) $conditions['AND'][] = array('OR' => array('Attribute.event_id' => $this->Tag->findEventIdsByTagNames($include)));
if (!empty($exclude)) $conditions['AND'][] = array('Attribute.event_id !=' => $this->Tag->findEventIdsByTagNames($exclude));
}
if ($type != 'ALL') {
$conditions['Attribute.type ='] = $type;
}
if ($category != 'ALL') {
$conditions['Attribute.category ='] = $category;
}
// organisation search field
$temp = array();
if (isset($org)) {
$this->loadModel('Organisation');
$orgArray = explode("\n", $org);
foreach ($orgArray as $i => $orgArrayElement) {
$saveWord = trim($orgArrayElement);
if (empty($saveWord)) continue;
if ($saveWord[0] == '!') {
$org_names = $this->Organisation->find('all', array(
'fields' => array('id', 'name'),
if ($category != 'ALL') {
$conditions['Attribute.category ='] = $category;
}
// organisation search field
if (isset($org)) {
$temp = array();
$this->loadModel('Organisation');
$orgArray = explode("\n", $org);
foreach ($orgArray as $i => $orgArrayElement) {
$saveWord = trim($orgArrayElement);
if (empty($saveWord)) {
continue;
}
if ($saveWord[0] == '!') {
$org_names = $this->Organisation->find('all', array(
'fields' => array('id', 'name'),
'conditions' => array('lower(name) LIKE' => '%' . strtolower(substr($saveWord, 1)) . '%'),
));
foreach ($org_names as $org_name) $temp['AND'][] = array('Event.orgc_id !=' => $org_name['Organisation']['id']);
} else {
$org_names = $this->Organisation->find('all', array(
'fields' => array('id', 'name'),
));
foreach ($org_names as $org_name) {
$temp['AND'][] = array('Event.orgc_id !=' => $org_name['Organisation']['id']);
}
} else {
$org_names = $this->Organisation->find('all', array(
'fields' => array('id', 'name'),
'conditions' => array('lower(name) LIKE' => '%' . strtolower($saveWord) . '%'),
));
foreach ($org_names as $org_name) $temp['OR'][] = array('Event.orgc_id' => $org_name['Organisation']['id']);
));
foreach ($org_names as $org_name) {
$temp['OR'][] = array('Event.orgc_id' => $org_name['Organisation']['id']);
}
}
if ($i == 0 && $saveWord != '') {
$keyWordText3 = $saveWord;
} else if (($i > 0 && $i < 9) && $saveWord != '') {
$keyWordText3 = $keyWordText3 . ', ' . $saveWord;
} else if ($i == 9 && $saveWord != '') {
$keyWordText3 = $keyWordText3 . ' and several other organisations';
}
}
$this->set('orgSearch', $keyWordText3);
if (!empty($temp)) {
$conditions['AND'][] = $temp;
}
if ($i == 0 && $saveWord != '') $keyWordText3 = $saveWord;
else if (($i > 0 && $i < 9) && $saveWord != '') $keyWordText3 = $keyWordText3 . ', ' . $saveWord;
else if ($i == 9 && $saveWord != '') $keyWordText3 = $keyWordText3 . ' and several other organisations';
}
$this->set('orgSearch', $keyWordText3);
if (!empty($temp)) {
$conditions['AND'][] = $temp;
if ($this->request->data['Attribute']['alternate']) {
$alternateSearch = true;
}
}
if (isset($attributeTags)) {
$this->set('attributeTags', $attributeTags);
}
$this->set('tags', $tags);
$this->set('typeSearch', $type);
$this->set('categorySearch', $category);
$conditions['AND'][] = array('Attribute.deleted' => 0);
if ($this->request->data['Attribute']['alternate']) {
if ($alternateSearch) {
$events = $this->searchAlternate($conditions);
$this->set('events', $events);
$this->render('alternate_search_result');
@ -1361,6 +1536,7 @@ class AttributesController extends AppController {
),
)
);
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
if (!$this->_isSiteAdmin()) {
// merge in private conditions
$this->paginate = Set::merge($this->paginate, array(
@ -1396,10 +1572,13 @@ class AttributesController extends AppController {
}
}
$this->set('attributes', $attributes);
// and store into session
$this->Session->write('paginate_conditions', $this->paginate);
$this->Session->write('paginate_conditions_keyword', $keyword);
$this->Session->write('paginate_conditions_keyword2', $keyword2);
if (isset($attributeTags))
$this->Session->write('paginate_conditions_attributetags', $attributeTags);
$this->Session->write('paginate_conditions_org', $org);
$this->Session->write('paginate_conditions_type', $type);
$this->Session->write('paginate_conditions_ioc', $ioc);
@ -1411,46 +1590,7 @@ class AttributesController extends AppController {
// set the same view as the index page
$this->render('index');
}
} else {
// no search keyword is given, show the search form
// adding filtering by category and type
// combobox for types
$types = array('' => array('ALL' => 'ALL'), 'types' => array());
$types['types'] = array_merge($types['types'], $this->_arrayToValuesIndexArray(array_keys($this->Attribute->typeDefinitions)));
ksort($types['types']);
$this->set('types', $types);
// combobox for categories
$categories['categories'] = array_merge(array('ALL' => 'ALL'), $this->_arrayToValuesIndexArray(array_keys($this->Attribute->categoryDefinitions)));
$this->set('categories', $categories);
}
} else {
$this->set('attrDescriptions', $this->Attribute->fieldDescriptions);
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
// get from Session
$keyword = $this->Session->read('paginate_conditions_keyword');
$keyword2 = $this->Session->read('paginate_conditions_keyword2');
$org = $this->Session->read('paginate_conditions_org');
$type = $this->Session->read('paginate_conditions_type');
$category = $this->Session->read('paginate_conditions_category');
$tags = $this->Session->read('paginate_conditions_tags');
$this->set('keywordSearch', $keyword);
$this->set('keywordSearch2', $keyword2);
$this->set('orgSearch', $org);
$this->set('typeSearch', $type);
$this->set('tags', $tags);
$this->set('isSearch', 1);
$this->set('categorySearch', $category);
// re-get pagination
$this->Attribute->recursive = 0;
$this->paginate = $this->Session->read('paginate_conditions');
$this->set('attributes', $this->paginate());
// set the same view as the index page
$this->render('index');
}
}
@ -1520,9 +1660,9 @@ class AttributesController extends AppController {
// 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 = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false) {
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false) {
if ($tags) $tags = str_replace(';', ':', $tags);
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist');
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted');
foreach ($simpleFalse as $sF) {
if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false;
}
@ -1551,13 +1691,13 @@ class AttributesController extends AppController {
if (!isset($data['request'])) {
$data['request'] = $data;
}
$paramArray = array('value', 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist');
$paramArray = array('value', 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted');
foreach ($paramArray as $p) {
if (isset($data['request'][$p])) ${$p} = $data['request'][$p];
else ${$p} = null;
}
}
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist');
$simpleFalse = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted');
foreach ($simpleFalse as $sF) {
if (!is_array(${$sF}) && (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false')) ${$sF} = false;
}
@ -1668,7 +1808,13 @@ class AttributesController extends AppController {
if ($last) $conditions['AND'][] = array('Event.publish_timestamp >=' => $last);
if ($published) $conditions['AND'][] = array('Event.published' => $published);
if ($timestamp) $conditions['AND'][] = array('Attribute.timestamp >=' => $timestamp);
if ($to_ids) {
if ($to_ids === 'exclude') {
$conditions['AND'][] = array('Attribute.to_ids' => 0);
} else {
$conditions['AND'][] = array('Attribute.to_ids' => 1);
}
}
// change the fields here for the attribute export!!!! Don't forget to check for the permissions, since you are not going through fetchevent. Maybe create fetchattribute?
$params = array(
'conditions' => $conditions,
@ -1676,6 +1822,12 @@ class AttributesController extends AppController {
'withAttachments' => $withAttachments,
'enforceWarninglist' => $enforceWarninglist
);
if ($deleted) {
$params['deleted'] = 1;
if ($deleted === 'only') {
$params['conditions']['AND'][] = array('Attribute.deleted' => 1);
}
}
$results = $this->Attribute->fetchAttributes($this->Auth->user(), $params);
$this->loadModel('Whitelist');
$results = $this->Whitelist->removeWhitelistedFromArray($results, true);
@ -1814,8 +1966,8 @@ class AttributesController extends AppController {
$this->__downloadAttachment($this->Attribute->data['Attribute']);
}
public function text($key='download', $type = 'all', $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false) {
$simpleFalse = array('eventId', 'allowNonIDS', 'tags', 'from', 'to', 'last', 'enforceWarninglist');
public function text($key='download', $type = 'all', $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false, $allowNotPublished = false) {
$simpleFalse = array('eventId', 'allowNonIDS', 'tags', 'from', 'to', 'last', 'enforceWarninglist', 'allowNotPublished');
foreach ($simpleFalse as $sF) {
if (!is_array(${$sF}) && (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false')) ${$sF} = false;
}
@ -1837,7 +1989,7 @@ class AttributesController extends AppController {
$this->response->type('txt'); // set the content type
$this->header('Content-Disposition: download; filename="misp.' . $type . '.txt"');
$this->layout = 'text/default';
$attributes = $this->Attribute->text($this->Auth->user(), $type, $tags, $eventId, $allowNonIDS, $from, $to, $last, $enforceWarninglist);
$attributes = $this->Attribute->text($this->Auth->user(), $type, $tags, $eventId, $allowNonIDS, $from, $to, $last, $enforceWarninglist, $allowNotPublished);
$this->loadModel('Whitelist');
$attributes = $this->Whitelist->removeWhitelistedFromArray($attributes, true);
$this->set('attributes', $attributes);
@ -2487,6 +2639,178 @@ class AttributesController extends AppController {
$this->render('/Servers/json/simple');
}
public function addTag($id = false, $tag_id = false) {
if (!$this->request->is('post')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that. Only POST requests are accepted.')), 'status' => 200));
}
$rearrangeRules = array(
'request' => false,
'Attribute' => false,
'tag_id' => 'tag',
'attribute_id' => 'attribute',
'id' => 'attribute'
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) {
$id = $this->request->data['attribute'];
}
if ($id === 'selected') {
$idList = json_decode($this->request->data['attribute_ids'], true);
}
if ($tag_id === false) $tag_id = $this->request->data['tag'];
if (!is_numeric($tag_id)) {
$tag = $this->Attribute->AttributeTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
$tag_id = $tag['Tag']['id'];
}
if (!isset($idList)) {
$idList = array($id);
}
$success = 0;
$fails = 0;
foreach ($idList as $id) {
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) throw new NotFoundException(__('Invalid attribute'));
$this->Attribute->read();
if ($this->Attribute->data['Attribute']['deleted']) throw new NotFoundException(__('Invalid attribute'));
$eventId = $this->Attribute->data['Attribute']['event_id'];
$this->Attribute->Event->recursive = -1;
$event = $this->Attribute->Event->read(array(), $eventId);
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status' => 200));
}
}
$this->Attribute->recursive = -1;
$this->Attribute->AttributeTag->Tag->id = $tag_id;
if (!$this->Attribute->AttributeTag->Tag->exists()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
}
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->Attribute->AttributeTag->find('first', array(
'conditions' => array(
'attribute_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
$fails++;
continue;
}
$this->Attribute->AttributeTag->create();
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId))) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Attribute->Event->save($event);
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
$this->Attribute->save($this->Attribute->data);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to attribute (' . $id . ')', 'Attribute (' . $id . ') tagged as Tag (' . $tag_id . ')');
$success++;
} else {
$fails++;
}
}
if ($fails == 0) {
if ($success == 1) {
$message = 'Tag added.';
} else {
$message = $success . ' tags added.';
}
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $message, 'check_publish' => true)), 'status' => 200));
} else {
if ($fails == 1) {
$message = 'Tag could not be added.';
} else {
$message = $fails . ' tags could not be added.';
}
if ($success > 0) {
$message .= ' However, ' . $success . ' tag(s) were added.';
}
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $message)), 'status' => 200));
}
}
public function removeTag($id = false, $tag_id = false) {
if (!$this->request->is('post')) {
$this->set('id', $id);
$this->set('tag_id', $tag_id);
$this->set('model', 'Attribute');
$this->render('ajax/tagRemoveConfirmation');
} else {
$rearrangeRules = array(
'request' => false,
'Attribute' => false,
'tag_id' => 'tag',
'attribute_id' => 'attribute',
'id' => 'attribute'
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) $id = $this->request->data['attribute'];
if ($tag_id === false) $tag_id = $this->request->data['tag'];
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) throw new NotFoundException(__('Invalid attribute'));
$this->Attribute->read();
if ($this->Attribute->data['Attribute']['deleted']) throw new NotFoundException(__('Invalid attribute'));
$eventId = $this->Attribute->data['Attribute']['event_id'];
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
if (!is_numeric($tag_id)) {
$tag = $this->Attribute->AttributeTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200));
$tag_id = $tag['Tag']['id'];
}
if (!is_numeric($id)) $id = $this->request->data['Attribute']['id'];
$this->Attribute->Event->recursive = -1;
$event = $this->Attribute->Event->read(array(), $eventId);
// org should allow to (un)tag too, so that an event that gets pushed can be (un)tagged locally by the owning org
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'] && $event['Event']['distribution'] == 0) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status' => 200));
}
$this->Attribute->recursive = -1;
$attributeTag = $this->Attribute->AttributeTag->find('first', array(
'conditions' => array(
'attribute_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (empty($attributeTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid attribute - tag combination.')), 'status' => 200));
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
if ($this->Attribute->AttributeTag->delete($attributeTag['AttributeTag']['id'])) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Attribute->Event->save($event);
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
$this->Attribute->save($this->Attribute->data);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from attribute (' . $id . ')', 'Attribute (' . $id . ') untagged of Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag removed.', 'check_publish' => true)), 'status' => 200));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be removed.')), 'status' => 200));
}
}
}
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.');

View File

@ -31,6 +31,7 @@ class ACLComponent extends Component {
'add' => array('perm_add'),
'add_attachment' => array('perm_add'),
'add_threatconnect' => array('perm_add'),
'addTag' => array('perm_tagger'),
'attributeReplace' => array('perm_add'),
'attributeStatistics' => array('*'),
'bro' => array('*'),
@ -51,6 +52,7 @@ class ACLComponent extends Component {
'hoverEnrichment' => array('perm_add'),
'index' => array('*'),
'pruneOrphanedAttributes' => array(),
'removeTag' => array('perm_tagger'),
'reportValidationIssuesAttributes' => array(),
'restore' => array('perm_add'),
'restSearch' => array('*'),
@ -165,10 +167,10 @@ class ACLComponent extends Component {
),
'jobs' => array(
'cache' => array('*'),
'getError' => array(),
'getGenerateCorrelationProgress' => array('*'),
'getProgress' => array('*'),
'index' => array(),
'getError' => array()
'index' => array()
),
'logs' => array(
'admin_index' => array('perm_audit'),
@ -176,6 +178,7 @@ class ACLComponent extends Component {
'event_index' => array('*'),
'maxDateActivity' => array('*'),
'returnDates' => array('*'),
'pruneUpdateLogs' => array()
),
'news' => array(
'add' => array(),
@ -235,6 +238,7 @@ class ACLComponent extends Component {
'edit' => array(),
'fetchServersForSG' => array('*'),
'filterEventIndex' => array(),
'getPyMISPVersion' => array('*'),
'getVersion' => array('*'),
'index' => array('OR' => array('perm_sync', 'perm_admin')),
'previewEvent' => array(),
@ -283,16 +287,20 @@ class ACLComponent extends Component {
'sightings' => array(
'add' => array('perm_add'),
'delete' => array('perm_add'),
'index' => array('*')
),
'tags' => array(
'add' => array('perm_tag_editor'),
'attachTagToObject' => array('perm_tagger'),
'delete' => array('perm_tag_editor'),
'edit' => array('perm_tag_editor'),
'index' => array('*'),
'quickAdd' => array('perm_tag_editor'),
'removeTagFromObject' => array('perm_tagger'),
'selectTag' => array('perm_tagger'),
'selectTaxonomy' => array('perm_tagger'),
'showEventTag' => array('*'),
'showAttributeTag' => array('*'),
'tagStatistics' => array('*'),
'view' => array('*'),
'viewTag' => array('*'),

View File

@ -13,6 +13,18 @@ class RestResponseComponent extends Component {
'description' => "POST a User object in JSON format to this API to edit a user.",
'optional' => array('email', 'org_id', 'role_id', 'password', 'external_auth_required', 'external_auth_key', 'enable_password', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'change_pw', 'termsaccepted', 'newsread')
)
),
'Organisation' => array(
'admin_add' => array(
'description' => "POST an Organisation object in JSON format to this API to create a new organsiation.",
'mandatory' => array('name'),
'optional' => array('anonymise', 'description', 'type', 'nationality', 'sector', 'uuid', 'contacts', 'local')
),
'admin_edit' => array(
'description' => "POST an Organisation object in JSON format to this API to create a new organsiation.",
'mandatory' => array('name'),
'optional' => array('anonymise', 'description', 'type', 'nationality', 'sector', 'uuid', 'contacts', 'local')
)
)
);
@ -30,7 +42,7 @@ class RestResponseComponent extends Component {
public function saveSuccessResponse($controller, $action, $id = false, $format = false, $message = false) {
$action = $this->__dissectAdminRouting($action);
if (!$message) {
$message = Inflector::singularize($controller) . ' ' . $action['action'] . 'ed';
$message = Inflector::singularize($controller) . ' ' . $action['action'] . ((substr($action['action'], -1) == 'e') ? 'd' : 'ed');
}
$response['name'] = $message;
$response['message'] = $response['name'];

View File

@ -571,6 +571,7 @@ class EventsController extends AppController {
if (Configure::read('MISP.showCorrelationsOnIndex')) $events = $this->Event->attachCorrelationCountToEvents($this->Auth->user(), $events);
if (Configure::read('MISP.showSightingsCountOnIndex') && Configure::read('MISP.Plugin.Sightings_enable') !== false) $events = $this->Event->attachSightingsCountToEvents($this->Auth->user(), $events);
if (Configure::read('MISP.showProposalsCountOnIndex')) $events = $this->Event->attachProposalsCountToEvents($this->Auth->user(), $events);
if (Configure::read('MISP.showDiscussionsCountOnIndex')) $events = $this->Event->attachDiscussionsCountToEvents($this->Auth->user(), $events);
$events = $this->GalaxyCluster->attachClustersToEventIndex($events, true);
$this->set('events', $events);
}
@ -792,11 +793,11 @@ class EventsController extends AppController {
// workaround to get the event dates in to the attribute relations
$relatedDates = array();
if (isset($event['RelatedEvent'])) {
if (!empty($event['RelatedEvent'])) {
foreach ($event['RelatedEvent'] as $relation) {
$relatedDates[$relation['Event']['id']] = $relation['Event']['date'];
}
if (isset($event['RelatedAttribute'])) {
if (!empty($event['RelatedAttribute'])) {
foreach ($event['RelatedAttribute'] as $key => $relatedAttribute) {
foreach ($relatedAttribute as $key2 => $relation) {
$event['RelatedAttribute'][$key][$key2]['date'] = $relatedDates[$relation['id']];
@ -1008,7 +1009,9 @@ class EventsController extends AppController {
$sgs = $this->Event->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', 1);
if ($this->request->is('post')) {
if ($this->_isRest()) {
if (empty($this->data)) {
throw new MethodNotAllowedException('No valid event data received.');
}
// rearrange the response if the event came from an export
if (isset($this->request->data['response'])) $this->request->data = $this->request->data['response'];
@ -1194,9 +1197,9 @@ class EventsController extends AppController {
if (isset($this->data['Event']['submittedfile'])) {
if (Configure::read('MISP.take_ownership_xml_import')
&& (isset($this->data['Event']['takeownership']) && $this->data['Event']['takeownership'] == 1)) {
$results = $this->_addMISPExportFile($ext, true);
$results = $this->_addMISPExportFile($ext, true, $this->data['Event']['publish']);
} else {
$results = $this->_addMISPExportFile($ext);
$results = $this->_addMISPExportFile($ext, false, $this->data['Event']['publish']);
}
}
}
@ -1278,6 +1281,13 @@ class EventsController extends AppController {
}
public function edit($id = null) {
if (Validation::uuid($id)) {
$temp = $this->Event->find('first', array('recursive' => -1, 'fields' => array('Event.id'), 'conditions' => array('Event.uuid' => $id)));
if (empty($temp)) throw new NotFoundException('Invalid event');
$id = $temp['Event']['id'];
} else if (!is_numeric($id)) {
throw new NotFoundException(__('Invalid event'));
}
$this->Event->id = $id;
if (!$this->Event->exists()) {
throw new NotFoundException(__('Invalid event'));
@ -2172,7 +2182,7 @@ class EventsController extends AppController {
}
}
public function _addMISPExportFile($ext, $take_ownership = false) {
public function _addMISPExportFile($ext, $take_ownership = false, $publish = false) {
App::uses('FileAccessTool', 'Tools');
$data = (new FileAccessTool())->readFromFile($this->data['Event']['submittedfile']['tmp_name'], $this->data['Event']['submittedfile']['size']);
@ -2210,6 +2220,7 @@ class EventsController extends AppController {
$event = array('Event' => $event);
$created_id = 0;
$event['Event']['locked'] = 1;
$event['Event']['published'] = $publish;
$result['result'] = $this->Event->_add($event, true, $this->Auth->user(), '', null, false, null, $created_id, $validationIssues);
$result['id'] = $created_id;
$result['validationIssues'] = $validationIssues;
@ -2223,6 +2234,7 @@ class EventsController extends AppController {
}
$created_id = 0;
$temp['Event']['locked'] = 1;
$temp['Event']['published'] = $publish;
$result = $this->Event->_add($temp, true, $this->Auth->user(), '', null, false, null, $created_id, $validationIssues);
$results = array(0 => array('info' => $temp['Event']['info'], 'result' => $result, 'id' => $created_id, 'validationIssues' => $validationIssues));
}
@ -2941,56 +2953,60 @@ class EventsController extends AppController {
public function removeTag($id = false, $tag_id = false, $galaxy = false) {
if (!$this->request->is('post')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that. Only POST requests are accepted.')), 'status'=>200));
}
$rearrangeRules = array(
'request' => false,
'Event' => false,
'tag_id' => 'tag',
'event_id' => 'event',
'id' => 'event'
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) $id = $this->request->data['event'];
if ($tag_id === false) $tag_id = $this->request->data['tag'];
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')),'status'=>200));
if (!is_numeric($tag_id)) {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')), 'status'=>200));
$tag_id = $tag['Tag']['id'];
}
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $id);
// org should allow to tag too, so that an event that gets pushed can be tagged locally by the owning org
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id']) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')),'status'=>200));
}
$eventTag = $this->Event->EventTag->find('first', array(
'conditions' => array(
'event_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (empty($eventTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid event - ' . ($galaxy ? 'galaxy' : 'tag') . ' combination.')),'status'=>200));
$tag = $this->Event->EventTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
if ($this->Event->EventTag->delete($eventTag['EventTag']['id'])) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from event (' . $id . ')', 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.', 'check_publish' => true)), 'status'=>200));
$this->set('id', $id);
$this->set('tag_id', $tag_id);
$this->set('model', 'Event');
$this->render('/Attributes/ajax/tagRemoveConfirmation');
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => ($galaxy ? 'Galaxy' : 'Tag') . ' could not be removed.')),'status'=>200));
$rearrangeRules = array(
'request' => false,
'Event' => false,
'tag_id' => 'tag',
'event_id' => 'event',
'id' => 'event'
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) $id = $this->request->data['event'];
if ($tag_id === false) $tag_id = $this->request->data['tag'];
if (empty($tag_id)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')),'status'=>200));
if (!is_numeric($tag_id)) {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid ' . ($galaxy ? 'Galaxy' : 'Tag') . '.')), 'status'=>200));
$tag_id = $tag['Tag']['id'];
}
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $id);
// org should allow to tag too, so that an event that gets pushed can be tagged locally by the owning org
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id']) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')),'status'=>200));
}
$eventTag = $this->Event->EventTag->find('first', array(
'conditions' => array(
'event_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (empty($eventTag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid event - ' . ($galaxy ? 'galaxy' : 'tag') . ' combination.')),'status'=>200));
$tag = $this->Event->EventTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
if ($this->Event->EventTag->delete($eventTag['EventTag']['id'])) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from event (' . $id . ')', 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => ($galaxy ? 'Galaxy' : 'Tag') . ' removed.', 'check_publish' => true)), 'status'=>200));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => ($galaxy ? 'Galaxy' : 'Tag') . ' could not be removed.')),'status'=>200));
}
}
}
@ -3077,6 +3093,8 @@ class EventsController extends AppController {
foreach (${$source} as $k => $attribute) {
if ($attribute['type'] == 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
} else if ($attribute['type'] == 'ip-src|port/ip-dst|port') {
$types = array('ip-src|port', 'ip-dst|port');
} else if ($attribute['type'] == 'malware-sample') {
if (!isset($attribute['data_is_handled']) || !$attribute['data_is_handled']) {
App::uses('FileAccessTool', 'Tools');
@ -3480,10 +3498,10 @@ class EventsController extends AppController {
$this->loadModel('Log');
$hashes = array('md5' => 'malware-sample', 'sha1' => 'filename|sha1', 'sha256' => 'filename|sha256');
$categoryDefinitions = $this->Event->Attribute->categoryDefinitions;
$types = array();
$categories = array();
foreach ($categoryDefinitions as $k => $v) {
if (in_array('malware-sample', $v['types']) && !in_array($k, $types)) {
$types[] = $k;
if (in_array('malware-sample', $v['types']) && !in_array($k, $categories)) {
$categories[] = $k;
}
}
$parameter_options = array(
@ -3492,7 +3510,7 @@ class EventsController extends AppController {
'analysis' => array('valid_options' => array(0, 1, 2), 'default' => 0),
'info' => array('default' => 'Malware samples uploaded on ' . date('Y-m-d')),
'to_ids' => array('valid_options' => array(0, 1), 'default' => 1),
'category' => array('valid_options' => $types, 'default' => 'Payload installation'),
'category' => array('valid_options' => $categories, 'default' => 'Payload installation'),
'comment' => array('default' => '')
);
@ -3554,6 +3572,8 @@ class EventsController extends AppController {
));
if (empty($event)) throw new NotFoundException('Event not found.');
$this->Event->id = $data['event_id'];
$date = new DateTime();
$this->Event->saveField('timestamp', $date->getTimestamp());
$this->Event->saveField('published', 0);
} else {
$this->Event->create();
@ -3590,69 +3610,44 @@ class EventsController extends AppController {
$successCount = 0;
$errors = array();
foreach ($data['files'] as $file) {
if ($data['to_ids']) {
$temp = $this->Event->Attribute->handleMaliciousBase64($data['event_id'], $file['filename'], $file['data'], array_keys($hashes));
if ($temp['success']) {
foreach ($hashes as $hash => $typeName) {
if ($temp[$hash] == false) continue;
$file[$hash] = $temp[$hash];
$file['data'] = $temp['data'];
$this->Event->Attribute->create();
$attribute = array(
'value' => $file['filename'] . '|' . $file[$hash],
'distribution' => $data['distribution'],
'category' => $data['category'],
'type' => $typeName,
'event_id' => $data['event_id'],
'to_ids' => $data['to_ids'],
'comment' => $data['comment']
);
if ($hash == 'md5') $attribute['data'] = $file['data'];
$result = $this->Event->Attribute->save($attribute);
if (!$result) {
$this->Log->save(array(
'org' => $this->Auth->user('Organisation')['name'],
'model' => 'Event',
'model_id' => $data['event_id'],
'email' => $this->Auth->user('email'),
'action' => 'upload_sample',
'user_id' => $this->Auth->user('id'),
'title' => 'Error: Failed to create attribute using the upload sample functionality',
'change' => 'There was an issue creating an attribute (' . $typeName . ': ' . $file['filename'] . '|' . $file[$hash] . '). ' . 'The validation errors were: ' . json_encode($this->Event->Attribute->validationErrors),
));
if ($typeName == 'malware-sample') {
$errors[] = array('filename' => $file['filename'], 'hash' => $file[$hash], 'error' => $this->Event->Attribute->validationErrors);
}
} else if ($typeName == 'malware-sample') {
$successCount++;
$temp = $this->Event->Attribute->handleMaliciousBase64($data['event_id'], $file['filename'], $file['data'], array_keys($hashes));
if ($temp['success']) {
foreach ($hashes as $hash => $typeName) {
if ($temp[$hash] == false) continue;
$file[$hash] = $temp[$hash];
$file['data'] = $temp['data'];
$this->Event->Attribute->create();
$attribute = array(
'value' => $file['filename'] . '|' . $file[$hash],
'distribution' => $data['distribution'],
'category' => $data['category'],
'type' => $typeName,
'event_id' => $data['event_id'],
'to_ids' => $data['to_ids'],
'comment' => $data['comment']
);
if ($hash == 'md5') $attribute['data'] = $file['data'];
$result = $this->Event->Attribute->save($attribute);
if (!$result) {
$this->Log->save(array(
'org' => $this->Auth->user('Organisation')['name'],
'model' => 'Event',
'model_id' => $data['event_id'],
'email' => $this->Auth->user('email'),
'action' => 'upload_sample',
'user_id' => $this->Auth->user('id'),
'title' => 'Error: Failed to create attribute using the upload sample functionality',
'change' => 'There was an issue creating an attribute (' . $typeName . ': ' . $file['filename'] . '|' . $file[$hash] . '). ' . 'The validation errors were: ' . json_encode($this->Event->Attribute->validationErrors),
));
if ($typeName == 'malware-sample') {
$errors[] = array('filename' => $file['filename'], 'hash' => $file[$hash], 'error' => $this->Event->Attribute->validationErrors);
}
} else if ($typeName == 'malware-sample') {
$successCount++;
}
} else {
$errors[] = array('filename' => $file['filename'], 'hash' => $file['hash'], 'error' => 'Failed to encrypt and compress the file.');
}
} else {
$this->Event->Attribute->create();
$attribute = array(
'value' => $file['filename'],
'distribution' => $data['distribution'],
'category' => $data['category'],
'type' => 'attachment',
'event_id' => $data['event_id'],
'to_ids' => $data['to_ids'],
'data' => $file['data'],
'comment' => $data['comment']
);
$result = $this->Event->Attribute->save($attribute);
$this->Log->save(array(
'org' => $this->Auth->user('Organisation')['name'],
'model' => 'Event',
'model_id' => $data['event_id'],
'email' => $this->Auth->user('email'),
'action' => 'upload_sample',
'user_id' => $this->Auth->user('id'),
'title' => 'Error: Failed to create attribute using the upload sample functionality',
'change' => 'There was an issue creating an attribute (attachment: ' . $file['filename'] . '). ' . 'The validation errors were: ' . json_encode($this->Event->Attribute->validationErrors),
));
$errors[] = array('filename' => $file['filename'], 'hash' => $file['hash'], 'error' => 'Failed to encrypt and compress the file.');
}
}
if (!empty($errors)) {
@ -3692,8 +3687,12 @@ class EventsController extends AppController {
} else {
$json = $this->__buildGraphJson($id);
}
$this->set('json', $json);
$this->set('_serialize', 'json');
array_walk_recursive($json, function(&$item, $key){
if(!mb_detect_encoding($item, 'utf-8', true)){
$item = utf8_encode($item);
}
});
return new CakeResponse(array('body' => json_encode($json), 'status' => 200));
}
private function __buildGraphJson($id, $json = array()) {
@ -3794,6 +3793,13 @@ class EventsController extends AppController {
$links[] = $temp;
}
$json['links'] = $links;
} else {
if (!isset($json['links'])) {
$json['links'] = array();
}
if (!isset($json['nodes'])) {
$json['nodes'] = array();
}
}
return $json;
}

View File

@ -150,6 +150,12 @@ class FeedsController extends AppController {
if (empty($this->request->data['Feed']['target_event'])) {
$this->request->data['Feed']['target_event'] = 0;
}
if (empty($this->request->data['Feed']['input_source'])) {
$this->request->data['Feed']['input_source'] = 'network';
}
if (!isset($this->request->data['Feed']['delete_local_file'])) {
$this->request->data['Feed']['delete_local_file'] = 0;
}
$this->request->data['Feed']['settings'] = json_encode($this->request->data['Feed']['settings']);
$this->request->data['Feed']['event_id'] = !empty($this->request->data['Feed']['fixed_event']) ? $this->request->data['Feed']['target_event'] : 0;
if (!$error) {
@ -212,7 +218,7 @@ class FeedsController extends AppController {
$this->request->data['Feed']['settings']['delimiter'] = ',';
}
$this->request->data['Feed']['settings'] = json_encode($this->request->data['Feed']['settings']);
$fields = array('id', 'name', 'provider', 'enabled', 'rules', 'url', 'distribution', 'sharing_group_id', 'tag_id', 'fixed_event', 'event_id', 'publish', 'delta_merge', 'override_ids', 'settings');
$fields = array('id', 'name', 'provider', 'enabled', 'rules', 'url', 'distribution', 'sharing_group_id', 'tag_id', 'fixed_event', 'event_id', 'publish', 'delta_merge', 'source_format', 'override_ids', 'settings', 'input_source', 'delete_local_file');
$feed = array();
foreach ($fields as $field) {
if (isset($this->request->data['Feed'][$field])) {

View File

@ -287,4 +287,17 @@ class LogsController extends AppController {
$this->set('data', $data);
$this->set('_serialize', 'data');
}
public function pruneUpdateLogs() {
if (!$this->request->is('post')) {
//throw new MethodNotAllowedException('This functionality is only accessible via POST requests');
}
$this->Log->pruneUpdateLogsRouter($this->Auth->user());
if (Configure::read('MISP.background_jobs')) {
$this->Session->setFlash('The pruning job is queued.');
} else {
$this->Session->setFlash('The pruning is complete.');
}
$this->redirect($this->referer());
}
}

View File

@ -38,17 +38,27 @@ class OrganisationsController extends AppController {
}
}
$this->set('passedArgs', json_encode($passedArgs));
$this->paginate = array(
'conditions' => $conditions,
'recursive' => -1,
);
$this->paginate['conditions'] = $conditions;
$usersPerOrg = $this->User->getMembersCount();
$orgs = $this->paginate();
if ($this->_isSiteAdmin()) {
$this->loadModel('User');
$org_creator_ids = array();
foreach ($orgs as $org) {
if (!in_array($org['Organisation']['created_by'], $org_creator_ids)) {
if ($this->_isRest()) {
unset($this->paginate['limit']);
$orgs = $this->Organisation->find('all', $this->paginate);
} else {
if (isset($this->params['named']['viewall']) && $this->params['named']['viewall']) {
$orgCount = $this->Organisation->find('count');
$this->paginate['limit'] = $orgCount;
}
$this->set('viewall', isset($this->params['named']['viewall']) ? $this->params['named']['viewall'] : false);
$orgs = $this->paginate();
}
$this->loadModel('User');
$org_creator_ids = array();
foreach ($orgs as $k => $org) {
if (isset($usersPerOrg[$org['Organisation']['id']])) {
$orgs[$k]['Organisation']['user_count'] = $usersPerOrg[$org['Organisation']['id']];
}
if ($this->_isSiteAdmin()) {
if (!in_array($org['Organisation']['created_by'], array_keys($org_creator_ids))) {
$email = $this->User->find('first', array('recursive' => -1, 'fields' => array('id', 'email'), 'conditions' => array('id' => $org['Organisation']['created_by'])));
if (!empty($email)) {
$org_creator_ids[$org['Organisation']['created_by']] = $email['User']['email'];
@ -56,23 +66,59 @@ class OrganisationsController extends AppController {
$org_creator_ids[$org['Organisation']['created_by']] = 'Unknown';
}
}
$orgs[$k]['Organisation']['created_by_email'] = $org_creator_ids[$org['Organisation']['created_by']];
}
$this->set('org_creator_ids', $org_creator_ids);
}
$this->set('scope', $scope);
$this->set('orgs', $orgs);
$this->set('members', $usersPerOrg);
if ($this->_isRest()) {
return $this->RestResponse->viewData($orgs, $this->response->type());
} else {
$this->set('named', $this->params['named']);
$this->set('scope', $scope);
$this->set('orgs', $orgs);
}
}
public function admin_add() {
if ($this->request->is('post')) {
if ($this->_isRest()) {
if (isset($this->request->data['request'])) {
$this->request->data = $this->request->data['request'];
}
if (!isset($this->request->data['Organisation'])) {
$this->request->data['Organisation'] = $this->request->data;
}
if (isset($this->request->data['Organisation']['id'])){
unset($this->request->data['Organisation']['id']);
}
}
$this->Organisation->create();
$this->request->data['Organisation']['created_by'] = $this->Auth->user('id');
if ($this->_isRest()) {
if (!isset($this->request->data['Organisation']['local'])) {
$this->request->data['Organisation']['local'] = true;
}
}
if ($this->Organisation->save($this->request->data)) {
$this->Session->setFlash('The organisation has been successfully added.');
$this->redirect(array('admin' => false, 'action' => 'index'));
if ($this->_isRest()) {
$org = $this->Organisation->find('first', array(
'conditions' => array('Organisation.id' => $this->Organisation->id),
'recursive' => -1
));
return $this->RestResponse->viewData($org, $this->response->type());
} else {
$this->Session->setFlash('The organisation has been successfully added.');
$this->redirect(array('admin' => false, 'action' => 'index'));
}
} else {
$this->Session->setFlash('The organisation could not be added.');
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Organisations', 'admin_add', false, $this->Organisation->validationErrors, $this->response->type());
} else {
$this->Session->setFlash('The organisation could not be added.');
}
}
} else {
if ($this->_isRest()) {
return $this->RestResponse->describe('Organisations', 'admin_add', false, $this->response->type());
}
}
$this->set('countries', $this->_arrayToValuesIndexArray($this->Organisation->countries));
@ -82,12 +128,46 @@ class OrganisationsController extends AppController {
$this->Organisation->id = $id;
if (!$this->Organisation->exists()) throw new NotFoundException('Invalid organisation');
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->_isRest()) {
if (isset($this->request->data['request'])) {
$this->request->data = $this->request->data['request'];
}
if (!isset($this->request->data['Organisation'])) {
$this->request->data['Organisation'] = $this->request->data;
}
$existingOrg = $this->Organisation->find('first', array('conditions' => array('Organisation.id' => $id)));
$changeFields = array('name', 'type', 'nationality', 'sector', 'contacts', 'description', 'local', 'uuid');
$temp = array('Organisation' => array());
foreach ($changeFields as $field) {
if (isset($this->request->data['Organisation'][$field])) {
$temp['Organisation'][$field] = $this->request->data['Organisation'][$field];
} else {
$temp['Organisation'][$field] = $existingOrg['Organisation'][$field];
}
$this->request->data = $temp;
}
}
$this->request->data['Organisation']['id'] = $id;
if ($this->Organisation->save($this->request->data)) {
$this->Session->setFlash('Organisation updated.');
$this->redirect(array('admin' => false, 'action' => 'view', $this->Organisation->id));
if ($this->_isRest()) {
$org = $this->Organisation->find('first', array(
'conditions' => array('Organisation.id' => $this->Organisation->id),
'recursive' => -1
));
return $this->RestResponse->viewData($org, $this->response->type());
} else {
$this->Session->setFlash('Organisation updated.');
$this->redirect(array('admin' => false, 'action' => 'view', $this->Organisation->id));
}
} else {
$this->Session->setFlash('The organisation could not be updated.');
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Organisations', 'admin_edit', false, $this->Organisation->validationErrors, $this->response->type());
$this->Session->setFlash('The organisation could not be updated.');
}
}
} else {
if ($this->_isRest()) {
return $this->RestResponse->describe('Organisations', 'admin_edit', false, $this->response->type());
}
}
$this->set('countries', $this->_arrayToValuesIndexArray($this->Organisation->countries));
@ -110,11 +190,19 @@ class OrganisationsController extends AppController {
if ($org['Organisation']['local']) $url = '/organisations/index';
else $url = '/organisations/index/remote';
if ($this->Organisation->delete()) {
$this->Session->setFlash(__('Organisation deleted'));
$this->redirect($url);
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Organisations', 'admin_delete', $id, $this->response->type());
} else {
$this->Session->setFlash(__('Organisation deleted'));
$this->redirect($url);
}
} else {
$this->Session->setFlash(__('Organisation could not be deleted. Generally organisations should never be deleted, instead consider moving them to the known remote organisations list. Alternatively, if you are certain that you would like to remove an organisation and are aware of the impact, make sure that there are no users or events still tied to this organisation before deleting it.'));
$this->redirect($url);
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Organisations', 'admin_delete', $id, $this->Organisation->validationErrors, $this->response->type());
} else {
$this->Session->setFlash(__('Organisation could not be deleted. Generally organisations should never be deleted, instead consider moving them to the known remote organisations list. Alternatively, if you are certain that you would like to remove an organisation and are aware of the impact, make sure that there are no users or events still tied to this organisation before deleting it.'));
$this->redirect($url);
}
}
}
@ -124,28 +212,47 @@ class OrganisationsController extends AppController {
}
public function view($id) {
if (Validation::uuid($id)) {
$temp = $this->Organisation->find('first', array('recursive' => -1, 'fields' => array('Organisation.id'), 'conditions' => array('Organisation.uuid' => $id)));
if (empty($temp)) throw new NotFoundException('Invalid organisation.');
$id = $temp['Organisation']['id'];
} else if (!is_numeric($id)) {
throw new NotFoundException('Invalid organisation.');
}
$this->Organisation->id = $id;
if (!$this->Organisation->exists()) throw new NotFoundException('Invalid organisation');
$fullAccess = false;
$fields = array('id', 'name', 'date_created', 'date_modified', 'type', 'nationality', 'sector', 'contacts', 'description', 'local', 'uuid');
if ($this->_isSiteAdmin() || $this->Auth->user('Organisation')['id'] == $id) {
if ($this->_isSiteAdmin() || ($this->_isAdmin() && $this->Auth->user('Organisation')['id'] == $id)) {
$fullAccess = true;
$fields = array_merge($fields, array('created_by'));
}
$org = $this->Organisation->find('first', array(
'conditions' => array('id' => $id),
'fields' => $fields
'fields' => $fields,
'recursive' => -1
));
$this->set('local', $org['Organisation']['local']);
if ($fullAccess) {
$creator = $this->Organisation->User->find('first', array('conditions' => array('User.id' => $org['Organisation']['created_by'])));
$this->set('creator', $creator);
$creator = $this->Organisation->User->find('first', array(
'conditions' => array('User.id' => $org['Organisation']['created_by']),
'fields' => array('email'),
'recursive' => -1
)
);
if (!empty($creator)) {
$org['Organisation']['created_by_email'] = $creator['User']['email'];
}
}
if ($this->_isRest()) {
$org['Organisation']['user_count'] = $this->Organisation->User->getMembersCount($org['Organisation']['id']);
return $this->RestResponse->viewData($org, $this->response->type());
} else {
$this->set('fullAccess', $fullAccess);
$this->set('org', $org);
$this->set('id', $id);
}
$this->set('fullAccess', $fullAccess);
$this->set('org', $org);
$this->set('id', $id);
}
public function landingpage($id) {

View File

@ -720,7 +720,7 @@ class ServersController extends AppController {
// if Proxy is set up in the settings, try to connect to a test URL
$proxyStatus = $this->Server->proxyDiagnostics($diagnostic_errors);
$moduleTypes = array('Enrichment', 'Import', 'Export');
foreach ($moduleTypes as $type) {
$moduleStatus[$type] = $this->Server->moduleDiagnostics($diagnostic_errors, $type);
@ -738,9 +738,12 @@ class ServersController extends AppController {
$writeableFiles = $this->Server->writeableFilesDiagnostics($diagnostic_errors);
$readableFiles = $this->Server->readableFilesDiagnostics($diagnostic_errors);
$extensions = $this->Server->extensionDiagnostics();
// check if the encoding is not set to utf8
$dbEncodingStatus = $this->Server->databaseEncodingDiagnostics($diagnostic_errors);
$viewVars = array(
'diagnostic_errors', 'tabs', 'tab', 'issues', 'finalSettings', 'writeableErrors', 'readableErrors', 'writeableDirs', 'writeableFiles', 'readableFiles', 'extensions'
'diagnostic_errors', 'tabs', 'tab', 'issues', 'finalSettings', 'writeableErrors', 'readableErrors', 'writeableDirs', 'writeableFiles', 'readableFiles', 'extensions', 'dbEncodingStatus'
);
$viewVars = array_merge($viewVars, $additionalViewVars);
foreach ($viewVars as $viewVar) $this->set($viewVar, ${$viewVar});
@ -1155,4 +1158,9 @@ class ServersController extends AppController {
$this->set('response', array('version' => $versionArray['major'] . '.' . $versionArray['minor'] . '.' . $versionArray['hotfix'], 'perm_sync' => $this->userRole['perm_sync']));
$this->set('_serialize', 'response');
}
public function getPyMISPVersion() {
$this->set('response', array('version' => $this->pyMispVersion));
$this->set('_serialize', 'response');
}
}

View File

@ -181,6 +181,7 @@ class ShadowAttributesController extends AppController {
$response = $this->__accept($id);
if ($this->_isRest()) {
if (isset($response['success'])) {
$response['check_publish'] = true;
$this->set('name', $response['success']);
$this->set('message', $response['success']);
$this->set('url', '/shadow_attributes/accept/' . $id);
@ -436,6 +437,11 @@ class ShadowAttributesController extends AppController {
$this->set('event_id', $eventId);
// combobox for types
$types = array_keys($this->ShadowAttribute->typeDefinitions);
foreach ($types as $key => $value) {
if (in_array($value, array('malware-sample', 'attachment'))) {
unset($types[$key]);
}
}
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories
@ -705,6 +711,11 @@ class ShadowAttributesController extends AppController {
// combobox for types
$types = array_keys($this->ShadowAttribute->typeDefinitions);
foreach ($types as $key => $value) {
if (in_array($value, array('malware-sample', 'attachment'))) {
unset($types[$key]);
}
}
$types = $this->_arrayToValuesIndexArray($types);
$this->set('types', $types);
// combobox for categories

View File

@ -51,16 +51,9 @@ class SightingsController extends AppController {
}
} else {
if ($error) {
$this->set('errors', $error);
$this->set('name', 'Could not add the Sighting.');
$this->set('message', 'Could not add the Sighting.');
$this->set('_serialize', array('name', 'message', 'errors'));
return $this->RestResponse->saveFailResponse('Sighting', 'add', $id, $error);
} else {
$this->set('name', 'Sighting added.');
$this->set('message', $result . ' sighting' . (($result == 1) ? '' : 's') . ' successfuly added.');
$this->set('url', '/sightings/add/' . $id);
$this->set('id', $this->Sighting->id);
$this->set('_serialize', array('name', 'message', 'url', 'id'));
return $this->RestResponse->saveSuccessResponse('Sighting', 'add', $id, false, $result . ' sighting' . (($result == 1) ? '' : 's') . ' successfuly added.');
}
}
}
@ -76,15 +69,37 @@ class SightingsController extends AppController {
}
$result = $this->Sighting->delete($sighting['Sighting']['id']);
if (!$result) {
$this->set('errors', '');
$this->set('name', 'Failed');
$this->set('message', 'Could not delete the Sighting.');
$this->set('_serialize', array('name', 'message', 'errors'));
return $this->RestResponse->saveFailResponse('Sighting', 'delete', $id, 'Could not delete the Sighting.');
} else {
$this->set('name', 'Success');
$this->set('message', 'Sighting successfuly deleted.');
$this->set('url', '/sightings/delete/' . $id);
$this->set('_serialize', array('name', 'message', 'url'));
return $this->RestResponse->saveSuccessResponse('Sighting', 'delete', $id, false, 'Sighting successfuly deleted.');
}
}
public function index($eventid = false) {
$this->loadModel('Event');
$sightingConditions = array();
if ($eventid) {
$sightingConditions = array('Sighting.event_id' => $eventid);
}
$sightedEvents = $this->Sighting->find('list', array(
'group' => 'Sighting.event_id',
'fields' => array('Sighting.event_id'),
'conditions' => $sightingConditions
));
if (empty($sightedEvents)) {
$this->RestResponse->viewData(array());
}
$conditions = array('metadata' => true, 'contain' => false);
if ($eventid) {
$conditions['eventid'] = $sightedEvents;
}
$events = $this->Event->fetchEventIds($this->Auth->user(), false, false, false, false, false, false, $sightedEvents);
$sightings = array();
if (!empty($events)) {
foreach ($events as $k => $event) {
$sightings = array_merge($sightings, $this->Sighting->attachToEvent($event, $this->Auth->user()));
}
}
return $this->RestResponse->viewData($sightings);
}
}

View File

@ -11,6 +11,9 @@ class TagsController extends AppController {
'Tag.name' => 'asc'
),
'contain' => array(
'AttributeTag' => array(
'fields' => array('attribute_id')
),
'EventTag' => array(
'fields' => array('event_id')
),
@ -24,6 +27,7 @@ class TagsController extends AppController {
public $helpers = array('TextColour');
public function index($favouritesOnly = false) {
$this->loadModel('Attribute');
$this->loadModel('Event');
$this->loadModel('Taxonomy');
$taxonomies = $this->Taxonomy->listTaxonomies(array('full' => false, 'enabled' => true));
@ -69,6 +73,35 @@ class TagsController extends AppController {
$paginated[$k]['Tag']['count'] = count($events);
}
unset($paginated[$k]['EventTag']);
if (empty($tag['AttributeTag'])) {
$paginated[$k]['Tag']['attribute_count'] = 0;
} else {
$attributeIDs = array();
foreach ($tag['AttributeTag'] as $attributeTag) {
$attributeIDs[] = $attributeTag['attribute_id'];
}
$conditions = array('Attribute.id' => $attributeIDs);
if (!$this->_isSiteAdmin()) {
$conditions = array_merge(
$conditions,
array('OR' => array(
array('AND' => array(
array('Attribute.deleted =' => 0),
array('Attribute.distribution >' => 0),
array('Event.distribution >' => 0),
array('Event.published =' => 1)
)),
array('Event.orgc_id' => $this->Auth->user('org_id'))
)));
}
$attributes = $this->Attribute->find('all', array(
'fields' => array('Attribute.id', 'Attribute.deleted', 'Attribute.distribution', 'Event.id', 'Event.distribution', 'Event.orgc_id'),
'contain' => array('Event' => array('fields' => array('id', 'distribution', 'orgc_id'))),
'conditions' => $conditions
));
$paginated[$k]['Tag']['attribute_count'] = count($attributes);
}
unset($paginated[$k]['AttributeTag']);
if (!empty($tag['FavouriteTag'])) {
foreach ($tag['FavouriteTag'] as $ft) if ($ft['user_id'] == $this->Auth->user('id')) $paginated[$k]['Tag']['favourite'] = true;
if (!isset($tag['Tag']['favourite'])) $paginated[$k]['Tag']['favourite'] = false;
@ -213,10 +246,12 @@ class TagsController extends AppController {
public function view($id) {
if ($this->_isRest()) {
$contain = array('EventTag' => array('fields' => 'event_id'));
$contain['AttributeTag'] = array('fields' => 'attribute_id');
$tag = $this->Tag->find('first', array(
'conditions' => array('id' => $id),
'recursive' => -1,
'contain' => array('EventTag' => array('fields' => 'event_id'))
'contain' => $contain
));
if (empty($tag)) throw new MethodNotAllowedException('Invalid Tag');
if (empty($tag['EventTag'])) $tag['Tag']['count'] = 0;
@ -242,6 +277,35 @@ class TagsController extends AppController {
$tag['Tag']['count'] = count($events);
}
unset($tag['EventTag']);
if (empty($tag['AttributeTag'])) {
$tag['Tag']['attribute_count'] = 0;
} else {
$attributeIDs = array();
foreach ($tag['AttributeTag'] as $attributeTag) {
$attributeIDs[] = $attributeTag['attribute_id'];
}
$conditions = array('Attribute.id' => $attributeIDs);
if (!$this->_isSiteAdmin()) {
$conditions = array_merge(
$conditions,
array('OR' => array(
array('AND' => array(
array('Attribute.deleted =' => 0),
array('Attribute.distribution >' => 0),
array('Event.distribution >' => 0),
array('Event.published =' => 1)
)),
array('Event.orgc_id' => $this->Auth->user('org_id'))
)));
}
$attributes = $this->Tag->AttributeTag->Attribute->find('all', array(
'fields' => array('Attribute.id', 'Attribute.deleted', 'Attribute.distribution', 'Event.id', 'Event.distribution', 'Event.orgc_id'),
'contain' => array('Event' => array('fields' => array('id', 'distribution', 'orgc_id'))),
'conditions' => $conditions
));
$tag['Tag']['attribute_count'] = count($attributes);
}
unset($tag['AttributeTag']);
$this->set('Tag', $tag['Tag']);
$this->set('_serialize', 'Tag');
} else throw new MethodNotAllowedException('This action is only for REST users.');
@ -275,6 +339,34 @@ class TagsController extends AppController {
$this->render('/Events/ajax/ajaxTags');
}
public function showAttributeTag($id) {
$this->helpers[] = 'TextColour';
$this->loadModel('AttributeTag');
$this->Tag->AttributeTag->Attribute->id = $id;
if (!$this->Tag->AttributeTag->Attribute->exists()) throw new NotFoundException(__('Invalid attribute'));
$this->Tag->AttributeTag->Attribute->read();
$eventId = $this->Tag->AttributeTag->Attribute->data['Attribute']['event_id'];
$attributeTags = $this->AttributeTag->find('all', array(
'conditions' => array(
'attribute_id' => $id
),
'contain' => array('Tag'),
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
));
$event = $this->Tag->AttributeTag->Attribute->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'),
'conditions' => array('Event.id' => $eventId)
));
$this->set('event', $event);
$this->set('attributeTags', $attributeTags);
$this->set('attributeId', $id);
$this->layout = 'ajax';
$this->render('/Attributes/ajax/ajaxAttributeTags');
}
public function viewTag($id) {
$tag = $this->Tag->find('first', array(
'conditions' => array(
@ -289,7 +381,7 @@ class TagsController extends AppController {
}
public function selectTaxonomy($event_id) {
public function selectTaxonomy($id, $attributeTag = false) {
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) throw new NotFoundException('You don\'t have permission to do that.');
$favourites = $this->Tag->FavouriteTag->find('count', array('conditions' => array('FavouriteTag.user_id' => $this->Auth->user('id'))));
$this->loadModel('Taxonomy');
@ -298,13 +390,16 @@ class TagsController extends AppController {
$tags = $this->Taxonomy->getTaxonomyTags($k, false, true);
if (empty($tags)) unset($options[$k]);
}
$this->set('event_id', $event_id);
if ($attributeTag !== false) {
$this->set('attributeTag', true);
}
$this->set('object_id', $id);
$this->set('options', $options);
$this->set('favourites', $favourites);
$this->render('ajax/taxonomy_choice');
}
public function selectTag($event_id, $taxonomy_id) {
public function selectTag($id, $taxonomy_id, $attributeTag = false) {
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) throw new NotFoundException('You don\'t have permission to do that.');
$this->loadModel('Taxonomy');
$expanded = array();
@ -357,12 +452,15 @@ class TagsController extends AppController {
unset($expanded[$banned_tag]);
}
}
if ($attributeTag !== false) {
$this->set('attributeTag', true);
}
$this->set('object_id', $id);
foreach ($options as $k => $v) {
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
unset($options[$k]);
}
}
$this->set('event_id', $event_id);
$this->set('options', $options);
$this->set('expanded', $expanded);
$this->set('custom', $taxonomy_id == 0 ? true : false);
@ -415,4 +513,130 @@ class TagsController extends AppController {
$this->response->type('json');
$this->render('/Servers/json/simple');
}
private function __findObjectByUuid($object_uuid, &$type) {
$this->loadModel('Event');
$object = $this->Event->find('first', array(
'conditions' => array(
'Event.uuid' => $object_uuid,
),
'fields' => array('Event.orgc_id', 'Event.id'),
'recursive' => -1
));
$type = 'Event';
if (!empty($object)) {
if (!$this->_isSiteAdmin() && $object['Event']['orgc_id'] != $this->Auth->user('org_id')) {
throw new MethodNotAllowedException('Invalid Target.');
}
} else {
$type = 'Attribute';
$object = $this->Event->Attribute->find('first', array(
'conditions' => array(
'Attribute.uuid' => $object_uuid,
),
'fields' => array('Attribute.id'),
'recursive' => -1,
'contain' => array('Event.orgc_id')
));
if (!empty($object)) {
if (!$this->_isSiteAdmin() && $object['Event']['orgc_id'] != $this->Auth->user('org_id')) {
throw new MethodNotAllowedException('Invalid Target.');
}
} else {
throw new MethodNotAllowedException('Invalid Target.');
}
}
return $object;
}
public function attachTagToObject($object_uuid, $tag) {
if (!Validation::uuid($object_uuid)) {
throw new InvalidArgumentException('Invalid UUID');
}
if (is_numeric($tag)) {
$conditions = array('Tag.id' => $tag);
} else {
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag)));
}
$objectType = '';
$object = $this->__findObjectByUuid($object_uuid, $objectType);
$existingTag = $this->Tag->find('first', array('conditions' => $conditions, 'recursive' => -1));
if (empty($existingTag)) {
if (!is_numeric($tag)) {
if (!$this->userRole['perm_tag_editor']) {
throw new InvalidArgumentException('Tag not found and insufficient privileges to create it.');
}
$this->Tag->create();
$this->Tag->save(array('Tag' => array('name' => $tag, 'colour' => $this->Tag->random_color())));
$existingTag = $this->Tag->find('first', array('recursive' => -1, 'conditions' => array('Tag.id' => $this->Tag->id)));
} else {
throw new InvalidArgumentException('Invalid Tag.');
}
}
if (!$this->_isSiteAdmin()) {
if (!in_array($existingTag['Tag']['org_id'], array(0, $this->Auth->user('org_id')))) {
throw new MethodNotAllowedException('Invalid Tag.');
}
}
$this->loadModel($objectType);
$connectorObject = $objectType . 'Tag';
$existingAssociation = $this->$objectType->$connectorObject->find('first', array(
'conditions' => array(
strtolower($objectType) . '_id' => $object[$objectType]['id'],
'tag_id' => $existingTag['Tag']['id']
)
));
if (!empty($existingAssociation)) {
throw new MethodNotAllowedException('Cannot attach tag, ' . $objectType . ' already has the tag attached.');
}
$this->$objectType->$connectorObject->create();
$result = $this->$objectType->$connectorObject->save(array($connectorObject => array(
strtolower($objectType) . '_id' => $object[$objectType]['id'],
'tag_id' => $existingTag['Tag']['id']
)));
if ($result) {
$message = 'Tag ' . $existingTag['Tag']['name'] . '(' . $existingTag['Tag']['id'] . ') successfully attached to ' . $objectType . '(' . $object[$objectType]['id'] . ').';
return $this->RestResponse->saveSuccessResponse('Tags', 'attachTagToObject', false, $this->response->type(), $message);
} else {
return $this->RestResponse->saveFailResponse('Tags', 'attachTagToObject', false, 'Failed to attach tag to object.', $this->response->type());
}
}
public function removeTagFromObject($object_uuid, $tag) {
if (!Validation::uuid($object_uuid)) {
throw new InvalidArgumentException('Invalid UUID');
}
if (is_numeric($tag)) {
$conditions = array('Tag.id' => $tag);
} else {
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag)));
}
$existingTag = $this->Tag->find('first', array('conditions' => $conditions, 'recursive' => -1));
if (empty($existingTag)) {
throw new MethodNotAllowedException('Invalid Tag.');
}
$objectType = '';
$object = $this->__findObjectByUuid($object_uuid, $objectType);
if (empty($object)) {
throw new MethodNotAllowedException('Invalid Target.');
}
$connectorObject = $objectType . 'Tag';
$this->loadModel($objectType);
$existingAssociation = $this->$objectType->$connectorObject->find('first', array(
'conditions' => array(
strtolower($objectType) . '_id' => $object[$objectType]['id'],
'tag_id' => $existingTag['Tag']['id']
)
));
if (empty($existingAssociation)) {
throw new MethodNotAllowedException('Could not remove tag as it is not attached to the target ' . $objectType);
}
$result = $this->$objectType->$connectorObject->delete($existingAssociation[$connectorObject]['id']);
if ($result) {
$message = 'Tag ' . $existingTag['Tag']['name'] . '(' . $existingTag['Tag']['id'] . ') successfully removed from ' . $objectType . '(' . $object[$objectType]['id'] . ').';
return $this->RestResponse->saveSuccessResponse('Tags', 'removeTagFromObject', false, $this->response->type(), $message);
} else {
return $this->RestResponse->saveFailResponse('Tags', 'removeTagFromObject', false, 'Failed to remove tag from object.', $this->response->type());
}
}
}

View File

@ -19,68 +19,37 @@ class ThreadsController extends AppController {
public function viewEvent($id) {
$this->loadModel('Event');
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id));
if (empty($result)) throw new MethodNotAllowedException('You are not authorised to see that.');
$result = $result[0];
// 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')
);
$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'],
'sharing_group_id' => $result['Event']['sharing_group_id'],
'post_count' => 0,
'org_id' => $result['Event']['orgc_id']
);
$this->Thread->save($newThread);
$thread = ($this->Thread->read());
} else {
if ($thread['Thread']['distribution'] != $result['Event']['distribution']) {
$thread['Thread']['distribution'] = $result['Event']['distribution'];
$this->Thread->save($thread);
}
if ($thread['Thread']['sharing_group_id'] != $result['Event']['sharing_group_id']) {
$thread['Thread']['sharing_group_id'] = $result['Event']['sharing_group_id'];
$this->Thread->save($thread);
}
}
$this->loadModel('Post');
$this->paginate['Post'] = array(
'limit' => 5,
'conditions' => array('Post.thread_id' => $thread['Thread']['id']),
'contain' => array('User' => array('Organisation' => array('fields' => array('id', 'name')))),
);
$posts = $this->paginate('Post');
if (!$this->_isSiteAdmin()) {
foreach ($posts as $key => $post) {
if ($post['User']['org_id'] != $this->Auth->user('org_id')) {
$posts[$key]['User']['email'] = 'User ' . $post['User']['id'] . ' (' . $post['User']['org_id'] . ')';
$thread_id = false;
if ($result) {
$thread_id = $this->Thread->find('first', array('recursive' => -1, 'conditions' => array('Thread.event_id' => $id), 'fields' => array('Thread.id')));
if ($thread_id) {
if (!$this->_isRest()) {
$this->redirect(array('action' => 'view', $thread_id['Thread']['id'], true));
} else {
return $this->__view($thread_id['Thread']['id'], false, false);
}
} else {
if ($this->_isRest()) {
return $this->RestResponse->viewData(array(), $this->response->type());
} else {
throw new NotFoundException('Invalid Thread.');
}
}
} else {
throw new NotFoundException('Invalid Event.');
}
// 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']);
$this->disableCache();
$this->layout = 'ajax';
$this->render('/Elements/eventdiscussion');
}
public function view($thread_id, $eventView = false) {
$post_id = false;
if (isset($this->passedArgs['post_id'])) $post_id = $this->passedArgs['post_id'];
$response = $this->__view($thread_id, $eventView, $post_id);
if ($this->_isRest()) {
return $response;
}
}
private function __view($thread_id, $eventView, $post_id) {
if ($eventView) {
$id = $thread_id;
// Show the discussion
@ -111,7 +80,6 @@ class ThreadsController extends AppController {
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'])) {
@ -144,24 +112,41 @@ class ThreadsController extends AppController {
'conditions' => array('Post.thread_id' => $thread_id),
'contain' => array(
'User' => array(
'fields' => array('User.email', 'User.id'),
'Organisation' => array(
'fields' => array('id', 'name')
),
),
),
);
$posts = $this->paginate('Post');
if (!$this->_isSiteAdmin()) {
foreach ($posts as $key => $post) {
if ($post['User']['org_id'] != $this->Auth->user('org_id')) {
$posts[$key]['User']['email'] = 'User ' . $post['User']['id'] . ' (' . $post['User']['org_id'] . ')';
if ($this->_isRest()) {
$posts = $this->Thread->Post->find('all', array(
'contain' => $this->paginate['contain'],
'conditions' => $this->paginate['conditions']
));
} else {
$posts = $this->paginate('Post');
}
foreach ($posts as $k => $post) {
if (!empty($post['User'])) {
$posts[$k]['Post']['org_name'] = $post['User']['Organisation']['name'];
if ($this->_isSiteAdmin() || $this->Auth->user('org_id') == $post['User']['org_id']) {
$posts[$k]['Post']['user_email'] = $post['User']['email'];
}
$posts[$k]['Post']['user_id'] = $post['User']['id'];
$posts[$k] = $posts[$k]['Post'];
}
}
$this->set('posts', $posts);
$this->set('post_id', $post_id);
$this->set('thread_id', $thread_id);
$this->set('thread_title', $thread['Thread']['title']);
if ($this->_isRest()) {
if (!empty($posts)) {
$thread['Thread']['Post'] = $posts;
}
return $this->RestResponse->viewData($thread, $this->response->type());
} else {
$this->set('posts', $posts);
$this->set('post_id', $post_id);
$this->set('thread', $thread);
}
}
if ($eventView) {
$this->set('context', 'event');

View File

@ -382,6 +382,15 @@ class UsersController extends AppController {
}
$fieldList = array('password', 'email', 'external_auth_required', 'external_auth_key', 'enable_password', 'confirm_password', 'org_id', 'role_id', 'authkey', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'invited_by', 'change_pw', 'termsaccepted', 'newsread');
if ($this->User->save($this->request->data, true, $fieldList)) {
$notification_message = '';
if ($this->request->data['User']['notify']) {
$user = $this->User->find('first', array('conditions' => array('User.id' => $this->User->id), 'recursive' => -1));
$password = isset($this->request->data['User']['password']) ? $this->request->data['User']['password'] : false;
$result = $this->User->initiatePasswordReset($user, true, true, $password);
if ($result) {
$notification_message .= ' User notified of new credentials.';
}
}
if ($this->_isRest()) {
$user = $this->User->find('first', array(
'conditions' => array('User.id' => $this->User->id),
@ -390,7 +399,7 @@ class UsersController extends AppController {
$user['User']['password'] = '******';
return $this->RestResponse->viewData($user, $this->response->type());
} else {
$this->Session->setFlash(__('The user has been saved'));
$this->Session->setFlash(__('The user has been saved.' . $notification_message));
$this->redirect(array('action' => 'index'));
}
} else {
@ -711,6 +720,7 @@ class UsersController extends AppController {
}
}
if ($this->User->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
$date = date('Y-m-d H:i:s');
$org = array('Organisation' => array(
'id' => 1,
'name' => !empty(Configure::read('MISP.org')) ? Configure::read('MISP.org') : 'ADMIN',
@ -718,6 +728,7 @@ class UsersController extends AppController {
'type' => 'ADMIN',
'uuid' => CakeText::uuid(),
'local' => 1,
'date_created' => $date,
'sector' => '',
'nationality' => ''
));
@ -817,7 +828,7 @@ class UsersController extends AppController {
}
public function histogram($selected = null) {
if (!$this->request->is('ajax')) throw new MethodNotAllowedException('This function can only be accessed via AJAX.');
if (!$this->request->is('ajax') && !$this->_isRest()) throw new MethodNotAllowedException('This function can only be accessed via AJAX or the API.');
if ($selected == '[]') $selected = null;
$selectedTypes = array();
if ($selected) $selectedTypes = json_decode($selected);
@ -877,9 +888,13 @@ class UsersController extends AppController {
foreach ($sigTypes as $k => $type) {
$typeDb[$type] = $colours[$k];
}
$this->set('typeDb', $typeDb);
$this->set('sigTypes', $sigTypes);
$this->layout = 'ajax';
if ($this->_isRest()) {
return $this->RestResponse->viewData($data, $this->response->type());
} else {
$this->set('typeDb', $typeDb);
$this->set('sigTypes', $sigTypes);
$this->layout = 'ajax';
}
}
public function terms() {
@ -1022,26 +1037,7 @@ class UsersController extends AppController {
}
if ($this->request->is('post')) {
if (isset($this->request->data['User']['firstTime'])) $firstTime = $this->request->data['User']['firstTime'];
$org = Configure::read('MISP.org');
$options = array('passwordResetText', 'newUserText');
$subjects = array('[' . $org . ' MISP] New user registration', '[' . $org . ' MISP] Password reset');
$textToFetch = $options[($firstTime ? 0 : 1)];
$subject = $subjects[($firstTime ? 0 : 1)];
$this->loadModel('Server');
$body = Configure::read('MISP.' . $textToFetch);
if (!$body) $body = $this->Server->serverSettings['MISP'][$textToFetch]['value'];
$body = $this->User->adminMessageResolve($body);
$password = $this->User->generateRandomPassword();
$body = str_replace('$password', $password, $body);
$body = str_replace('$username', $user['User']['email'], $body);
$result = $this->User->sendEmail($user, $body, false, $subject);
if ($result) {
$this->User->id = $user['User']['id'];
$this->User->saveField('password', $password);
$this->User->saveField('change_pw', '1');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'New credentials sent.')),'status'=>200));
}
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'There was an error notifying the user. His/her credentials were not altered.')),'status'=>200));
return new CakeResponse($this->User->initiatePasswordReset($user, $id, $firstTime));
} else {
$this->layout = 'ajax';
$this->set('user', $user);
@ -1054,14 +1050,22 @@ class UsersController extends AppController {
public function statistics($page = 'data') {
$this->set('page', $page);
$this->set('pages', array('data' => 'Usage data', 'orgs' => 'Organisations', 'tags' => 'Tags', 'attributehistogram' => 'Attribute histogram'));
$result = array();
if ($page == 'data') {
$this->__statisticsData($this->params['named']);
$result = $this->__statisticsData($this->params['named']);
} else if ($page == 'orgs') {
$this->__statisticsOrgs($this->params['named']);
$result = $this->__statisticsOrgs($this->params['named']);
} else if ($page == 'tags') {
$this->__statisticsTags($this->params['named']);
$result = $this->__statisticsTags($this->params['named']);
} else if ($page == 'attributehistogram') {
$this->render('statistics_histogram');
if ($this->_isRest()) {
return $this->histogram($selected = null);
} else {
$this->render('statistics_histogram');
}
}
if ($this->_isRest()) {
return $result;
}
}
@ -1078,37 +1082,45 @@ class UsersController extends AppController {
}
// Some additional statistics
$this_month = strtotime('first day of this month');
$stats[0] = $this->User->Event->find('count', null);
$stats[1] = $this->User->Event->find('count', array('conditions' => array('Event.timestamp >' => $this_month)));
$stats['event_count'] = $this->User->Event->find('count', null);
$stats['event_count_month'] = $this->User->Event->find('count', array('conditions' => array('Event.timestamp >' => $this_month)));
$stats[2] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.deleted' => 0)));
$stats[3] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.timestamp >' => $this_month, 'Attribute.deleted' => 0)));
$stats['attribute_count'] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.deleted' => 0)));
$stats['attribute_count_month'] = $this->User->Event->Attribute->find('count', array('conditions' => array('Attribute.timestamp >' => $this_month, 'Attribute.deleted' => 0)));
$this->loadModel('Correlation');
$this->Correlation->recursive = -1;
$stats[4] = $this->Correlation->find('count', null);
$stats[4] = $stats[4] / 2;
$stats['correlation_count'] = $this->Correlation->find('count', null);
$stats['correlation_count'] = $stats['correlation_count'] / 2;
$stats[5] = $this->User->Event->ShadowAttribute->find('count', null);
$stats['proposal_count'] = $this->User->Event->ShadowAttribute->find('count', null);
$stats[6] = $this->User->find('count', null);
$stats[7] = count($orgs);
$stats['user_count'] = $this->User->find('count', null);
$stats['org_count'] = count($orgs);
$this->loadModel('Thread');
$stats[8] = $this->Thread->find('count', array('conditions' => array('Thread.post_count >' => 0)));
$stats[9] = $this->Thread->find('count', array('conditions' => array('Thread.date_created >' => date("Y-m-d H:i:s",$this_month), 'Thread.post_count >' => 0)));
$stats['thread_count'] = $this->Thread->find('count', array('conditions' => array('Thread.post_count >' => 0)));
$stats['thread_count_month'] = $this->Thread->find('count', array('conditions' => array('Thread.date_created >' => date("Y-m-d H:i:s",$this_month), 'Thread.post_count >' => 0)));
$stats[10] = $this->Thread->Post->find('count', null);
$stats[11] = $this->Thread->Post->find('count', array('conditions' => array('Post.date_created >' => date("Y-m-d H:i:s",$this_month))));
$stats['post_count'] = $this->Thread->Post->find('count', null);
$stats['post_count_month'] = $this->Thread->Post->find('count', array('conditions' => array('Post.date_created >' => date("Y-m-d H:i:s",$this_month))));
$this->set('stats', $stats);
$this->set('orgs', $orgs);
$this->set('start', strtotime(date('Y-m-d H:i:s') . ' -5 months'));
$this->set('end', strtotime(date('Y-m-d H:i:s')));
$this->set('startDateCal', $year . ', ' . $month . ', 01');
$range = '[5, 10, 50, 100]';
$this->set('range', $range);
$this->render('statistics_data');
if ($this->_isRest()) {
$data = array(
'stats' => $stats
);
return $this->RestResponse->viewData($data, $this->response->type());
} else {
$this->set('stats', $stats);
$this->set('orgs', $orgs);
$this->set('start', strtotime(date('Y-m-d H:i:s') . ' -5 months'));
$this->set('end', strtotime(date('Y-m-d H:i:s')));
$this->set('startDateCal', $year . ', ' . $month . ', 01');
$range = '[5, 10, 50, 100]';
$this->set('range', $range);
$this->render('statistics_data');
}
}
private function __statisticsOrgs($params = array()) {
@ -1155,9 +1167,13 @@ class UsersController extends AppController {
$orgs[$k]['logo'] = true;
}
}
$this->set('scope', $params['scope']);
$this->set('orgs', $orgs);
$this->render('statistics_orgs');
if ($this->_isRest()) {
return $this->RestResponse->viewData($orgs, $this->response->type());
} else {
$this->set('scope', $params['scope']);
$this->set('orgs', $orgs);
$this->render('statistics_orgs');
}
}
public function tagStatisticsGraph() {
@ -1198,19 +1214,31 @@ class UsersController extends AppController {
}
$taxonomyColourCodes = array();
$taxonomies = array_merge(array('custom'), $taxonomies);
$this->set('taxonomyColourCodes', $taxonomyColourCodes);
$this->set('taxonomies', $taxonomies);
$this->set('flatData', $flatData);
$this->set('treemap', $treemap);
$this->set('tags', $tags);
$this->layout = 'treemap';
$this->render('ajax/tag_statistics_graph');
if ($this->_isRest()) {
$data = array(
'flatData' => $flatData,
'treemap' => $treemap
);
return $this->RestResponse->viewData($data, $this->response->type());
} else {
$this->set('taxonomyColourCodes', $taxonomyColourCodes);
$this->set('taxonomies', $taxonomies);
$this->set('flatData', $flatData);
$this->set('treemap', $treemap);
$this->set('tags', $tags);
$this->layout = 'treemap';
$this->render('ajax/tag_statistics_graph');
}
}
private function __statisticsTags($params = array()) {
$trending_tags = array();
$all_tags = array();
$this->render('statistics_tags');
if ($this->_isRest()) {
return $this->tagStatisticsGraph();
} else {
$this->render('statistics_tags');
}
}
public function verifyGPG() {

View File

@ -496,4 +496,32 @@ class NidsExport {
}
return false;
}
public static function getProtocolPort($protocol, $customPort) {
if($customPort == null) {
switch ($protocol) {
case "http":
return '$HTTP_PORTS';
case "https":
return '443';
case "ssh":
return '22';
case "ftp":
return '[20,21]';
default:
return 'any';
}
} else {
return $customPort;
}
}
public static function getCustomIP($customIP) {
if(filter_var($customIP, FILTER_VALIDATE_IP)) {
return $customIP;
}
else {
return '$EXTERNAL_NET';
}
}
}

View File

@ -88,28 +88,124 @@ class NidsSuricataExport extends NidsExport {
}
public function urlRule($ruleFormat, $attribute, &$sid) {
// TODO in hindsight, an url should not be excluded given a host or domain name.
//$hostpart = parse_url($attribute['value'], PHP_URL_HOST);
//$overruled = $this->checkNames($hostpart);
// warning: only suricata compatible
$createRule = true;
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'flow:to_server,established; content:"' . $attribute['value'] . '"; fast_pattern; nocase; http_uri;';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP URL: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
$scheme = parse_url($attribute['value'], PHP_URL_SCHEME);
$data = parse_url($attribute['value']);
if (!array_key_exists('port', $data)) {
$data['port'] = null;
}
switch ($scheme) {
case "http":
$data['host'] = NidsExport::replaceIllegalChars($data['host']);
$suricata_protocol = 'http';
$suricata_src_ip = '$HOME_NET';
$suricata_src_port = 'any';
$suricata_dst_ip = NidsExport::getCustomIP($data['host']);
$suricata_dst_port = NidsExport::getProtocolPort($scheme, $data['port']);
$tag = 'tag:session,600,seconds;';
if (!array_key_exists('path', $data)) {
$data['path'] = NidsExport::replaceIllegalChars($data['host']);
$content = 'flow:to_server,established; content:"' . $data['host'] . '"; nocase; http_header;';
} else {
$content = 'flow:to_server,established; content:"' . $data['host'] . '"; fast_pattern; nocase; http_header; content:"' . $data['path'] . '"; nocase; http_uri;';
}
break;
case "https":
$data['host'] = NidsExport::replaceIllegalChars($data['host']);
$tag = 'tag:session,600,seconds;';
# IP: classic IP rule for HTTPS
if (filter_var($data['host'], FILTER_VALIDATE_IP)) {
$suricata_protocol = 'tcp';
$suricata_src_ip = '$HOME_NET';
$suricata_src_port = 'any';
$suricata_dst_ip = $data['host'];
$suricata_dst_port = NidsExport::getProtocolPort($scheme, $data['port']);
$content = 'flow:to_server; app-layer-protocol:tls;';
}
# Domain: rule on https certificate subject
else {
$suricata_protocol = 'tls';
$suricata_src_ip = '$EXTERNAL_NET';
$suricata_src_port = NidsExport::getProtocolPort($scheme, $data['port']);
$suricata_dst_ip = '$HOME_NET';
$suricata_dst_port = 'any';
$content = 'tls_cert_subject; content:"' . $data['host'] . '"; nocase; pcre:"/' . $data['host'] . '$/";';
}
break;
case "ssh":
# IP: classic IP rule for SSH
if (filter_var($data['host'], FILTER_VALIDATE_IP)) {
$suricata_protocol = 'tcp';
$suricata_src_ip = '$HOME_NET';
$suricata_src_port = 'any';
$suricata_dst_ip = $data['host'];
$suricata_dst_port = '$SSH_PORTS';
$content = 'flow:to_server; app-layer-protocol:ssh;';
$tag = '';
}
# Cannot create a satisfaisant rule (user could create a domain attribute if needed)
else {
$createRule = false;
}
break;
case "ftp":
# IP: classic IP rule for FTP
if (filter_var($data['host'], FILTER_VALIDATE_IP)) {
$suricata_protocol = 'tcp';
$suricata_src_ip = '$HOME_NET';
$suricata_src_port = 'any';
$suricata_dst_ip = $data['host'];
$suricata_dst_port = NidsExport::getProtocolPort($scheme, $data['port']);
$content = 'flow:to_server; app-layer-protocol:ftp;';
$tag = '';
}
# Cannot create a satisfaisant rule (user could create a domain attribute if needed)
else {
$createRule = false;
}
break;
# Unknown/No protocol: keep old behaviour
default:
$suricata_protocol = 'http';
$suricata_src_ip = '$HOME_NET';
$suricata_src_port = 'any';
$suricata_dst_ip = '$EXTERNAL_NET';
$suricata_dst_port = 'any';
$url = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'flow:to_server,established; content:"' . $url . '"; fast_pattern; nocase; http_uri;';
$tag = 'tag:session,600,seconds;';
break;
}
if ($createRule) {
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$this->rules[] = sprintf($ruleFormat, ($overruled) ? '#OVERRULED BY WHITELIST# ' : '', $suricata_protocol, // proto
$suricata_src_ip, // src_ip
$suricata_src_port, // src_port
'->', // direction
$suricata_dst_ip, // dst_ip
$suricata_dst_port, // dst_port
'Outgoing URL: ' . $attribute['value'], // msg
$content, // rule_content
$tag, // tag
$sid, // sid
1 // rev
);
}
}
public function userAgentRule($ruleFormat, $attribute, &$sid) {
$overruled = $this->checkWhitelist($attribute['value']);
@ -132,4 +228,4 @@ class NidsSuricataExport extends NidsExport {
);
}
}
}

View File

@ -8,6 +8,7 @@ class ComplexTypeTool {
'/^h\[tt\]p/i' => 'http',
'/\[\.\]/' => '.',
'/\[dot\]/' => '.',
'/\(dot\)/' => '.',
'/\\\\\./' => '.',
'/\.+/' => '.'
);
@ -97,7 +98,7 @@ class ComplexTypeTool {
* values: Expects an array (or a comma separated string) with numeric values denoting the columns containing indicators. If this is not set then every value will be checked. (column numbers start at 1)
*/
public function checkCSV($input, $settings = array()) {
$delimiter = isset($settings['delimiter']) ? $settings['delimiter'] : ",";
$delimiter = !empty($settings['delimiter']) ? $settings['delimiter'] : ",";
$lines = explode("\n", $input);
unset($input);
$values = !empty($settings['value']) ? $settings['value'] : array();
@ -203,17 +204,26 @@ class ComplexTypeTool {
}
$inputRefanged = rtrim($inputRefanged, ".");
if (strpos($input, '@') !== false) {
if (filter_var($input, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input);
if (filter_var($input, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input);
}
// note down and remove the port if it's a url / domain name / hostname / ip
// input2 from here on is the variable containing the original input with the port removed. It is only used by url / domain name / hostname / ip
$comment = false;
if (preg_match('/(:[0-9]{2,5})$/', $inputRefanged, $port)) {
$comment = 'On port ' . substr($port[0], 1);
$inputRefangedNoPort = str_replace($port[0], '', $inputRefanged);
} else $inputRefangedNoPort = $inputRefanged;
$port = substr($port[0], 1);
} else {
unset($port);
$inputRefangedNoPort = $inputRefanged;
}
// check for IP
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) {
if (isset($port)) {
return array('types' => array('ip-dst|port', 'ip-src|port', 'ip-src|port/ip-dst|port'), 'to_ids' => true, 'default_type' => 'ip-dst|port', 'comment' => $comment, 'value' => $inputRefangedNoPort . '|' . $port);
} else {
return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
}
}
if (strpos($inputRefangedNoPort, '/')) {
$temp = explode('/', $inputRefangedNoPort);
if (count($temp) == 2) {

View File

@ -39,6 +39,13 @@ class JSONConverterTool {
$ra = array('Attribute' => $ra);
}
}
if (isset($event['Event']['Attribute'][$key]['AttributeTag'])) {
foreach ($event['Event']['Attribute'][$key]['AttributeTag'] as $atk => $tag) {
unset($tag['Tag']['org_id']);
$event['Event']['Attribute'][$key]['Tag'][$atk] = $tag['Tag'];
}
unset($event['Event']['Attribute'][$key]['AttributeTag']);
}
}
}
unset($event['Event']['RelatedAttribute']);

View File

@ -115,6 +115,13 @@ class XMLConverterTool {
$event['Event']['Attribute'][$key]['SharingGroup'][0] = $event['Event']['Attribute'][$key]['SharingGroup'];
unset($event['Event']['Attribute'][$key]['SharingGroup']);
}
if (isset($event['Event']['Attribute'][$key]['AttributeTag'])) {
foreach ($event['Event']['Attribute'][$key]['AttributeTag'] as $atk => $tag) {
unset($tag['Tag']['org_id']);
$event['Event']['Attribute'][$key]['Tag'][$atk] = $tag['Tag'];
}
unset($event['Event']['Attribute'][$key]['AttributeTag']);
}
}
}
unset($event['Event']['RelatedAttribute']);

View File

@ -22,7 +22,6 @@
App::uses('Model', 'Model');
App::uses('LogableBehavior', 'Assets.models/behaviors');
class AppModel extends Model {
public $name;
@ -41,7 +40,8 @@ class AppModel extends Model {
32 => false, 33 => true, 38 => true, 39 => true, 40 => false,
42 => false, 44 => false, 45 => false, 49 => true, 50 => false,
51 => false, 52 => false, 55 => true, 56 => true, 57 => true,
58 => false, 59 => false
58 => false, 59 => false, 60 => false, 61 => false, 62 => false,
63 => false, 64 => false, 65 => false
)
)
);
@ -111,27 +111,30 @@ class AppModel extends Model {
// SQL scripts for updates
public function updateDatabase($command) {
$sql = '';
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
$sqlArray = array();
$indexArray = array();
$this->Log = ClassRegistry::init('Log');
$clean = true;
switch ($command) {
case 'extendServerOrganizationLength':
$sql = 'ALTER TABLE `servers` MODIFY COLUMN `organization` varchar(255) NOT NULL;';
$sqlArray[] = 'ALTER TABLE `servers` MODIFY COLUMN `organization` varchar(255) NOT NULL;';
break;
case 'convertLogFieldsToText':
$sql = 'ALTER TABLE `logs` MODIFY COLUMN `title` text, MODIFY COLUMN `change` text;';
$sqlArray[] = 'ALTER TABLE `logs` MODIFY COLUMN `title` text, MODIFY COLUMN `change` text;';
break;
case 'addEventBlacklists':
$sql = 'CREATE TABLE IF NOT EXISTS `event_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `event_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
break;
case 'addOrgBlacklists':
$sql = 'CREATE TABLE IF NOT EXISTS `org_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `org_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `org_name` varchar(255) COLLATE utf8_bin NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `org_blacklists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `org_uuid` varchar(40) COLLATE utf8_bin NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`), `org_name` varchar(255) COLLATE utf8_bin NOT NULL, `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;';
break;
case 'addEventBlacklistsContext':
$sql = 'ALTER TABLE `event_blacklists` ADD `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , ADD `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, ADD `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;';
$sqlArray[] = 'ALTER TABLE `event_blacklists` ADD `event_orgc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , ADD `event_info` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, ADD `comment` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;';
break;
case 'addSightings':
$sql = "CREATE TABLE IF NOT EXISTS sightings (
$sqlArray[] = "CREATE TABLE IF NOT EXISTS sightings (
id int(11) NOT NULL AUTO_INCREMENT,
attribute_id int(11) NOT NULL,
event_id int(11) NOT NULL,
@ -145,22 +148,22 @@ class AppModel extends Model {
break;
case 'makeAttributeUUIDsUnique':
$this->__dropIndex('attributes', 'uuid');
$sql = 'ALTER TABLE `attributes` ADD UNIQUE (uuid);';
$sqlArray[] = 'ALTER TABLE `attributes` ADD UNIQUE (uuid);';
break;
case 'makeEventUUIDsUnique':
$this->__dropIndex('events', 'uuid');
$sql = 'ALTER TABLE `events` ADD UNIQUE (uuid);';
$sqlArray[] = 'ALTER TABLE `events` ADD UNIQUE (uuid);';
break;
case 'cleanSessionTable':
$sql = 'DELETE FROM cake_sessions WHERE expires < ' . time() . ';';
$sqlArray[] = 'DELETE FROM cake_sessions WHERE expires < ' . time() . ';';
$clean = false;
break;
case 'destroyAllSessions':
$sql = 'DELETE FROM cake_sessions;';
$sqlArray[] = 'DELETE FROM cake_sessions;';
$clean = false;
break;
case 'addIPLogging':
$sql = 'ALTER TABLE `logs` ADD `ip` varchar(45) COLLATE utf8_bin DEFAULT NULL;';
$sqlArray[] = 'ALTER TABLE `logs` ADD `ip` varchar(45) COLLATE utf8_bin DEFAULT NULL;';
break;
case 'addCustomAuth':
$sqlArray[] = "ALTER TABLE `users` ADD `external_auth_required` tinyint(1) NOT NULL DEFAULT 0;";
@ -530,6 +533,74 @@ class AppModel extends Model {
$sqlArray[] = "ALTER TABLE taxonomy_entries ADD colour varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '';";
$sqlArray[] = "ALTER TABLE taxonomy_predicates ADD colour varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '';";
break;
case '2.4.60':
if ($dataSource == 'Database/Mysql') {
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS `attribute_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attribute_id` int(11) NOT NULL,
`event_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;';
$sqlArray[] = 'ALTER TABLE `attribute_tags` ADD INDEX `attribute_id` (`attribute_id`);';
$sqlArray[] = 'ALTER TABLE `attribute_tags` ADD INDEX `event_id` (`event_id`);';
$sqlArray[] = 'ALTER TABLE `attribute_tags` ADD INDEX `tag_id` (`tag_id`);';
} else if ($dataSource == 'Database/Postgres') {
$sqlArray[] = 'CREATE TABLE IF NOT EXISTS attribute_tags (
id bigserial NOT NULL,
attribute_id bigint NOT NULL,
event_id bigint NOT NULL,
tag_id bigint NOT NULL,
PRIMARY KEY (id)
);';
$sqlArray[] = 'CREATE INDEX idx_attribute_tags_attribute_id ON attribute_tags (attribute_id);';
$sqlArray[] = 'CREATE INDEX idx_attribute_tags_event_id ON attribute_tags (event_id);';
$sqlArray[] = 'CREATE INDEX idx_attribute_tags_tag_id ON attribute_tags (tag_id);';
}
$this->__dropIndex('attribute_tags', 'attribute_id');
$this->__dropIndex('attribute_tags', 'tag_id');
break;
case '2.4.61':
$sqlArray[] = 'ALTER TABLE feeds ADD input_source varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "network";';
$sqlArray[] = 'ALTER TABLE feeds ADD delete_local_file tinyint(1) DEFAULT 0;';
$indexArray[] = array('feeds', 'input_source');
break;
case '2.4.62':
$sqlArray[] = 'ALTER TABLE logs CHANGE `org` `org` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "";';
$sqlArray[] = 'ALTER TABLE logs CHANGE `email` `email` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "";';
$sqlArray[] = 'ALTER TABLE logs CHANGE `change` `change` text COLLATE utf8_bin NOT NULL DEFAULT "";';
break;
case '2.4.63':
$sqlArray[] = 'ALTER TABLE events DROP COLUMN org;';
$sqlArray[] = 'ALTER TABLE events DROP COLUMN orgc;';
$sqlArray[] = 'ALTER TABLE event_blacklists CHANGE comment comment TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci;';
break;
case '2.4.64':
$indexArray[] = array('feeds', 'input_source');
$indexArray[] = array('attributes', 'value1', 255);
$indexArray[] = array('attributes', 'value2', 255);
$indexArray[] = array('attributes', 'type');
$indexArray[] = array('galaxy_reference', 'galaxy_cluster_id');
$indexArray[] = array('galaxy_reference', 'referenced_galaxy_cluster_id');
$indexArray[] = array('galaxy_reference', 'referenced_galaxy_cluster_value', 255);
$indexArray[] = array('galaxy_reference', 'referenced_galaxy_cluster_type', 255);
$indexArray[] = array('correlations', '1_event_id');
$indexArray[] = array('warninglist_entries', 'warninglist_id');
$indexArray[] = array('galaxy_clusters', 'value', 255);
$indexArray[] = array('galaxy_clusters', 'tag_name');
$indexArray[] = array('galaxy_clusters', 'uuid');
$indexArray[] = array('galaxy_clusters', 'type');
$indexArray[] = array('galaxies', 'name');
$indexArray[] = array('galaxies', 'uuid');
$indexArray[] = array('galaxies', 'type');
break;
case '2.4.65':
$sqlArray[] = 'ALTER TABLE feeds CHANGE `enabled` `enabled` tinyint(1) DEFAULT 0;';
$sqlArray[] = 'ALTER TABLE feeds CHANGE `default` `default` tinyint(1) DEFAULT 0;';
$sqlArray[] = 'ALTER TABLE feeds CHANGE `distribution` `distribution` tinyint(4) NOT NULL DEFAULT 0;';
$sqlArray[] = 'ALTER TABLE feeds CHANGE `sharing_group_id` `sharing_group_id` int(11) NOT NULL DEFAULT 0;';
$sqlArray[] = 'ALTER TABLE attributes CHANGE `comment` `comment` text COLLATE utf8_bin;';
break;
case 'fixNonEmptySharingGroupID':
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
@ -550,7 +621,6 @@ class AppModel extends Model {
return false;
break;
}
if (!isset($sqlArray)) $sqlArray = array($sql);
foreach ($sqlArray as $sql) {
try {
$this->query($sql);
@ -579,6 +649,13 @@ class AppModel extends Model {
));
}
}
foreach ($indexArray as $iA) {
if (isset($iA[2])) {
$this->__addIndex($iA[0], $iA[1], $iA[2]);
} else {
$this->__addIndex($iA[0], $iA[1]);
}
}
if ($clean) $this->cleanCacheFiles();
return true;
}
@ -628,16 +705,18 @@ class AppModel extends Model {
if ($dataSource == 'Database/Postgres') {
$addIndex = "CREATE INDEX idx_" . $table . "_" . $field . " ON " . $table . " (" . $field . ");";
} else {
if (isset($length)) {
if (!$length) {
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`);";
} else {
$addIndex = "ALTER TABLE `" . $table . "` ADD INDEX `" . $field . "` (`" . $field . "`(" . $length . "));";
}
}
$result = true;
$duplicate = false;
try {
$this->query($addIndex);
} catch (Exception $e) {
$duplicate = (strpos($e->getMessage(), '1061') !== false);
$result = false;
}
$this->Log->create();
@ -648,8 +727,8 @@ class AppModel extends Model {
'email' => 'SYSTEM',
'action' => 'update_database',
'user_id' => 0,
'title' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table,
'change' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table,
'title' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table . ($duplicate ? ' (index already set)' : ''),
'change' => ($result ? 'Added index ' : 'Failed to add index ') . $field . ' to ' . $table . ($duplicate ? ' (index already set)' : ''),
));
}
@ -709,7 +788,16 @@ class AppModel extends Model {
$requiresLogout = true;
} else {
$this->__runCleanDB();
$db_version = $this->AdminSetting->find('first', array('conditions' => array('setting' => 'db_version')));
$db_version = $this->AdminSetting->find('all', array('conditions' => array('setting' => 'db_version')));
if (count($db_version) > 1) {
// we ran into a bug where we have more than one db_version entry. This bug happened in some rare circumstances around 2.4.50-2.4.57
foreach ($db_version as $k => $v) {
if ($k > 0) {
$this->AdminSetting->delete($v['AdminSetting']['id']);
}
}
}
$db_version = $db_version[0];
$updates = $this->__findUpgrades($db_version['AdminSetting']['value']);
if (!empty($updates)) {
foreach ($updates as $update => $temp) {

View File

@ -88,7 +88,7 @@ class Attribute extends AppModel {
'hostname' => array('desc' => 'A full host/dnsname of an attacker', 'formdesc' => "A full host/dnsname of an attacker. Also set the IDS flag on when this hostname is hardcoded in malware", 'default_category' => 'Network activity', 'to_ids' => 1),
'domain' => array('desc' => 'A domain name used in the malware', 'formdesc' => "A domain name used in the malware. Use this instead of hostname when the upper domain is important or can be used to create links between events.", 'default_category' => 'Network activity', 'to_ids' => 1),
'domain|ip' => array('desc' => 'A domain name and its IP address (as found in DNS lookup) separated by a |','formdesc' => "A domain name and its IP address (as found in DNS lookup) separated by a | (no spaces)", 'default_category' => 'Network activity', 'to_ids' => 1),
'email-src' => array('desc' => "The email address (or domainname) used to send the malware.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
'email-src' => array('desc' => "The email address used to send the malware.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
'email-dst' => array('desc' => "A recipient email address", 'formdesc' => "A recipient email address that is not related to your constituency.", 'default_category' => 'Network activity', 'to_ids' => 1),
'email-subject' => array('desc' => "The subject of the email", 'default_category' => 'Payload delivery', 'to_ids' => 0),
'email-attachment' => array('desc' => "File name of the email attachment.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
@ -459,6 +459,12 @@ class Attribute extends AppModel {
)
);
public $hasMany = array(
'AttributeTag' => array(
'dependent' => true
)
);
public $hashTypes = array(
'md5' => array(
'length' => 32,
@ -1252,6 +1258,94 @@ class Attribute extends AppModel {
}
}
// using Alnitak's solution from http://stackoverflow.com/questions/594112/matching-an-ip-to-a-cidr-mask-in-php5
private function __ipv4InCidr($ip, $cidr) {
list ($subnet, $bits) = explode('/', $cidr);
$ip = ip2long($ip);
$subnet = ip2long($subnet);
$mask = -1 << (32 - $bits);
$subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
return ($ip & $mask) == $subnet;
}
// using Snifff's solution from http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet
private function __ipv6InCidr($ip, $cidr) {
$ip = inet_pton($ip);
$binaryip = $this->__inet_to_bits($ip);
list($net, $maskbits) = explode('/', $cidr);
$net = inet_pton($net);
$binarynet = $this->__inet_to_bits($net);
$ip_net_bits = substr($binaryip, 0, $maskbits);
$net_bits = substr($binarynet, 0, $maskbits);
return ($ip_net_bits === $net_bits);
}
private function __cidrCorrelation($a) {
$ipValues = array();
$ip = $a['type'] == 'domain-ip' ? $a['value2'] : $a['value1'];
if (strpos($ip, '/') !== false) {
$ip_array = explode('/', $ip);
$ip_version = filter_var($ip_array[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 : 6;
$ipList = $this->find('list', array(
'conditions' => array(
'type' => array('ip-src', 'ip-dst', 'domain_ip'),
),
'fields' => array('value1', 'value2'),
'order' => false
));
$ipList = array_merge(array_keys($ipList), array_values($ipList));
foreach ($ipList as $key => $value) {
if ($value == '') {
unset($ipList[$key]);
}
}
foreach ($ipList as $ipToCheck) {
if (filter_var($ipToCheck, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && $ip_version == 4) {
if ($ip_version == 4) {
if ($this->__ipv4InCidr($ipToCheck, $ip)) {
$ipValues[] = $ipToCheck;
}
} else {
if ($this->__ipv6InCidr($ipToCheck, $ip)) {
$ipValues[] = $ipToCheck;
}
}
}
}
} else {
$ip = $a['value1'];
$ip_version = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? 4 : 6;
$cidrList = $this->find('list', array(
'conditions' => array(
'type' => array('ip-src', 'ip-dst'),
'value1 LIKE' => '%/%'
),
'fields' => array('value1'),
'order' => false
));
foreach ($cidrList as $cidr) {
$cidr_ip = explode('/', $cidr)[0];
if (filter_var($cidr_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && $ip_version == 4) {
if ($this->__ipv4InCidr($ip, $cidr)) {
$ipValues[] = $cidr;
}
} else {
if ($this->__ipv6InCidr($ip, $cidr)) {
$ipValues[] = $cidr;
}
}
}
}
if (!empty($ipValues)) {
$extraConditions = array('OR' => array(
'Attribute.value1' => $ipValues,
'Attribute.value2' => $ipValues
));
return $extraConditions;
}
return false;
}
public function __afterSaveCorrelation($a, $full = false, $event = false) {
// Don't do any correlation if the type is a non correlating type
if (!in_array($a['type'], $this->nonCorrelatingTypes)) {
@ -1266,23 +1360,30 @@ class Attribute extends AppModel {
if ($event['Event']['disable_correlation']) {
return true;
}
if (Configure::read('MISP.enable_advanced_correlations') && in_array($a['type'], array('ip-src', 'ip-dst', 'domain-ip'))) {
$extraConditions = $this->__cidrCorrelation($a);
}
$this->Correlation = ClassRegistry::init('Correlation');
$correlatingValues = array($a['value1']);
if (!empty($a['value2'])) $correlatingValues[] = $a['value2'];
foreach ($correlatingValues as $k => $cV) {
$correlatingAttributes[$k] = $this->find('all', array(
'conditions' => array(
'AND' => array(
'OR' => array(
'Attribute.value1' => $cV,
'Attribute.value2' => $cV
),
'Attribute.type !=' => $this->nonCorrelatingTypes,
'Attribute.disable_correlation' => 0,
'Event.disable_correlation' => 0
),
'Attribute.deleted' => 0
$conditions = array(
'AND' => array(
'OR' => array(
'Attribute.value1' => $cV,
'Attribute.value2' => $cV
),
'Attribute.type !=' => $this->nonCorrelatingTypes,
'Attribute.disable_correlation' => 0,
'Event.disable_correlation' => 0
),
'Attribute.deleted' => 0
);
if (!empty($extraConditions)) {
$conditions['AND']['OR'][] = $extraConditions;
}
$correlatingAttributes[$k] = $this->find('all', array(
'conditions' => $conditions,
'recursive => -1',
'fields' => array('Attribute.event_id', 'Attribute.id', 'Attribute.distribution', 'Attribute.sharing_group_id', 'Attribute.deleted'),
'contain' => array('Event' => array('fields' => array('Event.id', 'Event.date', 'Event.info', 'Event.org_id', 'Event.distribution', 'Event.sharing_group_id'))),
@ -1492,10 +1593,13 @@ class Attribute extends AppModel {
return $rules;
}
public function text($user, $type, $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false) {
//restricting to non-private or same org if the user is not a site-admin.
public function text($user, $type, $tags = false, $eventId = false, $allowNonIDS = false, $from = false, $to = false, $last = false, $enforceWarninglist = false, $allowNotPublished = false) {
//permissions are taken care of in fetchAttributes()
$conditions['AND'] = array();
if ($allowNonIDS === false) $conditions['AND'] = array('Attribute.to_ids' => 1, 'Event.published' => 1);
if ($allowNonIDS === false) {
$conditions['AND']['Attribute.to_ids'] = 1;
if ($allowNotPublished === false) $conditions['AND']['Event.published'] = 1;
}
if ($type !== 'all') $conditions['AND']['Attribute.type'] = $type;
if ($from) $conditions['AND']['Event.date >='] = $from;
if ($to) $conditions['AND']['Event.date <='] = $to;
@ -1991,6 +2095,8 @@ class Attribute extends AppModel {
),
),
);
$params['contain']['AttributeTag'] = array('Tag' => array('conditions' => array()));
if (empty($options['includeAllTags'])) $params['contain']['AttributeTag']['Tag']['conditions']['exportable'] = 1;
if (isset($options['contain'])) $params['contain'] = array_merge_recursive($params['contain'], $options['contain']);
else $option['contain']['Event']['fields'] = array('id', 'info', 'org_id', 'orgc_id');
if (Configure::read('MISP.proposals_block_attributes') && isset($options['conditions']['AND']['Attribute.to_ids']) && $options['conditions']['AND']['Attribute.to_ids'] == 1) {
@ -2142,4 +2248,35 @@ class Attribute extends AppModel {
}
else return 'Could not save changes.';
}
public function saveAndEncryptAttribute($attribute, $user) {
$hashes = array('md5' => 'malware-sample', 'sha1' => 'filename|sha1', 'sha256' => 'filename|sha256');
if ($attribute['encrypt']) {
$result = $this->handleMaliciousBase64($attribute['event_id'], $attribute['value'], $attribute['data'], array_keys($hashes));
if (!$result['success']) {
return 'Could not handle the sample';
}
foreach ($hashes as $hash => $typeName) {
if (!$result[$hash]) continue;
$attributeToSave = array(
'Attribute' => array(
'value' => $attribute['value'] . '|' . $result[$hash],
'category' => $attribute['category'],
'type' => $typeName,
'event_id' => $attribute['event_id'],
'comment' => $attribute['comment'],
'to_ids' => 1,
'distribution' => $attribute['distribution'],
'sharing_group_id' => isset($attribute['sharing_group_id']) ? $attribute['sharing_group_id'] : 0,
)
);
if ($hash == 'md5') $attributeToSave['Attribute']['data'] = $result['data'];
$this->create();
if (!$this->save($attributeToSave)) {
return $this->validationErrors;
}
}
}
return true;
}
}

View File

@ -0,0 +1,45 @@
<?php
App::uses('AppModel', 'Model');
class AttributeTag extends AppModel {
public $actsAs = array('Containable');
public $validate = array(
'attribute_id' => array(
'valueNotEmpty' => array(
'rule' => array('valueNotEmpty'),
),
),
'tag_id' => array(
'valueNotEmpty' => array(
'rule' => array('valueNotEmpty'),
),
),
);
public $belongsTo = array(
'Attribute' => array(
'className' => 'Attribute',
),
'Tag' => array(
'className' => 'Tag',
),
);
public function attachTagToAttribute($attribute_id, $event_id, $tag_id) {
$existingAssociation = $this->find('first', array(
'recursive' => -1,
'conditions' => array(
'tag_id' => $tag_id,
'attribute_id' => $attribute_id
)
));
if (empty($existingAssociation)) {
$this->create();
if (!$this->save(array('attribute_id' => $attribute_id, 'event_id' => $event_id, 'tag_id' => $tag_id))) return false;
}
return true;
}
}

View File

@ -461,6 +461,38 @@ class Event extends AppModel {
return $events;
}
public function attachDiscussionsCountToEvents($user, $events) {
$eventIds = Set::extract('/Event/id', $events);
$this->Thread = ClassRegistry::init('Thread');
$threads = $this->Thread->find('list', array(
'conditions' => array('Thread.event_id' => $eventIds),
'fields' => array('Thread.event_id', 'Thread.id')
));
$posts = $this->Thread->Post->find('all', array(
'conditions' => array('Post.thread_id' => $threads),
'recursive' => -1,
'fields' => array('Count(id) AS post_count', 'thread_id', 'max(date_modified) as last_post'),
'group' => array('Post.thread_id')
));
$event_threads = array();
foreach ($posts as $k => $v) {
foreach ($threads as $k2 => $v2) {
if ($v2 == $v['Post']['thread_id']) {
$event_threads[$k2] = array(
'post_count' => $v[0]['post_count'],
'last_post' => strtotime($v[0]['last_post'])
);
}
}
}
foreach ($events as $k => $v) {
$events[$k]['Event']['post_count'] = !empty($event_threads[$events[$k]['Event']['id']]) ? $event_threads[$events[$k]['Event']['id']]['post_count'] : 0;
$events[$k]['Event']['last_post'] = !empty($event_threads[$events[$k]['Event']['id']]) ? $event_threads[$events[$k]['Event']['id']]['last_post'] : 0;
}
return $events;
}
private function __buildEventConditionsCorrelation($user, $eventIds, $sgids) {
if (!is_array($eventIds)) $eventIds = array($eventIds);
if (!$user['Role']['perm_site_admin']) {
@ -892,8 +924,14 @@ class Event extends AppModel {
// cleanup the array from things we do not want to expose
foreach (array('Org', 'org_id', 'orgc_id', 'proposal_email_lock', 'org', 'orgc') as $field) unset($event['Event'][$field]);
foreach ($event['Event']['EventTag'] as $kt => $tag) {
if (!$tag['Tag']['exportable']) unset($event['Event']['EventTag'][$kt]);
if (!$tag['Tag']['exportable']) {
unset($event['Event']['EventTag'][$kt]);
} else {
unset($tag['org_id']);
$event['Event']['Tag'][] = $tag['Tag'];
}
}
unset($event['Event']['EventTag']);
// Add the local server to the list of instances in the SG
if (isset($event['Event']['SharingGroup']) && isset($event['Event']['SharingGroup']['SharingGroupServer'])) {
@ -935,6 +973,16 @@ class Event extends AppModel {
}
}
}
foreach ($attribute['AttributeTag'] as $kt => $tag) {
if (!$tag['Tag']['exportable']) {
unset($attribute['AttributeTag'][$kt]);
} else {
unset($tag['Tag']['org_id']);
$attribute['Tag'][] = $tag['Tag'];
}
}
unset($attribute['AttributeTag']);
// remove value1 and value2 from the output
unset($attribute['value1']);
@ -1021,7 +1069,7 @@ class Event extends AppModel {
}
}
public function downloadEventFromServer($eventId, $server, $HttpSocket=null, $proposalDownload = false) {
public function downloadEventFromServer($eventId, $server, $HttpSocket=null) {
$url = $server['Server']['url'];
$authkey = $server['Server']['authkey'];
if (null == $HttpSocket) {
@ -1040,18 +1088,12 @@ class Event extends AppModel {
//'Connection' => 'keep-alive' // // LATER followup cakephp issue about this problem: https://github.com/cakephp/cakephp/issues/1961
)
);
if (!$proposalDownload) {
$uri = $url . '/events/view/' . $eventId . '/deleted:true';
} else {
$uri = $url . '/shadow_attributes/getProposalsByUuid/' . $eventId;
}
$uri = $url . '/events/view/' . $eventId . '/deleted:true';
$response = $HttpSocket->get($uri, $data = '', $request);
if ($response->isOk()) {
return json_decode($response->body, true);
} else {
// TODO parse the XML response and keep the reason why it failed
return null;
}
return null;
}
public function downloadProposalsFromServer($uuidList, $server, $HttpSocket = null) {
@ -1074,17 +1116,12 @@ class Event extends AppModel {
$response = $HttpSocket->post($uri, json_encode($uuidList), $request);
if ($response->isOk()) {
return(json_decode($response->body, true));
} else if ($response->code == '405') {
// HACKY: without correct permission, the returning null causes Fallback for < 2.4.7 instances
// which queries every event, for proposal, which it doesn't have permission for
return array();
} else {
// TODO parse the XML response and keep the reason why it failed
return null;
return false;
}
}
public function fetchEventIds($user, $from = false, $to = false, $last = false, $list = false, $timestamp = false, $publish_timestamp = false) {
public function fetchEventIds($user, $from = false, $to = false, $last = false, $list = false, $timestamp = false, $publish_timestamp = false, $eventIdList = false) {
$conditions = array();
// restricting to non-private or same org if the user is not a site-admin.
if (!$user['Role']['perm_site_admin']) {
@ -1115,6 +1152,7 @@ class Event extends AppModel {
if ($last) $conditions['AND'][] = array('Event.publish_timestamp >=' => $last);
if ($timestamp) $conditions['AND'][] = array('Event.timestamp >=' => $timestamp);
if ($publish_timestamp) $conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp);
if ($eventIdList) $conditions['AND'][] = array('Event.id' => $eventIdList);
if ($list) {
$params = array(
'conditions' => $conditions,
@ -1215,7 +1253,6 @@ class Event extends AppModel {
if ($options['to']) $conditions['AND'][] = array('Event.date <=' => $options['to']);
if ($options['last']) $conditions['AND'][] = array('Event.publish_timestamp >=' => $options['last']);
if ($options['event_uuid']) $conditions['AND'][] = array('Event.uuid' => $options['event_uuid']);
if (isset($options['deleted']) && $options['deleted']) {
if (!$user['Role']['perm_sync']) {
$conditionsAttributes['AND'][] = array(
@ -1308,6 +1345,7 @@ class Event extends AppModel {
unset($params['contain']['Attribute']);
unset($params['contain']['ShadowAttribute']);
}
$params['contain']['Attribute']['AttributeTag'] = array('Tag' => array('conditions' => $tagConditions));
if ($user['Role']['perm_site_admin']) {
$params['contain']['User'] = array('fields' => 'email');
}
@ -1344,14 +1382,17 @@ class Event extends AppModel {
foreach ($event['Galaxy'] as $k => $galaxy) {
if ($galaxy['id'] == $cluster['GalaxyCluster']['Galaxy']['id']) {
$found = true;
unset($cluster['GalaxyCluster']['Galaxy']);
$event['Galaxy'][$k]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
$temp = $cluster;
unset($temp['GalaxyCluster']['Galaxy']);
$event['Galaxy'][$k]['GalaxyCluster'][] = $temp['GalaxyCluster'];
continue;
}
}
if (!$found) {
$event['Galaxy'][] = $cluster['GalaxyCluster']['Galaxy'];
unset($cluster['GalaxyCluster']['Galaxy']);
$event['Galaxy'][count($event['Galaxy']) - 1]['GalaxyCluster'][] = $cluster['GalaxyCluster'];
$temp = $cluster;
unset($temp['GalaxyCluster']['Galaxy']);
$event['Galaxy'][count($event['Galaxy']) - 1]['GalaxyCluster'][] = $temp['GalaxyCluster'];
}
}
}
@ -1395,14 +1436,24 @@ class Event extends AppModel {
}
}
}
// unset empty attribute tags that got added because the tag wasn't exportable
if (!empty($attribute['AttributeTag'])) {
foreach ($attribute['AttributeTag'] as $atk => $attributeTag) {
if (empty($attributeTag['Tag'])) unset($event['Attribute'][$key]['AttributeTag'][$atk]);
}
$event['Attribute'][$key]['AttributeTag'] = array_values($event['Attribute'][$key]['AttributeTag']);
}
$event['Attribute'][$key]['ShadowAttribute'] = array();
// If a shadowattribute can be linked to an attribute, link it to it then remove it from the event
// This is to differentiate between proposals that were made to an attribute for modification and between proposals for new attributes
foreach ($event['ShadowAttribute'] as $k => $sa) {
if (!empty($sa['old_id'])) {
if ($event['ShadowAttribute'][$k]['old_id'] == $attribute['id']) {
$results[$eventKey]['Attribute'][$key]['ShadowAttribute'][] = $sa;
unset($results[$eventKey]['ShadowAttribute'][$k]);
if (isset($event['ShadowAttribute'])) {
foreach ($event['ShadowAttribute'] as $k => $sa) {
if (!empty($sa['old_id'])) {
if ($event['ShadowAttribute'][$k]['old_id'] == $attribute['id']) {
$results[$eventKey]['Attribute'][$key]['ShadowAttribute'][] = $sa;
unset($results[$eventKey]['ShadowAttribute'][$k]);
}
}
}
}
@ -1429,6 +1480,10 @@ class Event extends AppModel {
}
$event['ShadowAttribute'] = array_values($event['ShadowAttribute']);
}
if ($event['Event']['orgc_id'] === $user['org_id'] && $user['Role']['perm_audit']) {
$UserEmail = $this->User->getAuthUser($event['Event']['user_id'])['email'];
$event['Event']['event_creator_email'] = $UserEmail;
}
}
return $results;
}
@ -1679,17 +1734,17 @@ class Event extends AppModel {
$body .= 'Tags: ' . $tags . "\n";
$body .= 'Threat Level: ' . $event['ThreatLevel']['name'] . "\n";
$body .= 'Analysis : ' . $this->analysisLevels[$event['Event']['analysis']] . "\n";
$body .= 'Description : ' . $event['Event']['info'] . "\n\n";
$body .= 'Description : ' . $event['Event']['info'] . "\n";
$relatedEvents = $this->getRelatedEvents($user, $event['Event']['id'], array());
if (!empty($relatedEvents)) {
$body .= '==============================================' . "\n";
$body .= 'Related to : '. "\n";
$body .= 'Related to: '. "\n";
foreach ($relatedEvents as &$relatedEvent) {
$body .= Configure::read('MISP.baseurl') . '/events/view/' . $relatedEvent['Event']['id'] . ' (' . $relatedEvent['Event']['date'] . ') ' ."\n";
}
$body .= '==============================================' . "\n";
}
$body .= 'Attributes (* indicates a new or modified attribute) :' . "\n";
$body .= 'Attributes (* indicates a new or modified attribute):' . "\n";
$bodyTempOther = "";
if (isset($event['Attribute'])) {
foreach ($event['Attribute'] as &$attribute) {
@ -1700,9 +1755,9 @@ class Event extends AppModel {
$strRepeatCount = $appendlen - 2 - strlen($attribute['type']);
$strRepeat = ($strRepeatCount > 0) ? str_repeat(' ', $strRepeatCount) : '';
if (isset($oldpublish) && isset($attribute['timestamp']) && $attribute['timestamp'] > $oldpublish) {
$line = '* ' . $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . " *\n";
$line = '* ' . $attribute['category'] . '/' . $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . " *\n";
} else {
$line = $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . "\n";
$line = $attribute['category'] . '/' . $attribute['type'] . $strRepeat . ': ' . $attribute['value'] . $ids . "\n";
}
// Defanging URLs (Not "links") emails domains/ips in notification emails
if ('url' == $attribute['type']) {
@ -1714,7 +1769,16 @@ class Event extends AppModel {
else if ('hostname' == $attribute['type'] or 'domain' == $attribute['type'] or 'ip-src' == $attribute['type'] or 'ip-dst' == $attribute['type']) {
$line = str_replace(".","[.]", $line);
}
if (!empty($attribute['AttributeTag'])) {
$line .= ' - Tags: ';
foreach ($attribute['AttributeTag'] as $k => $aT) {
if ($k > 0) {
$line .= ', ';
}
$line .= $aT['Tag']['name'];
}
$line .= "\n";
}
if ('other' == $attribute['type']) // append the 'other' attribute types to the bottom.
$bodyTempOther .= $line;
else $body .= $line;
@ -1854,7 +1918,7 @@ class Event extends AppModel {
unset($data['Event']['SharingGroup']);
}
if (isset($data['Event']['Attribute'])) {
foreach ($data['Event']['Attribute'] as $k => &$a) {
foreach ($data['Event']['Attribute'] as $k => $a) {
unset($data['Event']['Attribute']['id']);
if (isset($a['distribution']) && $a['distribution'] == 4) {
$data['Event']['Attribute'][$k]['sharing_group_id'] = $this->SharingGroup->captureSG($data['Event']['Attribute'][$k]['SharingGroup'], $user);
@ -1893,6 +1957,30 @@ class Event extends AppModel {
}
unset($data['Event']['Tag']);
}
if (isset($data['Event']['Attribute'])) {
foreach ($data['Event']['Attribute'] as $k => $a) {
if (isset($data['Event']['Attribute'][$k]['AttributeTag'])) {
if (isset($data['Event']['Attribute'][$k]['AttributeTag']['id'])) $data['Event']['Attribute'][$k]['AttributeTag'] = array($data['Event']['Attribute'][$k]['AttributeTag']);
$attributeTags = array();
foreach ($data['Event']['Attribute'][$k]['AttributeTag'] as $tk => $tag) {
$attributeTags[] = array('tag_id' => $this->Attribute->AttributeTag->Tag->captureTag($data['Event']['Attribute'][$k]['AttributeTag'][$tk]['Tag'], $user));
unset($data['Event']['Attribute'][$k]['AttributeTag'][$tk]);
}
$data['Event']['Attribute'][$k]['AttributeTag'] = $attributeTags;
} else {
$data['Event']['Attribute'][$k]['AttributeTag'] = array();
}
if (isset($data['Event']['Attribute'][$k]['Tag'])) {
if (isset($data['Event']['Attribute'][$k]['Tag']['name'])) $data['Event']['Attribute'][$k]['Tag'] = array($data['Event']['Attribute'][$k]['Tag']);
foreach ($data['Event']['Attribute'][$k]['Tag'] as $tag) {
$tag_id = $this->Attribute->AttributeTag->Tag->captureTag($tag, $user);
if ($tag_id) $data['Event']['Attribute'][$k]['AttributeTag'][] = array('tag_id' => $tag_id);
}
unset($data['Event']['Attribute'][$k]['Tag']);
}
}
}
return $data;
}
@ -1992,21 +2080,58 @@ class Event extends AppModel {
foreach ($data['Event']['Attribute'] as $k => &$attribute) {
$attribute['event_id'] = $this->id;
unset($attribute['id']);
$this->Attribute->create();
if (!$this->Attribute->save($attribute, array('fieldList' => $fieldList['Attribute']))) {
$validationErrors['Attribute'][$k] = $this->Attribute->validationErrors;
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'add',
'user_id' => $user['id'],
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
'change' => json_encode($this->Attribute->validationErrors),
));
if (isset($attribute['encrypt'])) {
$saveResult = $this->Attribute->saveAndEncryptAttribute($attribute, $user);
if ($saveResult !== true) {
$validationErrors['Attribute'][$k] = $saveResult;
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'add',
'user_id' => $user['id'],
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
'change' => json_encode($saveResult ? $saveResult : array()),
));
} else {
if (isset($attribute['AttributeTag'])) {
foreach ($attribute['AttributeTag'] as $at) {
$this->Attribute->AttributeTag->create();
$at['attribute_id'] = $this->Attribute->id;
$at['event_id'] = $this->id;
$this->Attribute->AttributeTag->save($at);
}
}
}
} else {
$this->Attribute->create();
if (!$this->Attribute->save($attribute, array('fieldList' => $fieldList['Attribute']))) {
$validationErrors['Attribute'][$k] = $this->Attribute->validationErrors;
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'add',
'user_id' => $user['id'],
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
'change' => json_encode($this->Attribute->validationErrors),
));
} else {
if (isset($attribute['AttributeTag'])) {
foreach ($attribute['AttributeTag'] as $at) {
$this->Attribute->AttributeTag->create();
$at['attribute_id'] = $this->Attribute->id;
$at['event_id'] = $this->id;
$this->Attribute->AttributeTag->save($at);
}
}
}
}
}
}
@ -2082,8 +2207,8 @@ class Event extends AppModel {
if (isset($data['Event']['published']) && $data['Event']['published'] && !$user['Role']['perm_publish']) $data['Event']['published'] = 0;
if (!isset($data['Event']['published'])) $data['Event']['published'] = 0;
$fieldList = array(
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'distribution', 'timestamp', 'sharing_group_id'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp', 'comment', 'sharing_group_id', 'deleted')
'Event' => array('date', 'threat_level_id', 'analysis', 'info', 'published', 'uuid', 'distribution', 'timestamp', 'sharing_group_id', 'disable_correlation'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'revision', 'distribution', 'timestamp', 'comment', 'sharing_group_id', 'deleted', 'disable_correlation')
);
$saveResult = $this->save(array('Event' => $data['Event']), array('fieldList' => $fieldList['Event']));
$this->Log = ClassRegistry::init('Log');
@ -2091,43 +2216,79 @@ class Event extends AppModel {
$validationErrors = array();
if (isset($data['Event']['Attribute'])) {
foreach ($data['Event']['Attribute'] as $k => $attribute) {
if (isset($attribute['uuid'])) {
$existingAttribute = $this->Attribute->findByUuid($attribute['uuid']);
if (count($existingAttribute)) {
if ($existingAttribute['Attribute']['event_id'] != $id) {
$result = $this->Log->save(array(
$attribute['event_id'] = $existingEvent['Event']['id'];
if (isset($attribute['encrypt'])) {
if (isset($attribute['uuid'])) {
$existingAttribute = $this->Attribute->findByUuid($attribute['uuid']);
if (!empty($existingAttribute)) {
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Event',
'model_id' => $id,
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'edit',
'action' => 'add',
'user_id' => $user['id'],
'title' => 'Duplicate UUID found in attribute',
'change' => 'An attribute was blocked from being saved due to a duplicate UUID. The uuid in question is: ' . $attribute['uuid'],
'title' => 'Attribute dropped because the encrypt parameter was passed along an attribute that already exists',
'change' => '',
));
unset($data['Event']['Attribute'][$k]);
} else {
// If a field is not set in the request, just reuse the old value
$recoverFields = array('value', 'to_ids', 'distribution', 'category', 'type', 'comment', 'sharing_group_id');
foreach ($recoverFields as $rF) if (!isset($attribute[$rF])) $data['Event']['Attribute'][$k][$rF] = $existingAttribute['Attribute'][$rF];
$data['Event']['Attribute'][$k]['id'] = $existingAttribute['Attribute']['id'];
// Check if the attribute's timestamp is bigger than the one that already exists.
// If yes, it means that it's newer, so insert it. If no, it means that it's the same attribute or older - don't insert it, insert the old attribute.
// Alternatively, we could unset this attribute from the request, but that could lead with issues if we decide that we want to start deleting attributes that don't exist in a pushed event.
if (isset($data['Event']['Attribute'][$k]['timestamp'])) {
if ($data['Event']['Attribute'][$k]['timestamp'] <= $existingAttribute['Attribute']['timestamp']) {
unset($data['Event']['Attribute'][$k]);
continue;
}
}
continue;
}
$saveResult = $this->Attribute->saveAndEncryptAttribute($attribute, $user);
if ($saveResult !== true) {
$attribute_short = (isset($attribute['category']) ? $attribute['category'] : 'N/A') . '/' . (isset($attribute['type']) ? $attribute['type'] : 'N/A') . ' ' . (isset($attribute['value']) ? $attribute['value'] : 'N/A');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'add',
'user_id' => $user['id'],
'title' => 'Attribute dropped due to validation for Event ' . $id . ' failed: ' . $attribute_short,
'change' => json_encode($saveResult ? $saveResult : array()),
));
}
} else {
if (isset($attribute['uuid'])) {
$existingAttribute = $this->Attribute->findByUuid($attribute['uuid']);
if (count($existingAttribute)) {
if ($existingAttribute['Attribute']['event_id'] != $id) {
$result = $this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'edit',
'user_id' => $user['id'],
'title' => 'Duplicate UUID found in attribute',
'change' => 'An attribute was blocked from being saved due to a duplicate UUID. The uuid in question is: ' . $attribute['uuid'],
));
unset($data['Event']['Attribute'][$k]);
} else {
$data['Event']['Attribute'][$k]['timestamp'] = $date;
// If a field is not set in the request, just reuse the old value
$recoverFields = array('value', 'to_ids', 'distribution', 'category', 'type', 'comment', 'sharing_group_id');
foreach ($recoverFields as $rF) if (!isset($attribute[$rF])) $data['Event']['Attribute'][$k][$rF] = $existingAttribute['Attribute'][$rF];
$data['Event']['Attribute'][$k]['id'] = $existingAttribute['Attribute']['id'];
// Check if the attribute's timestamp is bigger than the one that already exists.
// If yes, it means that it's newer, so insert it. If no, it means that it's the same attribute or older - don't insert it, insert the old attribute.
// Alternatively, we could unset this attribute from the request, but that could lead with issues if we decide that we want to start deleting attributes that don't exist in a pushed event.
if (isset($data['Event']['Attribute'][$k]['timestamp'])) {
if ($data['Event']['Attribute'][$k]['timestamp'] <= $existingAttribute['Attribute']['timestamp']) {
unset($data['Event']['Attribute'][$k]);
continue;
}
} else {
$data['Event']['Attribute'][$k]['timestamp'] = $date;
}
}
} else {
$this->Attribute->create();
}
} else {
$this->Attribute->create();
}
} else {
$this->Attribute->create();
}
$data['Event']['Attribute'][$k]['event_id'] = $this->id;
if ($data['Event']['Attribute'][$k]['distribution'] == 4) {
@ -2147,12 +2308,42 @@ class Event extends AppModel {
'title' => 'Attribute dropped due to validation for Event ' . $this->id . ' failed: ' . $attribute_short,
'change' => json_encode($this->Attribute->validationErrors),
));
} else {
if (isset($data['Event']['Attribute'][$k]['Tag']) && $user['Role']['perm_tagger']) {
foreach ($data['Event']['Attribute'][$k]['Tag'] as $tag) {
$tag_id = $this->Attribute->AttributeTag->Tag->captureTag($tag, $user);
if ($tag_id) {
$this->Attribute->AttributeTag->attachTagToAttribute($this->Attribute->id, $this->id, $tag_id);
} else {
// If we couldn't attach the tag it is most likely because we couldn't create it - which could have many reasons
// However, if a tag couldn't be added, it could also be that the user is a tagger but not a tag editor
// In which case if no matching tag is found, no tag ID is returned. Logging these is pointless as it is the correct behaviour.
if ($user['Role']['perm_tag_editor']) {
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attrubute',
'model_id' => $this->Attribute->id,
'email' => $user['email'],
'action' => 'edit',
'user_id' => $user['id'],
'title' => 'Failed create or attach Tag ' . $tag['name'] . ' to the attribute.',
'change' => ''
));
}
}
}
}
}
}
}
if (isset($data['Event']['EventTag']) && $user['Role']['perm_tagger']) {
foreach ($data['Event']['EventTag'] as $tag) {
$tag_id = $this->EventTag->Tag->captureTag($tag['Tag'], $user);
if (isset($event['Event']['EventTag'])) {
$event['Event']['Tag'] = $event['Event']['EventTag']['Tag'];
unset($event['Event']['EventTag']);
}
if (isset($data['Event']['Tag']) && $user['Role']['perm_tagger']) {
foreach ($data['Event']['Tag'] as $tag) {
$tag_id = $this->EventTag->Tag->captureTag($tag, $user);
if ($tag_id) {
$this->EventTag->attachTagToEvent($this->id, $tag_id);
} else {
@ -2270,7 +2461,8 @@ class Event extends AppModel {
'fields' => array('id', 'url', 'name')
)
),
)
),
'AttributeTag' => array('Tag')
),
'EventTag' => array('Tag'),
'Org' => array('fields' => array('id', 'uuid', 'name', 'local')),

View File

@ -63,7 +63,7 @@ class EventTag extends AppModel {
}
return true;
}
public function getSortedTagList($context = false) {
$conditions = array();
$tag_counts = $this->find('all', array(

View File

@ -23,8 +23,8 @@ class Feed extends AppModel {
public $validate = array(
'url' => array( // TODO add extra validation to refuse multiple time the same url from the same org
'rule' => array('url'),
'message' => 'Please enter a valid url.',
'rule' => array('urlOrExistingFilepath'),
'message' => 'Please enter a valid url or file path (make sure that the choice matches the input source setting).',
),
'provider' => 'valueNotEmpty',
'name' => 'valueNotEmpty',
@ -47,6 +47,26 @@ class Feed extends AppModel {
)
);
public function urlOrExistingFilepath($fields) {
$input_source = empty($this->data['Feed']['input_source']) ? 'network' : $this->data['Feed']['input_source'];
if ($input_source == 'local') {
if ($this->data['Feed']['source_format'] == 'misp') {
if (!is_dir($this->data['Feed']['url'])) {
return 'For MISP type local feeds, please specify the containing directory.';
}
} else {
if (!file_exists($this->data['Feed']['url'])) {
return 'For non-MISP type local feeds, please specify the file to be ingested.';
}
}
} else {
if (!filter_var($this->data['Feed']['url'], FILTER_VALIDATE_URL)) {
return false;
}
}
return true;
}
public function getFeedTypesOptions() {
$result = array();
foreach ($this->feed_types as $key => $value) {
@ -59,11 +79,19 @@ class Feed extends AppModel {
// returns an array with the UUIDs of events that are new or that need updating
public function getNewEventUuids($feed, $HttpSocket) {
$result = array();
$request = $this->__createFeedRequest();
$uri = $feed['Feed']['url'] . '/manifest.json';
$response = $HttpSocket->get($uri, '', $request);
if ($response->code != 200) return 1;
$manifest = json_decode($response->body, true);
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($feed['Feed']['url'] . '/manifest.json')) {
$data = file_get_contents($feed['Feed']['url'] . '/manifest.json');
}
} else {
$request = $this->__createFeedRequest();
$uri = $feed['Feed']['url'] . '/manifest.json';
$response = $HttpSocket->get($uri, '', $request);
if ($response->code != 200) return 1;
$data = $response->body;
unset($response);
}
$manifest = json_decode($data, true);
if (!$manifest) return 2;
$this->Event = ClassRegistry::init('Event');
$events = $this->Event->find('all', array(
@ -74,10 +102,16 @@ class Feed extends AppModel {
'fields' => array('Event.id', 'Event.uuid', 'Event.timestamp')
));
foreach ($events as $event) {
if ($event['Event']['timestamp'] < $manifest[$event['Event']['uuid']]['timestamp']) $result['edit'][] = array('uuid' => $event['Event']['uuid'], 'id' => $event['Event']['id']);
if ($event['Event']['timestamp'] < $manifest[$event['Event']['uuid']]['timestamp']) {
$result['edit'][] = array('uuid' => $event['Event']['uuid'], 'id' => $event['Event']['id']);
} else {
$this->__cleanupFile($feed, '/' . $event['Event']['uuid'] . '.json');
}
unset($manifest[$event['Event']['uuid']]);
}
$result['add'] = array_keys($manifest);
if (!empty($manifest)) {
$result['add'] = array_keys($manifest);
}
return $result;
}
@ -85,10 +119,21 @@ class Feed extends AppModel {
public function getManifest($feed, $HttpSocket) {
$result = array();
$request = $this->__createFeedRequest();
$uri = $feed['Feed']['url'] . '/manifest.json';
$response = $HttpSocket->get($uri, '', $request);
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($feed['Feed']['url'] . '/manifest.json')) {
$data = file_get_contents($feed['Feed']['url'] . '/manifest.json');
}
} else {
$uri = $feed['Feed']['url'] . '/manifest.json';
$response = $HttpSocket->get($uri, '', $request);
if ($response->code != 200) {
return false;
}
$data = $response->body;
unset($response);
}
try {
$events = json_decode($response->body, true);
$events = json_decode($data, true);
} catch (Exception $e) {
return false;
}
@ -98,20 +143,26 @@ class Feed extends AppModel {
public function getFreetextFeed($feed, $HttpSocket, $type = 'freetext', $page = 1, $limit = 60, &$params = array()) {
$result = array();
$feedCache = APP . 'tmp' . DS . 'cache' . DS . 'misp_feed_' . intval($feed['Feed']['id']) . '.cache';
$doFetch = true;
if (file_exists($feedCache)) {
$file = new File($feedCache);
if (time() - $file->lastChange() < 600) {
$doFetch = false;
$data = file_get_contents($feedCache);
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($feed['Feed']['url'])) {
$data = file_get_contents($feed['Feed']['url']);
}
}
if ($doFetch) {
$response = $HttpSocket->get($feed['Feed']['url'], '', array());
if ($response->code == 200) {
$data = $response->body;
file_put_contents($feedCache, $data);
} else {
$feedCache = APP . 'tmp' . DS . 'cache' . DS . 'misp_feed_' . intval($feed['Feed']['id']) . '.cache';
$doFetch = true;
if (file_exists($feedCache)) {
$file = new File($feedCache);
if (time() - $file->lastChange() < 600) {
$doFetch = false;
$data = file_get_contents($feedCache);
}
}
if ($doFetch) {
$response = $HttpSocket->get($feed['Feed']['url'], '', array());
if ($response->code == 200) {
$data = $response->body;
file_put_contents($feedCache, $data);
}
}
}
App::uses('ComplexTypeTool', 'Tools');
@ -182,6 +233,7 @@ class Feed extends AppModel {
if (isset($actions['add']) && !empty($actions['add'])) {
foreach ($actions['add'] as $uuid) {
$result = $this->__addEventFromFeed($HttpSocket, $feed, $uuid, $user, $filterRules);
$this->__cleanupFile($feed, '/' . $uuid . '.json');
if ($result === 'blocked') continue;
if ($result === true) {
$results['add']['success'] = $uuid;
@ -198,6 +250,7 @@ class Feed extends AppModel {
if (isset($actions['edit']) && !empty($actions['edit'])) {
foreach ($actions['edit'] as $editTarget) {
$result = $this->__updateEventFromFeed($HttpSocket, $feed, $editTarget['uuid'], $editTarget['id'], $user, $filterRules);
$this->__cleanupFile($feed, '/' . $uuid . '.json');
if ($result === 'blocked') continue;
if ($result === true) {
$results['edit']['success'] = $uuid;
@ -309,15 +362,22 @@ class Feed extends AppModel {
}
public function downloadEventFromFeed($feed, $uuid, $user) {
$HttpSocket = $this->__setupHttpSocket($feed);
$request = $this->__createFeedRequest();
$uri = $feed['Feed']['url'] . '/' . $uuid . '.json';
$response = $HttpSocket->get($uri, '', $request);
if ($response->code != 200) {
return false;
$path = $feed['Feed']['url'] . '/' . $uuid . '.json';
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($path)) {
$data = file_get_contents($path);
}
} else {
return $this->__prepareEvent($response->body, $feed);
$HttpSocket = $this->__setupHttpSocket($feed);
$request = $this->__createFeedRequest();
$response = $HttpSocket->get($path, '', $request);
if ($response->code != 200) {
return false;
}
$data = $response->body;
unset($response->body);
}
return $this->__prepareEvent($data, $feed);
}
private function __saveEvent($event, $user) {
@ -348,7 +408,9 @@ class Feed extends AppModel {
if (!isset($event['Event']['uuid'])) return false;
$event['Event']['distribution'] = $feed['Feed']['distribution'];
$event['Event']['sharing_group_id'] = $feed['Feed']['sharing_group_id'];
foreach ($event['Event']['Attribute'] as $key => $attribute) $event['Event']['Attribute'][$key]['distribution'] = 5;
if (!empty($event['Event']['Attribute'])) {
foreach ($event['Event']['Attribute'] as $key => $attribute) $event['Event']['Attribute'][$key]['distribution'] = 5;
}
if ($feed['Feed']['tag_id']) {
if (!isset($event['Event']['Tag'])) $event['Event']['Tag'] = array();
$found = false;
@ -392,31 +454,49 @@ class Feed extends AppModel {
}
private function __addEventFromFeed($HttpSocket, $feed, $uuid, $user, $filterRules) {
$request = $this->__createFeedRequest();
$uri = $feed['Feed']['url'] . '/' . $uuid . '.json';
$response = $HttpSocket->get($uri, '', $request);
if ($response->code != 200) {
if (!Validation::uuid($uuid)) {
return false;
} else {
$event = $this->__prepareEvent($response->body, $feed);
if (is_array($event)) {
$this->Event = ClassRegistry::init('Event');
return $this->Event->_add($event, true, $user);
} else return $event;
}
$path = $feed['Feed']['url'] . '/' . $uuid . '.json';
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($path)) {
$data = file_get_contents($path);
}
} else {
$request = $this->__createFeedRequest();
$response = $HttpSocket->get($path, '', $request);
if ($response->code != 200) {
return false;
}
$data = $response->body;
unset($response);
}
$event = $this->__prepareEvent($data, $feed);
if (is_array($event)) {
$this->Event = ClassRegistry::init('Event');
return $this->Event->_add($event, true, $user);
} else return $event;
}
private function __updateEventFromFeed($HttpSocket, $feed, $uuid, $eventId, $user, $filterRules) {
$request = $this->__createFeedRequest();
$uri = $feed['Feed']['url'] . '/' . $uuid . '.json';
$response = $HttpSocket->get($uri, '', $request);
if ($response->code != 200) {
if (!Validation::uuid($uuid)) {
return false;
} else {
$event = $this->__prepareEvent($response->body, $feed);
$this->Event = ClassRegistry::init('Event');
return $this->Event->_edit($event, $user, $uuid, $jobId = null);
}
$path = $feed['Feed']['url'] . '/' . $uuid . '.json';
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($path)) {
$data = file_get_contents($path);
}
} else {
$request = $this->__createFeedRequest();
$response = $HttpSocket->get($path, '', $request);
if ($response->code != 200) {
return false;
}
}
$event = $this->__prepareEvent($response->body, $feed);
$this->Event = ClassRegistry::init('Event');
return $this->Event->_edit($event, $user, $uuid, $jobId = null);
}
public function addDefaultFeeds($newFeeds) {
@ -450,7 +530,11 @@ class Feed extends AppModel {
if (isset($this->data['Feed']['settings']) && !empty($this->data['Feed']['settings'])) {
$this->data['Feed']['settings'] = json_decode($this->data['Feed']['settings'], true);
}
$HttpSocket = $syncTool->setupHttpSocketFeed($this->data);
if (isset($this->data['Feed']['input_source']) && $this->data['Feed']['input_source'] == 'local') {
$HttpSocket = false;
} else {
$HttpSocket = $syncTool->setupHttpSocketFeed($this->data);
}
if ($this->data['Feed']['source_format'] == 'misp') {
if ($jobId) {
$job->id = $jobId;
@ -461,7 +545,15 @@ class Feed extends AppModel {
$job->id = $jobId;
$job->saveField('message', 'Fetching events.');
}
if (empty($actions)) {
if ($jobId) {
$job->id = $jobId;
$job->saveField('message', 'Job complete.');
}
return true;
}
$result = $this->downloadFromFeed($actions, $this->data, $HttpSocket, $user, $jobId);
$this->__cleanupFile($feed, '/manifest.json');
if ($jobId) {
$job->id = $jobId;
$job->saveField('message', 'Job complete.');
@ -489,6 +581,7 @@ class Feed extends AppModel {
if ($result !== true) {
return false;
}
$this->__cleanupFile($this->data, '');
if ($jobId) {
$job->saveField('progress', '100');
$job->saveField('message', 'Job complete.');
@ -497,6 +590,17 @@ class Feed extends AppModel {
return $result;
}
private function __cleanupFile($feed, $file) {
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (isset($feed['Feed']['delete_local_file']) && $feed['Feed']['delete_local_file']) {
if (file_exists($feed['Feed']['url'] . $file)) {
unlink($feed['Feed']['url'] . $file);
}
}
}
return true;
}
public function saveFreetextFeedData($feed, $data, $user, $jobId = false) {
$this->Event = ClassRegistry::init('Event');
$event = false;
@ -551,12 +655,20 @@ class Feed extends AppModel {
if (empty($data)) {
return true;
}
$prunedCopy = array();
foreach ($data as $key => $value) {
foreach ($prunedCopy as $copy) {
if ($copy['type'] == $value['type'] && $copy['category'] == $value['category'] && $copy['value'] == $value['value']) {
continue 2;
}
}
$data[$key]['event_id'] = $event['Event']['id'];
$data[$key]['distribution'] = $feed['Feed']['distribution'];
$data[$key]['sharing_group_id'] = $feed['Feed']['sharing_group_id'];
$data[$key]['to_ids'] = $feed['Feed']['override_ids'] ? 0 : $data[$key]['to_ids'];
$prunedCopy[] = $data[$key];
}
$data = $prunedCopy;
if ($jobId) {
$job = ClassRegistry::init('Job');
$job->id = $jobId;

View File

@ -43,7 +43,8 @@ class Log extends AppModel {
'merge',
'undelete',
'file_upload',
'export'
'export',
'pruneUpdateLogs'
)),
'message' => 'Options : ...'
)
@ -85,6 +86,7 @@ class Log extends AppModel {
if (!isset($this->data['Log'][$field]) || empty($this->data['Log'][$field])) $this->data['Log'][$field] = $empty;
}
if (!isset($this->data['Log']['created'])) $this->data['Log']['created'] = date('Y-m-d H:i:s');
if (!isset($this->data['Log']['org'])) $this->data['Log']['org'] = 'SYSTEM';
return true;
}
@ -140,4 +142,78 @@ class Log extends AppModel {
'model_id' => $model_id,
));
}
// to combat a certain bug that causes the upgrade scripts to loop without being able to set the correct version
// this function remedies a fixed upgrade bug instance by eliminating the massive number of erroneous upgrade log entries
public function pruneUpdateLogs($jobId = false, $user) {
$max = $this->find('first', array('fields' => array('MAX(id) AS lastid')));
if (!empty($max)) {
$max = $max[0]['lastid'];
}
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
$this->Job->id = $jobId;
if (!$this->Job->exists()) {
$jobId = false;
}
}
$iterations = ($max / 1000);
for ($i = 0; $i < $iterations; $i++) {
$this->deleteAll(array(
'OR' => array(
'action' => 'update_database',
'AND' => array(
'action' => 'edit',
'model' => 'AdminSetting'
)
),
'id >' => $i * 1000,
'id <' => ($i+1) * 1000));
if ($jobId) {
$this->Job->saveField('progress', $i * 100 / $iterations);
}
}
$this->create();
$this->save(array(
'org' => $user['Organisation']['name'],
'email' =>$user['email'],
'user_id' => $user['id'],
'action' => 'pruneUpdateLogs',
'title' => 'Pruning updates',
'change' => 'Pruning completed in ' . $i . ' iteration(s).',
'model' => 'Log',
'model_id' => 0
));
}
public function pruneUpdateLogsRouter($user) {
if (Configure::read('MISP.background_jobs')) {
$job = ClassRegistry::init('Job');
$job->create();
$data = array(
'worker' => 'default',
'job_type' => 'prune_update_logs',
'job_input' => 'All update entries',
'status' => 0,
'retries' => 0,
'org_id' => $user['org_id'],
'org' => $user['Organisation']['name'],
'message' => 'Purging the heretic.',
);
$job->save($data);
$jobId = $job->id;
$process_id = CakeResque::enqueue(
'default',
'AdminShell',
array('prune_update_logs', $jobId, $user['id']),
true
);
$job->saveField('process_id', $process_id);
return $process_id;
} else {
$result = $this->pruneUpdateLogs(false, $user);
return $result;
}
}
}

View File

@ -84,7 +84,7 @@ class Organisation extends AppModel{
$this->data['Organisation']['uuid'] = CakeText::uuid();
}
$date = date('Y-m-d H:i:s');
if (!isset($this->data['Organisation']['date_created']) || empty($this->data['Organisation']['date_created'])) $this->data['Organisation']['date_created'] = $date;
if (!isset($this->data['Organisation']['id'])) $this->data['Organisation']['date_created'] = $date;
$this->data['Organisation']['date_modified'] = $date;
if (!isset($this->data['Organisation']['nationality']) || empty($this->data['Organisation']['nationality'])) $this->data['Organisation']['nationality'] = 'Not specified';
return true;

View File

@ -128,6 +128,15 @@ class Server extends AppModel {
'test' => 'testLive',
'type' => 'boolean',
),
'enable_advanced_correlations' => array(
'level' => 0,
'description' => 'Enable some performance heavy correlations (currently CIDR correlation)',
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
'type' => 'boolean',
'null' => true
),
'maintenance_message' => array(
'level' => 2,
'description' => 'The message that users will see if the instance is not live.',
@ -598,6 +607,15 @@ class Server extends AppModel {
'type' => 'boolean',
'null' => true
),
'showDiscussionsCountOnIndex' => array(
'level' => 1,
'description' => 'When enabled, the aggregate number of discussion posts for the event becomes visible to the currently logged in user on the event index UI.',
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
'type' => 'boolean',
'null' => true
),
'disableUserSelfManagement' => array(
'level' => 1,
'description' => 'When enabled only Org and Site admins can edit a user\'s profile.',
@ -891,6 +909,15 @@ class Server extends AppModel {
'test' => 'testPasswordRegex',
'type' => 'string',
),
'sanitise_attribute_on_delete' => array(
'level' => 1,
'description' => 'Enabling this setting will sanitise the contents of an attribute on a soft delete',
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
'type' => 'boolean',
'null' => true
)
),
'SecureAuth' => array(
'branch' => 1,
@ -923,7 +950,7 @@ class Server extends AppModel {
),
'defaults' => array(
'level' => 0,
'description' => 'The session type used by MISP. The default setting is database, which will use the MySQL tables for the session data (supported options: database, php). The recommended option is php and setting your PHP up to use redis sessions via your php.ini. Just add \'session.save_handler = redis\' and "session.save_path = \'tcp://localhost:6379\'" (replace the latter with your redis connection) to ',
'description' => 'The session type used by MISP. The default setting is php, which will use the session settings configured in php.ini for the session data (supported options: php, database). The recommended option is php and setting your PHP up to use redis sessions via your php.ini. Just add \'session.save_handler = redis\' and "session.save_path = \'tcp://localhost:6379\'" (replace the latter with your redis connection) to ',
'value' => '',
'errorMessage' => '',
'test' => 'testForSessionDefaults',
@ -1329,6 +1356,7 @@ class Server extends AppModel {
'errorMessage' => '',
'test' => 'testDebugAdmin',
'type' => 'boolean',
'null' => true
),
);
@ -1552,54 +1580,18 @@ class Server extends AppModel {
}
}
} else {
// Fallback for < 2.4.7 instances
$k = 0;
foreach ($events as $eid => $event) {
$proposals = $eventModel->downloadEventFromServer($event, $server, null, true);
if (null != $proposals) {
if (isset($proposals['ShadowAttribute']['id'])) {
$temp = $proposals['ShadowAttribute'];
$proposals['ShadowAttribute'] = array(0 => $temp);
}
foreach ($proposals['ShadowAttribute'] as &$proposal) {
$oldsa = $shadowAttribute->findOldProposal($proposal);
$proposal['event_id'] = $eid;
if (!$oldsa || $oldsa['timestamp'] < $proposal['timestamp']) {
if ($oldsa) $shadowAttribute->delete($oldsa['id']);
if (!isset($pulledProposals[$eid])) $pulledProposals[$eid] = 0;
$pulledProposals[$eid]++;
if (isset($proposal['old_id'])) {
$oldAttribute = $eventModel->Attribute->find('first', array('recursive' => -1, 'conditions' => array('uuid' => $proposal['uuid'])));
if ($oldAttribute) $proposal['old_id'] = $oldAttribute['Attribute']['id'];
else $proposal['old_id'] = 0;
}
// check if this is a proposal from an old MISP instance
if (!isset($proposal['Org']) && isset($proposal['org']) && !empty($proposal['org'])) {
$proposal['Org'] = $proposal['org'];
$proposal['EventOrg'] = $proposal['event_org'];
} else if (!isset($proposal['Org']) && !isset($proposal['EventOrg'])) {
continue;
}
$proposal['org_id'] = $this->Organisation->captureOrg($proposal['Org'], $user);
$proposal['event_org_id'] = $this->Organisation->captureOrg($proposal['EventOrg'], $user);
unset($proposal['Org']);
unset($proposal['EventOrg']);
$shadowAttribute->create();
if (!isset($proposal['deleted']) || !$proposal['deleted']) {
if ($shadowAttribute->save($proposal)) $shadowAttribute->sendProposalAlertEmail($eid);
}
}
}
}
if ($jobId) {
if ($k % 10 == 0) {
$job->id = $jobId;
$job->saveField('progress', 50 * (($k + 1) / count($events)));
}
}
$k++;
}
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Server',
'model_id' => $id,
'email' => $user['email'],
'action' => 'error',
'user_id' => $user['id'],
'title' => 'Pulling of proposals has failed.',
'change' => ''
));
}
}
if ($jobId) {
@ -2123,7 +2115,6 @@ class Server extends AppModel {
}
public function testDebugAdmin($value) {
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
if ($this->testBool($value) !== true) return 'This setting has to be either true or false.';
if (!$value) return true;
return 'Enabling debug is not recommended. Turn this on temporarily if you need to see a stack trace to debug an issue, but make sure this is not left on.';
@ -2160,7 +2151,6 @@ class Server extends AppModel {
}
public function testBool($value) {
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
if ($value !== true && $value !== false) return 'Value is not a boolean, make sure that you convert \'true\' to true for example.';
return true;
}
@ -3294,4 +3284,12 @@ class Server extends AppModel {
}
return $results;
}
public function databaseEncodingDiagnostics(&$diagnostic_errors) {
if (!isset($this->getDataSource()->config['encoding']) || strtolower($this->getDataSource()->config['encoding']) != 'utf8') {
$diagnostic_errors++;
return false;
}
return true;
}
}

View File

@ -37,7 +37,7 @@ class Sighting extends AppModel {
return true;
}
public function attachToEvent(&$event, &$user) {
public function attachToEvent(&$event, $user) {
$ownEvent = false;
if ($user['Role']['perm_site_admin'] || $event['Event']['org_id'] == $user['org_id']) $ownEvent = true;
$conditions = array('Sighting.event_id' => $event['Event']['id']);

View File

@ -45,6 +45,9 @@ class Tag extends AppModel {
'TemplateTag',
'FavouriteTag' => array(
'dependent' => true
),
'AttributeTag' => array(
'dependent' => true
)
);
@ -104,6 +107,25 @@ class Tag extends AppModel {
return $ids;
}
public function findAttributeIdsByAttributeTagNames($array) {
$ids = array();
foreach ($array as $a) {
$conditions['OR'][] = array('LOWER(name) LIKE' => strtolower($a));
}
$params = array(
'recursive' => 1,
'contain' => 'AttributeTag',
'conditions' => $conditions
);
$result = $this->find('all', $params);
foreach ($result as $tag) {
foreach ($tag['AttributeTag'] as $attributeTag) {
$ids[] = $attributeTag['attribute_id'];
}
}
return $ids;
}
public function captureTag($tag, $user) {
$existingTag = $this->find('first', array(
'recursive' => -1,
@ -176,9 +198,11 @@ class Tag extends AppModel {
}
public function getTagsForNamespace($namespace) {
$contain = array('EventTag');
$contain[] = 'AttributeTag';
$tags_temp = $this->find('all', array(
'recursive' => -1,
'contain' => 'EventTag',
'contain' => $contain,
'conditions' => array('UPPER(name) LIKE' => strtoupper($namespace) . '%'),
));
$tags = array();

View File

@ -3,7 +3,7 @@ App::uses('AppModel', 'Model');
App::uses('AuthComponent', 'Controller/Component');
App::uses('RandomTool', 'Tools');
class User extends AppModel {
class User extends AppModel {
public $displayField = 'email';
@ -242,6 +242,7 @@ class User extends AppModel {
$this->data['User']['confirm_password'] = $this->data['User']['password'];
}
}
if (!isset($this->data['User']['certif_public']) || empty($this->data['User']['certif_public'])) $this->data['User']['certif_public'] = '';
if (!isset($this->data['User']['authkey']) || empty($this->data['User']['authkey'])) $this->data['User']['authkey'] = $this->generateAuthKey();
if (!isset($this->data['User']['nids_sid']) || empty($this->data['User']['nids_sid'])) $this->data['User']['nids_sid'] = mt_rand(1000000, 9999999);
return true;
@ -882,21 +883,35 @@ class User extends AppModel {
return $fields;
}
public function getMembersCount() {
public function getMembersCount($org_id = false) {
// for Organizations List
$conditions = array();
$findType = 'all';
if ($org_id !== false) {
$findType = 'first';
$conditions = array('User.org_id' => $org_id);
}
$fields = array('org_id', 'COUNT(User.id) AS num_members');
$params = array(
'fields' => $fields,
'recursive' => -1,
'group' => array('org_id'),
'order' => array('org_id'),
'conditions' => $conditions
);
$orgs = $this->find('all', $params);
$usersPerOrg = [];
foreach ($orgs as $key => $value) {
$usersPerOrg[$value['User']['org_id']] = $value[0]['num_members'];
$orgs = $this->find($findType, $params);
if (empty($orgs)) {
return 0;
}
if ($org_id !== false) {
return $orgs[0]['num_members'];
} else {
$usersPerOrg = [];
foreach ($orgs as $key => $value) {
$usersPerOrg[$value['User']['org_id']] = $value[0]['num_members'];
}
return $usersPerOrg;
}
return $usersPerOrg;
}
public function findAdminsResponsibleForUser($user){
@ -928,4 +943,40 @@ class User extends AppModel {
return $admin['User'];
}
public function initiatePasswordReset($user, $firstTime = false, $simpleReturn = false, $fixedPassword = false) {
$org = Configure::read('MISP.org');
$options = array('passwordResetText', 'newUserText');
$subjects = array('[' . $org . ' MISP] New user registration', '[' . $org . ' MISP] Password reset');
$textToFetch = $options[($firstTime ? 0 : 1)];
$subject = $subjects[($firstTime ? 0 : 1)];
$this->Server = ClassRegistry::init('Server');
$body = Configure::read('MISP.' . $textToFetch);
if (!$body) $body = $this->Server->serverSettings['MISP'][$textToFetch]['value'];
$body = $this->adminMessageResolve($body);
if ($fixedPassword) {
$password = $fixedPassword;
} else {
$password = $this->generateRandomPassword();
}
$body = str_replace('$password', $password, $body);
$body = str_replace('$username', $user['User']['email'], $body);
$result = $this->sendEmail($user, $body, false, $subject);
if ($result) {
$this->id = $user['User']['id'];
$this->saveField('password', $password);
$this->saveField('change_pw', '1');
if ($simpleReturn) {
return true;
} else {
return array('body'=> json_encode(array('saved' => true, 'success' => 'New credentials sent.')),'status'=>200);
}
}
if ($simpleReturn) {
return false;
} else {
return array('body'=> json_encode(array('saved' => false, 'errors' => 'There was an error notifying the user. His/her credentials were not altered.')),'status'=>200);
}
}
}

View File

@ -155,7 +155,7 @@ class Warninglist extends AppModel{
}
private function __checkValue($listValues, $value, $type, $listType) {
if (strpos($type, '|')) $value = explode('|', $value);
if (strpos($type, '|') || $type = 'malware-sample') $value = explode('|', $value);
else $value = array($value);
$components = array(0, 1);
foreach ($components as $component) {
@ -164,6 +164,10 @@ class Warninglist extends AppModel{
$result = $this->__evalCIDRList($listValues, $value[$component]);
} else if ($listType === 'string') {
$result = $this->__evalString($listValues, $value[$component]);
} else if ($listType === 'substring') {
$result = $this->__evalSubString($listValues, $value[$component]);
} else if ($listType === 'hostname') {
$result = $this->__evalHostname($listValues, $value[$component]);
}
if ($result) return ($component + 1);
}
@ -243,6 +247,43 @@ class Warninglist extends AppModel{
return false;
}
private function __evalSubString($listValues, $value) {
foreach ($listValues as $listValue) {
if (strpos($value, $listValue) !== false) {
return true;
}
}
return false;
}
private function __evalHostname($listValues, $value) {
// php's parse_url is dumb, so let's use some hacky workarounds
if (strpos($value, '//') == false) {
$value = 'http://' . $value;
}
$hostname = parse_url($value, PHP_URL_HOST);
// If the hostname is not found, just return false
if (!isset($hostname)) {
return false;
}
$value = explode('.', $hostname);
$pieces = count($value);
foreach ($listValues as $listValue) {
$listValue = explode('.', $listValue);
if (count($listValue) > $pieces) {
continue;
}
$piecesListValue = count($listValue);
$listValue = implode('.', $listValue);
$temp = array_slice($value, -$piecesListValue, $piecesListValue);
$temp = implode('.', $temp);
if ($listValue == $temp) {
return true;
}
}
return false;
}
public function fetchTLDLists() {
$tldLists = $this->find('list', array('conditions' => array('Warninglist.name' => $this->__tlds, 'Warninglist.enabled' => 1), 'recursive' => -1, 'fields' => array('Warninglist.id', 'Warninglist.name')));
$tlds = array();

View File

@ -109,13 +109,14 @@
}
?>
<script type="text/javascript">
var fieldsArray = new Array('AttributeCategory', 'AttributeType', 'AttributeValue', 'AttributeDistribution', 'AttributeComment', 'AttributeToIds', 'AttributeBatchImport', 'AttributeSharingGroupId');
<?php
$formInfoTypes = array('distribution' => 'Distribution', 'category' => 'Category', 'type' => 'Type');
echo 'var formInfoFields = ' . json_encode($formInfoTypes) . PHP_EOL;
foreach ($formInfoTypes as $formInfoType => $humanisedName) {
echo 'var ' . $formInfoType . 'FormInfoValues = {' . PHP_EOL;
foreach ($info[$formInfoType] as $key => $formInfoData) {
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
}
echo '}' . PHP_EOL;
}
@ -157,11 +158,10 @@ $(document).ready(function() {
$('#SGContainer').hide();
}
});
$("#AttributeCategory, #AttributeType, #AttributeDistribution").change(function() {
initPopoverContent('Attribute');
});
<?php if ($ajax): ?>
$('#cancel_attribute_add').click(function() {
cancelPopoverForm();

View File

@ -0,0 +1,4 @@
<?php
$mayModify = (($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Event']['orgc_id'] == $me['org_id']) || ($isAclModifyOrg && $event['Event']['orgc_id'] == $me['org_id']));
echo $this->element('ajaxAttributeTags', array('attributeId' => $attributeId, 'attributeTags' => $attributeTags, 'tagAccess' => ($isSiteAdmin || $mayModify || $me['org_id'] == $event['Event']['org_id'])));
?>

View File

@ -33,6 +33,8 @@
));
?>
<div class="input clear"></div>
<div class="input clear"></div>
<?php
echo $this->Form->input('comment', array(
'type' => 'textarea',

View File

@ -0,0 +1,25 @@
<div class="confirmation">
<?php
echo $this->Form->create($model, array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => '/' . strtolower($model) . 's/removeTag/' . $id . '/' . $tag_id));
$action = "removeObjectTag('" . $model . "', '" . h($id) . "', '" . h($tag_id) . "');";
?>
<legend>Remove Tag</legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<p>Remove tag (<?php echo h($tag_id); ?>) from <?php echo ucfirst(h($model)); ?> (<?php echo h($id); ?>)?</p>
<table>
<tr>
<td style="vertical-align:top">
<span id="PromptYesButton" class="btn btn-primary" onClick="<?php echo $action; ?>">Yes</span>
</td>
<td style="width:540px;">
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt();">No</span>
</td>
</tr>
</table>
</div>
<?php
echo $this->Form->end();
?>
</div>

View File

@ -67,13 +67,14 @@
echo $this->element('side_menu', array('menuList' => 'event', 'menuItem' => 'addAttribute', 'event' => $event));
?>
<script type="text/javascript">
var fieldsArray = new Array('AttributeCategory', 'AttributeType', 'AttributeValue', 'AttributeDistribution', 'AttributeComment', 'AttributeToIds', 'AttributeBatchImport', 'AttributeSharingGroupId');
<?php
$formInfoTypes = array('distribution' => 'Distribution', 'category' => 'Category', 'type' => 'Type');
echo 'var formInfoFields = ' . json_encode($formInfoTypes) . PHP_EOL;
foreach ($formInfoTypes as $formInfoType => $humanisedName) {
echo 'var ' . $formInfoType . 'FormInfoValues = {' . PHP_EOL;
foreach ($info[$formInfoType] as $key => $formInfoData) {
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
}
echo '}' . PHP_EOL;
}
@ -101,7 +102,7 @@ $(document).ready(function() {
if ($('#AttributeDistribution').val() == 4) $('#SGContainer').show();
else $('#SGContainer').hide();
});
$("#AttributeCategory").on('change', function(e) {
formCategoryChanged('Attribute');
if ($(this).val() === 'Attribution' || $(this).val() === 'Targeting data') {
@ -114,7 +115,7 @@ $(document).ready(function() {
$('#SGContainer').hide();
}
});
$("#AttributeCategory, #AttributeType, #AttributeDistribution").change(function() {
initPopoverContent('Attribute');
});

View File

@ -4,6 +4,7 @@
if ($isSearch == 1) {
echo "<h4>Results for all attributes";
if ($keywordSearch != null) echo " with the value containing \"<b>" . h($keywordSearch) . "</b>\"";
if ($attributeTags != null) echo " being tagged with \"<b>" . h($attributeTags) . "</b>\"";
if ($keywordSearch2 != null) echo " from the events \"<b>" . h($keywordSearch2) . "</b>\"";
if ($tags != null) echo " from events tagged \"<b>" . h($tags) . "</b>\"";
if ($categorySearch != "ALL") echo " of category \"<b>" . h($categorySearch) . "</b>\"";
@ -36,6 +37,7 @@ if ($isSearch == 1) {
<th><?php echo $this->Paginator->sort('category');?></th>
<th><?php echo $this->Paginator->sort('type');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
<th>Tags</th>
<th><?php echo $this->Paginator->sort('comment');?></th>
<th<?php echo ' title="' . $attrDescriptions['signature']['desc'] . '"';?>>
<?php echo $this->Paginator->sort('IDS');?></th>
@ -101,6 +103,21 @@ foreach ($attributes as $attribute):
}
?>
</td>
<td style = "max-width:200px;width:10px;">
<?php foreach ($attribute['AttributeTag'] as $tag):
$tagText = "&nbsp;";
if (Configure::read('MISP.full_tags_on_attribute_index') == 1) $tagText = h($tag['Tag']['name']);
else if (Configure::read('MISP.full_tags_on_attribute_index') == 2) {
if (strpos($tag['Tag']['name'], '=')) {
$tagText = explode('=', $tag['Tag']['name']);
$tagText = h(trim(end($tagText), "\""));
}
else $tagText = h($tag['Tag']['name']);
}
?>
<span class="tag useCursorPointer" style="margin-bottom:3px;background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>;" title="<?php echo h($tag['Tag']['name']); ?>" onClick="document.location.href='<?php echo $baseurl; ?>/attributes/search/attributetag:<?php echo h($tag['Tag']['id']);?>';"><?php echo $tagText; ?></span>
<?php endforeach; ?>
</td>
<td ondblclick="document.location ='document.location ='<?php echo $baseurl;?>/events/view/<?php echo $attribute['Event']['id'];?>';">
<?php
$sigDisplay = nl2br(h($attribute['Attribute']['comment']));

View File

@ -5,6 +5,7 @@
You can search for attributes based on contained expression within the value, event ID, submitting organisation, category and type. <br />For the value, event ID and organisation, you can enter several search terms by entering each term as a new line. To exclude things from a result, use the NOT operator (!) in front of the term.<br/><br />
<?php
echo $this->Form->input('keyword', array('type' => 'textarea', 'rows' => 2, 'label' => 'Containing the following expressions', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('attributetags', array('type' => 'textarea', 'rows' => 2, 'label' => 'Being an attribute matching the following tags', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('keyword2', array('type' => 'textarea', 'rows' => 2, 'label' => 'Being attributes of the following event IDs, event UUIDs or attribute UUIDs', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('tags', array('type' => 'textarea', 'rows' => 2, 'label' => 'Being an attribute of an event matching the following tags', 'div' => 'clear', 'class' => 'input-xxlarge'));

View File

@ -21,6 +21,8 @@
<?php
endif;
endif;
$date = time();
$day = 86400;
?>
<th><?php echo $this->Paginator->sort('id');?></th>
<th>Clusters</th>
@ -37,6 +39,9 @@
<?php if (Configure::read('MISP.showProposalsOnIndex')):?>
<th title="Proposal Count">#Prop</th>
<?php endif; ?>
<?php if (Configure::read('MISP.showDiscussionsCountOnIndex')):?>
<th title="Post Count">#Posts</th>
<?php endif; ?>
<?php if ($isSiteAdmin): ?>
<th><?php echo $this->Paginator->sort('user_id', 'Email');?></th>
<?php endif; ?>
@ -163,6 +168,21 @@
<?php echo !empty($event['Event']['proposals_count']) ? h($event['Event']['proposals_count']) : ''; ?>&nbsp;
</td>
<?php endif;?>
<?php if (Configure::read('MISP.showDiscussionsCountOnIndex')): ?>
<td class = "bold" style="width:30px;" ondblclick="location.href ='<?php echo $baseurl."/events/view/".$event['Event']['id'];?>'" title="<?php echo (!empty($event['Event']['proposals_count']) ? h($event['Event']['proposals_count']) : '0') . ' proposal(s)';?>">
<?php
if (!empty($event['Event']['post_count'])) {
$post_count = h($event['Event']['post_count']);
if (($date - $event['Event']['last_post']) < $day) {
$post_count .= ' (<span class="red bold">NEW</span>)';
}
} else {
$post_count = '';
}
?>
<span style=" white-space: nowrap;"><?php echo $post_count?></span>&nbsp;
</td>
<?php endif;?>
<?php if ('true' == $isSiteAdmin): ?>
<td class="short" ondblclick="location.href ='<?php echo $baseurl."/events/view/".$event['Event']['id'];?>'">
<?php echo h($event['User']['email']); ?>&nbsp;

View File

@ -0,0 +1,23 @@
<div style="width:100%;display:inline-block;">
<?php
$full = $isAclTagger && $tagAccess;
foreach ($attributeTags as $tag):
$tagClass = $full ? 'tagFirstHalf' : 'tag';
?>
<div style="padding:1px; overflow:hidden; white-space:nowrap; display:flex; float:left; margin-right:2px;">
<a href="<?php echo $baseurl;?>/attributes/search/attributetag:<?php echo h($tag['Tag']['id']); ?>" class="<?php echo $tagClass; ?>" style="display:inline-block; background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<?php if ($full): ?>
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeObjectTagPopup('attribute', '<?php echo h($attributeId); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php endif;?>
</div>
<?php
endforeach;
?>
<div style="float:left">
<?php if ($full): ?>
<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup('<?php echo h($attributeId); ?>' + '/true', 'tags', 'selectTaxonomy');">+</button>
<?php else:?>
&nbsp;
<?php endif; ?>
</div>
</div>

View File

@ -1,33 +1,20 @@
<div style="width:100%;display:inline-block;">
<?php
foreach ($tags as $tag): ?>
<div style="overflow:hidden;white-space:nowrap;float:left;">
<div style="padding-right:0px;float: left;">
<?php if ($isAclTagger && $tagAccess): ?>
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class="tagFirstHalf" style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<?php else: ?>
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class=tag style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<?php endif; ?>
</div>
<div style="padding-left:0px;padding-right:5px;float:left;">
<?php if ($isAclTagger && $tagAccess): ?>
<?php
echo $this->Form->create('Event', array('id' => 'removeTag_' . h($tag['Tag']['id']), 'url' => '/events/removeTag/' . h($event['Event']['id']) . '/' . h($tag['Tag']['id']), 'style' => 'margin:0px;'));
?>
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeEventTag('<?php echo h($event['Event']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php
echo $this->Form->end();
?>
<?php else: ?>
&nbsp;
<?php endif; ?>
</div>
$full = $isAclTagger && $tagAccess;
foreach ($tags as $tag):
$tagClass = $full ? 'tagFirstHalf' : 'tag';
?>
<div style="padding:1px; overflow:hidden; white-space:nowrap; display:flex; float:left; margin-right:2px;">
<a href="<?php echo $baseurl;?>/events/index/searchtag:<?php echo h($tag['Tag']['id']); ?>" class="<?php echo $tagClass; ?>" style="display:inline-block; background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<?php if ($full): ?>
<div class="tagSecondHalf useCursorPointer noPrint" onClick="removeObjectTagPopup('event', '<?php echo h($event['Event']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php endif;?>
</div>
<?php
<?php
endforeach;
?>
<div style="float:left">
<?php if ($isAclTagger && $tagAccess): ?>
<?php if ($full): ?>
<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'tags', 'selectTaxonomy');">+</button>
<?php else:?>
&nbsp;

View File

@ -129,6 +129,7 @@
<div class="tabMenu tabMenuEditBlock noPrint">
<span id="create-button" title="Add attribute" class="icon-plus useCursorPointer" onClick="clickCreateButton(<?php echo $event['Event']['id']; ?>, '<?php echo $possibleAction; ?>');"></span>
<span id="multi-edit-button" title="Edit selected Attributes" class="icon-edit mass-select useCursorPointer" onClick="editSelectedAttributes(<?php echo $event['Event']['id']; ?>);"></span>
<span id="multi-tag-button" title="Tag selected Attributes" class="icon-tag mass-select useCursorPointer" onClick="getPopup('selected/true', 'tags', 'selectTaxonomy');"></span>
<span id="multi-delete-button" title="Delete selected Attributes" class = "icon-trash mass-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'deleteAttributes');"></span>
<span id="multi-accept-button" title="Accept selected Proposals" class="icon-ok mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'acceptProposals');"></span>
<span id="multi-discard-button" title="Discard selected Proposals" class = "icon-remove mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'discardProposals');"></span>
@ -169,6 +170,7 @@
<th><?php echo $this->Paginator->sort('category');?></th>
<th><?php echo $this->Paginator->sort('type');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
<th>Tags</th>
<th><?php echo $this->Paginator->sort('comment');?></th>
<?php
if ($mayChangeCorrelation && !$event['Event']['disable_correlation']):
@ -292,8 +294,7 @@
$extension = explode('.', $object['value']);
$extension = end($extension);
$uri = 'data:image/' . strtolower(h($extension)) . ';base64,' . h($object['image']);
$img = '<img src="' . $uri . '" style="width:200px;" title="' . h($object['value']) . '" />';
echo '<a href="' . $baseurl . '/' . ($object['objectType'] == 0 ? 'attributes' : 'shadow_attributes') . '/download/' . h($object['id']) . '">' . $img . '</a>';
echo '<img class="screenshot screenshot-collapsed useCursorPointer" src="' . $uri . '" title="' . h($object['value']) . '" />';
} else {
$t = ($object['objectType'] == 0 ? 'attributes' : 'shadow_attributes');
$filenameHash = explode('|', nl2br(h($object['value'])));
@ -305,12 +306,12 @@
} else {
echo '<a href="' . $baseurl . '/' . h($t) . '/download/' . h($object['id']) . '" class="' . $linkClass . '">' . h($filenameHash[0]) . '</a>';
}
if (isset($filenameHash[1])) echo ' | ' . $filenameHash[1];
if (isset($filenameHash[1])) echo '<br />' . $filenameHash[1];
}
} else if (strpos($object['type'], '|') !== false) {
$filenameHash = explode('|', $object['value']);
echo h($filenameHash[0]);
if (isset($filenameHash[1])) echo ' | ' . $filenameHash[1];
if (isset($filenameHash[1])) echo '<br />' . $filenameHash[1];
} else if ('vulnerability' == $object['type']) {
if (! is_null(Configure::read('MISP.cveurl'))) {
$cveUrl = Configure::read('MISP.cveurl');
@ -350,6 +351,21 @@
?>
</div>
</td>
<td class="shortish <?php echo $extra; ?>">
<?php
if ($object['objectType'] == 0):
?>
<div class="attributeTagContainer">
<?php echo $this->element('ajaxAttributeTags', array('attributeId' => $object['id'], 'attributeTags' => $object['AttributeTag'], 'tagAccess' => ($isSiteAdmin || $mayModify || $me['org_id'] == $event['Event']['org_id']) )); ?>
</div>
<?php
else:
?>
&nbsp;
<?php
endif;
?>
</td>
<td class="showspaces bitwider <?php echo $extra; ?>">
<div id = "<?php echo $currentType . '_' . $object['id'] . '_comment_placeholder'; ?>" class = "inline-field-placeholder"></div>
<div id = "<?php echo $currentType . '_' . $object['id'] . '_comment_solid'; ?>" class="inline-field-solid" ondblclick="activateField('<?php echo $currentType; ?>', '<?php echo $object['id']; ?>', 'comment', <?php echo $event['Event']['id'];?>);">
@ -360,12 +376,14 @@
if ($mayChangeCorrelation && !$event['Event']['disable_correlation']):
if ($object['objectType'] == 0):
?>
<td class="short" style="padding-top:3px;">
<td class="short <?php echo $extra; ?>" style="padding-top:3px;">
<input class="correlation-toggle" type="checkbox" data-attribute-id="<?php echo h($object['id']); ?>" <?php echo $object['disable_correlation'] ? '' : 'checked'; ?>>
</td>
<?php
else:
echo '&nbsp;';
?>
<td class="short <?php echo $extra; ?>" style="padding-top:3px;">&nbsp;</td>
<?php
endif;
endif;
?>
@ -599,6 +617,9 @@ attributes or the appropriate distribution level. If you think there is a mistak
getPopup(attribute_id, 'attributes', 'toggleCorrelation', '', '#confirmation_box');
return false;
});
$('.screenshot').click(function() {
screenshotPopup($(this).attr('src'), $(this).attr('title'));
});
});
</script>
<?php

View File

@ -22,8 +22,8 @@
<?php
foreach ($posts as $post) {
?>
<a name="message_<?php echo h($post['Post']['id']);?>"></a>
<table class="discussionBox" id=<?php echo '"' . h($post['Post']['id']) . '"';?> >
<a name="message_<?php echo h($post['id']);?>"></a>
<table class="discussionBox" id=<?php echo '"' . h($post['id']) . '"';?> >
<tr>
<td class="discussionBoxTD discussionBoxTDtop" colspan="2">
<div>
@ -31,12 +31,12 @@
<tr>
<td>
<?php
echo 'Date: ' . h($post['Post']['date_created']);
echo 'Date: ' . h($post['date_created']);
?>
</td>
<td style="text-align:right">
<a href="#top" class="whitelink">Top</a> |
<a href="<?php echo "#".$post['Post']['id']; ?>" class="whitelink">#<?php echo h($post['Post']['id'])?></a>
<a href="<?php echo "#".$post['id']; ?>" class="whitelink">#<?php echo h($post['id'])?></a>
</td>
</tr>
</table>
@ -46,10 +46,10 @@
<tr>
<td class="discussionBoxTD discussionBoxTDMid discussionBoxTDMidLeft">
<?php
if (isset($post['User']['Organisation'])) {
$imgAbsolutePath = APP . WEBROOT_DIR . DS . 'img' . DS . 'orgs' . DS . h($post['User']['Organisation']['name']) . '.png';
if (file_exists($imgAbsolutePath)) echo $this->Html->image('orgs/' . h($post['User']['Organisation']['name']) . '.png', array('alt' => h($post['User']['Organisation']['name']), 'title' => h($post['User']['Organisation']['name']), 'style' => 'width:48px; height:48px'));
else echo $this->Html->tag('span', h($post['User']['Organisation']['name']), array('class' => 'welcome', 'style' => 'float:center;'));
if (isset($post['org_name'])) {
$imgAbsolutePath = APP . WEBROOT_DIR . DS . 'img' . DS . 'orgs' . DS . h($post['org_name']) . '.png';
if (file_exists($imgAbsolutePath)) echo $this->Html->image('orgs/' . h($post['org_name']) . '.png', array('alt' => h($post['org_name']), 'title' => h($post['org_name']), 'style' => 'width:48px; height:48px'));
else echo $this->Html->tag('span', h($post['org_name']), array('class' => 'welcome', 'style' => 'float:center;'));
} else {
echo 'Deactivated user';
}
@ -57,22 +57,22 @@
</td>
<td class="discussionBoxTD discussionBoxTDMid discussionBoxTDMidRight">
<?php
echo $this->Command->convertQuotes(nl2br(h($post['Post']['contents'])));
if ($post['Post']['post_id'] !=0 || ($post['Post']['date_created'] != $post['Post']['date_modified'])) {
echo $this->Command->convertQuotes(nl2br(h($post['contents'])));
if ($post['post_id'] !=0 || ($post['date_created'] != $post['date_modified'])) {
?>
<br /><br />
<?php
}
if ($post['Post']['post_id'] != 0) {
if ($post['post_id'] != 0) {
?>
<span style="font-style:italic">
In reply to post
<a href="<?php echo "#".h($post['Post']['post_id']); ?>">#<?php echo h($post['Post']['post_id'])?></a>
<a href="<?php echo "#".h($post['post_id']); ?>">#<?php echo h($post['post_id'])?></a>
</span>
<?php
}
if ($post['Post']['date_created'] != $post['Post']['date_modified']) {
echo '<span style="font-style:italic">Message edited at ' . h($post['Post']['date_modified']) . '<span>';
if ($post['date_created'] != $post['date_modified']) {
echo '<span style="font-style:italic">Message edited at ' . h($post['date_modified']) . '<span>';
}
?>
</td>
@ -82,24 +82,24 @@
<table style="width:100%">
<tr>
<td>
<?php echo h($post['User']['email']); ?>
<?php echo !empty($post['user_email']) ? h($post['user_email']) : 'User ' . h($post['user_id']) . ' (' . (h($post['org_name'])) . ')'; ?>
</td>
<td style="text-align:right">
<?php
if (!$isSiteAdmin) {
if ($post['Post']['user_id'] == $myuserid) {
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['Post']['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['Post']['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
if ($post['user_id'] == $myuserid) {
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
} else {
?>
<a href="<?php echo $baseurl.'/posts/add/post/'.h($post['Post']['id']); ?>" class="icon-comment" title = "Reply"></a>
<a href="<?php echo $baseurl.'/posts/add/post/'.h($post['id']); ?>" class="icon-comment" title = "Reply"></a>
<?php
}
} else {
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['Post']['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['Post']['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
echo $this->Html->link('', array('controller' => 'posts', 'action' => 'edit', h($post['id']), h($context)), array('class' => 'icon-edit', 'title' => 'Edit'));
echo $this->Form->postLink('', array('controller' => 'posts', 'action' => 'delete', h($post['id']), h($context)), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete this post?'));
?>
<a href = "<?php echo $baseurl.'/posts/add/post/'.h($post['Post']['id']); ?>" class="icon-comment" title = "Reply"></a>
<a href = "<?php echo $baseurl.'/posts/add/post/'.h($post['id']); ?>" class="icon-comment" title = "Reply"></a>
<?php
}
@ -135,7 +135,7 @@
<div class="comment">
<?php
if (isset($currentEvent)) $url = '/posts/add/event/' . $currentEvent;
else $url = '/posts/add/thread/' . $thread_id;
else $url = '/posts/add/thread/' . $thread['Thread']['id'];
echo $this->Form->create('Post', array('url' => $url));
?>
<fieldset>

View File

@ -48,7 +48,7 @@
}
foreach ($cluster_fields as $cluster_field):
?>
<tr>
<tr class="cluster_<?php echo h($cluster_field['key']); ?>">
<td style="width:25%;vertical-align: text-top; padding-bottom:10px;"><?php echo h(ucfirst($cluster_field['key'])); ?></td>
<td style="width:75%; padding-bottom:10px;">
<?php
@ -69,7 +69,11 @@
echo nl2br(h(implode("\n", $cluster_field['value'])));
}
} else {
echo h($cluster_field['value']);
if ($cluster_field['key'] == 'source' && filter_var($cluster_field['value'], FILTER_VALIDATE_URL)) {
echo '<a href="' . h($cluster_field['value']) . '">' . h($cluster_field['value']) . '</a>';;
} else {
echo h($cluster_field['value']);
}
}
?>
</td>

View File

@ -1,4 +1,11 @@
<div style="border:1px solid #dddddd; margin-top:1px; width:95%; padding:10px">
<?php
if (!$dbEncodingStatus):
?>
<div style="font-size:12pt;padding-left:3px;width:100%;background-color:red;color:white;font-weight:bold;">Incorrect database encoding setting: Your database connection is currently NOT set to UTF-8. Please make sure to uncomment the 'encoding' => 'utf8' line in <?php echo APP; ?>Config/database.php</div>
<?php
endif;
?>
<h3>MISP version</h3>
<p>Since version 2.3.14, every version of MISP includes a json file with the current version. This is checked against the latest tag on github, if there is a version mismatch the tool will warn you about it. Make sure that you update MISP regularly.</p>
<div style="background-color:#f7f7f9;width:400px;">
@ -89,7 +96,7 @@
}
?>
</div>
<h3>PHP Settings</h3>
<?php
$phpcolour = 'green';
@ -138,26 +145,26 @@
endforeach;
?>
<h4>PHP Extensions</h4>
<?php
<?php
foreach (array('web', 'cli') as $context):
?>
<div style="background-color:#f7f7f9;width:400px;">
<b><?php echo ucfirst(h($context));?></b><br />
<?php
<?php
if (isset($extensions[$context]['extensions'])):
foreach ($extensions[$context]['extensions'] as $extension => $status):
?>
<?php echo h($extension); ?>:.... <span style="color:<?php echo $status ? 'green' : 'red';?>;font-weight:bold;"><?php echo $status ? 'OK' : 'Not loaded'; ?></span>
<?php
<?php
endforeach;
else:
?>
<span class="red">Issues reading PHP settings. This could be due to the test script not being readable.</span>
<?php
<?php
endif;
?>
</div><br />
<?php
<?php
endforeach;
?>
<h3>
@ -177,7 +184,7 @@
echo 'STIX and CyBox.... <span class="red">Could not read test script (stixtest.py).</span>';
$testReadError = true;
}
}
}
}
if (!$testReadError) {
if ($stix['operational'] == 0) {
@ -299,6 +306,11 @@
</div><br />
<span class="btn btn-inverse" style="padding-top:1px;padding-bottom:1px;" onClick="checkOrphanedAttributes();">Check for orphaned attributes</span><br /><br />
<?php echo $this->Form->postButton('Remove orphaned attributes', $baseurl . '/attributes/pruneOrphanedAttributes', $options = array('class' => 'btn btn-primary', 'style' => 'padding-top:1px;padding-bottom:1px;')); ?>
<h3>
Database cleanup scripts
</h3>
<p>If you run into an issue with an infinite upgrade loop (when upgrading from version ~2.4.50) that ends up filling your database with upgrade script log messages, run the following script.</p>
<?php echo $this->Form->postButton('Prune upgrade logs', $baseurl . '/logs/pruneUpdateLogs', $options = array('class' => 'btn btn-primary', 'style' => 'padding-top:1px;padding-bottom:1px;')); ?>
<h3>
Legacy Administrative Tools
</h3>

View File

@ -47,13 +47,11 @@
<?php endif; ?>
<li class="divider"></li>
<?php
$publishButtons = ' style="display:none;"';
$exportButtons = ' style="display:none;"';
$publishButtons = ' hidden';
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && ($isSiteAdmin || (isset($mayPublish) && $mayPublish))) $publishButtons = "";
if (isset($event['Event']['published']) && $event['Event']['published']) $exportButtons = "";
?>
<li<?php echo $publishButtons; ?> class="publishButtons not-published"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')">Publish Event</a></li>
<li<?php echo $publishButtons; ?> class="publishButtons not-published"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')">Publish (no email)</a></li>
<li class="publishButtons not-published<?php echo h($publishButtons); ?>"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')">Publish Event</a></li>
<li class="publishButtons not-published<?php echo h($publishButtons); ?>"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')">Publish (no email)</a></li>
<?php if (Configure::read('MISP.delegation')):?>
<?php if ((Configure::read('MISP.unpublishedprivate') || (isset($event['Event']['distribution']) && $event['Event']['distribution'] == 0)) && (!isset($delegationRequest) || !$delegationRequest) && ($isSiteAdmin || (isset($isAclDelegate) && $isAclDelegate))): ?>
<li id='lidelegateEvent'><a href="#" onClick="delegatePopup('<?php echo h($event['Event']['id']); ?>');">Delegate Publishing</a></li>

View File

@ -7,16 +7,20 @@
'label' => '<b>MISP XML or JSON file</b>',
'type' => 'file',
));
if (Configure::read('MISP.take_ownership_xml_import')):
?>
?>
<div class="input clear"></div>
<?php
<?php
if (Configure::read('MISP.take_ownership_xml_import')):
echo $this->Form->input('Event.takeownership', array(
'checked' => false,
'label' => 'Take ownership of the event',
'title' => 'Warning: This will change the creator organisation of the event, tampering with the event\'s ownership and releasability and can lead to unexpected behaviour when synchronising the event with instances that have another creator for the same event.'
));
endif;
echo $this->Form->input('publish', array(
'checked' => false,
'label' => 'Publish imported events',
));
?>
</fieldset>
<?php

View File

@ -198,7 +198,7 @@ foreach ($sigTypes as $sigType) {
<p>As of version 2.3.38, it is possible to restrict the text exports on two additional flags. The first allows the user to restrict based on event ID, whilst the second is a boolean switch allowing non IDS flagged attributes to be exported. Additionally, choosing "all" in the type field will return all eligible attributes. </p>
<pre>
<?php
echo $baseurl.'/attributes/text/download/[type]/[tags]/[event_id]/[allowNonIDS]/[from]/[to]/[last]';
echo $baseurl.'/attributes/text/download/[type]/[tags]/[event_id]/[allowNonIDS]/[from]/[to]/[last]/[enforceWarninglist]/[allowNotPublished]';
?>
</pre>
<b>type</b>: The attribute type, any valid MISP attribute type is accepted.<br />
@ -209,6 +209,7 @@ foreach ($sigTypes as $sigType) {
<b>to</b>: Events with the date set to a date before the one specified in the to field (format: 2015-02-15). This filter will use the date of the event.<br />
<b>last</b>: Events published within the last x amount of time, where x can be defined in days, hours, minutes (for example 5d or 12h or 30m). This filter will use the published timestamp of the event.<br />
<b>enforceWarninglist</b>: All attributes that have a hit on a warninglist will be excluded.<br />
<b>allowNotPublished</b>: Include not published Events.</b>
You can also chain several tag commands together with the '&amp;&amp;' operator. Please be aware the colons (:) cannot be used in the tag search.
Use semicolons instead (the search will automatically search for colons instead). For example, to include tag1 and tag2 but exclude tag3 you would use:<br />
<pre>

View File

@ -197,19 +197,19 @@
var options = <?php echo json_encode($optionsRearranged);?>;
$(document).ready(function(){
popoverStartup();
<?php
if (!empty($optionsRearranged)):
?>
$('#changeFrom').change(function(){
changeFreetextImportFrom();
});
$('#changeFrom').trigger('change');
<?php
if (!empty($optionsRearranged)):
?>
$('#changeFrom').change(function(){
changeFreetextImportFrom();
});
$('#changeFrom').trigger('change');
<?php
endif;
?>
$('#checkAll').change(function() {
$('.idsCheckbox').prop('checked', $('#checkAll').is(':checked'));
});
<?php
endif;
?>
});
</script>
<?php

View File

@ -15,6 +15,23 @@
'placeholder' => 'Name of the content provider',
'class' => 'form-control span6'
));
echo $this->Form->input('input_source', array(
'label' => 'Input Source',
'div' => 'input clear',
'options' => array('network' => 'Network', 'local' => 'Local'),
'class' => 'form-control span6'
));
?>
<div class="input clear"></div>
<div id="DeleteLocalFileDiv" class="optionalField">
<?php
echo $this->Form->input('delete_local_file', array(
'label' => 'Remove input after ingestion'
));
?>
</div>
<div class="input clear"></div>
<?php
echo $this->Form->input('url', array(
'div' => 'input clear',
'placeholder' => 'URL of the feed',
@ -173,8 +190,7 @@ $(document).ready(function() {
});
feedFormUpdate();
});
$("#FeedSourceFormat, #FeedFixedEvent").change(function() {
$("#FeedSourceFormat, #FeedFixedEvent, #FeedInputSource").change(function() {
feedFormUpdate();
});
</script>

View File

@ -15,6 +15,23 @@
'placeholder' => 'Name of the content provider',
'class' => 'form-control span6'
));
echo $this->Form->input('input_source', array(
'label' => 'Input Source',
'div' => 'input clear',
'options' => array('network' => 'Network', 'local' => 'Local'),
'class' => 'form-control span6'
));
?>
<div class="input clear"></div>
<div id="DeleteLocalFileDiv" class="optionalField">
<?php
echo $this->Form->input('delete_local_file', array(
'label' => 'Remove input after ingestion'
));
?>
</div>
<div class="input clear"></div>
<?php
echo $this->Form->input('url', array(
'div' => 'input clear',
'placeholder' => 'URL of the feed',
@ -185,7 +202,7 @@ $(document).ready(function() {
feedFormUpdate();
});
$("#FeedSourceFormat, #FeedFixedEvent").change(function() {
$("#FeedSourceFormat, #FeedFixedEvent, #FeedInputSource").change(function() {
feedFormUpdate();
});
</script>

View File

@ -27,6 +27,7 @@
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('source_format', 'Feed Format');?></th>
<th><?php echo $this->Paginator->sort('provider');?></th>
<th><?php echo $this->Paginator->sort('input_source', 'Input');?></th>
<th><?php echo $this->Paginator->sort('url');?></th>
<th>Target</th>
<th>Publish</th>
@ -73,6 +74,7 @@ foreach ($feeds as $item):
</td>
<td><?php echo $feed_types[$item['Feed']['source_format']]['name']; ?>&nbsp;</td>
<td><?php echo h($item['Feed']['provider']); ?>&nbsp;</td>
<td><?php echo h($item['Feed']['input_source']); ?>&nbsp;</td>
<td><?php echo h($item['Feed']['url']); ?>&nbsp;</td>
<td class="shortish">
<?php

View File

@ -35,6 +35,7 @@
<body>
<div id="popover_form" class="ajax_popover_form"></div>
<div id="confirmation_box" class="confirmation_box"></div>
<div id="screenshot_box" class="screenshot_box"></div>
<div id="gray_out" class="gray_out"></div>
<div id="container">
<?php echo $this->element('global_menu');

View File

@ -15,22 +15,37 @@
),
);
if (!in_array($scope, array_keys($texts))) $scope = 'local';
$partial = array();
foreach($named as $key => $value):
if ($key == 'page' || $key == 'viewall'):
continue;
endif;
$partial[] = h($key) . ':' . h($value);
endforeach;
$viewall_button_text = 'Paginate';
if (!$viewall):
$viewall_button_text = 'View all';
$partial[] = 'viewall:1';
endif;
?>
<h2><?php echo $texts[$scope]['text'] . $texts[$scope]['extra']; ?></h2>
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
<h2><?php echo $texts[$scope]['text'] . $texts[$scope]['extra']; ?></h2>
<div class="pagination">
<ul>
<?php
$this->Paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
<li class="all">
<a href="<?php echo $baseurl . '/organisations/index/' . implode('/', $partial); ?>"><?php echo $viewall_button_text; ?></a>
</li>
</ul>
</div>
<div class="tabMenuFixedContainer" style="display:inline-block;">
@ -86,10 +101,12 @@ foreach ($orgs as $org): ?>
<td class="short" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'"><?php echo h($org['Organisation']['type']); ?></td>
<td><?php echo h($org['Organisation']['contacts']); ?></td>
<?php if ($isSiteAdmin): ?>
<td class="short" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'"><?php echo h($org_creator_ids[$org['Organisation']['created_by']]); ?></td>
<td class="short" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'">
<?php echo (isset($org['Organisation']['created_by_email'])) ? h($org['Organisation']['created_by_email']) : '&nbsp;'; ?>
</td>
<?php endif; ?>
<td class="short <?php echo $org['Organisation']['local'] ? 'green' : 'red';?>" ondblclick="document.location.href ='/organisations/view/<?php echo $org['Organisation']['id'];?>'"><?php echo $org['Organisation']['local'] ? 'Yes' : 'No';?></td>
<td class="short"><?php echo isset($members[$org['Organisation']['id']]) ? $members[$org['Organisation']['id']] : '0';?></td>
<td class="short"><?php echo isset($org['Organisation']['user_count']) ? $org['Organisation']['user_count'] : '0';?></td>
<td class="short action-links">
<?php if ($isSiteAdmin): ?>
<a href='/admin/organisations/edit/<?php echo $org['Organisation']['id'];?>' class = "icon-edit" title = "Edit"></a>
@ -117,6 +134,9 @@ endforeach; ?>
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
?>
<li class="all">
<a href="<?php echo $baseurl . '/organisations/index/' . implode('/', $partial); ?>"><?php echo $viewall_button_text; ?></a>
</li>
</ul>
</div>

View File

@ -43,10 +43,10 @@
<dt><?php echo 'Created by'; ?></dt>
<dd>
<?php
if (isset($creator['User']['email'])) {
echo h($creator['User']['email']);
if (isset($org['Organisation']['created_by_email'])) {
echo h($org['Organisation']['created_by_email']);
} else {
echo "SYSTEM";
echo "Unknown";
}
?>
&nbsp;

View File

@ -24,6 +24,9 @@ echo $this->Form->end();
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'addRole'));
$this->Js->get('#RolePermission')->event('change', 'deactivateActions()');
foreach ($permFlags as $k => $flag) {
if ($k == 'perm_audit' || $k == 'perm_auth') {
continue;
}
if ($k !== 'perm_site_admin') $this->Js->get('#' . $flag['id'])->event('change', 'checkPerms("' . $flag['id'] . '")');
else $this->Js->get('#RolePermSiteAdmin')->event('change', 'checkPerms("RolePermSiteAdmin");activateAll();');
}

View File

@ -24,6 +24,9 @@
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'editRole'));
$this->Js->get('#RolePermission')->event('change', 'deactivateActions()');
foreach ($permFlags as $k => $flag) {
if ($k == 'perm_audit' || $k == 'perm_auth') {
continue;
}
if ($k !== 'perm_site_admin') $this->Js->get('#' . $flag['id'])->event('change', 'checkPerms("' . $flag['id'] . '")');
else $this->Js->get('#RolePermSiteAdmin')->event('change', 'checkPerms("RolePermSiteAdmin");activateAll();');
}

View File

@ -140,10 +140,10 @@ var formInfoValues = {
'ServerOrganization' : "The organization having the external server you want to sync with. Example: BE",
'ServerAuthkey' : "You can find the authentication key on your profile on the external server.",
'ServerPush' : "Allow the upload of events and their attributes.",
'ServerPull' : "Allow the download of events and their attributes from the server.",
'ServerUnpublishEvent' : 'Unpublish new event (working with Pull event).',
'ServerPublishWithoutEmail' : 'Publish new event without email (working with Push event).',
'ServerSubmittedCert' : "You can also upload a certificate file if the instance you are trying to connect to has its own signing authority.",
'ServerPull' : "Allow the download of events and their attributes from the server.",
'ServerUnpublishEvent' : 'Unpublish new event (working with Pull event).',
'ServerPublishWithoutEmail' : 'Publish new event without email (working with Push event).',
'ServerSubmittedCert' : "You can also upload a certificate file if the instance you are trying to connect to has its own signing authority. (*.pem)",
'ServerSelfSigned' : "Click this, if you would like to allow a connection despite the other instance using a self-signed certificate (not recommended)."
};

View File

@ -97,7 +97,7 @@
?>
<div class="clear">
<p>
<span class="bold">Server certificate file: </span>
<span class="bold">Server certificate file (*.pem): </span>
<span id="serverEditCertValue">
<?php
if (isset($server['Server']['cert_file']) && !empty($server['Server']['cert_file'])) echo h($server['Server']['cert_file']);

View File

@ -18,6 +18,7 @@
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th>Connection test</th>
<th><?php echo $this->Paginator->sort('internal');?></th>
@ -59,6 +60,7 @@ foreach ($servers as $server):
}
?>
<tr>
<td class="short"><?php echo h($server['Server']['id']); ?></td>
<td>
<?php
if (!empty($server['Server']['name'])) echo h($server['Server']['name']);

View File

@ -145,6 +145,9 @@
<th><?php echo $this->Paginator->sort('category');?></th>
<th><?php echo $this->Paginator->sort('type');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
<?php if (Configure::read('MISP.attribute_tagging')): ?>
<th>Tags</th>
<?php endif; ?>
<th><?php echo $this->Paginator->sort('comment');?></th>
<th>Related Events</th>
<th title="<?php echo $attrDescriptions['signature']['desc'];?>"><?php echo $this->Paginator->sort('to_ids', 'IDS');?></th>
@ -177,6 +180,15 @@
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['category']); ?></td>
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['type']); ?></td>
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['value']); ?></td>
<?php if (Configure::read('MISP.attribute_tagging')): ?>
<td class="shortish <?php echo $extra; ?>">
<?php if (!empty($object['Tag'])) foreach ($object['Tag'] as $tag): ?>
<span class="tag" style="background-color:<?php echo h($tag['colour']); ?>;color:<?php echo $this->TextColour->getTextColour($tag['colour']);?>">
<?php echo h($tag['name']); ?>
</span>
<?php endforeach; ?>&nbsp;
</td>
<?php endif; ?>
<td class="shortish <?php echo $extra; ?>"><?php echo h($object['comment']); ?></td>
<td class="shortish <?php echo $extra; ?>">
<ul class="inline" style="margin:0px;">

View File

@ -16,7 +16,7 @@
<textarea class="input-xxlarge" placeholder="A description of the sharing group." cols="30" rows="6" id="SharingGroupDescription"></textarea>
<div style="display:block;">
<input type="checkbox" style="float:left;" title="Active sharing groups can be selected by users of the local instance when creating events. Generally, sharing groups received through synchronisation will have this disabled until manually enabled." value="1" id="SharingGroupActive" checked></input>
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable</label>
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable (active)</label>
</div>
<span class="btn btn-inverse" onClick="simpleTabPage(2);">Next page</span>
</div>

View File

@ -16,7 +16,7 @@
<textarea class="input-xxlarge" placeholder="A description of the sharing group." cols="30" rows="6" id="SharingGroupDescription"><?php echo h($sharingGroup['SharingGroup']['description']); ?></textarea>
<div style="display:block;">
<input type="checkbox" style="float:left;" title="Active sharing groups can be selected by users of the local instance when creating events. Generally, sharing groups received through synchronisation will have this disabled until manually enabled." <?php if ($sharingGroup['SharingGroup']['active']) echo "checked"; ?> id="SharingGroupActive"></input>
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable</label>
<label for="SharingGroupActive" style="padding-left:20px;">Make the sharing group selectable (active)</label>
</div>
<span class="btn btn-inverse" onClick="simpleTabPage(2);">Next page</span>
</div>

View File

@ -2,7 +2,12 @@
<legend>Select Tag</legend>
<div style="display:none;">
<?php
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $event_id, 'style' => 'margin:0px;'));
if (isset($attributeTag)) {
echo $this->Form->create('Attribute', array('url' => '/attributes/addTag/' . $object_id, 'style' => 'margin:0px;'));
} else {
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $object_id, 'style' => 'margin:0px;'));
}
echo $this->Form->input('attribute_ids', array('style' => 'display:none;', 'label' => false));
echo $this->Form->input('tag', array('value' => 0));
echo $this->Form->end();
?>
@ -13,15 +18,17 @@
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<?php foreach ($options as $k => &$option): ?>
<tr id="field_<?php echo h($k); ?>" style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitTagForm('<?php echo h($event_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>"><?php echo h($option); ?></td>
<tr style="border-top:1px solid black;" class="templateChoiceButton" id="field_<?php echo h($k); ?>">
<?php if (isset($attributeTag)): ?>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitAttributeTagForm('<?php echo h($object_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>"><?php echo h($option); ?></td>
<?php else: ?>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitTagForm('<?php echo h($object_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>"><?php echo h($option); ?></td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id);?>', 'tags', 'selectTaxonomy');" title="Select Taxonomy">Back to Taxonomy Selection</td>
</tr>
</table>
</div>
<div class="popover-back useCursorPointer" onClick="getPopup('<?php echo h($object_id); if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTaxonomy');" title="Select Taxonomy">Back to Taxonomy Selection</div>
<div class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();">Cancel</div>
</div>
<script type="text/javascript">
@ -30,7 +37,7 @@
resizePopoverBody();
$("#filterField").focus();
});
$('#filterField').keyup(function() {
var filterString = $("#filterField").val().toLowerCase();
$.each(tags, function(index, value) {
@ -41,7 +48,6 @@
}
});
});
$(window).resize(function() {
resizePopoverBody();
});

View File

@ -4,18 +4,18 @@
<table style="width:100%;">
<?php if ($favourites): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/favourites', 'tags', 'selectTag');">Favourite Tags</td>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/favourites<?php if (isset($attributeTag)) echo '/true' ?>', 'tags', 'selectTag');">Favourite Tags</td>
</tr>
<?php endif;?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/0', 'tags', 'selectTag');">Custom Tags</td>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/0<?php if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');">Custom Tags</td>
</tr>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/all', 'tags', 'selectTag');">All Tags</td>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/all<?php if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');">All Tags</td>
</tr>
<?php foreach ($options as $k => &$option): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($event_id); ?>/<?php echo h($k);?>', 'tags', 'selectTag');">Taxonomy Library: <?php echo h($option); ?></td>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/<?php echo h($k); if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');">Taxonomy Library: <?php echo h($option); ?></td>
</tr>
<?php endforeach; ?>
</table>

View File

@ -32,6 +32,7 @@
<th>Restricted to</th>
<th>Taxonomy</th>
<th>Tagged events</th>
<th>Tagged attributes</th>
<th>Favourite</th>
<?php if ($isAclTagEditor): ?>
<th class="actions"><?php echo __('Actions');?></th>
@ -59,6 +60,7 @@ foreach ($list as $item): ?>
&nbsp;
</td>
<td class="shortish"><?php echo h($item['Tag']['count']); ?>&nbsp;</td>
<td class="shortish"><a href="<?php echo $baseurl . "/attributes/search/attributetag:" . $item['Tag']['id']; ?>"><?php echo h($item['Tag']['attribute_count']); ?></a> </td>
<td class="short" id ="checkbox_row_<?php echo h($item['Tag']['id']);?>">
<input id="checkBox_<?php echo h($item['Tag']['id']); ?>" type="checkbox" onClick="toggleSetting(event, 'favourite_tag', '<?php echo h($item['Tag']['id']); ?>')" <?php echo $item['Tag']['favourite'] ? 'checked' : ''; ?>/>
</td>

View File

@ -73,6 +73,7 @@
<th><?php echo $this->Paginator->sort('tag');?></th>
<th><?php echo $this->Paginator->sort('expanded');?></th>
<th><?php echo $this->Paginator->sort('events');?></th>
<th><?php echo $this->Paginator->sort('attributes');?></th>
<th><?php echo $this->Paginator->sort('tag');?></th>
<th>Action</th>
</tr><?php
@ -97,6 +98,17 @@
?>
</td>
<td class="short">
<?php
if ($item['existing_tag']):
?>
<a href='<?php echo $baseurl."/attributes/search/attributetag:". h($item['existing_tag']['Tag']['id']);?>'><?php echo count($item['existing_tag']['AttributeTag']);?></a>
<?php
else:
echo 'N/A';
endif;
?>
</td>
<td class="short">
<?php
if ($item['existing_tag']):
$url = $baseurl . '/events/index/searchtag:' . h($item['existing_tag']['Tag']['id']);

View File

@ -1,9 +1,9 @@
<div class="threads view">
<h3><?php
if (isset($event_id)) {
echo '<a href="' . $baseurl . '/events/view/' . $event_id . '">' . h($thread_title) . '</a>';
echo '<a href="' . $baseurl . '/events/view/' . $event_id . '">' . h($thread['Thread']['title']) . '</a>';
} else {
echo h($thread_title);
echo h($thread['Thread']['title']);
}
?></h3>
<?php

View File

@ -68,13 +68,13 @@
<div class="clear"><span onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;">Fetch GPG key</span></div>
<?php
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => 'SMIME key', 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => 'Paste the user\'s SMIME public key in PEM format here.'));
echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published', 'type' => 'checkbox'));
echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests', 'type' => 'checkbox'));
echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published', 'type' => 'checkbox', 'checked' => true));
echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests', 'type' => 'checkbox', 'checked' => true));
?>
<div class="clear"></div>
<?php
echo $this->Form->input('disabled', array('label' => 'Disable this user account'));
echo $this->Form->input('notify', array('label' => 'Send credentials automatically', 'type' => 'checkbox', 'checked' => true));
?>
</fieldset>
<?php

View File

@ -1,7 +1,7 @@
<div class="events">
<?php echo $this->Form->create('User');?>
<fieldset>
<legend>Filter Event Index</legend>
<legend>Filter User Index</legend>
<div class="overlay_spacing">
<?php
echo $this->Form->input('rule', array(

View File

@ -103,7 +103,7 @@ if (h($user['User']['change_pw']) == 1) {
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
url: '<?php echo $baseurl . "/events/index/searchemail:" . h($user['User']['email']); ?>',
url: '<?php echo $baseurl . "/events/index/searchemail:" . urlencode(h($user['User']['email'])); ?>',
type:'GET',
beforeSend: function (XMLHttpRequest) {
$(".loading").show();

View File

@ -5,38 +5,38 @@
?>
<div class = "index">
<h2>Statistics</h2>
<?php
<?php
echo $this->element('Users/statisticsMenu');
?>
<p>Some statistics about this instance. The changes since the beginning of this month are noted in brackets wherever applicable</p>
<div style="width:250px;">
<dl>
<dt>Events</dt>
<dd><?php echo h($stats[0]);
if ($stats[1]) echo ' <span style="color:green">(+' . h($stats[1]) . ')</span>&nbsp;';
<dd><?php echo h($stats['event_count']);
if ($stats['event_count_month']) echo ' <span style="color:green">(+' . h($stats['event_count_month']) . ')</span>&nbsp;';
else echo ' <span style="color:red">(0)</span>&nbsp;';?>
</dd>
<dt><?php echo 'Attributes'; ?></dt>
<dd><?php echo h($stats[2]);
if ($stats[1]) echo ' <span style="color:green">(+' . h($stats[3]) . ')</span>&nbsp;';
<dd><?php echo h($stats['attribute_count']);
if ($stats['event_count_month']) echo ' <span style="color:green">(+' . h($stats['attribute_count_month']) . ')</span>&nbsp;';
else echo ' <span style="color:red">(0)</span>&nbsp;';?>
</dd>
<dt><?php echo 'Correlations found'; ?></dt>
<dd><?php echo h($stats[4]); ?>&nbsp;</dd>
<dd><?php echo h($stats['correlation_count']); ?>&nbsp;</dd>
<dt><?php echo 'Proposals active'; ?></dt>
<dd><?php echo h($stats[5]); ?>&nbsp;</dd>
<dd><?php echo h($stats['proposal_count']); ?>&nbsp;</dd>
<dt><?php echo 'Users'; ?></dt>
<dd><?php echo h($stats[6]); ?>&nbsp;</dd>
<dd><?php echo h($stats['user_count']); ?>&nbsp;</dd>
<dt><?php echo 'Organisations'; ?></dt>
<dd><?php echo h($stats[7]); ?>&nbsp;</dd>
<dd><?php echo h($stats['org_count']); ?>&nbsp;</dd>
<dt><?php echo 'Discussion threads'; ?></dt>
<dd><?php echo h($stats[8]);
if ($stats[9]) echo ' <span style="color:green">(+' . h($stats[9]) . ')</span>&nbsp;';
<dd><?php echo h($stats['thread_count']);
if ($stats['thread_count_month']) echo ' <span style="color:green">(+' . h($stats['thread_count_month']) . ')</span>&nbsp;';
else echo ' <span style="color:red">(0)</span>&nbsp;';?>
</dd>
<dt><?php echo 'Discussion posts'; ?></dt>
<dd><?php echo h($stats[10]);
if ($stats[11]) echo ' <span style="color:green">(+' . h($stats[11]) . ')</span>&nbsp;';
<dd><?php echo h($stats['post_count']);
if ($stats['post_count_month']) echo ' <span style="color:green">(+' . h($stats['post_count_month']) . ')</span>&nbsp;';
else echo ' <span style="color:red">(0)</span>&nbsp;';?>
</dd>
</dl>

View File

@ -1,5 +1,6 @@
<div class="whitelist index">
<h2>Import Whitelist</h2>
<h2>Signature Whitelist</h2>
<p>Regex entries (in the standard php regex /{regex}/{modifier} format) entered below will restrict matching attributes from being included in the IDS flag sensitive exports (such as NIDS exports).</p>
<div class="pagination">
<ul>
<?php

View File

@ -1,5 +1,6 @@
<div class="whitelist index">
<h2>Signature Whitelist</h2>
<p>Regex entries (in the standard php regex /{regex}/{modifier} format) entered below will restrict matching attributes from being included in the IDS flag sensitive exports (such as NIDS exports).</p>
<div class="pagination">
<ul>
<?php

19
app/composer.license Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

BIN
app/composer.phar Normal file

Binary file not shown.

@ -1 +1 @@
Subproject commit c38f62ae12eb18a77390727df754aab3894a53ed
Subproject commit f3f5b3b3ac4a7e453a2a25adcb0342a0454c1155

@ -1 +1 @@
Subproject commit 0e320249de47f57e48f318709d1179fde4e0ea9c
Subproject commit 14cf779bf348adbe29926b2527f0a8d394515fa2

Some files were not shown because too many files have changed in this diff Show More