mirror of https://github.com/MISP/MISP
Merge branch '2.4' into issues_1643
commit
f35d247930
|
@ -137,14 +137,8 @@ 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:
|
||||
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
8/ 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
|
||||
|
|
|
@ -183,11 +183,6 @@ 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:
|
||||
|
||||
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
|
@ -303,4 +298,3 @@ sudo ldconfig
|
|||
|
||||
## install pyzmq
|
||||
sudo pip install pyzmq
|
||||
|
||||
|
|
|
@ -128,14 +128,8 @@ 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:
|
||||
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
8/ 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
|
||||
|
|
|
@ -184,11 +184,6 @@ 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:
|
||||
|
||||
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
|
|
|
@ -29,12 +29,15 @@ CREATE TABLE IF NOT EXISTS `attributes` (
|
|||
`timestamp` int(11) NOT NULL DEFAULT 0,
|
||||
`distribution` tinyint(4) NOT NULL DEFAULT 0,
|
||||
`sharing_group_id` int(11) NOT NULL,
|
||||
`comment` text COLLATE utf8_bin NOT NULL,
|
||||
`comment` text COLLATE utf8_bin,
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`disable_correlation` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `event_id` (`event_id`),
|
||||
INDEX `value1` (`value1`(255)),
|
||||
INDEX `value2` (`value2`(255)),
|
||||
INDEX `type` (`type`),
|
||||
INDEX `category` (`category`),
|
||||
INDEX `sharing_group_id` (`sharing_group_id`),
|
||||
UNIQUE INDEX `uuid` (`uuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
@ -137,6 +140,7 @@ CREATE TABLE IF NOT EXISTS `events` (
|
|||
`locked` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`threat_level_id` int(11) NOT NULL,
|
||||
`publish_timestamp` int(11) NOT NULL DEFAULT 0,
|
||||
`disable_correlation` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `uuid` (`uuid`),
|
||||
FULLTEXT INDEX `info` (`info`(255)),
|
||||
|
@ -206,14 +210,26 @@ CREATE TABLE IF NOT EXISTS `feeds` (
|
|||
`provider` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`url` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`rules` text COLLATE utf8_bin DEFAULT NULL,
|
||||
`enabled` BOOLEAN NOT NULL,
|
||||
`distribution` tinyint(4) NOT NULL,
|
||||
`enabled` tinyint(1) DEFAULT 0,
|
||||
`distribution` tinyint(4) NOT NULL DEFAULT 0,
|
||||
`sharing_group_id` int(11) NOT NULL DEFAULT 0,
|
||||
`tag_id` int(11) NOT NULL DEFAULT 0,
|
||||
`default` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
`default` tinyint(1) DEFAULT 0,
|
||||
`source_format` varchar(255) COLLATE utf8_bin DEFAULT 'misp',
|
||||
`fixed_event` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`delta_merge` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`event_id` int(11) NOT NULL DEFAULT 0,
|
||||
`publish` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`override_ids` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`settings` text NOT NULL DEFAULT '',
|
||||
`input_source` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "network",
|
||||
`delete_local_file` tinyint(1) DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `input_source` (`input_source`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
|
||||
-- -------------------------------------------------------
|
||||
|
||||
--
|
||||
|
@ -330,9 +346,9 @@ CREATE TABLE IF NOT EXISTS `logs` (
|
|||
`model_id` int(11) NOT NULL,
|
||||
`action` varchar(20) COLLATE utf8_bin NOT NULL,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`change` text CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
`email` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`org` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`change` text COLLATE utf8_bin NOT NULL DEFAULT "",
|
||||
`email` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "",
|
||||
`org` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "",
|
||||
`description` text CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
@ -475,12 +491,12 @@ CREATE TABLE IF NOT EXISTS `servers` (
|
|||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `shadow_attributes`
|
||||
-- Table structure for table ``)ributes`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `shadow_attributes` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`old_id` int(11) NOT NULL,
|
||||
`old_id` int(11) DEFAULT 0,
|
||||
`event_id` int(11) NOT NULL,
|
||||
`type` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
|
||||
`category` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
|
@ -496,6 +512,7 @@ CREATE TABLE IF NOT EXISTS `shadow_attributes` (
|
|||
`deleted` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`timestamp` int(11) NOT NULL DEFAULT 0,
|
||||
`proposal_to_delete` BOOLEAN NOT NULL DEFAULT 0,
|
||||
`disable_correlation` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `event_id` (`event_id`),
|
||||
INDEX `event_uuid` (`event_uuid`),
|
||||
|
@ -503,7 +520,9 @@ CREATE TABLE IF NOT EXISTS `shadow_attributes` (
|
|||
INDEX `uuid` (`uuid`),
|
||||
INDEX `old_id` (`old_id`),
|
||||
INDEX `value1` (`value1`(255)),
|
||||
INDEX `value2` (`value2`(255))
|
||||
INDEX `value2` (`value2`(255)),
|
||||
INDEX `type` (`type`),
|
||||
INDEX `category` (`category`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
@ -601,15 +620,21 @@ CREATE TABLE `sharing_groups` (
|
|||
--
|
||||
|
||||
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,
|
||||
org_id int(11) NOT NULL,
|
||||
date_sighting bigint(20) NOT NULL,
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`attribute_id` int(11) NOT NULL,
|
||||
`event_id` int(11) NOT NULL,
|
||||
`org_id` int(11) NOT NULL,
|
||||
`date_sighting` bigint(20) NOT NULL,
|
||||
`uuid` varchar(255) COLLATE utf8_bin DEFAULT "",
|
||||
`source` varchar(255) COLLATE utf8_bin DEFAULT "",
|
||||
`type` int(11) DEFAULT 0,
|
||||
PRIMARY KEY (id),
|
||||
INDEX attribute_id (attribute_id),
|
||||
INDEX event_id (event_id),
|
||||
INDEX org_id (org_id)
|
||||
INDEX `attribute_id` (`attribute_id`),
|
||||
INDEX `event_id` (`event_id`),
|
||||
INDEX `org_id` (`org_id`),
|
||||
INDEX `uuid` (`uuid`),
|
||||
INDEX `source` (`source`),
|
||||
INDEX `type` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
@ -624,6 +649,7 @@ CREATE TABLE IF NOT EXISTS `tags` (
|
|||
`colour` varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||
`exportable` tinyint(1) NOT NULL,
|
||||
`org_id` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`hide_tag` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
FULLTEXT INDEX `name` (`name`),
|
||||
INDEX `org_id` (`org_id`)
|
||||
|
@ -924,7 +950,7 @@ CREATE TABLE IF NOT EXISTS `whitelist` (
|
|||
--
|
||||
|
||||
INSERT INTO `admin_settings` (`id`, `setting`, `value`) VALUES
|
||||
(1, 'db_version', '2.4.51');
|
||||
(1, 'db_version', '2.4.66');
|
||||
|
||||
INSERT INTO `feeds` (`id`, `provider`, `name`, `url`, `distribution`, `default`, `enabled`) VALUES
|
||||
(1, 'CIRCL', 'CIRCL OSINT Feed', 'https://www.circl.lu/doc/misp/feed-osint', 3, 1, 0),
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/var/www/MISP/app/tmp/logs/resque-*-error.log {
|
||||
rotate 30
|
||||
dateext
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
weekly
|
||||
copytruncate
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
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 };
|
|
@ -176,14 +176,8 @@ 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:
|
||||
|
||||
cp INSTALL/misp.logrotate /etc/logrotate.d/misp
|
||||
|
||||
9/ MISP configuration
|
||||
8/ 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
|
||||
|
|
|
@ -193,24 +193,8 @@ 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:
|
||||
|
||||
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
|
||||
8/ 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
|
||||
|
|
2
PyMISP
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit 26a8f4c66230c0df10b2f9637e53ee1542a26f40
|
||||
Subproject commit a81f6b5c15e2effbc0b6118f1e1524b0950a576c
|
|
@ -1 +1 @@
|
|||
{"major":2, "minor":4, "hotfix":65}
|
||||
{"major":2, "minor":4, "hotfix":66}
|
||||
|
|
|
@ -69,19 +69,25 @@ $config = array(
|
|||
// Uncomment the following to enable client SSL certificate authentication
|
||||
/*
|
||||
'CertAuth' =>
|
||||
array(
|
||||
'ca' => array('FIRST.Org'), // allowed CAs
|
||||
'caId' => 'O', // which attribute will be used to verify the CA
|
||||
'userModel' => 'User', // name of the User class to check if user exists
|
||||
'userModelKey' => 'nids_sid', // User field that will be used for querying
|
||||
'map' => array( // maps client certificate attributes to User properties
|
||||
array(
|
||||
|
||||
// CA
|
||||
'ca' => array('FIRST.Org'), // List of CAs authorized
|
||||
'caId' => 'O', // Certificate field used to verify the CA. In this example, the field O (organization) of the client certificate has to equal to 'FIRST.Org' in order to validate the CA
|
||||
|
||||
// User/client configuration
|
||||
'userModel' => 'User', // name of the User class (MISP class) to check if the user exists
|
||||
'userModelKey' => 'email', // User field that will be used for querying. In this example, the field email of the MISP accounts will be used to search if the user exists.
|
||||
'map' => array( // maps client certificate attributes to User properties. This map will be used as conditions to find if the user exists. In this example, the client certificate fields 'O' (organization) and 'emailAddress' have to match with the MISP fields 'org' and 'email' to validate the user.
|
||||
'O' => 'org',
|
||||
'emailAddress' => 'email',
|
||||
),
|
||||
),
|
||||
|
||||
// Synchronization/RestAPI
|
||||
'syncUser' => true, // should the User be synchronized with an external REST API
|
||||
'userDefaults' => array( // default user attributes, only used when creating new users
|
||||
'role_id' => 4,
|
||||
),
|
||||
'userDefaults' => array( // default user attributes, only used when creating new users. By default, new users are "Read only" users (role_id: 6).
|
||||
'role_id' => 6,
|
||||
),
|
||||
'restApi' => array( // API parameters
|
||||
'url' => 'https://example.com/data/users', // URL to query
|
||||
'headers' => array(), // additional headers, used for authentication
|
||||
|
@ -93,7 +99,7 @@ $config = array(
|
|||
'pgp_public' => 'gpgkey',
|
||||
),
|
||||
),
|
||||
'userDefaults' => array('role_id' => 3), // default attributes for new users
|
||||
'userDefaults' => array('role_id' => 6), // default attributes for new users. By default, new users are "Read only" users (role_id: 6).
|
||||
),
|
||||
*/
|
||||
/*
|
||||
|
|
|
@ -46,9 +46,9 @@ class AppController extends Controller {
|
|||
|
||||
public $helpers = array('Utility');
|
||||
|
||||
private $__jsVersion = '2.4.62';
|
||||
private $__jsVersion = '2.4.66';
|
||||
public $pyMispVersion = '2.4.65';
|
||||
public $phpmin = '5.5.9';
|
||||
public $phpmin = '5.6.5';
|
||||
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
|
||||
|
|
|
@ -286,8 +286,12 @@ class ACLComponent extends Component {
|
|||
),
|
||||
'sightings' => array(
|
||||
'add' => array('perm_add'),
|
||||
'advanced' => array('perm_add'),
|
||||
'delete' => array('perm_add'),
|
||||
'index' => array('*')
|
||||
'index' => array('*'),
|
||||
'listSightings' => array('perm_add'),
|
||||
'quickDelete' => array('perm_add'),
|
||||
'viewSightings' => array('perm_add')
|
||||
),
|
||||
'tags' => array(
|
||||
'add' => array('perm_tag_editor'),
|
||||
|
|
|
@ -748,6 +748,8 @@ class EventsController extends AppController {
|
|||
$this->set('attributeFilter', isset($this->params['named']['attributeFilter']) ? $this->params['named']['attributeFilter'] : 'all');
|
||||
$this->disableCache();
|
||||
$this->layout = 'ajax';
|
||||
$this->loadModel('Sighting');
|
||||
$this->set('sightingTypes', $this->Sighting->type);
|
||||
$this->set('currentUri', $this->params->here);
|
||||
$this->render('/Elements/eventattribute');
|
||||
}
|
||||
|
@ -859,6 +861,8 @@ class EventsController extends AppController {
|
|||
}
|
||||
$this->set('contributors', $contributors);
|
||||
$this->set('typeGroups', array_keys($this->Event->Attribute->typeGroupings));
|
||||
$this->loadModel('Sighting');
|
||||
$this->set('sightingTypes', $this->Sighting->type);
|
||||
}
|
||||
|
||||
public function view($id = null, $continue=false, $fromEvent=null) {
|
||||
|
@ -3093,8 +3097,6 @@ 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');
|
||||
|
|
|
@ -18,42 +18,110 @@ class SightingsController extends AppController {
|
|||
// takes an attribute ID or UUID
|
||||
public function add($id = false) {
|
||||
if (!$this->userRole['perm_add']) throw new MethodNotAllowedException('You are not authorised to add sightings data as you don\'t have write access.');
|
||||
if (!$this->request->is('post')) throw new MethodNotAllowedException('This action can only be accessed via a post request.');
|
||||
$now = time();
|
||||
$values = false;
|
||||
$timestamp = false;
|
||||
$error = false;
|
||||
if ($id === 'stix') {
|
||||
$result = $this->Sighting->handleStixSighting(file_get_contents('php://input'));
|
||||
if ($result['success']) {
|
||||
$result['data'] = json_decode($result['data'], true);
|
||||
$timestamp = isset($result['data']['timestamp']) ? strtotime($result['data']['timestamp']) : $now;
|
||||
if (isset($result['data']['values'])) $values = $result['data']['values'];
|
||||
else $error = 'No valid values found could be extracted from the sightings document.';
|
||||
} $error = $result['message'];
|
||||
} else {
|
||||
if (isset($this->request->data['request'])) $this->request->data = $this->request->data['request'];
|
||||
if (isset($this->request->data['Sighting'])) $this->request->data = $this->request->data['Sighting'];
|
||||
$timestamp = isset($this->request->data['timestamp']) ? $this->request->data['timestamp'] : $now;
|
||||
if (isset($this->request->data['value'])) $this->request->data['values'] = array($this->request->data['value']);
|
||||
$values = isset($this->request->data['values']) ? $this->request->data['values'] : false;
|
||||
if (!$id && isset($this->request->data['id'])) $id = $this->request->data['id'];
|
||||
}
|
||||
if (!$error) $result = $this->Sighting->saveSightings($id, $values, $timestamp, $this->Auth->user());
|
||||
if ($result == 0) $error = 'No valid attributes found that would match the sighting criteria.';
|
||||
|
||||
if ($this->request->is('ajax')) {
|
||||
if ($error) {
|
||||
$error_message = 'Could not add the Sighting. Reason: ' . $error;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $error_message)), 'status' => 200));
|
||||
if ($this->request->is('post')) {
|
||||
$now = time();
|
||||
$values = false;
|
||||
$timestamp = false;
|
||||
$error = false;
|
||||
if ($id === 'stix') {
|
||||
$result = $this->Sighting->handleStixSighting(file_get_contents('php://input'));
|
||||
if ($result['success']) {
|
||||
$result['data'] = json_decode($result['data'], true);
|
||||
$timestamp = isset($result['data']['timestamp']) ? strtotime($result['data']['timestamp']) : $now;
|
||||
$type = '0';
|
||||
$source = '';
|
||||
if (isset($result['data']['values'])) $values = $result['data']['values'];
|
||||
else $error = 'No valid values found could be extracted from the sightings document.';
|
||||
} $error = $result['message'];
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result . ' sighting' . (($result == 1) ? '' : 's') . ' added.')), 'status' => 200));
|
||||
if (isset($this->request->data['request'])) $this->request->data = $this->request->data['request'];
|
||||
if (isset($this->request->data['Sighting'])) $this->request->data = $this->request->data['Sighting'];
|
||||
if (!empty($this->request->data['date']) && !empty($this->request->data['time'])) {
|
||||
$timestamp = DateTime::createFromFormat('Y-m-d:H:i:s', $this->request->data['date'] . ':' . $this->request->data['time']);
|
||||
$timestamp = $timestamp->getTimestamp();
|
||||
} else {
|
||||
$timestamp = isset($this->request->data['timestamp']) ? $this->request->data['timestamp'] : $now;
|
||||
}
|
||||
if (isset($this->request->data['value'])) $this->request->data['values'] = array($this->request->data['value']);
|
||||
$values = isset($this->request->data['values']) ? $this->request->data['values'] : false;
|
||||
if (!$id && isset($this->request->data['id'])) $id = $this->request->data['id'];
|
||||
$type = isset($this->request->data['type']) ? $this->request->data['type'] : '0';
|
||||
$source = isset($this->request->data['source']) ? trim($this->request->data['source']) : '';
|
||||
}
|
||||
if (!$error) $result = $this->Sighting->saveSightings($id, $values, $timestamp, $this->Auth->user(), $type, $source);
|
||||
if ($result == 0) $error = 'No valid attributes found that would match the sighting criteria.';
|
||||
|
||||
if ($this->request->is('ajax')) {
|
||||
if ($error) {
|
||||
$error_message = 'Could not add the Sighting. Reason: ' . $error;
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $error_message)), 'status' => 200));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result . ' ' . $this->Sighting->type[$type] . (($result == 1) ? '' : 's') . ' added.')), 'status' => 200));
|
||||
}
|
||||
} else {
|
||||
if ($error) {
|
||||
return $this->RestResponse->saveFailResponse('Sighting', 'add', $id, $error);
|
||||
} else {
|
||||
return $this->RestResponse->saveSuccessResponse('Sighting', 'add', $id, false, $result . ' ' . $this->Sighting->type[$type] . (($result == 1) ? '' : 's') . ' successfuly added.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($error) {
|
||||
return $this->RestResponse->saveFailResponse('Sighting', 'add', $id, $error);
|
||||
if (!$this->request->is('ajax')) {
|
||||
throw new MethodNotAllowedException('This method is only accessible via POST requests and ajax GET requests.');
|
||||
} else {
|
||||
return $this->RestResponse->saveSuccessResponse('Sighting', 'add', $id, false, $result . ' sighting' . (($result == 1) ? '' : 's') . ' successfuly added.');
|
||||
$this->layout = false;
|
||||
$this->loadModel('Attribute');
|
||||
$attributes = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id)));
|
||||
if (empty($attributes)) {
|
||||
throw new MethodNotAllowedExeption('Invalid Attribute.');
|
||||
}
|
||||
$this->set('event_id', $attributes[0]['Attribute']['event_id']);
|
||||
$this->set('id', $id);
|
||||
$this->render('ajax/add_sighting');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function advanced($id) {
|
||||
if (empty($id)) {
|
||||
throw new MethodNotAllowedException('Invalid attribute.');
|
||||
}
|
||||
$input_id = $id;
|
||||
$id = $this->Sighting->explodeIdList($id);
|
||||
$this->loadModel('Attribute');
|
||||
$attributes = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id)));
|
||||
if (empty($attributes)) {
|
||||
throw new MethodNotAllowedException('Invalid attribute.');
|
||||
}
|
||||
$this->set('id', $input_id);
|
||||
$this->render('/Sightings/ajax/advanced');
|
||||
}
|
||||
|
||||
public function quickDelete($id, $rawId, $context) {
|
||||
if (!$this->userRole['perm_modify_org']) throw new MethodNotAllowedException('You are not authorised to remove sightings data as you don\'t have permission to modify your organisation\'s data.');
|
||||
if (!$this->request->is('post')) {
|
||||
$this->set('id', $id);
|
||||
$sighting = $this->Sighting->find('first', array('conditions' => array('Sighting.id' => $id), 'recursive' => -1, 'fields' => array('Sighting.attribute_id')));
|
||||
$this->set('rawId', $rawId);
|
||||
$this->set('context', $context);
|
||||
$this->render('ajax/quickDeleteConfirmationForm');
|
||||
} else {
|
||||
if (!isset($id)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => 'Invalid request.')), 'status' => 200));
|
||||
} else {
|
||||
$sighting = $this->Sighting->find('first', array('conditions' => array('Sighting.id' => $id), 'recursive' => -1));
|
||||
if (empty($sighting)) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => 'Invalid sighting.')), 'status' => 200));
|
||||
}
|
||||
if (!$this->_isSiteAdmin() && $sighting['Sighting']['org_id'] != $this->Auth->user('org_id')) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => 'Invalid sighting.')), 'status' => 200));
|
||||
}
|
||||
$result = $this->Sighting->delete($id);
|
||||
if ($result) {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Sighting deleted.')), 'status' => 200));
|
||||
} else {
|
||||
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => 'Sighting could not be deleted')), 'status' => 200));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,4 +170,107 @@ class SightingsController extends AppController {
|
|||
}
|
||||
return $this->RestResponse->viewData($sightings);
|
||||
}
|
||||
|
||||
public function listSightings($id, $context = 'attribute', $org_id = false) {
|
||||
$this->loadModel('Event');
|
||||
$rawId = $id;
|
||||
$id = $this->Sighting->explodeIdList($id);
|
||||
if ($context === 'attribute') {
|
||||
$object = $this->Event->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id, 'Attribute.deleted' => 0)));
|
||||
} else {
|
||||
// let's set the context to event here, since we reuse the variable later on for some additional lookups.
|
||||
// Passing $context = 'org' could have interesting results otherwise...
|
||||
$context = 'event';
|
||||
$object = $this->Event->fetchEvent($this->Auth->user(), $options = array('eventid' => $id, 'metadata' => true));
|
||||
}
|
||||
if (empty($object)) {
|
||||
throw new MethodNotAllowedException('Invalid object.');
|
||||
}
|
||||
$conditions = array(
|
||||
'Sighting.' . $context . '_id' => $id
|
||||
);
|
||||
if ($org_id) {
|
||||
$conditions[] = array('Sighting.org_id' => $org_id);
|
||||
}
|
||||
$sightings = $this->Sighting->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'recursive' => -1,
|
||||
'contain' => array('Organisation.name'),
|
||||
'order' => array('Sighting.date_sighting DESC')
|
||||
));
|
||||
$this->set('org_id', $org_id);
|
||||
$this->set('rawId', $rawId);
|
||||
$this->set('context', $context);
|
||||
$this->set('types', array('Sighting', 'False-positive', 'Expiration'));
|
||||
$this->set('sightings', $sightings);
|
||||
$this->layout = false;
|
||||
$this->render('ajax/list_sightings');
|
||||
}
|
||||
|
||||
public function viewSightings($id, $context = 'attribute') {
|
||||
$this->loadModel('Event');
|
||||
$id = $this->Sighting->explodeIdList($id);
|
||||
if ($context === 'attribute') {
|
||||
$attribute_id = $id;
|
||||
$object = $this->Event->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id, 'Attribute.deleted' => 0)));
|
||||
if (empty($object)) {
|
||||
throw new MethodNotAllowedException('Invalid object.');
|
||||
}
|
||||
$eventIds = array();
|
||||
foreach ($object as $k => $v) {
|
||||
$eventIds[] = $v['Attribute']['event_id'];
|
||||
}
|
||||
$events = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $eventIds));
|
||||
} else {
|
||||
$attribute_id = false;
|
||||
// let's set the context to event here, since we reuse the variable later on for some additional lookups.
|
||||
// Passing $context = 'org' could have interesting results otherwise...
|
||||
$context = 'event';
|
||||
$events = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id));
|
||||
|
||||
}
|
||||
if (empty($events)) {
|
||||
throw new MethodNotAllowedException('Invalid object.');
|
||||
}
|
||||
$results = array();
|
||||
$raw = array();
|
||||
foreach ($events as $event) {
|
||||
$raw = array_merge($raw, $this->Sighting->attachToEvent($event, $this->Auth->user(), $attribute_id));
|
||||
}
|
||||
foreach ($raw as $sighting) {
|
||||
$results[$sighting['type']][date('Ymd', $sighting['date_sighting'])][] = $sighting;
|
||||
}
|
||||
$tsv = 'date\tSighting\tFalse-positive\n';
|
||||
$dataPoints = array();
|
||||
$startDate = (date('Ymd') - 3);
|
||||
$details = array();
|
||||
foreach ($results as $type => $data) {
|
||||
foreach ($data as $date => $sighting) {
|
||||
if ($date < $startDate) {
|
||||
$startDate = $date;
|
||||
}
|
||||
$temp = array();
|
||||
foreach ($sighting as $sightingInstance) {
|
||||
if (!isset($sightingInstance['Organisation']['name'])) {
|
||||
$org = 'Anonymised';
|
||||
} else {
|
||||
$org = $sightingInstance['Organisation']['name'];
|
||||
}
|
||||
$temp[$org] = isset($temp[$org]) ? $temp[$org] + 1 : 1;
|
||||
}
|
||||
$dataPoints[$date][$type] = array('count' => count($sighting), 'details' => $temp);
|
||||
}
|
||||
}
|
||||
for ($i = $startDate; $i < date('Ymd') + 1; $i++) {
|
||||
if (checkdate(substr($i, 4, 2), substr($i, 6, 2), substr($i, 0, 4))) {
|
||||
$tsv .= $i . '\t' . (isset($dataPoints[$i][0]['count']) ? $dataPoints[$i][0]['count'] : 0) . '\t' . (isset($dataPoints[$i][1]['count']) ? $dataPoints[$i][1]['count'] : 0) . '\n';
|
||||
$details[$i][0] = isset($dataPoints[$i][0]['details']) ? $dataPoints[$i][0]['details'] : array();
|
||||
$details[$i][1] = isset($dataPoints[$i][1]['details']) ? $dataPoints[$i][1]['details'] : array();
|
||||
}
|
||||
}
|
||||
$this->set('tsv', $tsv);
|
||||
$this->set('results', $results);
|
||||
$this->layout = 'ajax';
|
||||
$this->render('ajax/view_sightings');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,21 +22,24 @@ class ThreadsController extends AppController {
|
|||
$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));
|
||||
if ($thread_id) {
|
||||
$thread_id = $thread_id['Thread']['id'];
|
||||
} 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.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($array(), $this->response->type());
|
||||
}
|
||||
$thread_id = false;
|
||||
}
|
||||
}
|
||||
if ($thread_id) {
|
||||
$post_id = false;
|
||||
if (isset($this->passedArgs['post_id'])) $post_id = $this->passedArgs['post_id'];
|
||||
$response = $this->__view($thread_id, false, $post_id);
|
||||
if ($this->_isRest()) {
|
||||
return $response;
|
||||
}
|
||||
} else {
|
||||
throw new NotFoundException('Invalid Event.');
|
||||
throw new NotFoundException('Invalid Thread.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +83,7 @@ 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'])) {
|
||||
|
|
|
@ -1049,7 +1049,7 @@ class UsersController extends AppController {
|
|||
// shows some statistics about the instance
|
||||
public function statistics($page = 'data') {
|
||||
$this->set('page', $page);
|
||||
$this->set('pages', array('data' => 'Usage data', 'orgs' => 'Organisations', 'tags' => 'Tags', 'attributehistogram' => 'Attribute histogram'));
|
||||
$this->set('pages', array('data' => 'Usage data', 'orgs' => 'Organisations', 'tags' => 'Tags', 'attributehistogram' => 'Attribute histogram', 'sightings' => 'Sightings toplists'));
|
||||
$result = array();
|
||||
if ($page == 'data') {
|
||||
$result = $this->__statisticsData($this->params['named']);
|
||||
|
@ -1063,6 +1063,8 @@ class UsersController extends AppController {
|
|||
} else {
|
||||
$this->render('statistics_histogram');
|
||||
}
|
||||
} else if ($page == 'sightings') {
|
||||
$result = $this->__statisticsSightings($this->params['named']);
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $result;
|
||||
|
@ -1123,6 +1125,56 @@ class UsersController extends AppController {
|
|||
}
|
||||
}
|
||||
|
||||
private function __statisticsSightings($params = array()) {
|
||||
$this->loadModel('Sighting');
|
||||
$conditions = array('Sighting.org_id' => $this->Auth->user('org_id'));
|
||||
if (isset($params['timestamp'])) {
|
||||
$conditions['Sighting.date_sighting >'] = $params['timestamp'];
|
||||
}
|
||||
$sightings = $this->Sighting->find('all', array(
|
||||
'conditions' => $conditions,
|
||||
'fields' => array('Sighting.date_sighting', 'Sighting.type', 'Sighting.source', 'Sighting.event_id')
|
||||
));
|
||||
$data = array();
|
||||
$toplist = array();
|
||||
$eventids = array();
|
||||
foreach ($sightings as $k => $v) {
|
||||
if ($v['Sighting']['source'] == '') {
|
||||
$v['Sighting']['source'] = 'Undefined';
|
||||
}
|
||||
$v['Sighting']['type'] = array('sighting', 'false-positive', 'expiration')[$v['Sighting']['type']];
|
||||
if (isset($data[$v['Sighting']['source']][$v['Sighting']['type']])) {
|
||||
$data[$v['Sighting']['source']][$v['Sighting']['type']]++;
|
||||
} else {
|
||||
$data[$v['Sighting']['source']][$v['Sighting']['type']] = 1;
|
||||
}
|
||||
if (!isset($toplist[$v['Sighting']['source']])) {
|
||||
$toplist[$v['Sighting']['source']] = 1;
|
||||
} else {
|
||||
$toplist[$v['Sighting']['source']]++;
|
||||
}
|
||||
if (!isset($eventids[$v['Sighting']['source']][$v['Sighting']['type']])) {
|
||||
$eventids[$v['Sighting']['source']][$v['Sighting']['type']] = array();
|
||||
}
|
||||
if (!in_array($v['Sighting']['event_id'], $eventids[$v['Sighting']['source']][$v['Sighting']['type']])) {
|
||||
$eventids[$v['Sighting']['source']][$v['Sighting']['type']][] = $v['Sighting']['event_id'];
|
||||
}
|
||||
}
|
||||
arsort($toplist);
|
||||
if ($this->_isRest()) {
|
||||
$data = array(
|
||||
'toplist' => $toplist,
|
||||
'eventids' => $eventids
|
||||
);
|
||||
return $this->RestResponse->viewData($data, $this->response->type());
|
||||
} else {
|
||||
$this->set('eventids', $eventids);
|
||||
$this->set('toplist', $toplist);
|
||||
$this->set('data', $data);
|
||||
$this->render('statistics_sightings');
|
||||
}
|
||||
}
|
||||
|
||||
private function __statisticsOrgs($params = array()) {
|
||||
$this->loadModel('Organisation');
|
||||
$conditions = array();
|
||||
|
|
|
@ -8,7 +8,6 @@ class ComplexTypeTool {
|
|||
'/^h\[tt\]p/i' => 'http',
|
||||
'/\[\.\]/' => '.',
|
||||
'/\[dot\]/' => '.',
|
||||
'/\(dot\)/' => '.',
|
||||
'/\\\\\./' => '.',
|
||||
'/\.+/' => '.'
|
||||
);
|
||||
|
@ -210,6 +209,7 @@ class ComplexTypeTool {
|
|||
// 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);
|
||||
$port = substr($port[0], 1);
|
||||
} else {
|
||||
|
@ -217,13 +217,7 @@ class ComplexTypeTool {
|
|||
$inputRefangedNoPort = $inputRefanged;
|
||||
}
|
||||
// check for IP
|
||||
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 (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 (strpos($inputRefangedNoPort, '/')) {
|
||||
$temp = explode('/', $inputRefangedNoPort);
|
||||
if (count($temp) == 2) {
|
||||
|
|
|
@ -41,7 +41,7 @@ class AppModel extends Model {
|
|||
42 => false, 44 => false, 45 => false, 49 => true, 50 => false,
|
||||
51 => false, 52 => false, 55 => true, 56 => true, 57 => true,
|
||||
58 => false, 59 => false, 60 => false, 61 => false, 62 => false,
|
||||
63 => false, 64 => false, 65 => false
|
||||
63 => false, 64 => false, 65 => false, 66 => false
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -78,6 +78,12 @@ class AppModel extends Model {
|
|||
case '2.4.55':
|
||||
$this->updateDatabase('addSightings');
|
||||
break;
|
||||
case '2.4.66':
|
||||
$this->updateDatabase('2.4.66');
|
||||
$this->cleanCacheFiles();
|
||||
$this->Sighting = Classregistry::init('Sighting');
|
||||
$this->Sighting->addUuids();
|
||||
break;
|
||||
default:
|
||||
$this->updateDatabase($command);
|
||||
break;
|
||||
|
@ -557,8 +563,6 @@ class AppModel extends Model {
|
|||
$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";';
|
||||
|
@ -601,6 +605,18 @@ class AppModel extends Model {
|
|||
$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 '2.4.66':
|
||||
$sqlArray[] = 'ALTER TABLE shadow_attributes CHANGE old_id old_id int(11) DEFAULT 0;';
|
||||
$sqlArray[] = 'ALTER TABLE sightings ADD COLUMN uuid varchar(255) COLLATE utf8_bin DEFAULT "";';
|
||||
$sqlArray[] = 'ALTER TABLE sightings ADD COLUMN source varchar(255) COLLATE utf8_bin DEFAULT "";';
|
||||
$sqlArray[] = 'ALTER TABLE sightings ADD COLUMN type int(11) DEFAULT 0;';
|
||||
$indexArray[] = array('sightings', 'uuid');
|
||||
$indexArray[] = array('sightings', 'source');
|
||||
$indexArray[] = array('sightings', 'type');
|
||||
$indexArray[] = array('attributes', 'category');
|
||||
$indexArray[] = array('shadow_attributes', 'category');
|
||||
$indexArray[] = array('shadow_attributes', 'type');
|
||||
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;';
|
||||
|
@ -649,11 +665,14 @@ 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 (!empty($indexArray)) {
|
||||
if ($clean) $this->cleanCacheFiles();
|
||||
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();
|
||||
|
|
|
@ -1336,14 +1336,14 @@ class Attribute extends AppModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
$extraConditions = array();
|
||||
if (!empty($ipValues)) {
|
||||
$extraConditions = array('OR' => array(
|
||||
'Attribute.value1' => $ipValues,
|
||||
'Attribute.value2' => $ipValues
|
||||
));
|
||||
return $extraConditions;
|
||||
}
|
||||
return false;
|
||||
return $extraConditions;
|
||||
}
|
||||
|
||||
public function __afterSaveCorrelation($a, $full = false, $event = false) {
|
||||
|
|
|
@ -924,14 +924,8 @@ 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]);
|
||||
} else {
|
||||
unset($tag['org_id']);
|
||||
$event['Event']['Tag'][] = $tag['Tag'];
|
||||
}
|
||||
if (!$tag['Tag']['exportable']) unset($event['Event']['EventTag'][$kt]);
|
||||
}
|
||||
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'])) {
|
||||
|
@ -973,16 +967,6 @@ 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']);
|
||||
|
@ -1480,10 +1464,6 @@ 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;
|
||||
}
|
||||
|
@ -2461,8 +2441,7 @@ class Event extends AppModel {
|
|||
'fields' => array('id', 'url', 'name')
|
||||
)
|
||||
),
|
||||
),
|
||||
'AttributeTag' => array('Tag')
|
||||
)
|
||||
),
|
||||
'EventTag' => array('Tag'),
|
||||
'Org' => array('fields' => array('id', 'uuid', 'name', 'local')),
|
||||
|
|
|
@ -655,20 +655,12 @@ 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;
|
||||
|
|
|
@ -28,19 +28,31 @@ class Sighting extends AppModel {
|
|||
),
|
||||
);
|
||||
|
||||
public $type = array(
|
||||
0 => 'sighting',
|
||||
1 => 'false-positive',
|
||||
2 => 'expiration'
|
||||
);
|
||||
|
||||
public function beforeValidate($options = array()) {
|
||||
parent::beforeValidate();
|
||||
$date = date('Y-m-d H:i:s');
|
||||
if (empty($this->data['Sighting']['id']) && empty($this->data['Sighting']['date_sighting'])) {
|
||||
$this->data['Sighting']['date_sighting'] = $date;
|
||||
}
|
||||
if (empty($this->data['Sighting']['uuid'])) {
|
||||
$this->data['Sighting']['uuid'] = CakeText::uuid();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function attachToEvent(&$event, $user) {
|
||||
public function attachToEvent($event, $user, $attribute_id = false) {
|
||||
$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']);
|
||||
if ($attribute_id) {
|
||||
$conditions[] = array('Sighting.attribute_id' => $attribute_id);
|
||||
}
|
||||
if (!$ownEvent && (!Configure::read('Plugin.Sightings_policy') || Configure::read('Plugin.Sightings_policy') == 0)) {
|
||||
$conditions['Sighting.org_id'] = $user['org_id'];
|
||||
}
|
||||
|
@ -81,10 +93,11 @@ class Sighting extends AppModel {
|
|||
return $sightings;
|
||||
}
|
||||
|
||||
public function saveSightings($id, $values, $timestamp, $user) {
|
||||
public function saveSightings($id, $values, $timestamp, $user, $type = false, $source = false) {
|
||||
$conditions = array();
|
||||
if ($id && $id !== 'stix') {
|
||||
if (strlen($id) == 36) $conditions = array('Attribute.uuid' => $id);
|
||||
$id = $this->explodeIdList($id);
|
||||
if (!is_array($id) && strlen($id) == 36) $conditions = array('Attribute.uuid' => $id);
|
||||
else $conditions = array('Attribute.id' => $id);
|
||||
} else {
|
||||
if (!$values) return 0;
|
||||
|
@ -100,12 +113,18 @@ class Sighting extends AppModel {
|
|||
if (empty($attributes)) return 0;
|
||||
$sightingsAdded = 0;
|
||||
foreach ($attributes as $attribute) {
|
||||
if ($type === '2') {
|
||||
// remove existing expiration by the same org if it exists
|
||||
$this->deleteAll(array('Sighting.org_id' => $user['org_id'], 'Sighting.type' => $type, 'Sighting.attribute_id' => $attribute['Attribute']['id']));
|
||||
}
|
||||
$this->create();
|
||||
$sighting = array(
|
||||
'attribute_id' => $attribute['Attribute']['id'],
|
||||
'event_id' => $attribute['Attribute']['event_id'],
|
||||
'org_id' => $user['org_id'],
|
||||
'date_sighting' => $timestamp,
|
||||
'type' => $type,
|
||||
'source' => $source
|
||||
);
|
||||
$sightingsAdded += $this->save($sighting) ? 1 : 0;
|
||||
}
|
||||
|
@ -139,4 +158,26 @@ class Sighting extends AppModel {
|
|||
public function generateRandomFileName() {
|
||||
return (new RandomTool())->random_str(FALSE, 12);
|
||||
}
|
||||
|
||||
public function addUuids() {
|
||||
$sightings = $this->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('uuid' => '')
|
||||
));
|
||||
$this->saveMany($sightings);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function explodeIdList($id) {
|
||||
if (strpos($id, '|')) {
|
||||
$id = explode('|', $id);
|
||||
foreach ($id as $k => $v) {
|
||||
if (!is_numeric($v)) {
|
||||
unset($id[$k]);
|
||||
}
|
||||
}
|
||||
$id = array_values($id);
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -900,9 +900,6 @@ App::uses('RandomTool', 'Tools');
|
|||
'conditions' => $conditions
|
||||
);
|
||||
$orgs = $this->find($findType, $params);
|
||||
if (empty($orgs)) {
|
||||
return 0;
|
||||
}
|
||||
if ($org_id !== false) {
|
||||
return $orgs[0]['num_members'];
|
||||
} else {
|
||||
|
@ -957,7 +954,7 @@ App::uses('RandomTool', 'Tools');
|
|||
if ($fixedPassword) {
|
||||
$password = $fixedPassword;
|
||||
} else {
|
||||
$password = $this->generateRandomPassword();
|
||||
$password = $this->generateRandomPassword();
|
||||
}
|
||||
$body = str_replace('$password', $password, $body);
|
||||
$body = str_replace('$username', $user['User']['email'], $body);
|
||||
|
|
|
@ -187,7 +187,10 @@ class CertificateAuthenticate extends BaseAuthenticate
|
|||
CakeLog::write('alert', 'Could not insert model at database from RestAPI data.');
|
||||
}
|
||||
unset($org);
|
||||
}
|
||||
} else {
|
||||
// No match -- User doesn't exist !!!
|
||||
self::$user = false;
|
||||
}
|
||||
unset($U, $User, $q, $k);
|
||||
}
|
||||
unset($cn);
|
||||
|
|
|
@ -4,7 +4,9 @@ This plugin enables CakePHP applications to use client SSL certificates to state
|
|||
|
||||
Basically it loads the `SSL_CLIENT_*` variables, parses and maps the certificate information to the user. So you first need a server that checks client certificates and forwards that information to the PHP `$_SERVER` environment.
|
||||
|
||||
## Usage
|
||||
## Configuration
|
||||
|
||||
1. Enable the plugin
|
||||
|
||||
Enable the plugin at bootstrap.php:
|
||||
|
||||
|
@ -12,34 +14,59 @@ Enable the plugin at bootstrap.php:
|
|||
CakePlugin::load('CertAuth');
|
||||
```
|
||||
|
||||
And configure it:
|
||||
2. Configure
|
||||
|
||||
* Uncomment the line "'auth'=>array('CertAuth.Certificate')," in Config.php, section "Security"
|
||||
|
||||
```php
|
||||
Configure::write('CertAuth',
|
||||
array(
|
||||
'ca' => array( 'FIRST.Org' ), // allowed CAs
|
||||
'caId' => 'O', // which attribute will be used to verify the CA
|
||||
'userModel' => 'User', // name of the User class to check if user exists
|
||||
'userModelKey' => 'nids_sid', // User field that will be used for querying
|
||||
'map' => array( // maps client certificate attributes to User properties
|
||||
'O' => 'org',
|
||||
'emailAddress'=>'email',
|
||||
),
|
||||
'syncUser' => true, // should the User be synchronized with an external REST API
|
||||
'restApi' => array( // API parameters
|
||||
'url' => 'https://example.com/data/users', // URL to query
|
||||
'headers' => array(), // additional headers, used for authentication
|
||||
'param' => array( 'email' => 'email'), // query parameters to add to the URL, mapped to USer properties
|
||||
'map' => array( // maps REST result to the User properties
|
||||
'uid' => 'id',
|
||||
'name' => 'name',
|
||||
'company' => 'org',
|
||||
'email' => 'email',
|
||||
),
|
||||
),
|
||||
'userDefaults' => array ( 'role_id' => 3 ), // default attributes for new users
|
||||
)
|
||||
);
|
||||
....
|
||||
'Security' =>
|
||||
array(
|
||||
'level' => 'medium',
|
||||
'salt' => '',
|
||||
'cipherSeed' => '',
|
||||
'auth'=>array('CertAuth.Certificate'), // additional authentication methods
|
||||
//'auth'=>array('ShibbAuth.ApacheShibb'dd),
|
||||
),
|
||||
.....
|
||||
```
|
||||
|
||||
* Uncomment the following lines in Config.php, section "CertAuth" and configure them.
|
||||
|
||||
```php
|
||||
'CertAuth' =>
|
||||
array(
|
||||
|
||||
// CA
|
||||
'ca' => array('FIRST.Org'), // List of CAs authorized
|
||||
'caId' => 'O', // Certificate field used to verify the CA. In this example, the field O (organization) of the client certificate has to equal to 'FIRST.Org' in order to validate the CA
|
||||
|
||||
// User/client configuration
|
||||
'userModel' => 'User', // name of the User class (MISP class) to check if the user exists
|
||||
'userModelKey' => 'email', // User field that will be used for querying. In this example, the field email of the MISP accounts will be used to search if the user exists.
|
||||
'map' => array( // maps client certificate attributes to User properties. This map will be used as conditions to find if the user exists. In this example, the client certificate fields 'O' (organization) and 'emailAddress' have to match with the MISP fields 'org' and 'email' to validate the user.
|
||||
'O' => 'org',
|
||||
'emailAddress' => 'email',
|
||||
),
|
||||
|
||||
// Synchronization/RestAPI
|
||||
'syncUser' => true, // should the User be synchronized with an external REST API
|
||||
'userDefaults' => array( // default user attributes, only used when creating new users. By default, new users are "Read only" users (role_id: 6).
|
||||
'role_id' => 6,
|
||||
),
|
||||
'restApi' => array( // API parameters
|
||||
'url' => 'https://example.com/data/users', // URL to query
|
||||
'headers' => array(), // additional headers, used for authentication
|
||||
'param' => array('email' => 'email'), // query parameters to add to the URL, mapped to User properties
|
||||
'map' => array( // maps REST result to the User properties
|
||||
'uid' => 'nids_sid',
|
||||
'team' => 'org',
|
||||
'email' => 'email',
|
||||
'pgp_public' => 'gpgkey',
|
||||
),
|
||||
),
|
||||
'userDefaults' => array('role_id' => 6), // default attributes for new users. By default, new users are "Read only" users (role_id: 6).
|
||||
),
|
||||
```
|
||||
|
||||
If you set *syncUser* to *true* and *restApi.url* to *null*, new users will be created with the defaults defined by *userDefaults* without the need for a REST server.
|
||||
|
|
|
@ -15,49 +15,69 @@
|
|||
$attributeSightings = array();
|
||||
$attributeOwnSightings = array();
|
||||
$attributeSightingsPopover = array();
|
||||
if (isset($event['Sighting']) && !empty($event['Sighting'])) {
|
||||
$sightingsData = array();
|
||||
$sparklineData = array();
|
||||
$startDates = array();
|
||||
if (!empty($event['Sighting'])) {
|
||||
foreach ($event['Sighting'] as $sighting) {
|
||||
$attributeSightings[$sighting['attribute_id']][] = $sighting;
|
||||
if (isset($sighting['org_id']) && $sighting['org_id'] == $me['org_id']) {
|
||||
if (isset($attributeOwnSightings[$sighting['attribute_id']])) {
|
||||
$attributeOwnSightings[$sighting['attribute_id']]['count']++;
|
||||
if (!isset($attributeOwnSightings[$sighting['attribute_id']]['date']) || $attributeOwnSightings[$sighting['attribute_id']]['date'] < $sighting['date_sighting']) {
|
||||
$attributeOwnSightings[$sighting['attribute_id']]['date'] = $sighting['date_sighting'];
|
||||
}
|
||||
} else {
|
||||
$attributeOwnSightings[$sighting['attribute_id']]['count'] = 1;
|
||||
$attributeOwnSightings[$sighting['attribute_id']]['date'] = $sighting['date_sighting'];
|
||||
$type = $sightingTypes[$sighting['type']];
|
||||
if (!isset($sightingsData[$sighting['attribute_id']][$type])) {
|
||||
$sightingsData[$sighting['attribute_id']][$type] = array('count' => 0);
|
||||
}
|
||||
$sightingsData[$sighting['attribute_id']][$type]['count']++;
|
||||
$orgName = isset($sighting['Organisation']['name']) ? $sighting['Organisation']['name'] : 'Others';
|
||||
if (!isset($startDates[$sighting['attribute_id']]) || $startDates[$sighting['attribute_id']] > $sighting['date_sighting']) {
|
||||
$startDates[$sighting['attribute_id']] = $sighting['date_sighting'];
|
||||
}
|
||||
if (!isset($sightingsData[$sighting['attribute_id']][$type]['orgs'][$orgName])) {
|
||||
$sightingsData[$sighting['attribute_id']][$type]['orgs'][$orgName] = array('count' => 1, 'date' => $sighting['date_sighting']);
|
||||
} else {
|
||||
$sightingsData[$sighting['attribute_id']][$type]['orgs'][$orgName]['count']++;
|
||||
if ($sightingsData[$sighting['attribute_id']][$type]['orgs'][$orgName]['date'] < $sighting['date_sighting']) {
|
||||
$sightingsData[$sighting['attribute_id']][$type]['orgs'][$orgName]['date'] = $sighting['date_sighting'];
|
||||
}
|
||||
}
|
||||
if (isset($sighting['org_id'])) {
|
||||
if (isset($attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']])) {
|
||||
$attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']]['count']++;
|
||||
if (!isset($attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']]['date']) || $attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']]['date'] < $sighting['date_sighting']) {
|
||||
$attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']]['date'] = $sighting['date_sighting'];
|
||||
}
|
||||
} else {
|
||||
$attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']]['count'] = 1;
|
||||
$attributeSightingsPopover[$sighting['attribute_id']][$sighting['Organisation']['name']]['date'] = $sighting['date_sighting'];
|
||||
}
|
||||
$date = date("Ymd", $sighting['date_sighting']);
|
||||
if (!isset($sparklineData[$sighting['attribute_id']][$type][$date])) {
|
||||
$sparklineData[$sighting['attribute_id']][$type][$date] = 1;
|
||||
} else {
|
||||
if (isset($attributeSightingsPopover[$sighting['attribute_id']]['Other organisations'])) {
|
||||
$attributeSightingsPopover[$sighting['attribute_id']]['Other organisations']['count']++;
|
||||
if (!isset($attributeSightingsPopover[$sighting['attribute_id']]['Other organisations']['date']) || $attributeSightingsPopover[$sighting['attribute_id']]['Other organisations']['date'] < $sighting['date_sighting']) {
|
||||
$attributeSightingsPopover[$sighting['attribute_id']]['Other organisations']['date'] = $sighting['date_sighting'];
|
||||
$sparklineData[$sighting['attribute_id']][$type][$date]++;
|
||||
}
|
||||
}
|
||||
$csv = array();
|
||||
$to = new DateTime();
|
||||
$from = new DateTime();
|
||||
foreach ($sparklineData as $aid => $data) {
|
||||
foreach ($data as $type => $sighting) {
|
||||
$from->setTimestamp(($startDates[$aid] - 259200));
|
||||
for ($date = clone $from; $date < $to; $date->modify('+1 day')) {
|
||||
if (!isset($csv[$aid][$type])) {
|
||||
$csv[$aid][$type] = 'Date,Close\n';
|
||||
}
|
||||
$currentDate = $date->format('Ymd');
|
||||
if (isset($sighting[$currentDate])) {
|
||||
$csv[$aid][$type] .= $currentDate . ',' . $sighting[$currentDate] . '\n';
|
||||
} else {
|
||||
$csv[$aid][$type] .= $currentDate . ',0\n';
|
||||
}
|
||||
} else {
|
||||
$attributeSightingsPopover[$sighting['attribute_id']]['Other organisations']['count'] = 1;
|
||||
$attributeSightingsPopover[$sighting['attribute_id']]['Other organisations']['date'] = $sighting['date_sighting'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($attributeSightingsPopover)) {
|
||||
$attributeSightingsPopoverText = array();
|
||||
foreach ($attributeSightingsPopover as $aid => &$attribute) {
|
||||
$attributeSightingsPopoverText[$aid] = '';
|
||||
foreach ($attribute as $org => $data) {
|
||||
$attributeSightingsPopoverText[$aid] .= '<span class=\'bold\'>' . h($org) . '</span>: <span class=\'green bold\'>' . h($data['count']) . ' (' . date('Y-m-d H:i:s', $data['date']) . ')</span><br />';
|
||||
unset($sparklineData);
|
||||
foreach ($sightingsData as $aid => $data) {
|
||||
$sightingsData[$aid]['html'] = '';
|
||||
foreach ($data as $type => $typeData) {
|
||||
$name = (($type != 'expiration') ? Inflector::pluralize($type) : $type);
|
||||
$sightingsData[$aid]['html'] .= '<span class=\'blue bold\'>' . ucfirst(h($name)) . '</span><br />';
|
||||
foreach ($typeData['orgs'] as $org => $orgData) {
|
||||
$extra = (($org == $me['Organisation']['name']) ? " class= 'bold'" : "");
|
||||
if ($type == 'expiration') {
|
||||
$sightingsData[$aid]['html'] .= '<span ' . $extra . '>' . h($org) . '</span>: <span class=\'orange bold\'>' . date('Y-m-d H:i:s', $orgData['date']) . '</span><br />';
|
||||
} else {
|
||||
$sightingsData[$aid]['html'] .= '<span ' . $extra . '>' . h($org) . '</span>: <span class=\'' . (($type == 'sighting') ? 'green' : 'red') . ' bold\'>' . h($orgData['count']) . ' (' . date('Y-m-d H:i:s', $orgData['date']) . ')</span><br />';
|
||||
}
|
||||
}
|
||||
$sightingsData[$aid]['html'] .= '<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,11 +148,14 @@
|
|||
<div id="attributeList" class="attributeListContainer">
|
||||
<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>
|
||||
<span id="multi-edit-button" title="Edit selected Attributes" class="hidden icon-edit mass-select useCursorPointer" onClick="editSelectedAttributes(<?php echo $event['Event']['id']; ?>);"></span>
|
||||
<span id="multi-tag-button" title="Tag selected Attributes" class="hidden icon-tag mass-select useCursorPointer" onClick="getPopup('selected/true', 'tags', 'selectTaxonomy');"></span>
|
||||
<span id="multi-delete-button" title="Delete selected Attributes" class="hidden icon-trash mass-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'deleteAttributes');"></span>
|
||||
<span id="multi-accept-button" title="Accept selected Proposals" class="hidden 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="hidden icon-remove mass-proposal-select useCursorPointer" onClick="multiSelectAction(<?php echo $event['Event']['id']; ?>, 'discardProposals');"></span>
|
||||
<?php if (Configure::read('Plugin.Sightings_enable')): ?>
|
||||
<span id="multi-sighting-button" title="Sightings display for selected attributes" class="hidden icon-wrench mass-select useCursorPointer sightings_advanced_add" data-object-id="selected"></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="tabMenu tabMenuToolsBlock noPrint">
|
||||
<?php if ($mayModify): ?>
|
||||
|
@ -184,6 +207,7 @@
|
|||
<th title="<?php echo $attrDescriptions['distribution']['desc'];?>"><?php echo $this->Paginator->sort('distribution');?></th>
|
||||
<?php if (Configure::read('Plugin.Sightings_enable') !== false): ?>
|
||||
<th>Sightings</th>
|
||||
<th>Activity</th>
|
||||
<?php endif; ?>
|
||||
<th class="actions">Actions</th>
|
||||
</tr>
|
||||
|
@ -279,7 +303,7 @@
|
|||
<?php echo h($object['type']); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td id="<?php echo h($currentType) . '_' . h($object['id']) . '_container'; ?>" class="showspaces <?php echo $extra; ?> limitedWidth">
|
||||
<td id="<?php echo h($currentType) . '_' . h($object['id']) . '_container'; ?>" class="showspaces <?php echo $extra; ?> limitedWidth shortish">
|
||||
<div id = "<?php echo $currentType . '_' . $object['id'] . '_value_placeholder'; ?>" class = "inline-field-placeholder"></div>
|
||||
<?php
|
||||
if ('attachment' !== $object['type'] && 'malware-sample' !== $object['type']) $editable = ' ondblclick="activateField(\'' . $currentType . '\', \'' . $object['id'] . '\', \'value\', \'' . $event['Event']['id'] . '\');"';
|
||||
|
@ -311,7 +335,13 @@
|
|||
} else if (strpos($object['type'], '|') !== false) {
|
||||
$filenameHash = explode('|', $object['value']);
|
||||
echo h($filenameHash[0]);
|
||||
if (isset($filenameHash[1])) echo '<br />' . $filenameHash[1];
|
||||
if (isset($filenameHash[1])) {
|
||||
$separator = '<br />';
|
||||
if (in_array($object['type'], array('ip-dst|port', 'ip-src|port'))) {
|
||||
$separator = ':';
|
||||
}
|
||||
echo $separator . h($filenameHash[1]);
|
||||
}
|
||||
} else if ('vulnerability' == $object['type']) {
|
||||
if (! is_null(Configure::read('MISP.cveurl'))) {
|
||||
$cveUrl = Configure::read('MISP.cveurl');
|
||||
|
@ -452,25 +482,48 @@
|
|||
endif;
|
||||
if (Configure::read('Plugin.Sightings_enable') !== false):
|
||||
?>
|
||||
<td class="short <?php echo $extra;?>">
|
||||
<td class="shortish <?php echo $extra;?>">
|
||||
<span id="sightingForm_<?php echo h($object['id']);?>">
|
||||
<?php
|
||||
if ($object['objectType'] == 0):
|
||||
echo $this->Form->create('Sighting', array('id' => 'Sighting_' . $object['id'], 'url' => '/sightings/add/' . $object['id'], 'style' => 'display:none;'));
|
||||
echo $this->Form->input('type', array('label' => false, 'id' => 'Sighting_' . $object['id'] . '_type'));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</span>
|
||||
<span class="icon-thumbs-up useCursorPointer" onClick="addSighting('<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']);?>', '<?php echo h($page); ?>');"> </span>
|
||||
<span id="sightingCount_<?php echo h($object['id']); ?>" class="bold sightingsCounter_<?php echo h($object['id']); ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?php echo isset($attributeSightingsPopoverText[$object['id']]) ? $attributeSightingsPopoverText[$object['id']] : ''; ?>">
|
||||
<?php echo (!empty($attributeSightings[$object['id']]) ? count($attributeSightings[$object['id']]) : 0); ?>
|
||||
<?php
|
||||
$temp = array();
|
||||
if (isset($csv[$object['id']]['sighting'])) {
|
||||
$temp[0] = $csv[$object['id']]['sighting'];
|
||||
}
|
||||
if (isset($csv[$object['id']]['false-positive'])) {
|
||||
$temp[1] = $csv[$object['id']]['false-positive'];
|
||||
}
|
||||
?>
|
||||
<span class="icon-thumbs-up useCursorPointer" onClick="addSighting('0', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']);?>', '<?php echo h($page); ?>');"> </span>
|
||||
<span class="icon-thumbs-down useCursorPointer" onClick="addSighting('1', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']);?>', '<?php echo h($page); ?>');"> </span>
|
||||
<span class="icon-wrench useCursorPointer sightings_advanced_add" data-object-id="<?php echo h($object['id']); ?>"> </span>
|
||||
<span id="sightingCount_<?php echo h($object['id']); ?>" class="bold sightingsCounter_<?php echo h($object['id']); ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?php echo isset($sightingsData[$object['id']]['html']) ? $sightingsData[$object['id']]['html'] : ''; ?>">
|
||||
<?php
|
||||
$s = (!empty($sightingsData[$object['id']]['sighting']['count']) ? $sightingsData[$object['id']]['sighting']['count'] : 0);
|
||||
$f = (!empty($sightingsData[$object['id']]['false-positive']['count']) ? $sightingsData[$object['id']]['false-positive']['count'] : 0);
|
||||
$e = (!empty($sightingsData[$object['id']]['expiration']['count']) ? $sightingsData[$object['id']]['expiration']['count'] : 0);
|
||||
?>
|
||||
</span>
|
||||
<span id="ownSightingCount_<?php echo h($object['id']); ?>" class="bold green sightingsCounter_<?php echo h($object['id']); ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?php echo isset($attributeSightingsPopoverText[$object['id']]) ? $attributeSightingsPopoverText[$object['id']] : ''; ?>">
|
||||
<?php echo '(' . (isset($attributeOwnSightings[$object['id']]['count']) ? $attributeOwnSightings[$object['id']]['count'] : 0) . ')'; ?>
|
||||
<span id="ownSightingCount_<?php echo h($object['id']); ?>" class="bold sightingsCounter_<?php echo h($object['id']); ?>" data-placement="top" data-toggle="popover" data-trigger="hover" data-content="<?php echo isset($sightingsData[$object['id']]['html']) ? $sightingsData[$object['id']]['html'] : ''; ?>">
|
||||
<?php echo '(<span class="green">' . h($s) . '</span>/<span class="red">' . h($f) . '</span>/<span class="orange">' . h($e) . '</span>)'; ?>
|
||||
</span>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
<td class="short <?php echo $extra; ?>">
|
||||
<?php
|
||||
if ($object['objectType'] == 0) {
|
||||
echo $this->element('sparkline', array('id' => $object['id'], 'csv' => $temp));
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
@ -588,8 +641,6 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
popoverStartup();
|
||||
$('.select_attribute').removeAttr('checked');
|
||||
$('.select_proposal').removeAttr('checked');
|
||||
$('.mass-select').hide();
|
||||
$('.mass-proposal-select').hide();
|
||||
$('.select_attribute').click(function(e) {
|
||||
if ($(this).is(':checked')) {
|
||||
if (e.shiftKey) {
|
||||
|
@ -620,6 +671,20 @@ attributes or the appropriate distribution level. If you think there is a mistak
|
|||
$('.screenshot').click(function() {
|
||||
screenshotPopup($(this).attr('src'), $(this).attr('title'));
|
||||
});
|
||||
$('.sightings_advanced_add').click(function() {
|
||||
var selected = [];
|
||||
var object_id = $(this).data('object-id');
|
||||
if (object_id == 'selected') {
|
||||
$(".select_attribute").each(function() {
|
||||
if ($(this).is(":checked")) {
|
||||
selected.push($(this).data("id"));
|
||||
}
|
||||
});
|
||||
object_id = selected.join('|');
|
||||
}
|
||||
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id;
|
||||
genericPopup(url, '#screenshot_box');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<!--
|
||||
Modified version of http://www.tnoda.com/blog/2013-12-19
|
||||
-->
|
||||
<?php
|
||||
echo $this->Html->script('d3');
|
||||
//echo $this->Html->css('sightingstyle');
|
||||
?>
|
||||
<div id="spark_<?php echo h($id); ?>"></div>
|
||||
<script>
|
||||
var width = 100;
|
||||
var height = 25;
|
||||
var x = d3.scale.linear().range([0, width - 2]);
|
||||
var y = d3.scale.linear().range([height - 4, 0]);
|
||||
var parseDate = d3.time.format("%Y%m%d").parse;
|
||||
var line = d3.svg.line()
|
||||
.interpolate("linear")
|
||||
.x(function(d) { return x(d.date); })
|
||||
.y(function(d) { return y(d.close); });
|
||||
function sparkline(elemId, data) {
|
||||
data.forEach(function(d) {
|
||||
d.date = parseDate(d.Date);
|
||||
d.close = +d.Close;
|
||||
});
|
||||
x.domain(d3.extent(data, function(d) { return d.date; }));
|
||||
y.domain(d3.extent(data, function(d) { return d.close; }));
|
||||
var svg = d3.select(elemId)
|
||||
.append('svg')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.append('g')
|
||||
.attr('transform', 'translate(0, 2)');
|
||||
svg.append('path')
|
||||
.datum(data)
|
||||
.attr('class', 'sparkline')
|
||||
.attr('d', line);
|
||||
svg.append('circle')
|
||||
.attr('class', 'sparkcircle')
|
||||
.attr('cx', x(data[data.length - 1].date))
|
||||
.attr('cy', y(data[data.length - 1].close))
|
||||
.attr('r', 2);
|
||||
}
|
||||
|
||||
var myData = "<?php echo isset($csv[0]) ? $csv[0] : ''; ?>";
|
||||
if (myData != '') {
|
||||
var data = d3.csv.parse(myData);
|
||||
sparkline('#spark_<?php echo h($id); ?>', data);
|
||||
}
|
||||
</script>
|
|
@ -67,21 +67,21 @@ echo $this->Form->end();
|
|||
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;
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
$('#EventDistribution').change(function() {
|
||||
if ($('#EventDistribution').val() == 4) $('#SGContainer').show();
|
||||
else $('#SGContainer').hide();
|
||||
});
|
||||
|
||||
|
||||
$("#EventDistribution, #EventAnalysis, #EventThreatLevelId").change(function() {
|
||||
initPopoverContent('Event');
|
||||
});
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
if ($('#EventDistribution').val() == 4) $('#SGContainer').show();
|
||||
else $('#SGContainer').hide();
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<div class="confirmation">
|
||||
<?php
|
||||
echo $this->Form->create($model, array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => $url));
|
||||
echo $this->Form->input($varName, array(
|
||||
'type' => 'text',
|
||||
'value' => 'test',
|
||||
'style' => 'display:none;',
|
||||
'label' => false,
|
||||
));
|
||||
?>
|
||||
<legend><?php echo h(Inflector::humanize($action)); ?></legend>
|
||||
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
|
||||
<p><?php echo h($message); ?></p>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span id="PromptYesButton" class="btn btn-primary" onClick="multiSelectAction('<?php echo h($id); ?>', '<?php echo h($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>
|
|
@ -16,7 +16,7 @@
|
|||
'class' => 'form-control span6'
|
||||
));
|
||||
echo $this->Form->input('input_source', array(
|
||||
'label' => 'Input Source',
|
||||
'label' => 'Source Format',
|
||||
'div' => 'input clear',
|
||||
'options' => array('network' => 'Network', 'local' => 'Local'),
|
||||
'class' => 'form-control span6'
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
'class' => 'form-control span6'
|
||||
));
|
||||
echo $this->Form->input('input_source', array(
|
||||
'label' => 'Input Source',
|
||||
'label' => 'Source Format',
|
||||
'div' => 'input clear',
|
||||
'options' => array('network' => 'Network', 'local' => 'Local'),
|
||||
'class' => 'form-control span6'
|
||||
|
@ -189,9 +189,12 @@ var rules = {"pull": {"tags": {"OR":[], "NOT":[]}, "orgs": {"OR":[], "NOT":[]}}}
|
|||
var validOptions = ['pull'];
|
||||
var validFields = ['tags', 'orgs'];
|
||||
var modelContext = 'Feed';
|
||||
var tags = [];
|
||||
var orgs = [];
|
||||
|
||||
$(document).ready(function() {
|
||||
rules = convertServerFilterRules(rules);
|
||||
serverRulePopulateTagPicklist();
|
||||
feedDistributionChange();
|
||||
$("#pull_modify").click(function() {
|
||||
serverRuleFormActivate('pull');
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
</head>
|
||||
<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="confirmation_box" class="confirmation_box"></div>
|
||||
<div id="gray_out" class="gray_out"></div>
|
||||
<div id="container">
|
||||
<?php echo $this->element('global_menu');
|
||||
|
|
|
@ -24,9 +24,6 @@ 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();');
|
||||
}
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
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();');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<h3>Add Sighting</h3>
|
||||
<div id="sightingsEventId" class="hidden" data-event-id="<?php echo h($event_id); ?>"></div>
|
||||
<?php
|
||||
echo $this->Form->create('Sighting', array('id', 'url' => '/sightings/add/' . urlencode(h($id)), 'style' => 'margin-bottom:0px;'));
|
||||
echo $this->Form->input('type', array(
|
||||
'options' => array('Sighting', 'Fase-positive', 'Expiration'),
|
||||
'default' => 0,
|
||||
'style' => 'width:230px;margin-right:0px;'
|
||||
));
|
||||
echo $this->Form->input('source', array(
|
||||
'placeholder' => 'honeypot, IDS sensor id, SIEM,...',
|
||||
'style' => 'width:447px;',
|
||||
'div' => array('style' => 'width:457px !important;')
|
||||
));
|
||||
echo $this->Form->label('Sighting date');
|
||||
echo $this->Form->input('date', array(
|
||||
'type' => 'text',
|
||||
'id' => 'datepicker',
|
||||
'default' => date('Y-m-d'),
|
||||
'style' => 'width:110px;',
|
||||
'div' => array('style' => 'width:120px !important;'),
|
||||
'label' => false
|
||||
));
|
||||
echo $this->Form->input('time', array(
|
||||
'class' => 'input-mini',
|
||||
'default' => date('H:i:s'),
|
||||
'id' => 'timepicker',
|
||||
'style' => 'width:120px;',
|
||||
'div' => array('style' => 'width:120px !important;'),
|
||||
'label' => false
|
||||
));
|
||||
?>
|
||||
<span id="submitButton" class="btn btn-primary" onClick="submitPopoverForm('<?php echo h($id);?>', 'addSighting', '<?php echo h($event_id); ?>')">Add</span>
|
||||
<div class="input clear"></div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
|
@ -0,0 +1,59 @@
|
|||
<div class="sightings_advanced">
|
||||
<div class="popover-legend"><p><?php echo __('Sighting details'); ?></p></div>
|
||||
<div style="margin:10px;">
|
||||
<span id="sightingsGraphToggle" class="btn btn-primary qet toggle-left sightingsToggle" data-type="graph">Graph</span>
|
||||
<span id="sightingsListAllToggle" class="btn btn-inverse qet toggle sightingsToggle" data-type="all">All</span>
|
||||
<span id="sightingsListMyToggle" class="btn btn-inverse qet toggle sightingsToggle" data-type="org">My org</span>
|
||||
<span id="sightingsAddToggle" class="btn btn-inverse qet toggle-right sightingsToggle" data-type="add">Add sighting</span>
|
||||
</div>
|
||||
<div id="mainContents" style="margin-top:40px;padding:10px;">
|
||||
<div id="sightingsData" class="sightingTab"></div>
|
||||
<span style="float:right;margin-bottom:10px;" class="btn btn-inverse" id="cancel">Cancel</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
id = "<?php echo h($id); ?>";
|
||||
$('#cancel').click(function() {
|
||||
cancelPopoverForm();
|
||||
});
|
||||
$('#datepicker').datepicker({
|
||||
startDate: '-180d',
|
||||
endDate: '+1d',
|
||||
orientation: 'bottom',
|
||||
autoclose: true,
|
||||
format: 'yyyy-mm-dd'
|
||||
});
|
||||
$('#timepicker').timepicker({
|
||||
minuteStep: 1,
|
||||
showMeridian: false,
|
||||
showSeconds: true,
|
||||
maxHours: 24
|
||||
});
|
||||
loadSightingGraph(id, "attribute");
|
||||
});
|
||||
$('.sightingsToggle').click(function() {
|
||||
$('.sightingsToggle').removeClass('btn-primary');
|
||||
$('.sightingsToggle').addClass('btn-inverse');
|
||||
$(this).removeClass('btn-inverse');
|
||||
$(this).addClass('btn-primary');
|
||||
var type = $(this).data('type');
|
||||
$('.sightingTab').empty();
|
||||
if (type == 'graph') {
|
||||
loadSightingGraph(id, "attribute");
|
||||
} else if (type == 'add') {
|
||||
$.get( "/sightings/add/" + id, function(data) {
|
||||
$("#sightingsData").html(data);
|
||||
});
|
||||
} else {
|
||||
var org = "";
|
||||
if (type == 'org') org = "/<?php echo h($me['org_id']);?>"
|
||||
$.get( "/sightings/listSightings/" + id + "/attribute" + org, function(data) {
|
||||
$("#sightingsData").html(data);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php echo $this->Js->writeBuffer(); // Write cached scripts
|
|
@ -0,0 +1,51 @@
|
|||
<div>
|
||||
<div id="org_id" class="hidden"><?php echo h($org_id); ?></div>
|
||||
<table class="table table-striped table-hover table-condensed" style="display:block; overflow-y:auto;max-height:500px;">
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Organisation</th>
|
||||
<th>Type</th>
|
||||
<th>Source</th>
|
||||
<th>Event ID</th>
|
||||
<th>Attribute ID</th>
|
||||
<th class="actions">Actions</th>
|
||||
</tr>
|
||||
<?php
|
||||
foreach ($sightings as $item):
|
||||
?>
|
||||
<tr>
|
||||
<td class="short"><?php echo date('Y-m-d H:i:s', $item['Sighting']['date_sighting']);?></td>
|
||||
<td class="short">
|
||||
<?php
|
||||
$imgAbsolutePath = APP . WEBROOT_DIR . DS . 'img' . DS . 'orgs' . DS . h($item['Organisation']['name']) . '.png';
|
||||
if (file_exists($imgAbsolutePath)):
|
||||
echo $this->Html->image('orgs/' . h($item['Organisation']['name']) . '.png', array('alt' => h($item['Organisation']['name']), 'title' => h($item['Organisation']['name']), 'style' => 'width:24px; height:24px'));
|
||||
else:
|
||||
echo h($item['Organisation']['name']);
|
||||
endif;
|
||||
|
||||
?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php
|
||||
echo $types[$item['Sighting']['type']];
|
||||
?>
|
||||
</td>
|
||||
<td class="short"><?php echo h($item['Sighting']['source']);?></td>
|
||||
<td class="short"><?php echo h($item['Sighting']['event_id']);?></td>
|
||||
<td class="short"><?php echo h($item['Sighting']['attribute_id']);?></td>
|
||||
<td class="short action-links">
|
||||
<?php
|
||||
if ($isSiteAdmin || ($item['Sighting']['org_id'] == $me['org_id'] && $isAclAdd)):
|
||||
?>
|
||||
<span class="icon-trash useCursorPointer" onClick="quickDeleteSighting('<?php echo h($item['Sighting']['id']); ?>', '<?php echo h($rawId); ?>', '<?php echo h($context); ?>');"></span>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
</table>
|
||||
</div>
|
|
@ -0,0 +1,24 @@
|
|||
<div class="confirmation">
|
||||
<?php
|
||||
echo $this->Form->create('Sighting', array('style' => 'margin:0px;', 'id' => 'PromptForm', 'url' => '/sightings/quickDelete/' . $id . '/' . urlencode($rawId) . '/' . $context));
|
||||
?>
|
||||
<legend>Remove Sighting</legend>
|
||||
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
|
||||
<p>Remove sighting (<?php echo h($id); ?>)?</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top">
|
||||
<span id="PromptYesButton" class="btn btn-primary" onClick="removeSighting('<?php echo h($id); ?>', '<?php echo h($rawId); ?>', '<?php echo h($context); ?>');">Yes</span>
|
||||
</td>
|
||||
<td style="width:540px;">
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
<span class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt(1);">No</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</div>
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
echo $this->Html->script('d3');
|
||||
echo $this->Html->css('sightingstyle');
|
||||
?>
|
||||
<div id="graphContent" class="graphContent"></div>
|
||||
<script>
|
||||
var myData = "<?php echo $tsv; ?>";
|
||||
|
||||
var colours = {
|
||||
'Sighting': 'blue',
|
||||
'False-positive': 'red'
|
||||
}
|
||||
|
||||
var margin = {
|
||||
top: 20,
|
||||
right: 60,
|
||||
bottom: 30,
|
||||
left: 25
|
||||
},
|
||||
width = 980 - margin.left - margin.right,
|
||||
height = 300 - margin.top - margin.bottom;
|
||||
|
||||
var parseDate = d3.time.format("%Y%m%d").parse;
|
||||
|
||||
var x = d3.time.scale()
|
||||
.range([0, width]);
|
||||
|
||||
var y = d3.scale.linear()
|
||||
.range([height, 0]);
|
||||
|
||||
var color = d3.scale.category10();
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom");
|
||||
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left");
|
||||
|
||||
var line = d3.svg.line()
|
||||
.interpolate("linear")
|
||||
.x(function(d) {
|
||||
return x(d.date);
|
||||
})
|
||||
.y(function(d) {
|
||||
return y(d.count);
|
||||
});
|
||||
|
||||
var svg = d3.select("#graphContent").append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
var data = d3.tsv.parse(myData);
|
||||
|
||||
color.domain(d3.keys(data[0]).filter(function(key) {
|
||||
return key !== "date";
|
||||
}));
|
||||
|
||||
data.forEach(function(d) {
|
||||
d.date = parseDate(d.date);
|
||||
});
|
||||
|
||||
var sightings = color.domain().map(function(name) {
|
||||
return {
|
||||
name: name,
|
||||
values: data.map(function(d) {
|
||||
return {
|
||||
date: d.date,
|
||||
count: +d[name]
|
||||
};
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
x.domain(d3.extent(data, function(d) {
|
||||
return d.date;
|
||||
}));
|
||||
|
||||
y.domain([
|
||||
d3.min(sightings, function(c) {
|
||||
return d3.min(c.values, function(v) {
|
||||
return v.count;
|
||||
});
|
||||
}),
|
||||
d3.max(sightings, function(c) {
|
||||
return d3.max(c.values, function(v) {
|
||||
return v.count;
|
||||
});
|
||||
})
|
||||
]);
|
||||
|
||||
var legend = svg.selectAll('g')
|
||||
.data(sightings)
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('class', 'sightingsLegend');
|
||||
|
||||
legend.append('rect')
|
||||
.attr('x', width - 20)
|
||||
.attr('y', function(d, i) {
|
||||
return i * 20;
|
||||
})
|
||||
.attr('width', 10)
|
||||
.attr('height', 10)
|
||||
.style('fill', function(d) {
|
||||
return colours[d.name];
|
||||
});
|
||||
|
||||
legend.append('text')
|
||||
.attr('x', width - 8)
|
||||
.attr('y', function(d, i) {
|
||||
return (i * 20) + 9;
|
||||
})
|
||||
.text(function(d) {
|
||||
return d.name;
|
||||
});
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis)
|
||||
.append("text")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", 6)
|
||||
.attr("dy", ".71em")
|
||||
.style("text-anchor", "end")
|
||||
.text("Count");
|
||||
|
||||
var sightings = svg.selectAll(".sightings")
|
||||
.data(sightings)
|
||||
.enter().append("g")
|
||||
.attr("class", "sightings");
|
||||
|
||||
sightings.append("path")
|
||||
.attr("class", "line")
|
||||
.attr("d", function(d) {
|
||||
return line(d.values);
|
||||
})
|
||||
.style("stroke", function(d) {
|
||||
return colours[d.name];
|
||||
});
|
||||
|
||||
</script>
|
|
@ -0,0 +1,71 @@
|
|||
<div class = "index">
|
||||
<h2>Statistics</h2>
|
||||
<?php
|
||||
echo $this->element('Users/statisticsMenu');
|
||||
?>
|
||||
<p>A toplist of the top sources for the sightings of your organisation.</p>
|
||||
<table class="table table-striped table-hover table-condensed" style="display:block; overflow-y:auto;width:700px;">
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>#Entries</th>
|
||||
<th>#Sighting</th>
|
||||
<th>#False-positive</th>
|
||||
<th>Expiration</th>
|
||||
</tr>
|
||||
<?php
|
||||
$count = 0;
|
||||
foreach ($toplist as $source => $total):
|
||||
if ($count > 9) break;
|
||||
?>
|
||||
<tr>
|
||||
<td style="width:20%;"><?php echo empty($source) ? 'Undefined' : h($source);?></td>
|
||||
<td style="width:20%;"><?php echo h($total);?></td>
|
||||
<td style="width:20%;">
|
||||
<?php
|
||||
if (isset($data[$source]['sighting'])):
|
||||
?>
|
||||
<a href="<?php echo $baseurl; ?>/events/index/searcheventid:<?php echo h(implode('|', $eventids[$source]['sighting'])); ?>"><?php echo h($data[$source]['sighting']); ?></a>
|
||||
<?php
|
||||
else:
|
||||
echo '0';
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
<td style="width:20%;">
|
||||
<?php
|
||||
if (isset($data[$source]['false-positive'])):
|
||||
?>
|
||||
<a href="<?php echo $baseurl; ?>/events/index/searcheventid:<?php echo h(implode('|', $eventids[$source]['false-positive'])); ?>"><?php echo h($data[$source]['false-positive']); ?></a>
|
||||
<?php
|
||||
else:
|
||||
echo '0';
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
<td style="width:20%;">
|
||||
<?php
|
||||
if (isset($data[$source]['expiration'])):
|
||||
?>
|
||||
<a href="<?php echo $baseurl; ?>/events/index/searcheventid:<?php echo h(implode('|', $eventids[$source]['expiration'])); ?>"><?php echo h($data[$source]['expiration']); ?></a>
|
||||
<?php
|
||||
else:
|
||||
echo '0';
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<?php
|
||||
$count++;
|
||||
endforeach;
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->element('side_menu', array('menuList' => 'globalActions', 'menuItem' => 'statistics'));
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
loadSightingsData();
|
||||
});
|
||||
</script>
|
|
@ -1,6 +1,5 @@
|
|||
<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>
|
||||
<h2>Import Whitelist</h2>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<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
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f3f5b3b3ac4a7e453a2a25adcb0342a0454c1155
|
||||
Subproject commit 7db66e05dd22faee44d2c2e3d0b72903c4336e44
|
|
@ -762,6 +762,20 @@ a.proposal_link_red:hover {
|
|||
color:white;
|
||||
}
|
||||
|
||||
.popover-legend {
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
margin-bottom:5px;
|
||||
padding-left:0px;
|
||||
background-color:black;
|
||||
color:white;
|
||||
font-size: 21px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.popover-legend p {
|
||||
padding-left:10px;
|
||||
}
|
||||
|
||||
.legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
@ -1672,6 +1686,21 @@ table.table.table-striped tr.deleted_row td {
|
|||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.sparkline {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
stroke-width: 0.5px;
|
||||
}
|
||||
.sparkcircle {
|
||||
fill: #f00;
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
.sightings_advanced
|
||||
{
|
||||
width:1000px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotation {
|
||||
from {-webkit-transform: rotate(0deg);}
|
||||
to {-webkit-transform: rotate(359deg);}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
.graphContent {
|
||||
font: 10px sans-serif;
|
||||
}
|
||||
|
||||
.axis path,
|
||||
.axis line {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.x.axis path {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.line {
|
||||
fill: none;
|
||||
stroke: steelblue;
|
||||
stroke-width: 1.5px;
|
||||
}
|
|
@ -14,6 +14,14 @@ function deleteObject(type, action, id, event) {
|
|||
});
|
||||
}
|
||||
|
||||
function quickDeleteSighting(id, rawId, context) {
|
||||
url = "/sightings/quickDelete/" + id + "/" + rawId + "/" + context;
|
||||
$.get(url, function(data) {
|
||||
$("#confirmation_box").fadeIn();
|
||||
$("#confirmation_box").html(data);
|
||||
});
|
||||
}
|
||||
|
||||
function publishPopup(id, type) {
|
||||
var action = "alert";
|
||||
if (type == "publish") action = "publish";
|
||||
|
@ -37,6 +45,8 @@ function genericPopup(url, popupTarget) {
|
|||
$.get(url, function(data) {
|
||||
$(popupTarget).html(data);
|
||||
$(popupTarget).fadeIn();
|
||||
left = ($(window).width() / 2) - ($(popupTarget).width() / 2);
|
||||
$(popupTarget).css({'left': left + 'px'});
|
||||
$("#gray_out").fadeIn();
|
||||
});
|
||||
}
|
||||
|
@ -64,9 +74,11 @@ function editTemplateElement(type, id) {
|
|||
});
|
||||
}
|
||||
|
||||
function cancelPrompt() {
|
||||
$("#confirmation_box").fadeIn();
|
||||
$("#gray_out").fadeOut();
|
||||
function cancelPrompt(isolated) {
|
||||
if (isolated == undefined) {
|
||||
$("#gray_out").fadeOut();
|
||||
}
|
||||
$("#confirmation_box").fadeOut();
|
||||
$("#confirmation_box").empty();
|
||||
}
|
||||
|
||||
|
@ -94,6 +106,34 @@ function submitDeletion(context_id, action, type, id) {
|
|||
});
|
||||
}
|
||||
|
||||
function removeSighting(id, rawid, context) {
|
||||
if (context != 'attribute') {
|
||||
context = 'event';
|
||||
}
|
||||
var formData = $('#PromptForm').serialize();
|
||||
$.ajax({
|
||||
beforeSend: function (XMLHttpRequest) {
|
||||
$(".loading").show();
|
||||
},
|
||||
data: formData,
|
||||
success:function (data, textStatus) {
|
||||
handleGenericAjaxResponse(data);
|
||||
},
|
||||
complete:function() {
|
||||
$(".loading").hide();
|
||||
$("#confirmation_box").fadeOut();
|
||||
var org = "/" + $('#org_id').text();
|
||||
updateIndex(id, 'event');
|
||||
$.get( "/sightings/listSightings/" + rawid + "/" + context + org, function(data) {
|
||||
$("#sightingsData").html(data);
|
||||
});
|
||||
},
|
||||
type:"post",
|
||||
cache: false,
|
||||
url:"/sightings/quickDelete/" + id + "/" + rawid + "/" + context,
|
||||
});
|
||||
}
|
||||
|
||||
function toggleSetting(e, setting, id) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
@ -340,7 +380,8 @@ function postActivationScripts(name, type, id, field, event) {
|
|||
$(name + '_solid').hide();
|
||||
}
|
||||
|
||||
function addSighting(attribute_id, event_id, $page) {
|
||||
function addSighting(type, attribute_id, event_id, page) {
|
||||
$('#Sighting_' + attribute_id + '_type').val(type);
|
||||
$.ajax({
|
||||
data: $('#Sighting_' + attribute_id).closest("form").serialize(),
|
||||
cache: false,
|
||||
|
@ -527,13 +568,13 @@ function toggleAllTaxonomyCheckboxes() {
|
|||
}
|
||||
|
||||
function attributeListAnyAttributeCheckBoxesChecked() {
|
||||
if ($('.select_attribute:checked').length > 0) $('.mass-select').show();
|
||||
else $('.mass-select').hide();
|
||||
if ($('.select_attribute:checked').length > 0) $('.mass-select').removeClass('hidden');
|
||||
else $('.mass-select').addClass('hidden');
|
||||
}
|
||||
|
||||
function attributeListAnyProposalCheckBoxesChecked() {
|
||||
if ($('.select_proposal:checked').length > 0) $('.mass-proposal-select').show();
|
||||
else $('.mass-proposal-select').hide();
|
||||
if ($('.select_proposal:checked').length > 0) $('.mass-proposal-select').removeClass('hidden');
|
||||
else $('.mass-proposal-select').addClass('hidden');
|
||||
}
|
||||
|
||||
function taxonomyListAnyCheckBoxesChecked() {
|
||||
|
@ -731,6 +772,7 @@ function submitPopoverForm(context_id, referer, update_context_id) {
|
|||
var url = null;
|
||||
var context = 'event';
|
||||
var contextNamingConvention = 'Attribute';
|
||||
var closePopover = true;
|
||||
switch (referer) {
|
||||
case 'add':
|
||||
url = "/attributes/add/" + context_id;
|
||||
|
@ -777,20 +819,38 @@ function submitPopoverForm(context_id, referer, update_context_id) {
|
|||
case 'replaceAttributes':
|
||||
url = "/attributes/attributeReplace/" + context_id;
|
||||
break;
|
||||
case 'addSighting':
|
||||
url = "/sightings/add/" + context_id;
|
||||
closePopover = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (url !== null) {
|
||||
$.ajax({
|
||||
beforeSend: function (XMLHttpRequest) {
|
||||
$(".loading").show();
|
||||
$("#gray_out").fadeOut();
|
||||
$("#popover_form").fadeOut();
|
||||
if (closePopover) {
|
||||
$("#gray_out").fadeOut();
|
||||
$("#popover_form").fadeOut();
|
||||
}
|
||||
},
|
||||
data: $("#submitButton").closest("form").serialize(),
|
||||
success:function (data, textStatus) {
|
||||
var result = handleAjaxPopoverResponse(data, context_id, url, referer, context, contextNamingConvention);
|
||||
if (closePopover) {
|
||||
var result = handleAjaxPopoverResponse(data, context_id, url, referer, context, contextNamingConvention);
|
||||
}
|
||||
if (referer == 'addSighting') {
|
||||
updateIndex(update_context_id, 'event');
|
||||
$.get( "/sightings/listSightings/" + id + "/attribute", function(data) {
|
||||
$("#sightingsData").html(data);
|
||||
});
|
||||
$('.sightingsToggle').removeClass('btn-primary');
|
||||
$('.sightingsToggle').addClass('btn-inverse');
|
||||
$('#sightingsListAllToggle').removeClass('btn-inverse');
|
||||
$('#sightingsListAllToggle').addClass('btn-primary');
|
||||
}
|
||||
if (context == 'event' && (referer == 'add' || referer == 'massEdit' || referer == 'replaceAttributes')) eventUnpublish();
|
||||
$(".loading").show();
|
||||
$(".loading").hide();
|
||||
},
|
||||
type:"post",
|
||||
url:url
|
||||
|
@ -904,7 +964,10 @@ function showMessage(success, message, context) {
|
|||
}
|
||||
|
||||
function cancelPopoverForm() {
|
||||
$("#popover_form").empty();
|
||||
$("#gray_out").fadeOut();
|
||||
$("#popover_form").fadeOut();
|
||||
$("#screenshot_box").fadeOut();
|
||||
$("#confirmation_box").fadeOut();
|
||||
$('#gray_out').fadeOut();
|
||||
$('#popover_form').fadeOut();
|
||||
}
|
||||
|
@ -1107,6 +1170,7 @@ function getPopup(id, context, target, admin, popupType) {
|
|||
$(".loading").show();
|
||||
},
|
||||
dataType:"html",
|
||||
async: true,
|
||||
cache: false,
|
||||
success:function (data, textStatus) {
|
||||
$(".loading").hide();
|
||||
|
@ -1125,6 +1189,7 @@ function simplePopup(url) {
|
|||
$(".loading").show();
|
||||
},
|
||||
dataType:"html",
|
||||
async: true,
|
||||
cache: false,
|
||||
success:function (data, textStatus) {
|
||||
$(".loading").hide();
|
||||
|
@ -1925,7 +1990,6 @@ function simpleTabPageLast() {
|
|||
if ($('#SharingGroupRoaming').is(":checked")) {
|
||||
summaryservers = "any interconnected instances linked by an eligible organisation.";
|
||||
} else {
|
||||
console.log(servercounter);
|
||||
if (servercounter == 0) {
|
||||
summaryservers = "data marked with this sharing group will not be pushed.";
|
||||
}
|
||||
|
@ -2302,6 +2366,7 @@ function serverRuleUpdate() {
|
|||
});
|
||||
}
|
||||
statusOptions.forEach(function(status) {
|
||||
console.log();
|
||||
if (rules[type][field][status].length > 0) {
|
||||
$('#' + type + '_' + field + '_' + status).show();
|
||||
var t = '';
|
||||
|
@ -2761,6 +2826,28 @@ function loadTagTreemap() {
|
|||
});
|
||||
}
|
||||
|
||||
function loadSightingsData(timestamp) {
|
||||
url = "/sightings/toplist";
|
||||
if (timestamp != undefined) {
|
||||
url = url + '/' + timestamp;
|
||||
}
|
||||
$.ajax({
|
||||
async:true,
|
||||
beforeSend: function (XMLHttpRequest) {
|
||||
$(".loading").show();
|
||||
},
|
||||
success:function (data, textStatus) {
|
||||
$(".sightingsdiv").html(data);
|
||||
},
|
||||
complete:function() {
|
||||
$(".loading").hide();
|
||||
},
|
||||
type:"get",
|
||||
cache: false,
|
||||
url: url,
|
||||
});
|
||||
}
|
||||
|
||||
function quickEditEvent(id, field) {
|
||||
$.ajax({
|
||||
async:true,
|
||||
|
@ -2831,7 +2918,7 @@ function checkAndSetPublishedInfo() {
|
|||
|
||||
$(document).keyup(function(e){
|
||||
if (e.keyCode === 27) {
|
||||
$("#gray_out").fadeOut();
|
||||
$("#gray_out").fadeOut();
|
||||
$("#popover_form").fadeOut();
|
||||
$("#screenshot_box").fadeOut();
|
||||
$("#confirmation_box").fadeOut();
|
||||
|
@ -2844,3 +2931,9 @@ function closeScreenshot() {
|
|||
$("#screenshot_box").fadeOut();
|
||||
$("#gray_out").fadeOut();
|
||||
}
|
||||
|
||||
function loadSightingGraph(id, scope) {
|
||||
$.get( "/sightings/viewSightings/" + id + "/" + scope, function(data) {
|
||||
$("#sightingsData").html(data);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue