Merge branch '2.4' into issues_1643

pull/1809/head
devnull- 2017-02-28 15:47:28 +01:00 committed by GitHub
commit 89e76bc859
55 changed files with 1140 additions and 357 deletions

View File

@ -138,7 +138,14 @@ service apache2 reload
# Check out the /var/www/MISP/INSTALL/apache.misp.ssl file for an example
8/ MISP configuration
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
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config

View File

@ -185,7 +185,14 @@ sudo systemctl restart apache2
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
9/ MISP configuration
9/ 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
10/ MISP configuration
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
sudo -u www-data cp -a /var/www/MISP/app/Config/bootstrap.default.php /var/www/MISP/app/Config/bootstrap.php

View File

@ -129,7 +129,14 @@ service apache2 reload
# Check out the apache.misp.ssl file for an example
8/ MISP configuration
-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
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config

View File

@ -186,6 +186,13 @@ sudo systemctl restart apache2
sudo cp INSTALL/misp.logrotate /etc/logrotate.d/misp
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
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied

View File

@ -221,7 +221,7 @@ CREATE TABLE IF NOT EXISTS `feeds` (
`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 '',
`settings` text,
`input_source` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT "network",
`delete_local_file` tinyint(1) DEFAULT 0,
PRIMARY KEY (`id`),
@ -346,10 +346,10 @@ 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 COLLATE utf8_bin NOT NULL DEFAULT "",
`change` text COLLATE utf8_bin,
`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,
`description` text CHARACTER SET utf8 COLLATE utf8_bin,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

10
INSTALL/misp.logrotate Normal file
View File

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

8
INSTALL/misplogrotate.te Normal file
View File

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

View File

@ -177,7 +177,14 @@ service iptables save
# Check out the apache.misp.ssl file for an example
8/ MISP configuration
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
---------------------
# There are 4 sample configuration files in /var/www/MISP/app/Config that need to be copied
cd /var/www/MISP/app/Config

View File

@ -194,7 +194,24 @@ firewall-cmd --reload
# Check out the apache.misp.ssl file for an example
8/ MISP configuration
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
---------------------
# 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

@ -1 +1 @@
Subproject commit a81f6b5c15e2effbc0b6118f1e1524b0950a576c
Subproject commit 4be491b7a0427ea214f0e06dc03184a5f4ed7b05

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":66}
{"major":2, "minor":4, "hotfix":67}

View File

@ -1,8 +1,16 @@
#!/bin/bash
# Check if run as root
if [ "$EUID" -eq 0 ]; then
echo "Please DO NOT run the worker script as root"
exit 1
fi
# Extract base directory where this script is and cd into it
cd "${0%/*}"
../cake CakeResque.CakeResque stop --all
../cake CakeResque.CakeResque start --interval 5 --queue default
../cake CakeResque.CakeResque start --interval 5 --queue prio
../cake CakeResque.CakeResque start --interval 5 --queue cache
../cake CakeResque.CakeResque start --interval 5 --queue email
../cake CakeResque.CakeResque startscheduler -i 5
../cake CakeResque.CakeResque startscheduler --interval 5

View File

@ -46,7 +46,7 @@ class AppController extends Controller {
public $helpers = array('Utility');
private $__jsVersion = '2.4.66';
private $__jsVersion = '2.4.67';
public $pyMispVersion = '2.4.65';
public $phpmin = '5.6.5';
public $phprec = '7.0.0';
@ -329,6 +329,7 @@ class AppController extends Controller {
$this->set('isAclTagEditor', $role['perm_tag_editor']);
$this->set('isAclTemplate', $role['perm_template']);
$this->set('isAclSharingGroup', $role['perm_sharing_group']);
$this->set('isAclSighting', isset($role['perm_sighting']) ? $role['perm_sighting'] : false);
$this->userRole = $role;
} else {
$this->set('me', false);

View File

@ -285,13 +285,13 @@ class ACLComponent extends Component {
'view' => array('*'),
),
'sightings' => array(
'add' => array('perm_add'),
'advanced' => array('perm_add'),
'delete' => array('perm_add'),
'add' => array('perm_sighting'),
'advanced' => array('perm_sighting'),
'delete' => array('perm_sighting'),
'index' => array('*'),
'listSightings' => array('perm_add'),
'quickDelete' => array('perm_add'),
'viewSightings' => array('perm_add')
'listSightings' => array('perm_sighting'),
'quickDelete' => array('perm_sighting'),
'viewSightings' => array('perm_sighting')
),
'tags' => array(
'add' => array('perm_tag_editor'),
@ -355,8 +355,10 @@ class ACLComponent extends Component {
'admin_email' => array('perm_admin'),
'admin_filterUserIndex' => array('perm_admin'),
'admin_index' => array('perm_admin'),
'admin_quickEmail' => array('perm_admin'),
'admin_view' => array('perm_admin'),
'arrayCopy' => array(),
'attributehistogram' => array('*'),
'change_pw' => array('*'),
'checkAndCorrectPgps' => array(),
'dashboard' => array('*'),
@ -369,7 +371,6 @@ class ACLComponent extends Component {
'initiatePasswordReset' => array('perm_admin'),
'login' => array('*'),
'logout' => array('*'),
'attributehistogram' => array('*'),
'resetauthkey' => array('*'),
'request_API' => array('*'),
'routeafterlogin' => array('*'),

View File

@ -12,6 +12,10 @@ class RestResponseComponent extends Component {
'admin_edit' => array(
'description' => "POST a User object in JSON format to this API to edit a user.",
'optional' => array('email', 'org_id', 'role_id', 'password', 'external_auth_required', 'external_auth_key', 'enable_password', 'nids_sid', 'server_id', 'gpgkey', 'certif_public', 'autoalert', 'contactalert', 'disabled', 'change_pw', 'termsaccepted', 'newsread')
),
'admin_quickEmail' => array(
'description' => "POST a body and a subject in a JSON to send an e-mail through MISP to the user ID given in the URL",
'mandatory' => array('subject', 'body')
)
),
'Organisation' => array(

View File

@ -738,6 +738,8 @@ class EventsController extends AppController {
$this->set($variable, $currentModel->{$variable});
}
}
$sightingsData = $this->Event->getSightingData($event);
$this->set('sightingsData', $sightingsData);
if (Configure::read('Plugin.Enrichment_services_enable')) {
$this->loadModel('Module');
$modules = $this->Module->getEnabledModules();
@ -853,7 +855,8 @@ class EventsController extends AppController {
'recursive' => -1,
'contain' => array('Org', 'RequesterOrg'))));
}
$sightingsData = $this->Event->getSightingData($event);
$this->set('sightingsData', $sightingsData);
if (Configure::read('Plugin.Enrichment_services_enable')) {
$this->loadModel('Module');
$modules = $this->Module->getEnabledModules();
@ -3097,6 +3100,8 @@ class EventsController extends AppController {
foreach (${$source} as $k => $attribute) {
if ($attribute['type'] == 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
} else if ($attribute['type'] == 'ip-src|port/ip-dst|port') {
$types = array('ip-src|port', 'ip-dst|port');
} else if ($attribute['type'] == 'malware-sample') {
if (!isset($attribute['data_is_handled']) || !$attribute['data_is_handled']) {
App::uses('FileAccessTool', 'Tools');

View File

@ -12,32 +12,78 @@ class GalaxyClustersController extends AppController {
'GalaxyCluster.value' => 'ASC'
),
'contain' => array(
'Tag' => array(
'fields' => array('Tag.id'),
'EventTag' => array(
'fields' => array('EventTag.event_id')
),
'AttributeTag' => array(
'fields' => array('AttributeTag.event_id', 'AttributeTag.attribute_id')
)
),
'GalaxyElement' => array(
'conditions' => array('GalaxyElement.key' => 'synonyms'),
'fields' => array('value')
)
),
)
);
public function index($id) {
$this->paginate['conditions'] = array('GalaxyCluster.galaxy_id' => $id);
$clusters = $this->paginate();
$tagIds = array();
$sightings = array();
if (!empty($clusters)) {
$galaxyType = $clusters[0]['GalaxyCluster']['type'];
$tagPattern = 'misp-galaxy:' . $galaxyType . '="%s"';
$tags = $this->GalaxyCluster->getTags($galaxyType, false, $this->Auth->user());
foreach ($clusters as $k => $v) {
$clusters[$k]['event_ids'] = array();
if (!empty($v['Tag']['EventTag'])) {
$tagIds[] = $v['Tag']['id'];
$clusters[$k]['GalaxyCluster']['tags'] = array('tag_id' => $v['Tag']['id'], 'count' => count($v['Tag']['EventTag']));
foreach ($v['Tag']['EventTag'] as $eventTag) {
$clusters[$k]['event_ids'][] = $eventTag['event_id'];
}
} else {
$clusters[$k]['GalaxyCluster']['tags'] = 0;
}
$clusters[$k]['GalaxyCluster']['synonyms'] = array();
foreach ($v['GalaxyElement'] as $element) {
$clusters[$k]['GalaxyCluster']['synonyms'][] = $element['value'];
}
if (isset($tags[sprintf($tagPattern, $v['GalaxyCluster']['value'])])) {
$clusters[$k]['GalaxyCluster']['tags'] = $tags[sprintf($tagPattern, $v['GalaxyCluster']['value'])];
}
}
$this->loadModel('Sighting');
$sightings['event'] = $this->Sighting->getSightingsForObjectIds($this->Auth->user(), $tagIds);
foreach ($clusters as $k => $cluster) {
$objects = array('event');
foreach ($objects as $object) {
foreach ($cluster[$object . '_ids'] as $objectid) {
if (isset($sightings[$object][$objectid])) {
foreach ($sightings[$object][$objectid] as $date => $sightingCount) {
if (!isset($cluster['sightings'][$date])) {
$cluster['sightings'][$date] = $sightingCount;
} else {
$cluster['sightings'][$date] += $sightingCount;
}
}
}
}
}
$startDate = !empty($cluster['sightings']) ? min(array_keys($cluster['sightings'])) : date('Y-m-d');
$startDate = date('Y-m-d', strtotime("-3 days", strtotime($startDate)));
$to = date('Y-m-d', time());
for ($date = $startDate; strtotime($date) <= strtotime($to); $date = date('Y-m-d',strtotime("+1 day", strtotime($date)))) {
if (!isset($csv[$k])) {
$csv[$k] = 'Date,Close\n';
}
if (isset($cluster['sightings'][$date])) {
$csv[$k] .= $date . ',' . $cluster['sightings'][$date] . '\n';
} else {
$clusters[$k]['GalaxyCluster']['tags'] = 0;
$csv[$k] .= $date . ',0\n';
}
}
}
$this->set('csv', $csv);
$this->set('list', $clusters);
if ($this->request->is('ajax')) {
$this->layout = 'ajax';

View File

@ -31,8 +31,10 @@ class SightingsController extends AppController {
$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 $error = 'No valid values found that could be extracted from the sightings document.';
} else {
$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'];
@ -48,9 +50,12 @@ class SightingsController extends AppController {
$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 (!$error) {
$result = $this->Sighting->saveSightings($id, $values, $timestamp, $this->Auth->user(), $type, $source);
}
if (!is_numeric($result)) {
$error = $result;
}
if ($this->request->is('ajax')) {
if ($error) {
$error_message = 'Could not add the Sighting. Reason: ' . $error;
@ -82,17 +87,26 @@ class SightingsController extends AppController {
}
}
public function advanced($id) {
public function advanced($id, $context = 'attribute') {
if (empty($id)) {
throw new MethodNotAllowedException('Invalid attribute.');
throw new MethodNotAllowedException('Invalid ' . $context . '.');
}
$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.');
if ($context == 'attribute') {
$this->loadModel('Attribute');
$attributes = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id)));
if (empty($attributes)) {
throw new MethodNotAllowedException('Invalid attribute.');
}
} else {
$this->loadModel('Event');
$events = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id, 'metadata' => true));
if (empty($events)) {
throw new MethodNotAllowedException('Invalid event.');
}
}
$this->set('context', $context);
$this->set('id', $input_id);
$this->render('/Sightings/ajax/advanced');
}
@ -242,12 +256,16 @@ class SightingsController extends AppController {
}
$tsv = 'date\tSighting\tFalse-positive\n';
$dataPoints = array();
$startDate = (date('Ymd') - 3);
$startDate = (date('Ymd'));
$details = array();
$range = (!empty(Configure::read('MISP.Sightings_range')) && is_numeric(Configure::read('MISP.Sightings_range'))) ? Configure::read('MISP.Sightings_range') : 365;
$range = date('Ymd', strtotime("-" . $range . " days", time()));
foreach ($results as $type => $data) {
foreach ($data as $date => $sighting) {
if ($date < $startDate) {
$startDate = $date;
if ($date >= $range) {
$startDate = $date;
}
}
$temp = array();
foreach ($sighting as $sightingInstance) {
@ -261,6 +279,7 @@ class SightingsController extends AppController {
$dataPoints[$date][$type] = array('count' => count($sighting), 'details' => $temp);
}
}
$startDate = date('Ymd',strtotime("-3 days", strtotime($startDate)));
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';

View File

@ -11,11 +11,11 @@ class TagsController extends AppController {
'Tag.name' => 'asc'
),
'contain' => array(
'AttributeTag' => array(
'fields' => array('attribute_id')
),
'EventTag' => array(
'fields' => array('event_id')
'fields' => array('EventTag.event_id')
),
'AttributeTag' => array(
'fields' => array('AttributeTag.event_id', 'AttributeTag.attribute_id')
),
'FavouriteTag',
'Organisation' => array(
@ -49,9 +49,13 @@ class TagsController extends AppController {
} else {
$paginated = $this->paginate();
}
$tagList = array();
$csv = array();
foreach ($paginated as $k => $tag) {
if (empty($tag['EventTag'])) $paginated[$k]['Tag']['count'] = 0;
else {
$tagList[] = $tag['Tag']['id'];
if (empty($tag['EventTag'])) {
$paginated[$k]['Tag']['count'] = 0;
} else {
$eventIDs = array();
foreach ($tag['EventTag'] as $eventTag) {
$eventIDs[] = $eventTag['event_id'];
@ -72,7 +76,16 @@ class TagsController extends AppController {
));
$paginated[$k]['Tag']['count'] = count($events);
}
$paginated[$k]['event_ids'] = array();
$paginated[$k]['attribute_ids'] = array();
foreach($paginated[$k]['EventTag'] as $et) {
$paginated[$k]['event_ids'][] = $et['event_id'];
}
unset($paginated[$k]['EventTag']);
foreach($paginated[$k]['AttributeTag'] as $at) {
$paginated[$k]['attribute_ids'][] = $at['attribute_id'];
}
if (empty($tag['AttributeTag'])) {
$paginated[$k]['Tag']['attribute_count'] = 0;
} else {
@ -118,6 +131,39 @@ class TagsController extends AppController {
}
}
}
$this->loadModel('Sighting');
$sightings['event'] = $this->Sighting->getSightingsForObjectIds($this->Auth->user(), $tagList);
$sightings['attribute'] = $this->Sighting->getSightingsForObjectIds($this->Auth->user(), $tagList, 'attribute');
foreach ($paginated as $k => $tag) {
$objects = array('event', 'attribute');
foreach ($objects as $object) {
foreach ($tag[$object . '_ids'] as $objectid) {
if (isset($sightings[$object][$objectid])) {
foreach ($sightings[$object][$objectid] as $date => $sightingCount) {
if (!isset($tag['sightings'][$date])) {
$tag['sightings'][$date] = $sightingCount;
} else {
$tag['sightings'][$date] += $sightingCount;
}
}
}
}
}
$startDate = !empty($tag['sightings']) ? min(array_keys($tag['sightings'])) : date('Y-m-d');
$startDate = date('Y-m-d', strtotime("-3 days", strtotime($startDate)));
$to = date('Y-m-d', time());
for ($date = $startDate; strtotime($date) <= strtotime($to); $date = date('Y-m-d',strtotime("+1 day", strtotime($date)))) {
if (!isset($csv[$k])) {
$csv[$k] = 'Date,Close\n';
}
if (isset($tag['sightings'][$date])) {
$csv[$k] .= $date . ',' . $tag['sightings'][$date] . '\n';
} else {
$csv[$k] .= $date . ',0\n';
}
}
unset($paginated[$k]['event_ids']);
}
if ($this->_isRest()) {
foreach ($paginated as $key => $tag) {
$paginated[$key] = $tag['Tag'];
@ -125,6 +171,7 @@ class TagsController extends AppController {
$this->set('Tag', $paginated);
$this->set('_serialize', array('Tag'));
} else {
$this->set('csv', $csv);
$this->set('list', $paginated);
$this->set('favouritesOnly', $favouritesOnly);
}

View File

@ -39,11 +39,16 @@ class UsersController extends AppController {
}
$this->User->id = $id;
$this->User->recursive = 0;
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
$this->set('user', $this->User->read(null, $id));
$user = $this->User->read(null, $id);
if (!empty($user['User']['gpgkey'])) {
$pgpDetails = $this->User->verifySingleGPG($user);
$user['User']['pgp_status'] = isset($pgpDetails[2]) ? $pgpDetails[2] : 'OK';
$user['User']['fingerprint'] = !empty($pgpDetails[4]) ? $pgpDetails[4] : 'N/A';
}
$this->set('user', $user);
}
public function request_API(){
@ -293,13 +298,20 @@ class UsersController extends AppController {
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
$this->set('user', $this->User->read(null, $id));
if (!$this->_isSiteAdmin() && !($this->_isAdmin() && $this->Auth->user('org_id') == $this->User->data['User']['org_id'])) {
$user = $this->User->read(null, $id);
if (!empty($user['User']['gpgkey'])) {
$pgpDetails = $this->User->verifySingleGPG($user);
$user['User']['pgp_status'] = isset($pgpDetails[2]) ? $pgpDetails[2] : 'OK';
$user['User']['fingerprint'] = !empty($pgpDetails[4]) ? $pgpDetails[4] : 'N/A';
}
$user['User']['orgAdmins'] = $this->User->getOrgAdminsForOrg($user['User']['org_id'], $user['User']['id']);
$this->set('user', $user);
if (!$this->_isSiteAdmin() && !($this->_isAdmin() && $this->Auth->user('org_id') == $user['User']['org_id'])) {
throw new MethodNotAllowedException();
}
if ($this->_isRest()) {
$this->User->data['User']['password'] = '*****';
return $this->RestResponse->viewData(array('User' => $this->User->data['User']), $this->response->type());
$user['User']['password'] = '*****';
return $this->RestResponse->viewData(array('User' => $user['User']), $this->response->type());
} else {
$temp = $this->User->data['User']['invited_by'];
$this->set('id', $id);
@ -346,6 +358,7 @@ class UsersController extends AppController {
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'authkey' => $this->User->generateAuthKey(),
'termsaccepted' => 0
);
foreach ($defaults as $key => $value) {
@ -975,6 +988,76 @@ class UsersController extends AppController {
$this->set('fails', $this->User->checkAndCorrectPgps());
}
public function admin_quickEmail($user_id) {
if (!$this->_isAdmin()) throw new MethodNotAllowedException();
$conditions = array('User.id' => $user_id);
if (!$this->_isSiteAdmin()) {
$conditions['User.org_id'] = $this->Auth->user('org_id');
}
$user = $this->User->find('first', array(
'conditions' => $conditions,
'recursive' => -1
));
$error = false;
if (empty($user)) {
$error = 'Invalid user.';
}
if (!$error && $user['User']['disabled']) {
$error = 'Cannot send an e-mail to this user as the account is disabled.';
}
$encryption = false;
if (!$error && !empty($user['User']['gpgkey'])) {
$encryption = 'PGP';
} else if (!$error && !empty($user['User']['certif_public'])){
$encryption = 'SMIME';
}
$this->set('encryption', $encryption);
if (!$error && !$encryption && (Configure::read('GnuPG.onlyencrypted') || Configure::read('GnuPG.bodyonlyencrypted'))) {
$error = 'No encryption key found for the user and the instance posture blocks non encrypted e-mails from being sent.';
}
if ($error) {
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Users', 'admin_quickEmail', false, $error, $this->response->type());
} else {
$this->Session->setFlash('Cannot send an e-mail to this user as the account is disabled.');
$this->redirect('/admin/users/view/' . $user_id);
}
}
if ($this->request->is('post')) {
if (!isset($this->request->data['User'])) {
$this->request->data['User'] = $this->request->data;
}
if (empty($this->request->data['User']['subject']) || empty($this->request->data['User']['body'])) {
$message = 'Both the subject and the body have to be set.';
if ($this->_isRest()) {
throw new MethodNotAllowedException($message);
} else {
$this->Session->setFlash($message);
$this->redirect('/admin/users/quickEmail/' . $user_id);
}
}
$result = $this->User->sendEmail($user, $this->request->data['User']['body'], false, $this->request->data['User']['subject']);
if ($this->_isRest()) {
if ($result) {
return $this->RestResponse->saveSuccessResponse('User', 'admin_quickEmail', $id, $this->response->type(), 'User deleted.');
} else {
return $this->RestResponse->saveFailResponse('Users', 'admin_quickEmail', false, $this->User->validationErrors, $this->response->type());
}
} else {
if ($result) {
$this->Session->setFlash('Email sent.');
} else {
$this->Session->setFlash('Could not send e-mail.');
}
$this->redirect('/admin/users/view/' . $user_id);
}
} else if ($this->_isRest()) {
return $this->RestResponse->describe('Users', 'admin_quickEmail', false, $this->response->type());
}
$this->set('encryption', $encryption);
$this->set('user', $user);
}
public function admin_email() {
if (!$this->_isAdmin()) throw new MethodNotAllowedException();
// User has filled in his contact form, send out the email.

View File

@ -8,6 +8,7 @@ class ComplexTypeTool {
'/^h\[tt\]p/i' => 'http',
'/\[\.\]/' => '.',
'/\[dot\]/' => '.',
'/\(dot\)/' => '.',
'/\\\\\./' => '.',
'/\.+/' => '.'
);
@ -217,7 +218,13 @@ class ComplexTypeTool {
$inputRefangedNoPort = $inputRefanged;
}
// check for IP
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) {
if (isset($port)) {
return array('types' => array('ip-dst|port', 'ip-src|port', 'ip-src|port/ip-dst|port'), 'to_ids' => true, 'default_type' => 'ip-dst|port', 'comment' => $comment, 'value' => $inputRefangedNoPort . '|' . $port);
} else {
return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
}
}
if (strpos($inputRefangedNoPort, '/')) {
$temp = explode('/', $inputRefangedNoPort);
if (count($temp) == 2) {

View File

@ -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, 66 => false
63 => false, 64 => false, 65 => false, 66 => false, 67 => true
)
)
);
@ -84,6 +84,12 @@ class AppModel extends Model {
$this->Sighting = Classregistry::init('Sighting');
$this->Sighting->addUuids();
break;
case '2.4.67':
$this->updateDatabase('2.4.67');
$this->Sighting = Classregistry::init('Sighting');
$this->Sighting->addUuids();
$this->Sighting->deleteAll(array('NOT' => array('Sighting.type' => array(0, 1, 2))));
break;
default:
$this->updateDatabase($command);
break;
@ -617,6 +623,10 @@ class AppModel extends Model {
$indexArray[] = array('shadow_attributes', 'category');
$indexArray[] = array('shadow_attributes', 'type');
break;
case '2.4.67':
$sqlArray[] = "ALTER TABLE `roles` ADD `perm_sighting` tinyint(1) NOT NULL DEFAULT 0;";
$sqlArray[] = 'UPDATE `roles` SET `perm_sighting` = 1 WHERE `perm_add` = 1;';
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;';

View File

@ -330,7 +330,7 @@ class Attribute extends AppModel {
// This helps generate quick filtering for the event view, but we may reuse this and enhance it in the future for other uses (such as the API?)
public $typeGroupings = array(
'file' => array('attachment', 'pattern-in-file', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'authentihash', 'pehash', 'tlsh', 'filename', 'filename|md5', 'filename|sha1', 'filename|sha224', 'filename|sha256', 'filename|sha384', 'filename|sha512', 'filename|sha512/224', 'filename|sha512/256', 'filename|authentihash', 'filename|ssdeep', 'filename|tlsh', 'filename|imphash', 'filename|pehash', 'malware-sample', 'x509-fingerprint-sha1'),
'network' => array('ip-src', 'ip-dst', 'hostname', 'domain', 'domain|ip', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-traffic', 'x509-fingerprint-sha1'),
'network' => array('ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port', 'hostname', 'hostname|port', 'domain', 'domain|ip', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-traffic', 'x509-fingerprint-sha1'),
'financial' => array('btc', 'iban', 'bic', 'bank-account-nr', 'aba-rtn', 'bin', 'cc-number', 'prtn')
);
@ -462,6 +462,10 @@ class Attribute extends AppModel {
public $hasMany = array(
'AttributeTag' => array(
'dependent' => true
),
'Sighting' => array(
'className' => 'Sighting',
'dependent' => true,
)
);
@ -785,7 +789,7 @@ class Attribute extends AppModel {
break;
case 'hostname':
case 'domain':
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z]{2,}$#i", $value)) {
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z0-9\-]{2,}$#i", $value)) {
$returnValue = true;
} else {
$returnValue = 'Domain name has an invalid format. Please double check the value or select type "other".';
@ -793,14 +797,14 @@ class Attribute extends AppModel {
break;
case 'hostname|port':
$parts = explode('|', $value);
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z]{2,}$#i", $parts[0])) {
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z0-9\-]{2,}$#i", $parts[0])) {
if (!is_numeric($parts[1]) || $parts[1] > 1 || $parts[1] < 65536) {
$returnValue = true;
}
}
break;
case 'domain|ip':
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z]{2,}\|.*$#i", $value)) {
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z0-9\-]{2,}\|.*$#i", $value)) {
$parts = explode('|', $value);
if (filter_var($parts[1], FILTER_VALIDATE_IP)) {
$returnValue = true;
@ -818,7 +822,7 @@ class Attribute extends AppModel {
case 'dns-soa-email':
case 'jabber-id':
// we don't use the native function to prevent issues with partial email addresses
if (preg_match("#^[A-Z0-9._&%+-=~]*@[A-Z0-9.\-_]+\.[A-Z]{2,}$#i", $value)) {
if (preg_match("#^[A-Z0-9._&%+-=~]*@[A-Z0-9.\-_]+\.[A-Z0-9\-]{2,}$#i", $value)) {
$returnValue = true;
} else {
$returnValue = 'Email address has an invalid format. Please double check the value or select type "other".';
@ -2077,6 +2081,18 @@ class Attribute extends AppModel {
return $conditions;
}
public function listVisibleAttributes($user, $options = array()) {
$params = array(
'conditions' => $this->buildConditions($user),
'recursive' => -1,
'fields' => array('Attribute.id', 'Attribute.id'),
);
if (isset($options['conditions'])) {
$params['conditions']['AND'][] = $options['conditions'];
}
return $this->find('list', $params);
}
// Method that fetches all attributes for the various exports
// very flexible, it's basically a replacement for find, with the addition that it restricts access based on user
// options:

137
app/Model/Event.php Normal file → Executable file
View File

@ -318,6 +318,10 @@ class Event extends AppModel {
'EventTag' => array(
'className' => 'EventTag',
'dependent' => true,
),
'Sighting' => array(
'className' => 'Sighting',
'dependent' => true,
)
);
@ -825,6 +829,21 @@ class Event extends AppModel {
return 'Success';
}
public function addHeaders($request) {
$version = $this->checkMISPVersion();
$version = implode('.', $version);
try {
$commit = trim(shell_exec('git log --pretty="%H" -n1 HEAD'));
} catch (Exception $e) {
$commit = false;
}
$request['header']['MISP-version'] = $version;
if ($commit) {
$request['header']['commit'] = $commit;
}
return $request;
}
// Uploads the event and the associated Attributes to another Server
public function restfulEventToServer($event, $server, $urlPath, &$newLocation, &$newTextBody, $HttpSocket = null) {
if ($event['Event']['distribution'] == 4) {
@ -855,9 +874,11 @@ class Event extends AppModel {
'Authorization' => $authkey,
'Accept' => 'application/json',
'Content-Type' => 'application/json',
//'Connection' => 'keep-alive' // // LATER followup cakephp issue about this problem: https://github.com/cakephp/cakephp/issues/1961
)
);
$request = $this->addHeaders($request);
$uri = $url . '/events';
if (isset($urlPath)) {
$pieces = explode('/', $urlPath);
@ -924,8 +945,14 @@ class Event extends AppModel {
// cleanup the array from things we do not want to expose
foreach (array('Org', 'org_id', 'orgc_id', 'proposal_email_lock', 'org', 'orgc') as $field) unset($event['Event'][$field]);
foreach ($event['Event']['EventTag'] as $kt => $tag) {
if (!$tag['Tag']['exportable']) unset($event['Event']['EventTag'][$kt]);
if (!$tag['Tag']['exportable']) {
unset($event['Event']['EventTag'][$kt]);
} else {
unset($tag['org_id']);
$event['Event']['Tag'][] = $tag['Tag'];
}
}
unset($event['Event']['EventTag']);
// Add the local server to the list of instances in the SG
if (isset($event['Event']['SharingGroup']) && isset($event['Event']['SharingGroup']['SharingGroupServer'])) {
@ -967,6 +994,15 @@ 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']);
@ -1041,6 +1077,7 @@ class Event extends AppModel {
//'Connection' => 'keep-alive' // // LATER followup cakephp issue about this problem: https://github.com/cakephp/cakephp/issues/1961
)
);
$request = $this->addHeaders($request);
$uri = $url . '/events/0?uuid=' . $uuid;
// LATER validate HTTPS SSL certificate
@ -1072,6 +1109,7 @@ class Event extends AppModel {
//'Connection' => 'keep-alive' // // LATER followup cakephp issue about this problem: https://github.com/cakephp/cakephp/issues/1961
)
);
$request = $this->addHeaders($request);
$uri = $url . '/events/view/' . $eventId . '/deleted:true';
$response = $HttpSocket->get($uri, $data = '', $request);
if ($response->isOk()) {
@ -1096,6 +1134,7 @@ class Event extends AppModel {
//'Connection' => 'keep-alive' // LATER followup cakephp issue about this problem: https://github.com/cakephp/cakephp/issues/1961
)
);
$request = $this->addHeaders($request);
$uri = $url . '/shadow_attributes/getProposalsByUuidList';
$response = $HttpSocket->post($uri, json_encode($uuidList), $request);
if ($response->isOk()) {
@ -1341,6 +1380,11 @@ class Event extends AppModel {
$this->Sighting = ClassRegistry::init('Sighting');
}
foreach ($results as $eventKey => &$event) {
// Add information for auditor user
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;
}
// unset the empty sharing groups that are created due to the way belongsTo is handled
if (isset($event['SharingGroup']['SharingGroupServer'])) {
foreach ($event['SharingGroup']['SharingGroupServer'] as &$sgs) {
@ -1464,6 +1508,10 @@ class Event extends AppModel {
}
$event['ShadowAttribute'] = array_values($event['ShadowAttribute']);
}
if ($event['Event']['orgc_id'] === $user['org_id'] && $user['Role']['perm_audit']) {
$UserEmail = $this->User->getAuthUser($event['Event']['user_id'])['email'];
$event['Event']['event_creator_email'] = $UserEmail;
}
}
return $results;
}
@ -2028,8 +2076,8 @@ class Event extends AppModel {
}
// FIXME chri: validatebut the necessity for all these fields...impact on security !
$fieldList = array(
'Event' => array('org_id', 'orgc_id', 'date', 'threat_level_id', 'analysis', 'info', 'user_id', 'published', 'uuid', 'timestamp', 'distribution', 'sharing_group_id', 'locked'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'timestamp', 'distribution', 'comment', 'sharing_group_id', 'deleted'),
'Event' => array('org_id', 'orgc_id', 'date', 'threat_level_id', 'analysis', 'info', 'user_id', 'published', 'uuid', 'timestamp', 'distribution', 'sharing_group_id', 'locked', 'disable_correlation'),
'Attribute' => array('event_id', 'category', 'type', 'value', 'value1', 'value2', 'to_ids', 'uuid', 'timestamp', 'distribution', 'comment', 'sharing_group_id', 'deleted', 'disable_correlation'),
);
$saveResult = $this->save(array('Event' => $data['Event']), array('fieldList' => $fieldList['Event']));
$this->Log = ClassRegistry::init('Log');
@ -2441,7 +2489,8 @@ class Event extends AppModel {
'fields' => array('id', 'url', 'name')
)
),
)
),
'AttributeTag' => array('Tag')
),
'EventTag' => array('Tag'),
'Org' => array('fields' => array('id', 'uuid', 'name', 'local')),
@ -3147,4 +3196,84 @@ class Event extends AppModel {
'response' => $module['mispattributes']['responseType']
);
}
public function getSightingData($event) {
$this->Sighting = ClassRegistry::init('Sighting');
if (!empty($event['Sighting'])) {
$attributeSightings = array();
$attributeOwnSightings = array();
$attributeSightingsPopover = array();
$sightingsData = array();
$sparklineData = array();
$startDates = array();
$range = (!empty(Configure::read('MISP.Sightings_range')) && is_numeric(Configure::read('MISP.Sightings_range'))) ? Configure::read('MISP.Sightings_range') : 365;
$range = strtotime("-" . $range . " days", time());
foreach ($event['Sighting'] as $sighting) {
$type = $this->Sighting->type[$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 ($sighting['type'] == '0' && (!isset($startDates[$sighting['attribute_id']]) || $startDates[$sighting['attribute_id']] > $sighting['date_sighting'])) {
if ($sighting['date_sighting'] >= $range) {
$startDates[$sighting['attribute_id']] = $sighting['date_sighting'];
}
}
if ($sighting['type'] == '0' && (!isset($startDates['event']) || $startDates['event'] > $sighting['date_sighting'])) {
if ($sighting['date_sighting'] >= $range) {
$startDates['event'] = $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'];
}
}
$date = date("Y-m-d", $sighting['date_sighting']);
if (!isset($sparklineData[$sighting['attribute_id']][$date])) {
$sparklineData[$sighting['attribute_id']][$date] = 1;
} else {
$sparklineData[$sighting['attribute_id']][$date]++;
}
if (!isset($sparklineData['event'][$date])) {
$sparklineData['event'][$date] = 1;
} else {
$sparklineData['event'][$date]++;
}
}
$csv = array();
foreach ($startDates as $k => $v) {
$startDates[$k] = date('Y-m-d', $v);
}
$range = (!empty(Configure::read('MISP.Sightings_range')) && is_numeric(Configure::read('MISP.Sightings_range'))) ? Configure::read('MISP.Sightings_range') : 365;
foreach ($sparklineData as $aid => $data) {
$startDate = $startDates[$aid];
if (strtotime($startDate) < strtotime('-' . $range . ' days', time())) {
$startDate = date('Y-m-d');
}
$startDate = date('Y-m-d',strtotime("-3 days", strtotime($startDate)));
$to = date('Y-m-d', time());
$sighting = $data;
for ($date = $startDate; strtotime($date) <= strtotime($to); $date = date('Y-m-d',strtotime("+1 day", strtotime($date)))) {
if (!isset($csv[$aid])) {
$csv[$aid] = 'Date,Close\n';
}
if (isset($sighting[$date])) {
$csv[$aid] .= $date . ',' . $sighting[$date] . '\n';
} else {
$csv[$aid] .= $date . ',0\n';
}
}
}
return array(
'data' => $sightingsData,
'csv' => $csv
);
}
return array('data' => array(), 'csv' => array());
}
}

View File

@ -122,6 +122,9 @@ class Feed extends AppModel {
if (isset($feed['Feed']['input_source']) && $feed['Feed']['input_source'] == 'local') {
if (file_exists($feed['Feed']['url'] . '/manifest.json')) {
$data = file_get_contents($feed['Feed']['url'] . '/manifest.json');
if (empty($data)) return false;
} else {
throw new NotFoundException('Invalid file.');
}
} else {
$uri = $feed['Feed']['url'] . '/manifest.json';
@ -655,12 +658,20 @@ class Feed extends AppModel {
if (empty($data)) {
return true;
}
$prunedCopy = array();
foreach ($data as $key => $value) {
foreach ($prunedCopy as $copy) {
if ($copy['type'] == $value['type'] && $copy['category'] == $value['category'] && $copy['value'] == $value['value']) {
continue 2;
}
}
$data[$key]['event_id'] = $event['Event']['id'];
$data[$key]['distribution'] = $feed['Feed']['distribution'];
$data[$key]['sharing_group_id'] = $feed['Feed']['sharing_group_id'];
$data[$key]['to_ids'] = $feed['Feed']['override_ids'] ? 0 : $data[$key]['to_ids'];
$prunedCopy[] = $data[$key];
}
$data = $prunedCopy;
if ($jobId) {
$job = ClassRegistry::init('Job');
$job->id = $jobId;

View File

@ -19,9 +19,8 @@ class GalaxyCluster extends AppModel{
'foreignKey' => 'galaxy_id',
),
'Tag' => array(
'className' => 'Tag',
'foreignKey' => false,
'Tag.name = GalaxyCluster.tag_name'
'conditions' => array('GalaxyCluster.tag_name = Tag.name')
)
);

View File

@ -87,6 +87,12 @@ class Log extends AppModel {
}
if (!isset($this->data['Log']['created'])) $this->data['Log']['created'] = date('Y-m-d H:i:s');
if (!isset($this->data['Log']['org'])) $this->data['Log']['org'] = 'SYSTEM';
if (isset($this->data['Log']['title'])) {
if (strlen($this->data['Log']['title']) >= 65535) {
$this->data['Log']['title'] = substr($this->data['Log']['title'], 0, 65532) . '...';
}
}
return true;
}

View File

@ -39,22 +39,24 @@ class Role extends AppModel {
);
public $permFlags = array(
'perm_admin' => array('id' => 'RolePermAdmin', 'text' => 'Admin'),
'perm_site_admin' => array('id' => 'RolePermSiteAdmin', 'text' => 'Site Admin'),
'perm_sync' => array('id' => 'RolePermSync', 'text' => 'Sync Actions'),
'perm_audit' => array('id' => 'RolePermAudit', 'text' => 'Audit Actions'),
'perm_auth' => array('id' => 'RolePermAuth', 'text' => 'Auth key access'),
'perm_regexp_access' => array('id' => 'RolePermRegexpAccess', 'text' => 'Regex Actions'),
'perm_tagger' => array('id' => 'RolePermTagger', 'text' => 'Tagger'),
'perm_tag_editor' => array('id' => 'RolePermTagEditor', 'text' => 'Tag Editor'),
'perm_template' => array('id' => 'RolePermTemplate', 'text' => 'Template Editor'),
'perm_sharing_group' => array('id' => 'RolePermSharingGroup', 'text' => 'Sharing Group Editor'),
'perm_delegate' => array('id' => 'RolePermDelegate', 'text' => 'Delegations access')
'perm_admin' => array('id' => 'RolePermAdmin', 'text' => 'Admin', 'readonlyenabled' => false),
'perm_site_admin' => array('id' => 'RolePermSiteAdmin', 'text' => 'Site Admin', 'readonlyenabled' => false),
'perm_sync' => array('id' => 'RolePermSync', 'text' => 'Sync Actions', 'readonlyenabled' => false),
'perm_audit' => array('id' => 'RolePermAudit', 'text' => 'Audit Actions', 'readonlyenabled' => true),
'perm_auth' => array('id' => 'RolePermAuth', 'text' => 'Auth key access', 'readonlyenabled' => true),
'perm_regexp_access' => array('id' => 'RolePermRegexpAccess', 'text' => 'Regex Actions', 'readonlyenabled' => false),
'perm_tagger' => array('id' => 'RolePermTagger', 'text' => 'Tagger', 'readonlyenabled' => false),
'perm_tag_editor' => array('id' => 'RolePermTagEditor', 'text' => 'Tag Editor', 'readonlyenabled' => false),
'perm_template' => array('id' => 'RolePermTemplate', 'text' => 'Template Editor', 'readonlyenabled' => false),
'perm_sharing_group' => array('id' => 'RolePermSharingGroup', 'text' => 'Sharing Group Editor', 'readonlyenabled' => false),
'perm_delegate' => array('id' => 'RolePermDelegate', 'text' => 'Delegations Access', 'readonlyenabled' => false),
'perm_sighting' => array('id' => 'RolePermSighting', 'text' => 'Sighting Creator', 'readonlyenabled' => true)
);
public $premissionLevelName = array('Read Only', 'Manage Own Events', 'Manage Organisation Events', 'Manage and Publish Organisation Events');
public function beforeSave($options = array()) {
//Conversion from the named data access permission levels
switch ($this->data['Role']['permission']) {
case '0':
$this->data['Role']['perm_add'] = 0;
@ -64,7 +66,7 @@ class Role extends AppModel {
break;
case '1':
$this->data['Role']['perm_add'] = 1;
$this->data['Role']['perm_modify'] = 1; // SHOULD BE true
$this->data['Role']['perm_modify'] = 1;
$this->data['Role']['perm_modify_org'] = 0;
$this->data['Role']['perm_publish'] = 0;
break;
@ -76,8 +78,8 @@ class Role extends AppModel {
break;
case '3':
$this->data['Role']['perm_add'] = 1;
$this->data['Role']['perm_modify'] = 1; // ?
$this->data['Role']['perm_modify_org'] = 1; // ?
$this->data['Role']['perm_modify'] = 1;
$this->data['Role']['perm_modify_org'] = 1;
$this->data['Role']['perm_publish'] = 1;
break;
default:

View File

@ -735,15 +735,6 @@ class Server extends AppModel {
'type' => 'boolean',
'null' => true
),
'showCorrelationsOnIndex' => array(
'level' => 1,
'description' => 'When enabled, the number of correlations visible to the currently logged in user will be visible on the event index UI. This comes at a performance cost but can be very useful to see correlating events at a glance.',
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
'type' => 'boolean',
'null' => true
),
),
'GnuPG' => array(
'branch' => 1,
@ -1137,6 +1128,14 @@ class Server extends AppModel {
'test' => 'testBool',
'type' => 'boolean',
),
'Sightings_range' => array(
'level' => 1,
'description' => 'Set the range in which sightings will be taken into account when generating graphs. For example a sighting with a sighted_date of 7 years ago might not be relevant anymore. Setting given in number of days, default is 365 days',
'value' => 365,
'errorMessage' => '',
'test' => 'testForNumeric',
'type' => 'numeric'
),
'CustomAuth_enable' => array(
'level' => 2,
'description' => 'Enable this functionality if you would like to handle the authentication via an external tool and authenticate with MISP using a custom header.',
@ -2126,10 +2125,40 @@ class Server extends AppModel {
return true;
}
public function getHost() {
if (function_exists('apache_request_headers')){
$headers = apache_request_headers();
} else {
$headers = $_SERVER;
}
if ( array_key_exists( 'X-Forwarded-Host', $headers ) ) {
$host = $headers['X-Forwarded-Host'];
} else {
$host = $_SERVER['HTTP_HOST'];
}
return $host;
}
public function getProto() {
if (function_exists('apache_request_headers')){
$headers = apache_request_headers();
} else {
$headers = $_SERVER;
}
if (array_key_exists('X-Forwarded-Proto',$headers)){
$proto = $headers['X-Forwarded-Proto'];
} else {
$proto = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) === true ? 'HTTPS' : 'HTTP';
}
return $proto;
}
public function testBaseURL($value) {
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) === true ? 'HTTPS' : 'HTTP';
if ($value != strtolower($protocol) . '://' . $_SERVER['HTTP_HOST']) return false;
if ($value != strtolower($this->getProto()) . '://' . $this->getHost()) return false;
return true;
}
@ -2374,12 +2403,18 @@ class Server extends AppModel {
public function serverSettingsSaveValue($setting, $value) {
Configure::write($setting, $value);
if (Configure::read('Security.auth') && is_array(Configure::read('Security.auth')) && !empty(Configure::read('Security.auth'))) {
$authmethods = array();
foreach (Configure::read('Security.auth') as $auth) {
if (!in_array($auth, $authmethods)) $authmethods[] = $auth;
$arrayFix = array(
'Security.auth',
'ApacheSecureAuth.ldapFilter'
);
foreach ($arrayFix as $settingFix) {
if (Configure::read($settingFix) && is_array(Configure::read($settingFix)) && !empty(Configure::read($settingFix))) {
$arrayElements = array();
foreach (Configure::read($settingFix) as $array) {
if (!in_array($array, $arrayElements)) $arrayElements[] = $array;
}
Configure::write($settingFix, $arrayElements);
}
Configure::write('Security.auth', $authmethods);
}
$settingsToSave = array('debug', 'MISP', 'GnuPG', 'SMIME', 'Proxy', 'SecureAuth', 'Security', 'Session.defaults', 'Session.timeout', 'Session.autoRegenerate', 'site_admin_debug', 'Plugin', 'CertAuth', 'ApacheShibbAuth', 'ApacheSecureAuth');
$settingsArray = array();
@ -2535,17 +2570,21 @@ class Server extends AppModel {
try {
$response = $HttpSocket->get($uri, '', $request);
} catch (Exception $e) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Server',
'model_id' => $id,
'email' => $user['email'],
'action' => 'error',
'user_id' => $user['id'],
'title' => 'Error: Connection to the server has failed.',
));
if ($response->code != '200') {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Server',
'model_id' => $id,
'email' => $user['email'],
'action' => 'error',
'user_id' => $user['id'],
'title' => 'Error: Connection to the server has failed.',
));
}
}
if ($response->code != '200') {
return 1;
}
$remoteVersion = json_decode($response->body, true);

View File

@ -16,7 +16,11 @@ class Sighting extends AppModel {
'event_id' => 'numeric',
'attribute_id' => 'numeric',
'org_id' => 'numeric',
'date_sighting' => 'numeric'
'date_sighting' => 'numeric',
'type' => array(
'rule' => array('inList', array(0, 1, 2)),
'message' => 'Invalid type. Valid options are: 0 (Sighting), 1 (False-positive), 2 (Expiration).'
)
);
public $belongsTo = array(
@ -46,7 +50,7 @@ class Sighting extends AppModel {
return true;
}
public function attachToEvent($event, $user, $attribute_id = false) {
public function attachToEvent($event, $user, $attribute_id = false, $extraConditions = 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']);
@ -56,6 +60,9 @@ class Sighting extends AppModel {
if (!$ownEvent && (!Configure::read('Plugin.Sightings_policy') || Configure::read('Plugin.Sightings_policy') == 0)) {
$conditions['Sighting.org_id'] = $user['org_id'];
}
if ($extraConditions !== false) {
$conditions['AND'] = $extraConditions;
}
$contain = array();
if (Configure::read('MISP.showorg')) {
$contain['Organisation'] = array('fields' => array('Organisation.id', 'Organisation.uuid', 'Organisation.name'));
@ -100,7 +107,7 @@ class Sighting extends AppModel {
if (!is_array($id) && strlen($id) == 36) $conditions = array('Attribute.uuid' => $id);
else $conditions = array('Attribute.id' => $id);
} else {
if (!$values) return 0;
if (!$values) return 'No valid attributes found.';
foreach ($values as $value) {
foreach (array('value1', 'value2') as $field) {
$conditions['OR'][] = array(
@ -109,8 +116,11 @@ class Sighting extends AppModel {
}
}
}
if (!in_array($type, array(0, 1, 2))) {
return 'Invalid type, please change it before you POST 1000000 sightings.';
}
$attributes = $this->Attribute->fetchAttributes($user, array('conditions' => $conditions));
if (empty($attributes)) return 0;
if (empty($attributes)) return 'No valid attributes found that match the criteria.';
$sightingsAdded = 0;
foreach ($attributes as $attribute) {
if ($type === '2') {
@ -126,8 +136,15 @@ class Sighting extends AppModel {
'type' => $type,
'source' => $source
);
$result = $this->save($sighting);
if ($result === false) {
return json_encode($this->validationErrors);
}
$sightingsAdded += $this->save($sighting) ? 1 : 0;
}
if ($sightingsAdded == 0) {
return 'There was nothing to add.';
}
return $sightingsAdded;
}
@ -180,4 +197,40 @@ class Sighting extends AppModel {
}
return $id;
}
public function getSightingsForObjectIds($user, $tagList, $context = 'event', $type = '0') {
$range = (!empty(Configure::read('MISP.Sightings_range')) && is_numeric(Configure::read('MISP.Sightings_range'))) ? Configure::read('MISP.Sightings_range') : 365;
$conditions = array(
'Sighting.date_sighting >' => strtotime("-" . $range . " days"),
ucfirst($context) . 'Tag.tag_id' => $tagList
);
$contain = array(
ucfirst($context) => array(
ucfirst($context) . 'Tag' => array(
'Tag'
)
)
);
if ($type !== false) {
$conditions['Sighting.type'] = $type;
}
$this->bindModel(array('hasOne' => array(ucfirst($context) . 'Tag' => array('foreignKey' => false, 'conditions' => ucfirst($context) . 'Tag.' . $context . '_id = Sighting.' . $context . '_id'))));
$sightings = $this->find('all', array(
'recursive' => -1,
'contain' => array(ucfirst($context) . 'Tag'),
'conditions' => $conditions,
'fields' => array('Sighting.id', 'Sighting.' . $context . '_id', 'Sighting.date_sighting', ucfirst($context) . 'Tag.tag_id')
));
$sightingsRearranged = array();
foreach ($sightings as $sighting) {
$date = date("Y-m-d", $sighting['Sighting']['date_sighting']);
if (isset($sightingsRearranged[$sighting['Sighting'][$context . '_id']][$date])) {
$sightingsRearranged[$sighting['Sighting'][$context . '_id']][$date]++;
} else {
$sightingsRearranged[$sighting['Sighting'][$context . '_id']][$date] = 1;
}
}
return $sightingsRearranged;
}
}

View File

@ -434,8 +434,47 @@ App::uses('RandomTool', 'Tools');
)));
}
public function verifySingleGPG($user, $gpg = false) {
if (!$gpg) {
require_once 'Crypt/GPG.php';
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir'), 'binary' => (Configure::read('GnuPG.binary') ? Configure::read('GnuPG.binary') : '/usr/bin/gpg')));
}
$result = array();
try {
$currentTimestamp = time();
$temp = $gpg->importKey($user['User']['gpgkey']);
$key = $gpg->getKeys($temp['fingerprint']);
$subKeys = $key[0]->getSubKeys();
$sortedKeys = array('valid' => 0, 'expired' => 0, 'noEncrypt' => 0);
foreach ($subKeys as $subKey) {
$expiration = $subKey->getExpirationDate();
if ($expiration != 0 && $currentTimestamp > $expiration) {
$sortedKeys['expired']++;
continue;
}
if (!$subKey->canEncrypt()) {
$sortedKeys['noEncrypt']++;
continue;
}
$sortedKeys['valid']++;
}
if (!$sortedKeys['valid']) {
$result[2] = 'The user\'s PGP key does not include a valid subkey that could be used for encryption.';
if ($sortedKeys['expired']) $result[2] .= ' Found ' . $sortedKeys['expired'] . ' subkey(s) that have expired.';
if ($sortedKeys['noEncrypt']) $result[2] .= ' Found ' . $sortedKeys['noEncrypt'] . ' subkey(s) that are sign only.';
$result[0] = true;
}
} catch (Exception $e) {
$result[2] = $e->getMessage();
$result[0] = true;
}
$result[1] = $user['User']['email'];
$result[4] = $temp['fingerprint'];
return $result;
}
public function verifyGPG($id = false) {
require_once 'Crypt/GPG.php';
require_once 'Crypt/GPG.php';
$this->Behaviors->detach('Trim');
$results = array();
$conditions = array('not' => array('gpgkey' => ''));
@ -445,37 +484,10 @@ App::uses('RandomTool', 'Tools');
'recursive' => -1,
));
if (empty($users)) return $results;
$currentTimestamp = time();
$gpg = new Crypt_GPG(array('homedir' => Configure::read('GnuPG.homedir'), 'binary' => (Configure::read('GnuPG.binary') ? Configure::read('GnuPG.binary') : '/usr/bin/gpg')));
foreach ($users as $k => $user) {
try {
$temp = $gpg->importKey($user['User']['gpgkey']);
$key = $gpg->getKeys($temp['fingerprint']);
$subKeys = $key[0]->getSubKeys();
$sortedKeys = array('valid' => 0, 'expired' => 0, 'noEncrypt' => 0);
foreach ($subKeys as $subKey) {
$expiration = $subKey->getExpirationDate();
if ($expiration != 0 && $currentTimestamp > $expiration) {
$sortedKeys['expired']++;
continue;
}
if (!$subKey->canEncrypt()) {
$sortedKeys['noEncrypt']++;
continue;
}
$sortedKeys['valid']++;
}
if (!$sortedKeys['valid']) {
$results[$user['User']['id']][2] = 'The user\'s PGP key does not include a valid subkey that could be used for encryption.';
if ($sortedKeys['expired']) $results[$user['User']['id']][2] .= ' Found ' . $sortedKeys['expired'] . ' subkey(s) that have expired.';
if ($sortedKeys['noEncrypt']) $results[$user['User']['id']][2] .= ' Found ' . $sortedKeys['noEncrypt'] . ' subkey(s) that are sign only.';
$results[$user['User']['id']][0] = true;
}
} catch (Exception $e) {
$results[$user['User']['id']][2] = $e->getMessage();
$results[$user['User']['id']][0] = true;
}
$results[$user['User']['id']][1] = $user['User']['email'];
$results[$user['User']['id']] = $this->verifySingleGPG($user, $gpg);
}
return $results;
}
@ -900,6 +912,9 @@ 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 {
@ -954,7 +969,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);
@ -974,6 +989,28 @@ App::uses('RandomTool', 'Tools');
} else {
return array('body'=> json_encode(array('saved' => false, 'errors' => 'There was an error notifying the user. His/her credentials were not altered.')),'status'=>200);
}
}
public function getOrgAdminsForOrg($org_id, $excludeUserId = false) {
$adminRoles = $this->Role->find('list', array(
'recursive' => -1,
'conditions' => array('perm_admin' => 1),
'fields' => array('Role.id', 'Role.id')
));
$conditions = array(
'User.org_id' => $org_id,
'User.disabled' => 0,
'User.role_id' => $adminRoles
);
if ($excludeUserId) {
$conditions['User.id !='] = $excludeUserId;
}
return $this->find('list', array(
'recursive' => -1,
'conditions' => $conditions,
'fields' => array(
'User.id', 'User.email'
)
));
}
}

View File

@ -41,6 +41,20 @@ in the list given by apache.
'DefaultOrg' => 'DEFAULT_ORG',
),
```
If used with Apache as webserver it might be useful to make a distinction to filter out API/Syncs from SSO login. It can be added to the vhost as follows:
```Apache
<If "-T reqenv('HTTP_AUTHORIZATION')">
Require all granted
AuthType None
</If>
<Else>
Require valid-user
AuthType shibboleth
ShibRequestSetting requiresession On
ShibRequestSetting shibexportassertion Off
ShibUseHeaders On
</Else>
```

View File

@ -76,18 +76,17 @@
?>
</div>
</fieldset>
<p style="color:red;font-weight:bold;display:none;<?php if (isset($ajax) && $ajax) echo "text-align:center;"?>" id="warning-message">Warning: You are about to share data that is of a sensitive nature (Attribution / targeting data). Make sure that you are authorised to share this.</p>
<?php if ($ajax): ?>
<div class="overlay_spacing">
<table>
<tr>
<td style="vertical-align:top">
<td style="vertical-align:bottom">
<span id="submitButton" class="btn btn-primary" onClick="submitPopoverForm('<?php echo $event_id;?>', 'add')">Submit</span>
</td>
<td style="width:540px;">
<p style="color:red;font-weight:bold;display:none;text-align:center" id="warning-message">Warning: You are about to share data that is of a classified nature (Attribution / targeting data). Make sure that you are authorised to share this.</p>
<td style="width:540px;margin-bottom:0px;">
<p style="color:red;font-weight:bold;display:none;text-align:center;margin-bottom:0px;" id="warning-message">Warning: You are about to share data that is of a classified nature. Make sure that you are authorised to share this.</p>
</td>
<td style="vertical-align:top;">
<td style="vertical-align:bottom;">
<span class="btn btn-inverse" id="cancel_attribute_add">Cancel</span>
</td>
</tr>
@ -95,6 +94,9 @@
</div>
<?php
else:
?>
<p style="color:red;font-weight:bold;display:none;" id="warning-message">Warning: You are about to share data that is of a classified nature. Make sure that you are authorised to share this.</p>
<?php
echo $this->Form->button('Submit', array('class' => 'btn btn-primary'));
endif;
echo $this->Form->end();

View File

@ -39,7 +39,7 @@
<td ondblclick="document.location ='<?php echo $this->Html->url(array('admin' => true, 'action' => 'view', $user['User']['id']), true);?>';">
<?php echo h($user['User']['email']); ?>&nbsp;
</td>
<td ondblclick="document.location ='<?php echo $this->Html->url(array('admin' => true, 'action' => 'view', $user['User']['id']), true);?>';" class="<?php echo $user['Role']['perm_auth'] ? 'bold' : 'grey'; ?>">
<td ondblclick="document.location ='<?php echo $this->Html->url(array('admin' => true, 'action' => 'view', $user['User']['id']), true);?>';" class="quickSelect <?php echo $user['Role']['perm_auth'] ? 'bold' : 'grey'; ?>">
<?php echo h($user['User']['authkey']); ?>&nbsp;
</td>
<td class="short" ondblclick="document.location ='<?php echo $this->Html->url(array('admin' => true, 'action' => 'view', $user['User']['id']), true);?>';">
@ -93,4 +93,4 @@
<?php
endforeach;
?>
</table>
</table>

View File

@ -12,72 +12,21 @@
$page = 0;
}
if (Configure::read('Plugin.Sightings_enable') !== false) {
$attributeSightings = array();
$attributeOwnSightings = array();
$attributeSightingsPopover = array();
$sightingsData = array();
$sparklineData = array();
$startDates = array();
if (!empty($event['Sighting'])) {
foreach ($event['Sighting'] as $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'];
}
}
$date = date("Ymd", $sighting['date_sighting']);
if (!isset($sparklineData[$sighting['attribute_id']][$type][$date])) {
$sparklineData[$sighting['attribute_id']][$type][$date] = 1;
} else {
$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';
}
}
}
}
unset($sparklineData);
foreach ($sightingsData as $aid => $data) {
$sightingsData[$aid]['html'] = '';
foreach ($sightingsData['data'] as $aid => $data) {
$sightingsData['data'][$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 />';
$sightingsData['data'][$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 />';
$sightingsData['data'][$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['data'][$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 />';
$sightingsData['data'][$aid]['html'] .= '<br />';
}
}
}
@ -154,7 +103,7 @@
<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>
<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" data-object-context="attribute"></span>
<?php endif; ?>
</div>
<div class="tabMenu tabMenuToolsBlock noPrint">
@ -493,24 +442,21 @@
</span>
<?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'];
if (isset($sightingsData['csv'][$object['id']])) {
$temp = $sightingsData['csv'][$object['id']];
}
?>
<span class="icon-thumbs-up useCursorPointer" onClick="addSighting('0', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']);?>', '<?php echo h($page); ?>');">&nbsp;</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); ?>');">&nbsp;</span>
<span class="icon-wrench useCursorPointer sightings_advanced_add" data-object-id="<?php echo h($object['id']); ?>">&nbsp;</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'] : ''; ?>">
<span class="icon-wrench useCursorPointer sightings_advanced_add" data-object-id="<?php echo h($object['id']); ?>" data-object-context="attribute">&nbsp;</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['data'][$object['id']]['html']) ? $sightingsData['data'][$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);
$s = (!empty($sightingsData['data'][$object['id']]['sighting']['count']) ? $sightingsData['data'][$object['id']]['sighting']['count'] : 0);
$f = (!empty($sightingsData['data'][$object['id']]['false-positive']['count']) ? $sightingsData['data'][$object['id']]['false-positive']['count'] : 0);
$e = (!empty($sightingsData['data'][$object['id']]['expiration']['count']) ? $sightingsData['data'][$object['id']]['expiration']['count'] : 0);
?>
</span>
<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'] : ''; ?>">
<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['data'][$object['id']]['html']) ? $sightingsData['data'][$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
@ -519,7 +465,7 @@
</td>
<td class="short <?php echo $extra; ?>">
<?php
if ($object['objectType'] == 0) {
if ($object['objectType'] == 0 && !empty($temp)) {
echo $this->element('sparkline', array('id' => $object['id'], 'csv' => $temp));
}
?>
@ -673,6 +619,7 @@ attributes or the appropriate distribution level. If you think there is a mistak
});
$('.sightings_advanced_add').click(function() {
var selected = [];
var object_context = $(this).data('object-context');
var object_id = $(this).data('object-id');
if (object_id == 'selected') {
$(".select_attribute").each(function() {
@ -682,7 +629,7 @@ attributes or the appropriate distribution level. If you think there is a mistak
});
object_id = selected.join('|');
}
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id;
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
genericPopup(url, '#screenshot_box');
});
});

View File

@ -11,7 +11,7 @@ Modified version of http://www.tnoda.com/blog/2013-12-19
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 parseDate = d3.time.format("%Y-%m-%d").parse;
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.date); })
@ -40,7 +40,7 @@ Modified version of http://www.tnoda.com/blog/2013-12-19
.attr('r', 2);
}
var myData = "<?php echo isset($csv[0]) ? $csv[0] : ''; ?>";
var myData = "<?php echo isset($csv) ? $csv : ''; ?>";
if (myData != '') {
var data = d3.csv.parse(myData);
sparkline('#spark_<?php echo h($id); ?>', data);

View File

@ -1,4 +1,8 @@
<div class="events form">
<div class="message">
<?php echo 'The event created will be restricted to ' . (Configure::read('MISP.unpublishedprivate') ? 'your organisation only' : 'the organisations included in the distribution setting on the local instance only') . ' until it is published.';?>
</div>
<?php echo $this->Form->create('', array('type' => 'file'));?>
<fieldset>
<legend>Add Event</legend>

View File

@ -2,10 +2,12 @@
$mayModify = (($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
if (Configure::read('Plugin.Sightings_enable') !== false) {
$csv = array();
$sightingPopover = '';
if (isset($event['Sighting']) && !empty($event['Sighting'])) {
$ownSightings = array();
$orgSightings = array();
$sparklineData = array();
foreach ($event['Sighting'] as $sighting) {
if (isset($sighting['org_id']) && $sighting['org_id'] == $me['org_id']) $ownSightings[] = $sighting;
if (isset($sighting['org_id'])) {
@ -30,9 +32,6 @@
}
}
}
foreach ($orgSightings as $org => $data) {
$sightingPopover .= '<span class=\'bold\'>' . h($org) . '</span>: <span class=\'green bold\'>' . h($data['count']) . ' (' . date('Y-m-d H:i:s', $data['date']) . ')' . '</span><br />';
}
}
}
echo $this->element('side_menu', array('menuList' => 'event', 'menuItem' => 'viewEvent', 'mayModify' => $mayModify, 'mayPublish' => $mayPublish));
@ -163,14 +162,28 @@
<dd class="background-red bold not-published <?php echo ($event['Event']['published'] == 0) ? '' : 'hidden'; ?>">No</dd>
<dt class="bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>">Published</dt>
<dd class="green bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>">Yes</dd>
<?php if (Configure::read('Plugin.Sightings_enable') !== false): ?>
<dt>Sightings</dt>
<dd style="word-wrap: break-word;">
<span id="eventSightingCount" class="bold sightingsCounter" data-toggle="popover" data-trigger="hover" data-content="<?php echo $sightingPopover; ?>"><?php echo count($event['Sighting']); ?></span>
(<span id="eventOwnSightingCount" class="green bold sightingsCounter" data-toggle="popover" data-trigger="hover" data-content="<?php echo $sightingPopover; ?>"><?php echo isset($ownSightings) ? count($ownSightings) : 0; ?></span>)
<?php if (!Configure::read('Plugin.Sightings_policy')) echo '- restricted to own organisation only.'; ?>
</dd>
<?php endif;
<?php
if (Configure::read('Plugin.Sightings_enable') !== false):
?>
<dt>Sightings</dt>
<dd style="word-wrap: break-word;">
<span id="eventSightingCount" class="bold sightingsCounter" data-toggle="popover" data-trigger="hover" data-content="<?php echo $sightingPopover; ?>"><?php echo count($event['Sighting']); ?></span>
(<span id="eventOwnSightingCount" class="green bold sightingsCounter" data-toggle="popover" data-trigger="hover" data-content="<?php echo $sightingPopover; ?>"><?php echo isset($ownSightings) ? count($ownSightings) : 0; ?></span>)
<?php if (!Configure::read('Plugin.Sightings_policy')) echo '- restricted to own organisation only.'; ?>
<span class="icon-wrench useCursorPointer sightings_advanced_add" data-object-id="<?php echo h($event['Event']['id']); ?>" data-object-context="event">&nbsp;</span>
</dd>
<dt>Activity</dt>
<dd>
<?php
if (!empty($sightingsData['data'])) {
echo $this->element('sparkline', array('id' => $event['Event']['id'], 'csv' => $sightingsData['csv']['event']));
} else {
echo '&nbsp';
}
?>
</dd>
<?php
endif;
if (!empty($delegationRequest)):
if ($isSiteAdmin || $me['org_id'] == $delegationRequest['EventDelegation']['org_id']) {
$target = $isSiteAdmin ? $delegationRequest['Org']['name'] : 'you';

View File

@ -7,7 +7,7 @@
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
echo $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
@ -18,30 +18,34 @@
<tr>
<th><?php echo $this->Paginator->sort('value');?></th>
<th><?php echo $this->Paginator->sort('synonyms');?></th>
<th>Activity</th>
<th>#Events</th>
<th><?php echo $this->Paginator->sort('description');?></th>
<th class="actions"><?php echo __('Actions');?></th>
</tr>
<?php
foreach ($list as $item):
foreach ($list as $k => $item):
?>
<tr>
<td class="short bold"><?php echo h($item['GalaxyCluster']['value']); ?>&nbsp;</td>
<td class="short bold">
<?php
echo nl2br(h(implode("\n", $item['GalaxyCluster']['synonyms'])));
echo nl2br(h(implode("\n", $item['GalaxyCluster']['synonyms'])));
?>
&nbsp;
</td>
<td class="shortish">
<?php echo $this->element('sparkline', array('id' => $item['GalaxyCluster']['id'], 'csv' => $csv[$k])); ?>
</td>
<td class="short">
<?php
if ($item['GalaxyCluster']['tags']):
?>
<a href="<?php echo $baseurl; ?>/events/index/searchtag:<?php echo h($item['GalaxyCluster']['tags']['tag_id']);?>" class="bold"><?php echo h($item['GalaxyCluster']['tags']['count']);?></a>
<?php
<?php
else:
echo '0';
endif;
endif;
?>
</td>
<td><?php echo h($item['GalaxyCluster']['description']); ?>&nbsp;</td>
@ -50,7 +54,7 @@
</td>
</tr>
<?php
endforeach;
endforeach;
?>
</table>
<p>
@ -72,4 +76,4 @@
$(document).ready(function(){
});
</script>
<?php echo $this->Js->writeBuffer(); ?>
<?php echo $this->Js->writeBuffer(); ?>

View File

@ -8,11 +8,17 @@
<div class = 'input clear'></div>
<?php
$counter = 1;
foreach ($permFlags as $k => $flag) {
echo $this->Form->input($k, array('type' => 'checkbox', 'checked' => false));
if ($counter%3 == 0) echo "<div class = 'input clear'></div>";
$counter++;
}
foreach ($permFlags as $k => $flag):
?>
<div class="permFlags<?php echo ' ' . ($flag['readonlyenabled'] ? 'readonlyenabled' : 'readonlydisabled'); ?>">
<?php
echo $this->Form->input($k, array('type' => 'checkbox', 'class' => 'checkbox ' . ($flag['readonlyenabled'] ? 'readonlyenabled' : 'readonlydisabled'), 'checked' => false));
if ($counter%3 == 0) echo "<div class = 'input clear'></div>";
$counter++;
?>
</div>
<?php
endforeach;
?>
</fieldset>
<?php
@ -22,48 +28,14 @@ echo $this->Form->end();
</div>
<?php
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_site_admin') $this->Js->get('#' . $flag['id'])->event('change', 'checkPerms("' . $flag['id'] . '")');
else $this->Js->get('#RolePermSiteAdmin')->event('change', 'checkPerms("RolePermSiteAdmin");activateAll();');
}
?>
<script type="text/javascript">
// only be able to tick perm_sync if manage org events and above.
function deactivateActions() {
var e = document.getElementById("RolePermission");
if (e.options[e.selectedIndex].value == '0' || e.options[e.selectedIndex].value == '1') {
<?php
foreach ($permFlags as $k => $flag):
?>
document.getElementById("<?php echo $flag['id']; ?>").checked = false;
<?php
endforeach;
?>
}
}
function activateAll() {
if (document.getElementById("RolePermSiteAdmin").checked) {
<?php
foreach ($permFlags as $k => $flag):
if ($k !== 'perm_site_admin'):
?>
document.getElementById("<?php echo $flag['id']; ?>").checked = true;
<?php
endif;
endforeach;
?>
}
}
function checkPerms(id) {
var e = document.getElementById("RolePermission");
if (e.options[e.selectedIndex].value == '0' || e.options[e.selectedIndex].value == '1') {
document.getElementById(id).checked = false;
}
}
$(document).ready(function() {
checkRolePerms();
$(".checkbox, #RolePermission").change(function() {
checkRolePerms();
});
});
</script>
<?php echo $this->Js->writeBuffer();

View File

@ -8,11 +8,17 @@
<div class = 'input clear'></div>
<?php
$counter = 1;
foreach ($permFlags as $k => $flag) {
echo $this->Form->input($k, array('type' => 'checkbox'));
if ($counter%3 == 0) echo "<div class = 'input clear'></div>";
$counter++;
}
foreach ($permFlags as $k => $flag):
?>
<div class="permFlags<?php echo ' ' . ($flag['readonlyenabled'] ? 'readonlyenabled' : 'readonlydisabled'); ?>">
<?php
echo $this->Form->input($k, array('type' => 'checkbox', 'class' => 'checkbox ' . ($flag['readonlyenabled'] ? 'readonlyenabled' : 'readonlydisabled')));
if ($counter%3 == 0) echo "<div class = 'input clear'></div>";
$counter++;
?>
</div>
<?php
endforeach;
?>
</fieldset>
<?php
@ -22,49 +28,14 @@
</div>
<?php
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_site_admin') $this->Js->get('#' . $flag['id'])->event('change', 'checkPerms("' . $flag['id'] . '")');
else $this->Js->get('#RolePermSiteAdmin')->event('change', 'checkPerms("RolePermSiteAdmin");activateAll();');
}
?>
<script type="text/javascript">
// only be able to tick perm_sync if manage org events and above.
// only be able to tick perm_sync if manage org events and above.
function deactivateActions() {
var e = document.getElementById("RolePermission");
if (e.options[e.selectedIndex].value == '0' || e.options[e.selectedIndex].value == '1') {
<?php
foreach ($permFlags as $k => $flag):
?>
document.getElementById("<?php echo $flag['id']; ?>").checked = false;
<?php
endforeach;
?>
}
}
function activateAll() {
if (document.getElementById("RolePermSiteAdmin").checked) {
<?php
foreach ($permFlags as $k => $flag):
if ($k !== 'perm_site_admin'):
?>
document.getElementById("<?php echo $flag['id']; ?>").checked = true;
<?php
endif;
endforeach;
?>
}
}
function checkPerms(id) {
var e = document.getElementById("RolePermission");
if (e.options[e.selectedIndex].value == '0' || e.options[e.selectedIndex].value == '1') {
document.getElementById(id).checked = false;
}
}
$(document).ready(function() {
checkRolePerms();
$(".checkbox, #RolePermission").change(function() {
checkRolePerms();
});
});
</script>
<?php echo $this->Js->writeBuffer();

View File

@ -3,7 +3,7 @@
<?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'),
'options' => array('Sighting', 'False-positive', 'Expiration'),
'default' => 0,
'style' => 'width:230px;margin-right:0px;'
));

View File

@ -3,8 +3,14 @@
<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>
<span id="sightingsListMyToggle" class="btn btn-inverse qet toggle<?php echo $context == 'event' ? '-right' : ''; ?> sightingsToggle" data-type="org">My org</span>
<?php
if ($context == 'attribute'):
?>
<span id="sightingsAddToggle" class="btn btn-inverse qet toggle-right sightingsToggle" data-type="add">Add sighting</span>
<?php
endif;
?>
</div>
<div id="mainContents" style="margin-top:40px;padding:10px;">
<div id="sightingsData" class="sightingTab"></div>
@ -14,6 +20,7 @@
</div>
<script type="text/javascript">
var object_context = "<?php echo h($context);?>";
$(document).ready(function() {
id = "<?php echo h($id); ?>";
$('#cancel').click(function() {
@ -32,7 +39,7 @@ $(document).ready(function() {
showSeconds: true,
maxHours: 24
});
loadSightingGraph(id, "attribute");
loadSightingGraph(id, object_context);
});
$('.sightingsToggle').click(function() {
$('.sightingsToggle').removeClass('btn-primary');
@ -42,7 +49,7 @@ $('.sightingsToggle').click(function() {
var type = $(this).data('type');
$('.sightingTab').empty();
if (type == 'graph') {
loadSightingGraph(id, "attribute");
loadSightingGraph(id, object_context);
} else if (type == 'add') {
$.get( "/sightings/add/" + id, function(data) {
$("#sightingsData").html(data);
@ -50,7 +57,7 @@ $('.sightingsToggle').click(function() {
} else {
var org = "";
if (type == 'org') org = "/<?php echo h($me['org_id']);?>"
$.get( "/sightings/listSightings/" + id + "/attribute" + org, function(data) {
$.get( "/sightings/listSightings/" + id + "/" + object_context + org, function(data) {
$("#sightingsData").html(data);
});
}

View File

@ -33,12 +33,13 @@
<th>Taxonomy</th>
<th>Tagged events</th>
<th>Tagged attributes</th>
<th>Activity</th>
<th>Favourite</th>
<?php if ($isAclTagEditor): ?>
<th class="actions"><?php echo __('Actions');?></th>
<?php endif; ?>
</tr><?php
foreach ($list as $item): ?>
foreach ($list as $k => $item): ?>
<tr>
<td class="short"><?php echo h($item['Tag']['id']); ?>&nbsp;</td>
<td class="short"><span class="<?php echo ($item['Tag']['exportable'] ? 'icon-ok' : 'icon-remove'); ?>"></span></td>
@ -61,6 +62,9 @@ foreach ($list as $item): ?>
</td>
<td class="shortish"><?php echo h($item['Tag']['count']); ?>&nbsp;</td>
<td class="shortish"><a href="<?php echo $baseurl . "/attributes/search/attributetag:" . $item['Tag']['id']; ?>"><?php echo h($item['Tag']['attribute_count']); ?></a> </td>
<td class="shortish">
<?php echo $this->element('sparkline', array('id' => $item['Tag']['id'], 'csv' => $csv[$k])); ?>
</td>
<td class="short" id ="checkbox_row_<?php echo h($item['Tag']['id']);?>">
<input id="checkBox_<?php echo h($item['Tag']['id']); ?>" type="checkbox" onClick="toggleSetting(event, 'favourite_tag', '<?php echo h($item['Tag']['id']); ?>')" <?php echo $item['Tag']['favourite'] ? 'checked' : ''; ?>/>
</td>

View File

@ -0,0 +1,29 @@
<div class="events form">
<h2 style="margin-bottom:0px;">Contact <?php echo h($user['User']['email']); ?></h2>
<?php
$encryptionMessage = 'WARNING: This user does not have an encrpytion key set. The security posture of this instance allows for the sending of cleartext e-mails, so this is what will happen if you proceed.';
$encryptionColour = 'white red-background';
if ($encryption) {
$encryptionMessage = $encryption . ' key found for user, the e-mail will be sent encrypted using this key.';
$encryptionColour = 'white green-background';
}
?>
<div style="width:545px;" class="bold <?php echo $encryptionColour; ?>"><?php echo $encryptionMessage; ?></div>
<br />
<?php
echo $this->Form->create('User');
echo $this->Form->input('subject', array('type' => 'text', 'label' => 'Subject', 'style' => 'width:400px;'));
?>
<div class="clear"></div>
<?php
echo $this->Form->input('body', array('type' => 'textarea', 'class' => 'input-xxlarge'));
?>
<div class="clear"></div>
<?php
echo $this->Form->button(__('Submit'), array('class' => 'btn btn-primary'));
echo $this->Form->end();
?>
</div>
<?php
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'contact'));
?>

View File

@ -5,7 +5,7 @@ $buttonModifyStatus = $mayModify ? 'button_on':'button_off';
?>
<div class="users view">
<h2><?php echo __('User');?></h2>
<dl style="width:700px;">
<dl style="width:800px;">
<dt><?php echo __('Id'); ?></dt>
<dd>
<?php echo h($user['User']['id']); ?>
@ -23,7 +23,7 @@ $buttonModifyStatus = $mayModify ? 'button_on':'button_off';
</dd>
<dt><?php echo __('Email'); ?></dt>
<dd>
<?php echo h($user['User']['email']); ?>
<?php echo h($user['User']['email']); ?>&nbsp;<a class="icon-envelope" href="<?php echo $baseurl; ?>/admin/users/quickEmail/<?php echo h($user['User']['id']); ?>"></a>
&nbsp;
</dd>
<dt><?php echo __('Autoalert'); ?></dt>
@ -39,7 +39,7 @@ $buttonModifyStatus = $mayModify ? 'button_on':'button_off';
</dd>
<dt><?php echo __('Authkey'); ?></dt>
<dd>
<?php echo h($user['User']['authkey']); ?>
<span class="quickSelect"><?php echo h($user['User']['authkey']); ?></span>
(<?php echo $this->Html->link('reset', array('controller' => 'users', 'action' => 'resetauthkey', $user['User']['id']));?>)
&nbsp;
</dd>
@ -48,13 +48,47 @@ $buttonModifyStatus = $mayModify ? 'button_on':'button_off';
<?php echo h($user2['User']['email']); ?>
&nbsp;
</dd>
<dt><?php echo __('PGP key'); ?></dt>
<dd class="red">
<?php echo (h($user['User']['gpgkey'])) ? $this->Utility->space2nbsp(nl2br(h($user['User']['gpgkey']))) : "N/A"; ?>
<dt>Org admin</dt>
<dd>
<?php
foreach ($user['User']['orgAdmins'] as $orgAdminId => $orgAdminEmail):
?>
<a href="<?php echo $baseurl; ?>/admin/users/view/<?php echo h($orgAdminId); ?>"><?php echo h($orgAdminEmail); ?></a>
<a class="icon-envelope" href="<?php echo $baseurl; ?>/admin/users/quickEmail/<?php echo h($orgAdminId); ?>"></a>
<?php
if ($orgAdminEmail !== end($user['User']['orgAdmins'])) {
echo '<br />';
}
endforeach;
?>
&nbsp;
</dd>
<dt><?php echo __('PGP key'); ?></dt>
<dd class="quickSelect <?php echo $user['User']['gpgkey'] ? 'green' : 'bold red'; ?>">
<?php echo $user['User']['gpgkey'] ? nl2br(h($user['User']['gpgkey'])) : "N/A"; ?>
</dd>
<?php
if (!empty($user['User']['gpgkey'])):
?>
<dt>PGP fingerprint</dt>
<dd class="quickSelect bold <?php echo $user['User']['fingerprint'] ? 'green': 'red'; ?>">
<?php
echo $user['User']['fingerprint'] ? chunk_split(h($user['User']['fingerprint']), 4, ' ') : 'N/A';
?>
</dd>
<dt>PGP status</dt>
<dd class="bold <?php echo (empty($user['User']['pgp_status']) || $user['User']['pgp_status'] != 'OK') ? 'red': 'green'; ?>">
<?php
echo !empty($user['User']['pgp_status']) ? h($user['User']['pgp_status']) : 'N/A';
?>
</dd>
<?php
endif;
?>
<?php if (Configure::read('SMIME.enabled')): ?>
<dt><?php echo __('SMIME Public certificate'); ?></dt>
<dd class="red">
<dd class="quickSelect red">
<?php echo (h($user['User']['certif_public'])) ? $this->Utility->space2nbsp(nl2br(h($user['User']['certif_public']))) : "N/A"; ?>
</dd>
<?php endif; ?>

View File

@ -34,14 +34,16 @@
<dt><?php echo __('Authkey'); ?></dt>
<dd>
<?php
if ($user['Role']['perm_auth']) {
echo h($user['User']['authkey']);
if (!Configure::read('MISP.disableUserSelfManagement') || $isAdmin) {
echo '(' . $this->Html->link('reset', array('controller' => 'users', 'action' => 'resetauthkey', $user['User']['id'])) . ')';
}
} else {
if ($user['Role']['perm_auth']):
?>
<span class="quickSelect"><?php echo h($user['User']['authkey']); ?></span>
<?php
if (!Configure::read('MISP.disableUserSelfManagement') || $isAdmin):
echo ' (' . $this->Html->link('reset', array('controller' => 'users', 'action' => 'resetauthkey', $user['User']['id'])) . ')';
endif;
else:
echo "<a onclick=\"requestAPIAccess()\" style=\"cursor:pointer;\">Request API access</a>";
}
endif;
?>
&nbsp;
</dd>
@ -56,12 +58,30 @@
&nbsp;
</dd>
<dt><?php echo __('PGP key'); ?></dt>
<dd class="red">
<?php echo (h($user['User']['gpgkey'])) ? $this->Utility->space2nbsp(nl2br(h($user['User']['gpgkey']))) : "N/A"; ?>
<dd class="quickSelect <?php echo $user['User']['gpgkey'] ? 'green' : 'bold red'; ?>">
<?php echo $user['User']['gpgkey'] ? nl2br(h($user['User']['gpgkey'])) : "N/A"; ?>
</dd>
<?php
if (!empty($user['User']['gpgkey'])):
?>
<dt>PGP fingerprint</dt>
<dd class="quickSelect bold <?php echo $user['User']['fingerprint'] ? 'green': 'red'; ?>">
<?php
echo $user['User']['fingerprint'] ? chunk_split(h($user['User']['fingerprint']), 4, ' ') : 'N/A';
?>
</dd>
<dt>PGP status</dt>
<dd class="bold <?php echo (empty($user['User']['pgp_status']) || $user['User']['pgp_status'] != 'OK') ? 'red': 'green'; ?>">
<?php
echo !empty($user['User']['pgp_status']) ? h($user['User']['pgp_status']) : 'N/A';
?>
</dd>
<?php
endif;
?>
<?php if (Configure::read('SMIME.enabled')): ?>
<dt><?php echo __('SMIME Public certificate'); ?></dt>
<dd class="red">
<dd class="red quickSelect">
<?php echo (h($user['User']['certif_public'])) ? $this->Utility->space2nbsp(nl2br(h($user['User']['certif_public']))) : "N/A"; ?>
</dd>
<?php endif; ?>

View File

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

View File

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

@ -1 +1 @@
Subproject commit 7db66e05dd22faee44d2c2e3d0b72903c4336e44
Subproject commit 1f4db6d4a1b41659977416ab0aa0bdf01f95678c

View File

@ -1497,6 +1497,14 @@ a.proposal_link_red:hover {
background-color:red;
}
.blue-background {
background-color:#0088cc;
}
.green-background {
background-color:green;
}
.bold {
font-weight: bold;
}

View File

@ -2937,3 +2937,26 @@ function loadSightingGraph(id, scope) {
$("#sightingsData").html(data);
});
}
function checkRolePerms() {
if ($("#RolePermission").val() == '0' || $("#RolePermission").val() == '1') {
$('.readonlydisabled').prop('checked', false);
$('.readonlydisabled').hide();
} else {
$('.readonlydisabled').show();
$('.permFlags').show();
}
if ($("#RolePermSiteAdmin").prop('checked')) {
$('.checkbox').prop('checked', true);
}
}
// clicking on an element with this class will select all of its contents in a
// single click
$('.quickSelect').click(function() {
var range = document.createRange();
var selection = window.getSelection();
range.selectNodeContents(this);
selection.removeAllRanges();
selection.addRange(range);
});

View File

@ -0,0 +1 @@
MISPPath=/var/www/MISP

84
tools/misp-wipe/misp-wipe.sh Executable file
View File

@ -0,0 +1,84 @@
#@IgnoreInspection BashAddShebang
#/!bin/sh
##
## script to wipe MISP on debian/ubuntu
##
## Adapted from misp-backup by daverstephens@gmail.com
## https://github.com/daverstephens/The-SOC-Shop
## and @alexanderjaeger
## https://github.com/deralexxx/misp-backup
##
## This script can be used to reset a MISP instance
## by clearing all events, orgs and users.
## It is highy recommended ## to run misp-backup.sh first!
##
## Tested against MISP 2.4.55
##
## Run the script as the standard user with the command below
##
## cp misp-wipe.conf.sample misp-wipe.conf
## vi misp-wipe.conf # adjust values
## sudo sh -x misp-wipe.sh 2>&1 | tee misp-wipe.log
##
## Time to set some variables
##
FILE=./misp-wipe.conf
SQL=./misp-wipe.sql
# Source configuration file
if [ -f $FILE ];
then
echo "File $FILE exists."
. $FILE
else
echo "Config File $FILE does not exist. Please enter values manually"
## MySQL stuff
echo 'Please enter your MySQL root account username'
read MySQLRUser
echo 'Please enter your MySQL root account password'
read MySQLRPass
echo 'What would you like to call the backup archive?'
echo 'Eg. MISPBackup'
read OutputFileName
echo 'Where would you like to save the file?'
echo 'Eg. /tmp'
read OutputDirName
fi
# Fill in any missing values with defaults
# MISP path
MISPPath=${MISPPath:-$(locate MISP/app/webroot/index.php|sed 's/\/app\/webroot\/index\.php//')}
# Output
OutputFileName=${OutputFileName:-MISP-Backup}
OutputDirName=${OutputDirName:-/tmp}
# database.php
MySQLUUser=$(grep -o -P "(?<='login' => ').*(?=')" $MISPPath/app/Config/database.php)
MySQLUPass=$(grep -o -P "(?<='password' => ').*(?=')" $MISPPath/app/Config/database.php)
MISPDB=$(grep -o -P "(?<='database' => ').*(?=')" $MISPPath/app/Config/database.php)
DB_Port=$(grep -o -P "(?<='port' => ).*(?=,)" $MISPPath/app/Config/database.php)
MISPDBHost=$(grep -o -P "(?<='host' => ').*(?=')" $MISPPath/app/Config/database.php)
echo "Wiping MySQL tables"
MySQLRUser=${MySQLRUser:-$MySQLUUser}
MySQLRPass=${MySQLRPass:-$MySQLUPass}
mysql -u $MySQLRUser -p$MySQLRPass $MISPDB < $SQL
echo "Inserting default values to MySQL tables"
TMP=/tmp/misp-wipe-$$.sql
cd $MISPPath
sed -n '/Default values for initial installation/ { s///; :a; n; p; ba; }' INSTALL/MYSQL.sql | egrep -v '(admin_settings|db_version)' > $TMP
mysql -u $MySQLRUser -p$MySQLRPass $MISPDB < $TMP
rm -f $TMP
echo "Wiping files"
git clean -f -x app/webroot/img/orgs
#git clean -f -x app/webroot/img/custom
git clean -f -x app/tmp/logs/
git clean -f -d -x app/files
echo 'MISP Wipe Complete!!!'

View File

@ -0,0 +1,51 @@
-- Clear tables that should be empty
TRUNCATE `attributes`;
TRUNCATE `correlations`;
TRUNCATE `events`;
TRUNCATE `event_delegations`;
TRUNCATE `event_tags`;
TRUNCATE `favourite_tags`;
TRUNCATE `jobs`;
TRUNCATE `logs`;
TRUNCATE `posts`;
TRUNCATE `servers`;
TRUNCATE `shadow_attributes`;
TRUNCATE `shadow_attribute_correlations`;
TRUNCATE `sharing_groups`;
TRUNCATE `sharing_group_orgs`;
TRUNCATE `sharing_group_servers`;
TRUNCATE `sightings`;
TRUNCATE `threads`;
TRUNCATE `bruteforces`;
TRUNCATE `news`;
TRUNCATE `template_tags`;
TRUNCATE `whitelist`;
-- Clear tables that can be re-populated
TRUNCATE `taxonomies`;
TRUNCATE `taxonomy_entries`;
TRUNCATE `taxonomy_predicates`;
TRUNCATE `warninglists`;
TRUNCATE `warninglist_entries`;
TRUNCATE `warninglist_types`;
TRUNCATE `galaxies`;
TRUNCATE `galaxy_clusters`;
TRUNCATE `galaxy_elements`;
TRUNCATE `galaxy_reference`;
-- Clear tables that have defaults
TRUNCATE `feeds`;
TRUNCATE `regexp`;
TRUNCATE `roles`;
TRUNCATE `threat_levels`;
TRUNCATE `templates`;
TRUNCATE `template_elements`;
TRUNCATE `template_element_attributes`;
TRUNCATE `template_element_files`;
TRUNCATE `template_element_texts`;
-- Remove entries from tables and reset index
DELETE FROM `users` WHERE id > 3;
ALTER TABLE `users` AUTO_INCREMENT = 4;
DELETE FROM `organisations` WHERE id > 2;
ALTER TABLE `organisations` AUTO_INCREMENT = 3;