Merge branch 'develop' into 2.4

pull/8834/head
iglocska 2022-12-22 15:42:42 +01:00
commit fe83ea6b7a
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
143 changed files with 3178 additions and 1511 deletions

View File

@ -263,4 +263,6 @@ jobs:
run: |
tail -n +1 `pwd`/app/tmp/logs/*
tail -n +1 /var/log/apache2/*.log
sudo -u $USER app/Console/cake Log export /tmp/logs.json.gz --without-changes
zcat /tmp/logs.json.gz

View File

@ -1523,16 +1523,16 @@ INSERT IGNORE INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `pe
VALUES (2, 'Org Admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0);
INSERT IGNORE INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_publish_zmq`, `perm_publish_kafka`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `perm_sighting`, `perm_object_template`, `perm_decaying`, `default_role`)
VALUES (3, 'User', NOW(), NOW(), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1);
VALUES (3, 'User', NOW(), NOW(), 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1);
INSERT IGNORE INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_publish_zmq`, `perm_publish_kafka`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `perm_sighting`, `perm_object_template`, `perm_decaying`, `default_role`)
VALUES (4, 'Publisher', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0);
VALUES (4, 'Publisher', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0);
INSERT IGNORE INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_publish_zmq`, `perm_publish_kafka`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `perm_sighting`, `perm_object_template`, `perm_decaying`, `default_role`)
VALUES (5, 'Sync user', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0);
VALUES (5, 'Sync user', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0);
INSERT IGNORE INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_publish_zmq`, `perm_publish_kafka`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `perm_sighting`, `perm_object_template`, `perm_decaying`, `default_role`)
VALUES (6, 'Read Only', NOW(), NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
VALUES (6, 'Read Only', NOW(), NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-- --------------------------------------------------------
@ -1661,4 +1661,6 @@ INSERT IGNORE INTO `org_blocklists` (`org_uuid`, `created`, `org_name`, `comment
('58d38339-7b24-4386-b4b4-4c0f950d210f', NOW(), 'Setec Astrononomy', 'default example'),
('58d38326-eda8-443a-9fa8-4e12950d210f', NOW(), 'Acme Finance', 'default example');
INSERT IGNORE INTO `admin_settings` (`setting`, `value`) VALUES ('fix_login', NOW());
INSERT IGNORE INTO `admin_settings` (`setting`, `value`) VALUES
('fix_login', NOW()),
('default_role', 3);

2
PyMISP

@ -1 +1 @@
Subproject commit 24c52813876dd88a92b9fcc4b6c2cd259d80d733
Subproject commit cca5287b2b11a1951789680c75e10636dde98add

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":166}
{"major":2, "minor":4, "hotfix":167}

View File

@ -24,21 +24,33 @@ class LogShell extends AppShell
]);
$parser->addSubcommand('export', [
'help' => __('Export application logs to compressed file in JSON Lines format (one JSON encoded line per entry).'),
'parser' => array(
'arguments' => array(
'parser' => [
'arguments' => [
'file' => ['help' => __('Path to output file'), 'required' => true],
),
),
],
'options' => [
'without-changes' => ['boolean' => true, 'help' => __('Do not include add, edit or delete actions.')],
],
],
]);
$parser->addSubcommand('recompress', [
'help' => __('Recompress compressed data in logs.'),
]);
$parser->addSubcommand('accessLogRetention', [
'help' => __('Delete logs that are older than specified duration.'),
'parser' => array(
'arguments' => array(
'duration' => ['help' => __('Duration in days'), 'required' => true],
),
),
]);
return $parser;
}
public function export()
{
list($path) = $this->args;
$withoutChanges = $this->param('without-changes');
if (file_exists($path)) {
$this->error("File $path already exists");
@ -49,21 +61,24 @@ class LogShell extends AppShell
$this->error("Could not open $path for writing");
}
$rows = $this->Log->query("SELECT TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'logs';");
/** @var ProgressShellHelper $progress */
$progress = $this->helper('progress');
$progress->init([
'total' => $rows[0]['TABLES']['TABLE_ROWS'], // just estimate, but fast
'total' => $this->Log->tableRows(), // just estimate, but fast
'width' => 50,
]);
$lastId = 0;
while (true) {
$conditions = ['Log.id >' => $lastId]; // much faster than offset
if ($withoutChanges) {
$conditions['NOT'] = ['Log.action' => ['add', 'edit', 'delete']];
}
$logs = $this->Log->find('all', [
'conditions' => ['id >' => $lastId], // much faster than offset
'conditions' => $conditions,
'recursive' => -1,
'limit' => 100000,
'order' => ['id ASC'],
'order' => ['Log.id ASC'],
]);
if (empty($logs)) {
break;
@ -184,4 +199,15 @@ class LogShell extends AppShell
{
$this->AuditLog->recompress();
}
public function accessLogRetention()
{
list($duration) = $this->args;
if ($duration <= 0 || !is_numeric($duration)) {
$this->error("Invalid duration specified.");
}
$duration = new DateTime("-$duration days");
$deleted = $this->AccessLog->deleteOldLogs($duration);
$this->out(__n("Deleted %s entry", "Deleted %s entries", $deleted, $deleted));
}
}

View File

@ -61,6 +61,9 @@ class AccessLogsController extends AppController
if (empty(Configure::read('MISP.log_skip_access_logs_in_application_logs'))) {
$this->Flash->warning(__('Access logs are logged in both application logs and access logs. Make sure you reconfigure your log monitoring tools and update MISP.log_skip_access_logs_in_application_logs.'));
}
$this->AccessLog->virtualFields['has_query_log'] = 'query_log IS NOT NULL';
$this->paginate['fields'][] = 'has_query_log';
$this->paginate['conditions'] = $conditions;
$list = $this->paginate();
@ -102,6 +105,23 @@ class AccessLogsController extends AppController
$this->set('request', $data);
}
public function admin_queryLog($id)
{
$request = $this->AccessLog->find('first', [
'conditions' => ['AccessLog.id' => $id],
'fields' => ['AccessLog.query_log'],
]);
if (empty($request)) {
throw new NotFoundException(__('Access log not found'));
}
if (empty($request['AccessLog']['query_log'])) {
throw new NotFoundException(__('Query log is empty'));
}
$this->set('queryLog', $request['AccessLog']['query_log']);
}
/**
* @param array $params
* @return array

View File

@ -34,7 +34,7 @@ class AppController extends Controller
public $helpers = array('OrgImg', 'FontAwesome', 'UserName');
private $__queryVersion = '146';
public $pyMispVersion = '2.4.166';
public $pyMispVersion = '2.4.167';
public $phpmin = '7.2';
public $phprec = '7.4';
public $phptoonew = '8.0';
@ -43,7 +43,6 @@ class AppController extends Controller
private $isApiAuthed = false;
public $baseurl = '';
public $sql_dump = false;
public $restResponsePayload = null;
@ -102,7 +101,9 @@ class AppController extends Controller
{
$controller = $this->request->params['controller'];
$action = $this->request->params['action'];
if (empty($this->Session->read('creation_timestamp'))) {
$this->Session->write('creation_timestamp', time());
}
if (Configure::read('MISP.system_setting_db')) {
App::uses('SystemSetting', 'Model');
SystemSetting::setGlobalSetting();
@ -136,17 +137,12 @@ class AppController extends Controller
$this->response->header('X-XSS-Protection', '1; mode=block');
}
if (!empty($this->request->params['named']['sql'])) {
$this->sql_dump = intval($this->request->params['named']['sql']);
}
$this->_setupDatabaseConnection();
$this->set('debugMode', Configure::read('debug') >= 1 ? 'debugOn' : 'debugOff');
$isAjax = $this->request->is('ajax');
$this->set('ajax', $isAjax);
$this->set('queryVersion', $this->__queryVersion);
$this->User = ClassRegistry::init('User');
$language = Configure::read('MISP.language');
if (!empty($language) && $language !== 'eng') {
@ -155,6 +151,21 @@ class AppController extends Controller
Configure::write('Config.language', 'eng');
}
$this->User = ClassRegistry::init('User');
if ($this->Auth->user()) {
if ($this->User->checkForSessionDestruction($this->Auth->user('id'))) {
$this->Auth->logout();
$this->Session->destroy();
$message = __('User deauthenticated on administrator request. Please reauthenticate.');
if ($this->_isRest()) {
throw new ForbiddenException($message);
} else {
$this->Flash->warning($message);
$this->_redirectToLogin();
}
}
}
// For fresh installation (salt empty) generate a new salt
if (!Configure::read('Security.salt')) {
$this->User->Server->serverSettingsSaveValue('Security.salt', $this->User->generateRandomPassword(32));
@ -225,8 +236,9 @@ class AppController extends Controller
if ($this->_isRest() || $this->_isAutomation()) {
// disable CSRF for REST access
$this->Security->csrfCheck = false;
if ($this->__loginByAuthKey() === false || $this->Auth->user() === null) {
if ($this->__loginByAuthKey() === null) {
$loginByAuthKeyResult = $this->__loginByAuthKey();
if ($loginByAuthKeyResult === false || $this->Auth->user() === null) {
if ($loginByAuthKeyResult === null) {
$this->loadModel('Log');
$this->Log->createLogEntry('SYSTEM', 'auth_fail', 'User', 0, "Failed API authentication. No authkey was provided.");
}
@ -447,6 +459,9 @@ class AppController extends Controller
}
$this->Session->destroy();
}
} else {
$this->loadModel('Log');
$this->Log->createLogEntry('SYSTEM', 'auth_fail', 'User', 0, "Failed authentication using an API key of incorrect length.");
}
return false;
}
@ -674,7 +689,7 @@ class AppController extends Controller
$shouldBeLogged = $userMonitoringEnabled ||
Configure::read('MISP.log_paranoid') ||
(Configure::read('MISP.log_paranoid_api') && $user['logged_by_authkey']);
(Configure::read('MISP.log_paranoid_api') && isset($user['logged_by_authkey']) && $user['logged_by_authkey']);
if ($shouldBeLogged) {
$includeRequestBody = !empty(Configure::read('MISP.log_paranoid_include_post_body')) || $userMonitoringEnabled;
@ -684,8 +699,8 @@ class AppController extends Controller
}
if (
(empty(Configure::read('MISP.log_skip_access_logs_in_application_logs'))) &&
Configure::read('MISP.log_paranoid') || $userMonitoringEnabled
empty(Configure::read('MISP.log_skip_access_logs_in_application_logs')) &&
$shouldBeLogged
) {
$change = 'HTTP method: ' . $_SERVER['REQUEST_METHOD'] . PHP_EOL . 'Target: ' . $this->request->here;
if (

View File

@ -1961,7 +1961,7 @@ class AttributesController extends AppController
public function fetchViewValue($id, $field = null)
{
$user = $this->_closeSession();
$validFields = ['value', 'comment', 'type', 'category', 'to_ids', 'distribution', 'timestamp', 'first_seen', 'last_seen'];
$validFields = ['value', 'comment', 'type', 'category', 'distribution', 'timestamp', 'first_seen', 'last_seen'];
if (!isset($field) || !in_array($field, $validFields, true)) {
throw new MethodNotAllowedException(__('Invalid field requested.'));
}
@ -1989,9 +1989,7 @@ class AttributesController extends AppController
$attribute = $attribute[0];
$result = $attribute['Attribute'][$field];
if ($field === 'distribution') {
$result = $this->Attribute->shortDist[$result];
} elseif ($field === 'to_ids') {
$result = $result == 0 ? 'No' : 'Yes';
$this->set('shortDist', $this->Attribute->shortDist);
} elseif ($field === 'value') {
$this->loadModel('Warninglist');
$attribute['Attribute'] = $this->Warninglist->checkForWarning($attribute['Attribute']);
@ -2006,23 +2004,27 @@ class AttributesController extends AppController
public function fetchEditForm($id, $field = null)
{
$validFields = array('value', 'comment', 'type', 'category', 'to_ids', 'distribution', 'first_seen', 'last_seen');
if (!isset($field) || !in_array($field, $validFields)) {
throw new MethodNotAllowedException(__('Invalid field requested.'));
}
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This function can only be accessed via AJAX.'));
}
$fields = array('id', 'distribution', 'event_id');
if ($field == 'category' || $field == 'type') {
$fields[] = 'type';
$fields[] = 'category';
$validFields = array('value', 'comment', 'type', 'category', 'to_ids', 'distribution', 'first_seen', 'last_seen');
if (!isset($field) || !in_array($field, $validFields, true)) {
throw new NotFoundException(__('Invalid field requested.'));
}
$fieldsToFetch = array('id', 'event_id');
if ($field === 'category' || $field === 'type') {
$fieldsToFetch[] = 'type';
$fieldsToFetch[] = 'category';
if ($field === 'type') {
$fieldsToFetch[] = 'value';
}
} else {
$fields[] = $field;
$fieldsToFetch[] = $field;
}
$params = array(
'conditions' => array('Attribute.id' => $id),
'fields' => $fields,
'fields' => $fieldsToFetch,
'flatten' => 1,
'contain' => array(
'Event' => array(
@ -2044,15 +2046,28 @@ class AttributesController extends AppController
unset($distributionLevels[4]);
$this->set('distributionLevels', $distributionLevels);
} elseif ($field === 'category') {
$typeCategory = array();
$possibleCategories = [];
foreach ($this->Attribute->categoryDefinitions as $k => $category) {
foreach ($category['types'] as $type) {
$typeCategory[$type][] = $k;
if (in_array($attribute['Attribute']['type'], $category['types'], true)) {
$possibleCategories[] = $k;
}
}
$this->set('typeCategory', $typeCategory);
$this->set('possibleCategories', $possibleCategories);
} elseif ($field === 'type') {
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
$possibleTypes = $this->Attribute->categoryDefinitions[$attribute['Attribute']['category']]['types'];
$validTypes = AttributeValidationTool::validTypesForValue($possibleTypes, $this->Attribute->getCompositeTypes(), $attribute['Attribute']['value']);
$options = [];
foreach ($possibleTypes as $possibleType) {
if ($this->Attribute->typeIsAttachment($possibleType)) {
continue; // skip attachment types
}
$options[] = [
'name' => $possibleType,
'value' => $possibleType,
'disabled' => !in_array($possibleType, $validTypes, true),
];
}
$this->set('options', $options);
}
$this->set('object', $attribute['Attribute']);
$fieldURL = ucfirst($field);
@ -2798,10 +2813,7 @@ class AttributesController extends AppController
'fields' => ['Attribute.deleted', 'Attribute.event_id', 'Attribute.id', 'Attribute.object_id', 'Event.orgc_id', 'Event.user_id'],
'contain' => ['Event'],
]);
if (empty($attribute)) {
throw new NotFoundException(__('Invalid attribute'));
}
if ($attribute['Attribute']['deleted']) {
if (empty($attribute) || $attribute['Attribute']['deleted']) {
throw new NotFoundException(__('Invalid attribute'));
}
if (empty($tag_id)) {
@ -2831,19 +2843,19 @@ class AttributesController extends AppController
if (!$this->__canModifyTag($attribute, !empty($attributeTag['AttributeTag']['local']))) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You do not have permission to do that.')), 'status' => 200, 'type' => 'json'));
}
if (empty($attributeTag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid attribute - tag combination.')), 'status' => 200, 'type' => 'json'));
}
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
if ($this->Attribute->AttributeTag->delete($attributeTag['AttributeTag']['id'])) {
if (empty($attributeTag['AttributeTag']['local'])) {
$this->Attribute->touch($attribute);
}
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Removed tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" from attribute (' . $id . ')', 'Attribute (' . $id . ') untagged of Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag removed.', 'check_publish' => empty($attributeTag['AttributeTag']['local']))), 'status' => 200, 'type'=> 'json'));

View File

@ -1,15 +1,13 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property Community $Community
*/
class CommunitiesController extends AppController
{
public $components = array('Session', 'RequestHandler');
public function beforeFilter()
{
parent::beforeFilter();
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999

View File

@ -384,7 +384,8 @@ class ACLComponent extends Component
'event_index' => array('*'),
'returnDates' => array('*'),
'testForStolenAttributes' => array(),
'pruneUpdateLogs' => array()
'pruneUpdateLogs' => array(),
'index' => array('perm_audit')
),
'auditLogs' => [
'admin_index' => ['perm_audit'],
@ -395,6 +396,7 @@ class ACLComponent extends Component
'accessLogs' => [
'admin_index' => [],
'admin_request' => [],
'admin_queryLog' => [],
],
'modules' => array(
'index' => array('perm_auth'),
@ -434,6 +436,7 @@ class ACLComponent extends Component
'groupAttributesIntoObject' => array('perm_add'),
'revise_object' => array('perm_add'),
'view' => array('*'),
'createFromFreetext' => ['perm_add'],
),
'objectReferences' => array(
'add' => array('perm_add'),
@ -451,9 +454,9 @@ class ACLComponent extends Component
'objectChoice' => array('*'),
'objectMetaChoice' => array('perm_add'),
'view' => array('*'),
'viewElements' => array('*'),
'index' => array('*'),
'update' => array()
'update' => array(),
'possibleObjectTemplates' => ['*'],
),
'objectTemplateElements' => array(
'viewElements' => array('*')
@ -480,9 +483,9 @@ class ACLComponent extends Component
'display' => array('*'),
),
'posts' => array(
'add' => array('not_read_only_authkey'),
'delete' => array('not_read_only_authkey'),
'edit' => array('not_read_only_authkey'),
'add' => ['AND' => ['not_read_only_authkey', 'discussion_enabled']],
'delete' => ['AND' => ['not_read_only_authkey', 'discussion_enabled']],
'edit' => ['AND' => ['not_read_only_authkey', 'discussion_enabled']],
'pushMessageToZMQ' => array()
),
'regexp' => array(
@ -674,6 +677,7 @@ class ACLComponent extends Component
'taxonomyMassHide' => array('perm_tagger'),
'taxonomyMassUnhide' => array('perm_tagger'),
'toggleRequired' => array(),
'toggleHighlighted' => array(),
'update' => array(),
'import' => [],
'export' => ['*'],
@ -713,14 +717,15 @@ class ACLComponent extends Component
'view' => array('*'),
),
'threads' => array(
'index' => array('*'),
'view' => array('*'),
'viewEvent' => array('*'),
'index' => array('discussion_enabled'),
'view' => array('discussion_enabled'),
'viewEvent' => array('discussion_enabled'),
),
'users' => array(
'acceptRegistrations' => array(),
'admin_add' => ['AND' => ['perm_admin', 'add_user_enabled']],
'admin_delete' => array('perm_admin'),
'admin_destroy' => array(),
'admin_edit' => array('perm_admin'),
'admin_email' => array('perm_admin'),
'admin_filterUserIndex' => array('perm_admin'),
@ -774,7 +779,7 @@ class ACLComponent extends Component
'eventIndexColumnToggle' => ['*'],
),
'warninglists' => array(
'checkValue' => array('perm_auth'),
'checkValue' => ['*'],
'delete' => ['perm_warninglist'],
'enableWarninglist' => ['perm_warninglist'],
'getToggleField' => ['perm_warninglist'],
@ -864,6 +869,9 @@ class ACLComponent extends Component
$this->dynamicChecks['delegation_enabled'] = function (array $user) {
return (bool)Configure::read('MISP.delegation');
};
$this->dynamicChecks['discussion_enabled'] = function (array $user) {
return !Configure::read('MISP.discussion_disable');
};
// Returns true if current user is not using advanced auth key or if authkey is not read only
$this->dynamicChecks['not_read_only_authkey'] = function (array $user) {
return !isset($user['authkey_read_only']) || !$user['authkey_read_only'];

View File

@ -13,6 +13,15 @@ class BetterSecurityComponent extends SecurityComponent
*/
public $doNotGenerateToken = false;
public function blackHole(Controller $controller, $error = '', SecurityException $exception = null)
{
$action = $controller->request->params['action'];
$unlockedActions = JsonTool::encode($this->unlockedActions);
$isRest = $controller->IndexFilter->isRest() ? '1' : '0';
$this->log("Blackhole exception when accessing $controller->here (isRest: $isRest, action: $action, unlockedActions: $unlockedActions): {$exception->getMessage()}"); // log blackhole exception
return parent::blackHole($controller, $error, $exception);
}
public function generateToken(CakeRequest $request)
{
if (isset($request->params['requested']) && $request->params['requested'] === 1) {

View File

@ -44,15 +44,21 @@ class IndexFilterComponent extends Component
}
}
}
$data = $this->__massageData($data, $request, $paramArray);
$this->Controller->set('passedArgs', json_encode($this->Controller->passedArgs));
return $data;
}
private function __massageData($data, $request, $paramArray)
{
$data = array_filter($data, function($paramName) use ($paramArray) {
return !empty($paramArray[$paramName]);
}, ARRAY_FILTER_USE_KEY);
if (!empty($paramArray)) {
foreach ($paramArray as $p) {
if (
isset($options['ordered_url_params'][$p]) &&
(!in_array(strtolower((string)$options['ordered_url_params'][$p]), array('null', '0', false, 'false', null)))
) {
$data[$p] = $options['ordered_url_params'][$p];
$data[$p] = str_replace(';', ':', $data[$p]);
}
if (isset($request->params['named'][$p])) {
$data[$p] = str_replace(';', ':', $request->params['named'][$p]);
}
@ -67,28 +73,8 @@ class IndexFilterComponent extends Component
}
}
unset($v);
if (!empty($options['additional_delimiters'])) {
if (!is_array($options['additional_delimiters'])) {
$options['additional_delimiters'] = array($options['additional_delimiters']);
}
foreach ($data as $k => $v) {
$found = false;
foreach ($options['additional_delimiters'] as $delim) {
if (strpos($v, $delim) !== false) {
$found = true;
break;
}
}
if ($found) {
$data[$k] = explode($options['additional_delimiters'][0], str_replace($options['additional_delimiters'], $options['additional_delimiters'][0], $v));
foreach ($data[$k] as $k2 => $value) {
$data[$k][$k2] = trim($data[$k][$k2]);
}
}
}
}
$this->Controller->set('passedArgs', json_encode($this->Controller->passedArgs));
return $data;
}
public function isRest()

View File

@ -608,37 +608,34 @@ class RestResponseComponent extends Component
$type = 'csv';
} else {
$type = $format;
$dumpSql = !empty($this->Controller->sql_dump) && Configure::read('debug') > 1;
$dumpSql = intval($this->Controller->request->params['named']['sql'] ?? 0);
if ($dumpSql && Configure::read('debug') < 2) {
$dumpSql = 0; // disable dumping SQL if debugging is off
}
if (!$raw) {
if (is_string($response)) {
$response = array('message' => $response);
}
if ($dumpSql) {
$this->Log = ClassRegistry::init('Log');
if ($this->Controller->sql_dump === 2) {
$response = array('sql_dump' => $this->Log->getDataSource()->getLog(false, false));
if ($dumpSql === 2) {
$response = ['sql_dump' => $this->getSqlLog()];
} else {
$response['sql_dump'] = $this->Log->getDataSource()->getLog(false, false);
$response['sql_dump'] = $this->getSqlLog();
}
}
$flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
if (!$this->isAutomaticTool()) {
$flags |= JSON_PRETTY_PRINT; // Do not pretty print response for automatic tools
}
if (defined('JSON_THROW_ON_ERROR')) {
$flags |= JSON_THROW_ON_ERROR; // Throw exception on error if supported
}
$response = json_encode($response, $flags);
$prettyPrint = !$this->isAutomaticTool(); // Do not pretty print response for automatic tools
$response = JsonTool::encode($response, $prettyPrint);
} else {
if ($dumpSql) {
$this->Log = ClassRegistry::init('Log');
if ($this->Controller->sql_dump === 2) {
$response = json_encode(array('sql_dump' => $this->Log->getDataSource()->getLog(false, false)));
if ($dumpSql === 2) {
$response = JsonTool::encode(['sql_dump' => $this->getSqlLog()]);
} else {
$response = substr_replace(
$response,
sprintf(', "sql_dump": %s}', json_encode($this->Log->getDataSource()->getLog(false, false))),
sprintf(', "sql_dump": %s}', JsonTool::encode($this->getSqlLog())),
-2
);
}
@ -2104,4 +2101,12 @@ class RestResponseComponent extends Component
}
return '/' . $admin_routing . $controller . '/' . $action;
}
/**
* @return array
*/
private function getSqlLog()
{
return $this->Controller->User->getDataSource()->getLog(false, false);
}
}

View File

@ -990,7 +990,7 @@ class EventsController extends AppController
$possibleColumns[] = 'proposals';
}
if (Configure::read('MISP.showDiscussionsCountOnIndex')) {
if (Configure::read('MISP.showDiscussionsCountOnIndex') && !Configure::read('MISP.discussion_disable')) {
$possibleColumns[] = 'discussion';
}
@ -1022,6 +1022,7 @@ class EventsController extends AppController
if (in_array('tags', $columns, true) || in_array('clusters', $columns, true)) {
$events = $this->Event->attachTagsToEvents($events);
$events = $this->GalaxyCluster->attachClustersToEventIndex($user, $events, true);
$events = $this->__attachHighlightedTagsToEvents($events);
}
if (in_array('correlations', $columns, true)) {
@ -1036,7 +1037,7 @@ class EventsController extends AppController
$events = $this->Event->attachProposalsCountToEvents($user, $events);
}
if (in_array('discussion', $columns, true)) {
if (in_array('discussion', $columns, true) && !Configure::read('MISP.discussion_disable')) {
$events = $this->Event->attachDiscussionsCountToEvents($user, $events);
}
@ -1302,6 +1303,7 @@ class EventsController extends AppController
}
// remove galaxies tags
$containsProposals = !empty($event['ShadowAttribute']);;
$this->loadModel('Taxonomy');
foreach ($event['Object'] as $k => $object) {
if (isset($object['Attribute'])) {
@ -1312,6 +1314,9 @@ class EventsController extends AppController
$tagConflicts = $this->Taxonomy->checkIfTagInconsistencies($attribute['AttributeTag']);
$event['Object'][$k]['Attribute'][$k2]['tagConflicts'] = $tagConflicts;
}
if (!$containsProposals && !empty($attribute['ShadowAttribute'])) {
$containsProposals = true;
}
}
}
}
@ -1323,6 +1328,9 @@ class EventsController extends AppController
$tagConflicts = $this->Taxonomy->checkIfTagInconsistencies($attribute['AttributeTag']);
$attribute['tagConflicts'] = $tagConflicts;
}
if (!$containsProposals && !empty($attribute['ShadowAttribute'])) {
$containsProposals = true;
}
}
if (empty($this->passedArgs['sort'])) {
$filters['sort'] = 'timestamp';
@ -1337,6 +1345,7 @@ class EventsController extends AppController
}
$this->params->params['paging'] = array($this->modelClass => $params);
$this->set('event', $event);
$this->set('includeOrgColumn', (isset($conditions['extended']) || $containsProposals));
$this->set('includeSightingdb', (!empty($filters['includeSightingdb']) && Configure::read('Plugin.Sightings_sighting_db_enable')));
$this->set('deleted', isset($filters['deleted']) && $filters['deleted'] != 0);
$this->set('attributeFilter', isset($filters['attributeFilter']) ? $filters['attributeFilter'] : 'all');
@ -1386,32 +1395,11 @@ class EventsController extends AppController
$emptyEvent = (empty($event['Object']) && empty($event['Attribute']));
$this->set('emptyEvent', $emptyEvent);
$attributeCount = isset($event['Attribute']) ? count($event['Attribute']) : 0;
$objectCount = isset($event['Object']) ? count($event['Object']) : 0;
$oldest_timestamp = false;
// set the data for the contributors / history field
$contributors = $this->Event->ShadowAttribute->getEventContributors($event['Event']['id']);
$this->set('contributors', $contributors);
if ($this->__canPublishEvent($event, $user)) {
$proposalStatus = false;
if (isset($event['ShadowAttribute']) && !empty($event['ShadowAttribute'])) {
$proposalStatus = true;
}
if (!$proposalStatus && !empty($event['Attribute'])) {
foreach ($event['Attribute'] as $temp) {
if (!empty($temp['ShadowAttribute'])) {
$proposalStatus = true;
break;
}
}
}
$mess = $this->Session->read('Message');
if ($proposalStatus && empty($mess)) {
$this->Flash->info('This event has active proposals for you to accept or discard.');
}
}
// set the pivot data
$this->helpers[] = 'Pivot';
if ($continue) {
@ -1435,7 +1423,7 @@ class EventsController extends AppController
}
}
foreach ($relatedEventCorrelationCount as $key => $relation) {
$relatedEventCorrelationCount[$key] = count($relatedEventCorrelationCount[$key]);
$relatedEventCorrelationCount[$key] = count($relation);
}
$this->Event->removeGalaxyClusterTags($event);
@ -1449,11 +1437,15 @@ class EventsController extends AppController
}
$this->set('tagConflicts', $tagConflicts);
$attributeCount = isset($event['Attribute']) ? count($event['Attribute']) : 0;
$objectCount = isset($event['Object']) ? count($event['Object']) : 0;
$oldestTimestamp = PHP_INT_MAX;
$containsProposals = !empty($event['ShadowAttribute']);
$modDate = date("Y-m-d", $event['Event']['timestamp']);
$modificationMap = array($modDate => 1);
foreach ($event['Attribute'] as $k => $attribute) {
if ($oldest_timestamp === false || $oldest_timestamp > $attribute['timestamp']) {
$oldest_timestamp = $attribute['timestamp'];
if ($oldestTimestamp > $attribute['timestamp']) {
$oldestTimestamp = $attribute['timestamp'];
}
$modDate = date("Y-m-d", $attribute['timestamp']);
$modificationMap[$modDate] = !isset($modificationMap[$modDate]) ? 1 : $modificationMap[$modDate] + 1;
@ -1470,10 +1462,10 @@ class EventsController extends AppController
}
$event['Attribute'][$k]['tagConflicts'] = $tagConflicts;
}
if (!$containsProposals && !empty($attribute['ShadowAttribute'])) {
$containsProposals = true;
}
}
$attributeTagsName = $this->Event->Attribute->AttributeTag->extractAttributeTagsNameFromEvent($event);
$this->set('attributeTags', array_values($attributeTagsName['tags']));
$this->set('attributeClusters', array_values($attributeTagsName['clusters']));
foreach ($event['Object'] as $k => $object) {
$modDate = date("Y-m-d", $object['timestamp']);
@ -1481,8 +1473,8 @@ class EventsController extends AppController
if (!empty($object['Attribute'])) {
$attributeCount += count($object['Attribute']);
foreach ($object['Attribute'] as $k2 => $attribute) {
if ($oldest_timestamp === false || $oldest_timestamp > $attribute['timestamp']) {
$oldest_timestamp = $attribute['timestamp'];
if ($oldestTimestamp > $attribute['timestamp']) {
$oldestTimestamp = $attribute['timestamp'];
}
$modDate = date("Y-m-d", $attribute['timestamp']);
@ -1500,9 +1492,24 @@ class EventsController extends AppController
}
$event['Object'][$k]['Attribute'][$k2]['tagConflicts'] = $tagConflicts;
}
if (!$containsProposals && !empty($attribute['ShadowAttribute'])) {
$containsProposals = true;
}
}
}
}
if ($containsProposals && $this->__canPublishEvent($event, $user)) {
$mess = $this->Session->read('Message');
if (empty($mess)) {
$this->Flash->info(__('This event has active proposals for you to accept or discard.'));
}
}
$attributeTagsName = $this->Event->Attribute->AttributeTag->extractAttributeTagsNameFromEvent($event);
$this->set('attributeTags', array_values($attributeTagsName['tags']));
$this->set('attributeClusters', array_values($attributeTagsName['clusters']));
$this->set('warningTagConflicts', $warningTagConflicts);
$filters['sort'] = 'timestamp';
$filters['direction'] = 'desc';
@ -1584,9 +1591,10 @@ class EventsController extends AppController
if (!empty($filters['includeSightingdb']) && Configure::read('Plugin.Sightings_sighting_db_enable')) {
$this->set('sightingdbs', $this->Sightingdb->getSightingdbList($user));
}
$this->set('includeOrgColumn', $this->viewVars['extended'] || $containsProposals);
$this->set('includeSightingdb', !empty($filters['includeSightingdb']) && Configure::read('Plugin.Sightings_sighting_db_enable'));
$this->set('relatedEventCorrelationCount', $relatedEventCorrelationCount);
$this->set('oldest_timestamp', $oldest_timestamp);
$this->set('oldest_timestamp', $oldestTimestamp === PHP_INT_MAX ? false : $oldestTimestamp);
$this->set('missingTaxonomies', $this->Event->missingTaxonomies($event));
$this->set('currentUri', $attributeUri);
$this->set('filters', $filters);
@ -1645,6 +1653,7 @@ class EventsController extends AppController
$cortex_modules = $this->Module->getEnabledModules($user, false, 'Cortex');
$this->set('cortex_modules', $cortex_modules);
}
$this->set('sightingsDbEnabled', (bool)Configure::read('Plugin.Sightings_sighting_db_enable'));
}
public function view($id = null, $continue = false, $fromEvent = null)
@ -1805,6 +1814,8 @@ class EventsController extends AppController
$this->set('includeRelatedTags', (!empty($namedParams['includeRelatedTags'])) ? 1 : 0);
$this->set('includeDecayScore', (!empty($namedParams['includeDecayScore'])) ? 1 : 0);
$this->__setHighlightedTags($event);
if ($this->_isSiteAdmin() && $event['Event']['orgc_id'] !== $this->Auth->user('org_id')) {
$this->Flash->info(__('You are currently logged in as a site administrator and about to edit an event not belonging to your organisation. This goes against the sharing model of MISP. Use a normal user account for day to day work.'));
}
@ -2273,7 +2284,12 @@ class EventsController extends AppController
foreach ($analysisLevels as $key => $value) {
$fieldDesc['analysis'][$key] = $this->Event->analysisDescriptions[$key]['formdesc'];
}
$this->Flash->info(__('The event created will be visible to the organisations having an account on this platform, but not synchronised to other MISP instances until it is published.'));
if (Configure::read('MISP.unpublishedprivate')) {
$this->Flash->info(__('The event created will be visible only to your organisation until it is published.'));
} else {
$this->Flash->info(__('The event created will be visible to the organisations having an account on this platform, but not synchronised to other MISP instances until it is published.'));
}
$this->set('fieldDesc', $fieldDesc);
if (isset($this->params['named']['extends'])) {
$this->set('extends_uuid', $this->params['named']['extends']);
@ -2341,13 +2357,14 @@ class EventsController extends AppController
$results = $this->Event->addMISPExportFile($this->Auth->user(), $data, $isXml, $takeOwnership, $publish);
} catch (Exception $e) {
$this->log("Exception during processing MISP file import: {$e->getMessage()}");
$this->Flash->error(__('Could not process MISP export file. Probably file content is invalid.'));
$this->Flash->error(__('Could not process MISP export file. %s.', $e->getMessage()));
$this->redirect(['controller' => 'events', 'action' => 'add_misp_export']);
}
}
$this->set('results', $results);
$this->render('add_misp_export_result');
}
$this->set('title_for_layout', __('Import from MISP Export File'));
}
public function upload_stix($stix_version = '1', $publish = false)
@ -3985,6 +4002,7 @@ class EventsController extends AppController
$this->set('mayModify', $this->__canModifyEvent($event));
$this->set('typeDefinitions', $this->Event->Attribute->typeDefinitions);
$this->set('typeCategoryMapping', $typeCategoryMapping);
$this->set('defaultAttributeDistribution', $this->Event->Attribute->defaultDistribution());
$this->set('resultArray', $resultArray);
$this->set('importComment', '');
$this->set('title_for_layout', __('Freetext Import Results'));
@ -5258,6 +5276,7 @@ class EventsController extends AppController
$this->set('resultArray', $resultArray);
$this->set('typeDefinitions', $this->Event->Attribute->typeDefinitions);
$this->set('typeCategoryMapping', $typeCategoryMapping);
$this->set('defaultAttributeDistribution', $this->Event->Attribute->defaultDistribution());
$this->set('importComment', $importComment);
$this->render('resolved_attributes');
}
@ -5292,7 +5311,7 @@ class EventsController extends AppController
}
}
public function importModule($module, $eventId)
public function importModule($moduleName, $eventId)
{
$event = $this->Event->fetchSimpleEvent($this->Auth->user(), $eventId);
if (!$event) {
@ -5302,8 +5321,7 @@ class EventsController extends AppController
$eventId = $event['Event']['id'];
$this->loadModel('Module');
$moduleName = $module;
$module = $this->Module->getEnabledModule($module, 'Import');
$module = $this->Module->getEnabledModule($moduleName, 'Import');
if (!is_array($module)) {
throw new MethodNotAllowedException($module);
}
@ -5311,10 +5329,11 @@ class EventsController extends AppController
$module['mispattributes']['inputSource'] = array('paste');
}
if ($this->request->is('post')) {
$requestData = $this->request->data['Event'];
$fail = false;
$modulePayload = array(
'module' => $module['name'],
'event_id' => $eventId,
'module' => $module['name'],
'event_id' => $eventId,
);
if (isset($module['meta']['config'])) {
foreach ($module['meta']['config'] as $conf) {
@ -5322,11 +5341,11 @@ class EventsController extends AppController
}
}
if ($moduleName === 'csvimport') {
if (empty($this->request->data['Event']['config']['header']) && $this->request->data['Event']['config']['has_header'] === '1') {
$this->request->data['Event']['config']['header'] = ' ';
if (empty($requestData['config']['header']) && $requestData['config']['has_header'] === '1') {
$requestData['config']['header'] = ' ';
}
if (empty($this->request->data['Event']['config']['special_delimiter'])) {
$this->request->data['Event']['config']['special_delimiter'] = ' ';
if (empty($requestData['config']['special_delimiter'])) {
$requestData['config']['special_delimiter'] = ' ';
}
}
if (isset($module['mispattributes']['userConfig'])) {
@ -5337,18 +5356,19 @@ class EventsController extends AppController
$validation = true;
}
} else {
$validation = call_user_func_array(array($this->Module, $this->Module->configTypes[$config['type']]['validation']), array($this->request->data['Event']['config'][$configName]));
$validationMethod = Module::CONFIG_TYPES[$config['type']]['validation'];
$validation = $this->Module->{$validationMethod}($requestData['config'][$configName]);
}
if ($validation !== true) {
$fail = ucfirst($configName) . ': ' . $validation;
} else {
if (isset($config['regex']) && !empty($config['regex'])) {
$fail = preg_match($config['regex'], $this->request->data['Event']['config'][$configName]) ? false : ucfirst($configName) . ': ' . 'Invalid setting' . ($config['errorMessage'] ? ' - ' . $config['errorMessage'] : '');
$fail = preg_match($config['regex'], $requestData['config'][$configName]) ? false : ucfirst($configName) . ': ' . 'Invalid setting' . ($config['errorMessage'] ? ' - ' . $config['errorMessage'] : '');
if (!empty($fail)) {
$modulePayload['config'][$configName] = $this->request->data['Event']['config'][$configName];
$modulePayload['config'][$configName] = $requestData['config'][$configName];
}
} else {
$modulePayload['config'][$configName] = $this->request->data['Event']['config'][$configName];
$modulePayload['config'][$configName] = $requestData['config'][$configName];
}
}
}
@ -5356,31 +5376,29 @@ class EventsController extends AppController
}
if (!$fail) {
if (!empty($module['mispattributes']['inputSource'])) {
if (!isset($this->request->data['Event']['source'])) {
if (!isset($requestData['source'])) {
if (in_array('paste', $module['mispattributes']['inputSource'])) {
$this->request->data['Event']['source'] = '0';
$requestData['source'] = '0';
} else {
$this->request->data['Event']['source'] = '1';
$requestData['source'] = '1';
}
}
if ($this->request->data['Event']['source'] == '1') {
if (isset($this->request->data['Event']['data'])) {
$modulePayload['data'] = base64_decode($this->request->data['Event']['data']);
} elseif (!isset($this->request->data['Event']['fileupload']) || empty($this->request->data['Event']['fileupload'])) {
$fail = 'Invalid file upload.';
if ($requestData['source'] == '1') {
if (isset($requestData['data'])) {
$modulePayload['data'] = base64_decode($requestData['data']);
} elseif (empty($requestData['fileupload'])) {
$fail = __('Invalid file upload.');
} else {
$fileupload = $this->request->data['Event']['fileupload'];
$tmpfile = new File($fileupload['tmp_name']);
if ((isset($fileupload['error']) && $fileupload['error'] == 0) || (!empty($fileupload['tmp_name']) && $fileupload['tmp_name'] != 'none') && is_uploaded_file($tmpfile->path)) {
$fileupload = $requestData['fileupload'];
if ((isset($fileupload['error']) && $fileupload['error'] == 0) || (!empty($fileupload['tmp_name']) && $fileupload['tmp_name'] != 'none') && is_uploaded_file($fileupload['tmp_name'])) {
$filename = basename($fileupload['name']);
App::uses('FileAccessTool', 'Tools');
$modulePayload['data'] = FileAccessTool::readFromFile($fileupload['tmp_name'], $fileupload['size']);
$modulePayload['data'] = FileAccessTool::readAndDelete($fileupload['tmp_name']);
} else {
$fail = 'Invalid file upload.';
$fail = __('Invalid file upload.');
}
}
} else {
$modulePayload['data'] = $this->request->data['Event']['paste'];
$modulePayload['data'] = $requestData['paste'];
}
} else {
$modulePayload['data'] = '';
@ -5433,15 +5451,13 @@ class EventsController extends AppController
$this->set('resultArray', $resultArray);
$this->set('typeDefinitions', $this->Event->Attribute->typeDefinitions);
$this->set('typeCategoryMapping', $typeCategoryMapping);
$this->set('defaultAttributeDistribution', $this->Event->Attribute->defaultDistribution());
$render_name = 'resolved_attributes';
}
$distributions = $this->Event->Attribute->distributionLevels;
$sgs = $this->Event->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', 1);
if (empty($sgs)) {
unset($distributions[4]);
}
$this->set('distributions', $distributions);
$this->set('sgs', $sgs);
$distributionData = $this->Event->Attribute->fetchDistributionData($this->Auth->user());
$this->set('distributions', $distributionData['levels']);
$this->set('sgs', $distributionData['sgs']);
$this->set('title', __('Import Results'));
$this->set('title_for_layout', __('Import Results'));
$this->set('importComment', $importComment);
@ -5452,7 +5468,7 @@ class EventsController extends AppController
$this->Flash->error($fail);
}
}
$this->set('configTypes', $this->Module->configTypes);
$this->set('configTypes', Module::CONFIG_TYPES);
$this->set('module', $module);
$this->set('eventId', $eventId);
$this->set('event', $event);
@ -6217,4 +6233,31 @@ class EventsController extends AppController
$this->render('/genericTemplates/confirm');
}
}
/**
* @param array $event
* @return void
*/
private function __setHighlightedTags($event)
{
$this->loadModel('Taxonomy');
$highlightedTags = $this->Taxonomy->getHighlightedTags($this->Taxonomy->getHighlightedTaxonomies(), $event['EventTag']);
$this->set('highlightedTags', $highlightedTags);
}
/**
*
* @param array $events
* @return array
*/
private function __attachHighlightedTagsToEvents($events)
{
$this->loadModel('Taxonomy');
$highlightedTaxonomies = $this->Taxonomy->getHighlightedTaxonomies();
foreach ($events as $k => $event) {
$events[$k]['Event']['highlightedTags'] = $this->Taxonomy->getHighlightedTags($highlightedTaxonomies, $event['EventTag']);
}
return $events;
}
}

View File

@ -525,7 +525,7 @@ class GalaxiesController extends AppController
}
}
$result = $this->Galaxy->attachCluster($user, $target_type, $target_id, $cluster_id, $local);
$result = $this->Galaxy->attachCluster($user, $target_type, $target, $cluster_id, $local);
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result, 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
}

View File

@ -47,7 +47,7 @@ class GalaxyClustersController extends AppController
}
if ($filters['context'] == 'default') {
$contextConditions['GalaxyCluster.default'] = true;
$contextConditions['GalaxyCluster.default'] = true;
} elseif ($filters['context'] == 'custom') {
$contextConditions['GalaxyCluster.default'] = false;
} elseif ($filters['context'] == 'org') {
@ -146,9 +146,8 @@ class GalaxyClustersController extends AppController
'GalaxyCluster.default' => 0,
]
]);
$this->loadModel('Attribute');
$distributionLevels = $this->Attribute->distributionLevels;
unset($distributionLevels[5]);
$this->loadModel('Event');
$distributionLevels = $this->Event->shortDist;
$this->set('distributionLevels', $distributionLevels);
$this->set('list', $clusters);
$this->set('galaxy_id', $galaxyId);

View File

@ -1,6 +1,9 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property GalaxyElement $GalaxyElement
*/
class GalaxyElementsController extends AppController
{
public $components = array('Session', 'RequestHandler');
@ -16,8 +19,9 @@ class GalaxyElementsController extends AppController
public function index($clusterId)
{
$user = $this->_closeSession();
$filters = $this->IndexFilter->harvestParameters(array('context', 'searchall'));
$aclConditions = $this->GalaxyElement->buildClusterConditions($this->Auth->user(), $clusterId);
$aclConditions = $this->GalaxyElement->buildClusterConditions($user, $clusterId);
if (empty($filters['context'])) {
$filters['context'] = 'all';
}
@ -44,18 +48,15 @@ class GalaxyElementsController extends AppController
'context' => $filters['context'],
'searchall' => isset($filters['searchall']) ? $filters['searchall'] : ''
]));
$cluster = $this->GalaxyElement->GalaxyCluster->fetchIfAuthorized($this->Auth->user(), $clusterId, array('edit', 'delete'), false, false);
$cluster = $this->GalaxyElement->GalaxyCluster->fetchIfAuthorized($user, $clusterId, array('edit', 'delete'), false, false);
$canModify = !empty($cluster['authorized']);
$canModify = true;
$this->set('canModify', $canModify);
if ($filters['context'] == 'JSONView') {
if ($filters['context'] === 'JSONView') {
$expanded = $this->GalaxyElement->getExpandedJSONFromElements($elements);
$this->set('JSONElements', $expanded);
}
if ($this->request->is('ajax')) {
$this->layout = false;
$this->render('ajax/index');
}
$this->layout = false;
$this->render('ajax/index');
}
public function delete($elementId)

View File

@ -1,7 +1,9 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property Log $Log
*/
class LogsController extends AppController
{
public $components = array(
@ -23,23 +25,24 @@ class LogsController extends AppController
parent::beforeFilter();
// No need for CSRF tokens for a search
if ('admin_search' == $this->request->params['action']) {
if ('admin_search' === $this->request->params['action']) {
$this->Security->csrfCheck = false;
}
}
public function admin_index()
public function index()
{
$paramArray = array('id', 'title', 'created', 'model', 'model_id', 'action', 'user_id', 'change', 'email', 'org', 'description', 'ip');
$filterData = array(
'request' => $this->request,
'named_params' => $this->params['named'],
'named_params' => $this->request->params['named'],
'paramArray' => $paramArray,
'ordered_url_params' => func_get_args()
);
$exception = false;
$filters = $this->_harvestParameters($filterData, $exception);
unset($filterData);
if ($this->_isRest()) {
if ($filters === false) {
return $exception;
@ -71,8 +74,14 @@ class LogsController extends AppController
}
}
if (!$this->_isSiteAdmin()) {
$orgRestriction = $this->Auth->user('Organisation')['name'];
$conditions['AND']['Log.org'] = $orgRestriction;
if ($this->_isAdmin()) {
// ORG admins can see their own org info
$orgRestriction = $this->Auth->user('Organisation')['name'];
$conditions['Log.org'] = $orgRestriction;
} else {
// users can see their own info
$conditions['Log.user_id'] = $this->Auth->user('id');
}
}
$params = array(
'conditions' => $conditions,
@ -86,30 +95,42 @@ class LogsController extends AppController
}
$log_entries = $this->Log->find('all', $params);
return $this->RestResponse->viewData($log_entries, 'json');
} else {
$this->set('isSearch', 0);
$this->recursive = 0;
$validFilters = $this->Log->logMeta;
if (!$this->_isSiteAdmin()) {
$orgRestriction = $this->Auth->user('Organisation')['name'];
$conditions['Log.org'] = $orgRestriction;
$this->paginate['conditions'] = $conditions;
} else {
$validFilters = array_merge_recursive($validFilters, $this->Log->logMetaAdmin);
}
if (isset($this->params['named']['filter']) && in_array($this->params['named']['filter'], array_keys($validFilters))) {
$this->paginate['conditions']['Log.action'] = $validFilters[$this->params['named']['filter']]['values'];
}
foreach ($filters as $key => $value) {
if ($key === 'created') {
$key = 'created >=';
}
$this->paginate['conditions']["Log.$key"] = $value;
}
$this->set('validFilters', $validFilters);
$this->set('filter', isset($this->params['named']['filter']) ? $this->params['named']['filter'] : false);
$this->set('list', $this->paginate());
}
$this->set('isSearch', 0);
$this->recursive = 0;
$validFilters = $this->Log->logMeta;
if ($this->_isSiteAdmin()) {
$validFilters = array_merge_recursive($validFilters, $this->Log->logMetaAdmin);
}
else if (!$this->_isSiteAdmin() && $this->_isAdmin()) {
// ORG admins can see their own org info
$orgRestriction = $this->Auth->user('Organisation')['name'];
$conditions['Log.org'] = $orgRestriction;
$this->paginate['conditions'] = $conditions;
} else {
// users can see their own info
$conditions['Log.email'] = $this->Auth->user('email');
$this->paginate['conditions'] = $conditions;
}
if (isset($this->params['named']['filter']) && in_array($this->params['named']['filter'], array_keys($validFilters))) {
$this->paginate['conditions']['Log.action'] = $validFilters[$this->params['named']['filter']]['values'];
}
foreach ($filters as $key => $value) {
if ($key === 'created') {
$key = 'created >=';
}
$this->paginate['conditions']["Log.$key"] = $value;
}
$this->set('validFilters', $validFilters);
$this->set('filter', isset($this->params['named']['filter']) ? $this->params['named']['filter'] : false);
$this->set('list', $this->paginate());
}
public function admin_index()
{
$this->view = 'index';
return $this->index();
}
// Shows a minimalistic history for the currently selected event
@ -313,7 +334,7 @@ class LogsController extends AppController
}
// set the same view as the index page
$this->render('admin_index');
$this->render('index');
}
} else {
// get from Session

View File

@ -22,9 +22,10 @@ class ObjectTemplatesController extends AppController
public function beforeFilter()
{
parent::beforeFilter();
if (in_array($this->request->action, ['objectMetaChoice', 'objectChoice'], true)) {
if (in_array($this->request->action, ['objectMetaChoice', 'objectChoice', 'possibleObjectTemplates'], true)) {
$this->Security->doNotGenerateToken = true;
}
$this->Security->unlockedActions[] = 'possibleObjectTemplates';
}
public function objectMetaChoice($eventId)
@ -162,16 +163,6 @@ class ObjectTemplatesController extends AppController
$this->redirect($this->referer());
}
public function viewElements($id, $context = 'all')
{
$elements = $this->ObjectTemplate->ObjectTemplateElement->find('all', array(
'conditions' => array('ObjectTemplateElement.object_template_id' => $id)
));
$this->set('list', $elements);
$this->layout = false;
$this->render('ajax/view_elements');
}
public function index($all = false)
{
$passedArgsArray = array();
@ -183,11 +174,12 @@ class ObjectTemplatesController extends AppController
$this->set('all', true);
}
if (!empty($this->params['named']['searchall'])) {
$searchTerm = '%' . strtolower($this->request->params['named']['searchall']) . '%';
$this->paginate['conditions']['AND']['OR'] = array(
'ObjectTemplate.uuid LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%',
'LOWER(ObjectTemplate.name) LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%',
'ObjectTemplate.meta-category LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%',
'LOWER(ObjectTemplate.description) LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%'
'ObjectTemplate.uuid LIKE' => $searchTerm,
'LOWER(ObjectTemplate.name) LIKE' => $searchTerm,
'ObjectTemplate.meta-category LIKE' => $searchTerm,
'LOWER(ObjectTemplate.description) LIKE' => $searchTerm,
);
}
if ($this->_isRest()) {
@ -196,11 +188,11 @@ class ObjectTemplatesController extends AppController
unset($rules['order']);
$objectTemplates = $this->ObjectTemplate->find('all', $rules);
return $this->RestResponse->viewData($objectTemplates, $this->response->type());
} else {
$this->paginate['order'] = array('ObjectTemplate.name' => 'ASC');
$objectTemplates = $this->paginate();
$this->set('list', $objectTemplates);
}
$this->paginate['order'] = array('ObjectTemplate.name' => 'ASC');
$objectTemplates = $this->paginate();
$this->set('list', $objectTemplates);
$this->set('passedArgs', json_encode($passedArgs));
$this->set('passedArgsArray', $passedArgsArray);
}
@ -315,4 +307,28 @@ class ObjectTemplatesController extends AppController
}
return $this->RestResponse->viewData($template, $this->response->type());
}
public function possibleObjectTemplates()
{
session_abort();
$this->request->allowMethod(['post']);
$attributeTypes = $this->request->data['attributeTypes'];
$templates = $this->ObjectTemplate->fetchPossibleTemplatesBasedOnTypes($attributeTypes)['templates'];
$results = [];
foreach ($templates as $template) {
$template = $template['ObjectTemplate'];
if ($template['compatibility'] === true && empty($template['invalidTypes'])) {
$results[] = [
'id' => $template['id'],
'name' => $template['name'],
'description' => $template['description'],
'meta-category' => $template['meta-category'],
];
}
}
return $this->RestResponse->viewData($results, 'json');
}
}

View File

@ -60,33 +60,6 @@ class ObjectsController extends AppController
$sgs = $this->MispObject->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'name', false, array_keys($sharing_groups));
$this->set('sharing_groups', $sgs);
}
$multiple_template_elements = Hash::extract($template['ObjectTemplateElement'], sprintf('{n}[multiple=true]'));
$multiple_attribute_allowed = array();
foreach ($multiple_template_elements as $template_element) {
$relation_type = $template_element['object_relation'] . ':' . $template_element['type'];
$multiple_attribute_allowed[$relation_type] = true;
}
$this->set('multiple_attribute_allowed', $multiple_attribute_allowed);
// try to fetch similar objects
$cur_attrs = Hash::extract($this->request->data, 'Attribute.{n}.value');
$conditions = array(
'event_id' => $event_id,
'value1' => $cur_attrs,
'object_id !=' => '0'
);
$similar_objects = $this->MispObject->Attribute->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'fields' => 'object_id, count(object_id) as similarity_amount',
'group' => 'object_id',
'order' => 'similarity_amount DESC'
));
$similar_object_ids = array();
$similar_object_similarity_amount = array();
foreach ($similar_objects as $obj) {
$similar_object_ids[] = $obj['Attribute']['object_id'];
$similar_object_similarity_amount[$obj['Attribute']['object_id']] = $obj[0]['similarity_amount'];
}
if (isset($this->request->data['Attribute'])) {
foreach ($this->request->data['Attribute'] as &$attribute) {
@ -113,33 +86,35 @@ class ObjectsController extends AppController
'cur_object_tmp_uuid' => $curObjectTmpUuid,
'data' => $this->request->data
));
if (!empty($similar_object_ids)) {
$this->set('similar_objects_count', count($similar_object_ids));
$similar_object_ids = array_slice($similar_object_ids, 0, $similar_objects_display_threshold); // slice to honor the threshold
$similar_objects = $this->MispObject->fetchObjects($this->Auth->user(), array(
'conditions' => array(
'Object.id' => $similar_object_ids,
'Object.template_uuid' => $template['ObjectTemplate']['uuid']
)
));
foreach ($similar_objects as $key => $obj) {
$similar_objects[$key]['Object']['similarity_amount'] = $similar_object_similarity_amount[$obj['Object']['id']]; // sorting function cannot use external variables
}
usort($similar_objects, function ($a, $b) { // fetch Object returns object sorted by IDs, force the sort by the similarity amount
if ($a['Object']['similarity_amount'] == $b['Object']['similarity_amount']) {
return 0;
if ($action === 'add') {
list($similar_objects_count, $similar_objects, $simple_flattened_attribute, $simple_flattened_attribute_noval) = $this->MispObject->findSimilarObjects(
$this->Auth->user(),
$event_id,
$this->request->data['Attribute'],
$template,
$similar_objects_display_threshold
);
if ($similar_objects_count) {
$this->set('similar_objects_count', $similar_objects_count);
$this->set('similar_objects', $similar_objects);
$this->set('similar_objects_display_threshold', $similar_objects_display_threshold);
$this->set('simple_flattened_attribute', $simple_flattened_attribute);
$this->set('simple_flattened_attribute_noval', $simple_flattened_attribute_noval);
$multiple_template_elements = Hash::extract($template['ObjectTemplateElement'],'{n}[multiple=true]');
$multiple_attribute_allowed = array();
foreach ($multiple_template_elements as $template_element) {
$relation_type = $template_element['object_relation'] . ':' . $template_element['type'];
$multiple_attribute_allowed[$relation_type] = true;
}
return ($a['Object']['similarity_amount'] > $b['Object']['similarity_amount']) ? -1 : 1;
});
$this->set('similar_objects', $similar_objects);
$this->set('similar_object_similarity_amount', $similar_object_similarity_amount);
$this->set('similar_objects_display_threshold', $similar_objects_display_threshold);
$this->set('multiple_attribute_allowed', $multiple_attribute_allowed);
}
}
}
/**
* Create an object using a template
* Create an object using a template
* POSTing will take the input and validate it against the template
* GETing will return the template
*/
@ -343,10 +318,16 @@ class ObjectsController extends AppController
$template = $this->MispObject->prepareTemplate($template);
$element = array();
foreach ($template['ObjectTemplateElement'] as $templateElement) {
if ($templateElement['object_relation'] == $object_relation) {
if ($templateElement['object_relation'] === $object_relation) {
$element = $templateElement;
break;
}
}
if (empty($element)) {
throw new NotFoundException(__("Object template do not contains object relation $object_relation"));
}
$distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($this->Auth->user());
$this->layout = false;
$this->set('distributionData', $distributionData);
@ -431,7 +412,7 @@ class ObjectsController extends AppController
$savedObject = array();
if (!is_numeric($objectToSave)) {
$object_validation_errors = array();
foreach($objectToSave as $field => $field_errors) {
foreach ($objectToSave as $field => $field_errors) {
$object_validation_errors[] = sprintf('%s: %s', $field, implode(', ', $field_errors));
}
$error_message = __('Object could not be saved.') . PHP_EOL . implode(PHP_EOL, $object_validation_errors);
@ -458,12 +439,10 @@ class ObjectsController extends AppController
return $this->RestResponse->saveFailResponse('Objects', 'edit', false, $id, $this->response->type());
}
} else {
$message = __('Object attributes saved.');
if ($this->request->is('ajax')) {
$this->autoRender = false;
if (is_numeric($objectToSave)) {
$this->MispObject->Event->unpublishEvent($event);
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $message)), 'status'=>200, 'type' => 'json'));
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => __('Object attributes saved.'))), 'status'=>200, 'type' => 'json'));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'errors' => $error_message)), 'status'=>200, 'type' => 'json'));
}
@ -597,7 +576,7 @@ class ObjectsController extends AppController
$object = $object[0];
$result = $object['Object'][$field];
if ($field === 'distribution') {
$result = $this->MispObject->shortDist[$result];
$this->set('shortDist', $this->MispObject->Attribute->shortDist);
}
$this->set('value', $result);
$this->set('field', $field);
@ -634,7 +613,7 @@ class ObjectsController extends AppController
throw new NotFoundException(__('Invalid object'));
}
$this->layout = false;
if ($field == 'distribution') {
if ($field === 'distribution') {
$distributionLevels = $this->MispObject->shortDist;
unset($distributionLevels[4]);
$this->set('distributionLevels', $distributionLevels);
@ -732,7 +711,7 @@ class ObjectsController extends AppController
'fields' => array('template_uuid', 'template_version', 'id', 'event_id'),
'flatten' => 1,
'contain' => array(
'Event'
'Event' => ['fields' => ['id', 'user_id', 'org_id', 'orgc_id']]
)
);
// fetchObjects restrict access based on user
@ -1137,23 +1116,8 @@ class ObjectsController extends AppController
$selectedAttributes = $this->_jsonDecode($selectedAttributes);
$res = $this->MispObject->validObjectsFromAttributeTypes($this->Auth->user(), $eventId, $selectedAttributes);
$potentialTemplates = $res['templates'];
$attributeTypes = $res['types'];
usort($potentialTemplates, function($a, $b) {
if ($a['ObjectTemplate']['id'] == $b['ObjectTemplate']['id']) {
return 0;
} else if (is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) {
return count($a['ObjectTemplate']['compatibility']) > count($b['ObjectTemplate']['compatibility']) ? 1 : -1;
} else if (is_array($a['ObjectTemplate']['compatibility']) && !is_array($b['ObjectTemplate']['compatibility'])) {
return 1;
} else if (!is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) {
return -1;
} else { // sort based on invalidTypes count
return count($a['ObjectTemplate']['invalidTypes']) > count($b['ObjectTemplate']['invalidTypes']) ? 1 : -1;
}
});
$this->set('potential_templates', $potentialTemplates);
$this->set('selected_types', $attributeTypes);
$this->set('potential_templates', $res['templates']);
$this->set('selected_types', $res['types']);
$this->set('event_id', $eventId);
}
@ -1230,7 +1194,8 @@ class ObjectsController extends AppController
if (empty($template)) {
throw new NotFoundException(__('Invalid template.'));
}
$conformity_result = $this->MispObject->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $selected_attributes);
$attributeTypes = array_column(array_column($selected_attributes, 'Attribute'), 'type');
$conformity_result = $this->MispObject->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributeTypes);
$skipped_attributes = 0;
foreach ($selected_attributes as $i => $attribute) {
if (in_array($attribute['Attribute']['type'], $conformity_result['invalidTypes'], true)) {
@ -1278,6 +1243,151 @@ class ObjectsController extends AppController
}
}
public function createFromFreetext($eventId)
{
$this->request->allowMethod(['post']);
$event = $this->MispObject->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.uuid', 'Event.orgc_id', 'Event.user_id', 'Event.publish_timestamp'),
'conditions' => array('Event.id' => $eventId)
));
if (empty($event)) {
throw new NotFoundException(__('Invalid event.'));
}
if (!$this->__canModifyEvent($event)) {
throw new ForbiddenException(__('You do not have permission to do that.'));
}
$requestData = $this->request->data['Object'];
$selectedTemplateId = $requestData['selectedTemplateId'];
$template = $this->MispObject->ObjectTemplate->find('first', array(
'recursive' => -1,
'conditions' => array(
'ObjectTemplate.id' => $selectedTemplateId,
'ObjectTemplate.active' => true,
),
'contain' => ['ObjectTemplateElement'],
));
if (empty($template)) {
throw new NotFoundException(__('Invalid template.'));
}
if (isset($requestData['selectedObjectRelationMapping'])) {
$distribution = $requestData['distribution'];
$sharingGroupId = $requestData['sharing_group_id'] ?? 0;
$comment = $requestData['comment'];
if ($distribution == 4) {
$sg = $this->MispObject->SharingGroup->fetchSG($sharingGroupId, $this->Auth->user());
if (empty($sg)) {
throw new NotFoundException(__('Invalid sharing group.'));
}
} else {
$sharingGroupId = 0;
}
$attributes = $this->_jsonDecode($requestData['attributes']);
$selectedObjectRelationMapping = $this->_jsonDecode($requestData['selectedObjectRelationMapping']);
// Attach object relation to attributes and fix tag format
foreach ($attributes as $k => &$attribute) {
$attribute['object_relation'] = $selectedObjectRelationMapping[$k];
if (!empty($attribute['tags'])) {
$attribute['Tag'] = [];
foreach (explode(",", $attribute['tags']) as $tagName) {
$attribute['Tag'][] = [
'name' => trim($tagName),
];
}
unset($attribute['tags']);
}
}
$object = [
'Object' => [
'event_id' => $eventId,
'distribution' => $distribution,
'sharing_group_id' => $sharingGroupId,
'comment' => $comment,
'Attribute' => $attributes,
],
];
$object = $this->MispObject->fillObjectDataFromTemplate($object, $template);
$result = $this->MispObject->captureObject($object, $eventId, $this->Auth->user(), true, false, $event);
if ($result === true) {
return $this->RestResponse->saveSuccessResponse('Objects', 'Created from Attributes', $result, 'json');
} else {
$error = __('Failed to create an Object from Attributes. Error: ') . PHP_EOL . h($result);
return $this->RestResponse->saveFailResponse('Objects', 'Created from Attributes', false, $error, 'json');
}
} else {
$attributes = $this->_jsonDecode($requestData['attributes']);
$processedAttributes = [];
foreach ($attributes as $attribute) {
if ($attribute['type'] === 'ip-src/ip-dst') {
$types = array('ip-src', 'ip-dst');
} elseif ($attribute['type'] === 'ip-src|port/ip-dst|port') {
$types = array('ip-src|port', 'ip-dst|port');
} else {
$types = [$attribute['type']];
}
foreach ($types as $type) {
$attribute['type'] = $type;
$processedAttributes[] = $attribute;
}
}
$attributeTypes = array_column($processedAttributes, 'type');
$conformityResult = $this->MispObject->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributeTypes);
if ($conformityResult['valid'] !== true || !empty($conformityResult['invalidTypes'])) {
throw new NotFoundException(__('Invalid template.'));
}
$objectRelations = [];
foreach ($template['ObjectTemplateElement'] as $templateElement) {
$objectRelations[$templateElement['type']][] = $templateElement;
}
// Attach first object_relation according to attribute type that will be considered as default
foreach ($processedAttributes as &$attribute) {
$attribute['object_relation'] = $objectRelations[$attribute['type']][0]['object_relation'];
}
$distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($this->Auth->user());
$this->set('event', $event);
$this->set('distributionData', $distributionData);
$this->set('distributionLevels', $this->MispObject->Attribute->distributionLevels);
$this->set('template', $template);
$this->set('objectRelations', $objectRelations);
$this->set('attributes', $processedAttributes);
list($similar_objects_count, $similar_objects, $simple_flattened_attribute, $simple_flattened_attribute_noval) = $this->MispObject->findSimilarObjects(
$this->Auth->user(),
$eventId,
$processedAttributes,
$template
);
if ($similar_objects_count) {
$this->set('similar_objects_count', $similar_objects_count);
$this->set('similar_objects', $similar_objects);
$this->set('similar_objects_display_threshold', 15);
$this->set('simple_flattened_attribute', $simple_flattened_attribute);
$this->set('simple_flattened_attribute_noval', $simple_flattened_attribute_noval);
$multiple_template_elements = Hash::extract($template['ObjectTemplateElement'],'{n}[multiple=true]');
$multiple_attribute_allowed = array();
foreach ($multiple_template_elements as $template_element) {
$relation_type = $template_element['object_relation'] . ':' . $template_element['type'];
$multiple_attribute_allowed[$relation_type] = true;
}
$this->set('multiple_attribute_allowed', $multiple_attribute_allowed);
}
}
}
private function __objectIdToConditions($id)
{
if (is_numeric($id)) {

View File

@ -367,6 +367,9 @@ class TagsController extends AppController
// Remove galaxy tags
$event = $this->Tag->removeGalaxyClusterTags($user, $event);
$highlightedTags = $this->Taxonomy->getHighlightedTags($this->Taxonomy->getHighlightedTaxonomies(), $event['EventTag']);
$this->set('highlightedTaxonomies', $highlightedTags);
$this->set('tags', $event['EventTag']);
$this->set('missingTaxonomies', $this->Tag->EventTag->Event->missingTaxonomies($event));
$tagConflicts = $this->Taxonomy->checkIfTagInconsistencies($event['EventTag']);

View File

@ -59,7 +59,7 @@ class TaxonomiesController extends AppController
public function view($id)
{
$taxonomy = $this->Taxonomy->getTaxonomy($id, ['full' => $this->_isRest()]);
$taxonomy = $this->Taxonomy->getTaxonomy($id, $this->_isRest());
if (empty($taxonomy)) {
throw new NotFoundException(__('Taxonomy not found.'));
}
@ -498,6 +498,32 @@ class TaxonomiesController extends AppController
$this->render('ajax/toggle_required');
}
public function toggleHighlighted($id)
{
$taxonomy = $this->Taxonomy->find('first', array(
'recursive' => -1,
'conditions' => array('Taxonomy.id' => $id)
));
if (empty($taxonomy)) {
return $this->RestResponse->saveFailResponse('Taxonomy', 'toggleHighlighted', $id, 'Invalid Taxonomy', $this->response->type());
}
if ($this->request->is('post')) {
$taxonomy['Taxonomy']['highlighted'] = $this->request->data['Taxonomy']['highlighted'];
$result = $this->Taxonomy->save($taxonomy);
if ($result) {
return $this->RestResponse->saveSuccessResponse('Taxonomy', 'toggleHighlighted', $id, $this->response->type());
} else {
return $this->RestResponse->saveFailResponse('Taxonomy', 'toggleHighlighted', $id, $this->validationError, $this->response->type());
}
}
$this->set('highlighted', !$taxonomy['Taxonomy']['highlighted']);
$this->set('id', $id);
$this->autoRender = false;
$this->layout = false;
$this->render('ajax/toggle_highlighted');
}
/**
* @param string $action
* @param int $modelId

View File

@ -117,8 +117,14 @@ class UsersController extends AppController
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Something went wrong, please try again later.')), 'status'=>200, 'type' => 'json'));
}
public function unsubscribe($code)
public function unsubscribe($code, $type = null)
{
if ($type === null) {
$type = 'autoalert';
} else if (!in_array($type, ['autoalert', 'notification_daily', 'notification_weekly', 'notification_monthly'], true)) {
throw new NotFoundException("Invalid type $type.");
}
$user = $this->Auth->user();
if (!hash_equals($this->User->unsubscribeCode($user), rtrim($code, '.'))) {
@ -126,11 +132,11 @@ class UsersController extends AppController
$this->redirect(['action' => 'view', 'me']);
}
if ($user['autoalert']) {
$this->User->updateField($this->Auth->user(), 'autoalert', false);
$this->Flash->success(__('Successfully unsubscribed from event alert.'));
if ($user[$type]) {
$this->User->updateField($user, $type, false);
$this->Flash->success(__('Successfully unsubscribed from notification.'));
} else {
$this->Flash->info(__('Already unsubscribed from event alert.'));
$this->Flash->info(__('Already unsubscribed from notification.'));
}
$this->redirect(['action' => 'view', 'me']);
}
@ -1080,27 +1086,35 @@ class UsersController extends AppController
public function admin_delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$user = $this->User->find('first', array(
'conditions' => $this->__adminFetchConditions($id),
'recursive' => -1
));
if (empty($user)) {
throw new NotFoundException(__('Invalid user'));
}
if ($this->User->delete($id)) {
$fieldsDescrStr = 'User (' . $id . '): ' . $user['User']['email'];
$this->User->extralog($this->Auth->user(), "delete", $fieldsDescrStr, '');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('User', 'admin_delete', $id, $this->response->type(), 'User deleted.');
} else {
$this->Flash->success(__('User deleted'));
$this->redirect(array('action' => 'index'));
if ($this->request->is('post') || $this->request->is('delete')) {
$user = $this->User->find('first', array(
'conditions' => $this->__adminFetchConditions($id),
'recursive' => -1
));
if (empty($user)) {
throw new NotFoundException(__('Invalid user'));
}
if ($this->User->delete($id)) {
$fieldsDescrStr = 'User (' . $id . '): ' . $user['User']['email'];
$this->User->extralog($this->Auth->user(), "delete", $fieldsDescrStr, '');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('User', 'admin_delete', $id, $this->response->type(), 'User deleted.');
} else {
$this->Flash->success(__('User deleted'));
$this->redirect(array('action' => 'index'));
}
}
$this->Flash->error(__('User was not deleted'));
$this->redirect(array('action' => 'index'));
} else {
$this->set(
'question',
__('Are you sure you want to delete the user? It is highly recommended to never delete users but to disable them instead.')
);
$this->set('title', __('Delete user'));
$this->set('actionName', 'Delete');
$this->render('/genericTemplates/confirm');
}
$this->Flash->error(__('User was not deleted'));
$this->redirect(array('action' => 'index'));
}
public function admin_massToggleField($fieldName, $enabled)
@ -2828,4 +2842,55 @@ class UsersController extends AppController
}
return $conditions;
}
public function admin_destroy($id = null)
{
$conditionFields = ['id', 'email'];
$params = $this->IndexFilter->harvestParameters(['id', 'email']);
if (!empty($id)) {
$params['id'] = $id;
}
$conditions = [];
foreach ($conditionFields as $conditionField) {
if (!empty($params[$conditionField])) {
$conditions[$conditionField . ' LIKE'] = $params[$conditionField];
}
}
if (!empty($conditions)) {
$user_ids = $this->User->find('list', [
'recursive' => -1,
'fields' => ['email', 'id'],
'conditions' => $conditions
]);
} else {
$user_ids = [__('Every user') => 'all'];
}
if ($this->request->is('post')) {
$redis = RedisTool::init();
$kill_before = time();
foreach (array_values($user_ids) as $user_id) {
$redis->set('misp:session_destroy:' . $user_id, $kill_before);
}
$message = __(
'Session destruction cutoff set to the current timestamp for the given selection (%s). Session(s) will be destroyed on the next user interaction.',
implode(', ', array_keys($user_ids))
);
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('User', 'admin_destroy', false, $this->response->type(), $message);
}
$this->Flash->success($message);
$this->redirect($this->referer());
} else {
$this->set(
'question',
__(
'Do you really wish to destroy the session for: %s ? The session destruction will occur when the users try to interact with MISP the next time.',
implode(', ', array_keys($user_ids))
)
);
$this->set('title', __('Destroy sessions'));
$this->set('actionName', 'Destroy');
$this->render('/genericTemplates/confirm');
}
}
}

View File

@ -35,21 +35,21 @@ class RecentSightingsWidget
$data = array();
$count = 0;
foreach (JsonTool::decode($Sighting->restSearch($user, 'json', $filters)->intoString())->{'response'} as $el) {
$sighting = $el->{'Sighting'};
$event = $sighting->{'Event'};
$attribute = $sighting->{'Attribute'};
foreach (JsonTool::decode($Sighting->restSearch($user, 'json', $filters)->intoString())['response'] as $el) {
$sighting = $el['Sighting'];
$event = $sighting['Event'];
$attribute = $sighting['Attribute'];
if ($sighting->{'type'} == 0) $type = "Sighting";
elseif ($sighting->{'type'} == 1) $type = "False positive";
if ($sighting['type'] == 0) $type = "Sighting";
elseif ($sighting['type'] == 1) $type = "False positive";
else $type = "Expiration";
$output = $attribute->{'value'} . " (id: " . $attribute->{'id'} . ") in " . $event->{'info'} . " (id: " . $event->{'id'} . ")";
$output = $attribute['value'] . " (id: " . $attribute['id'] . ") in " . $event['info'] . " (id: " . $event['id'] . ")";
$data[] = array( 'title' => $type, 'value' => $output,
'html' => sprintf(
' (Event <a href="%s%s">%s</a>)',
Configure::read('MISP.baseurl') . '/events/view/', $event->{'id'},
$event->{'id'}
Configure::read('MISP.baseurl') . '/events/view/', $event['id'],
$event['id']
)
);
++$count;

View File

@ -31,21 +31,21 @@ class TresholdSightingsWidget
$data = array();
$sightings_score = array();
$restSearch = JsonTool::decode($Sighting->restSearch($user, 'json', $filters)->intoString())->{'response'};
$restSearch = JsonTool::decode($Sighting->restSearch($user, 'json', $filters)->intoString())['response'];
foreach ($restSearch as $el) {
$sighting = $el->{'Sighting'};
$attribute = $sighting->{'Attribute'};
$event = $sighting->{'Event'};
$sighting = $el['Sighting'];
$attribute = $sighting['Attribute'];
$event = $sighting['Event'];
if (!array_key_exists($attribute->{'id'}, $sightings_score)) $sightings_score[$attribute->{'id'}] = array( 'value' => $attribute->{'value'},
if (!array_key_exists($attribute['id'], $sightings_score)) $sightings_score[$attribute['id']] = array( 'value' => $attribute['value'],
'score' => 0,
'event_title' => $event->{'info'},
'event_id' => $event->{'id'});
'event_title' => $event['info'],
'event_id' => $event['id']);
# Sighting
if ($sighting->{'type'} == 0) $sightings_score[$attribute->{'id'}]['score'] = $sightings_score[$attribute->{'id'}]['score'] - 1;
if ($sighting['type'] == 0) $sightings_score[$attribute['id']]['score'] = $sightings_score[$attribute['id']]['score'] - 1;
# False Positive
elseif ($sighting->{'type'} == 1) $sightings_score[$attribute->{'id'}]['score'] = $sightings_score[$attribute->{'id'}]['score'] + 1;
elseif ($sighting['type'] == 1) $sightings_score[$attribute['id']]['score'] = $sightings_score[$attribute['id']]['score'] + 1;
}
foreach ($sightings_score as $attribute_id => $s) {

View File

@ -202,7 +202,7 @@ class AttributeValidationTool
$value = substr($value, 2); // remove 'AS'
}
if (strpos($value, '.') !== false) { // maybe value is in asdot notation
$parts = explode('.', $value);
$parts = explode('.', $value, 2);
if (self::isPositiveInteger($parts[0]) && self::isPositiveInteger($parts[1])) {
return $parts[0] * 65536 + $parts[1];
}
@ -412,12 +412,12 @@ class AttributeValidationTool
}
return __('Email address has an invalid format. Please double check the value or select type "other".');
case 'vulnerability':
if (preg_match("#^(CVE-)[0-9]{4}(-)[0-9]{4,}$#", $value)) {
if (preg_match("#^CVE-[0-9]{4}-[0-9]{4,}$#", $value)) {
return true;
}
return __('Invalid format. Expected: CVE-xxxx-xxxx...');
case 'weakness':
if (preg_match("#^(CWE-)[0-9]{1,}$#", $value)) {
if (preg_match("#^CWE-[0-9]+$#", $value)) {
return true;
}
return __('Invalid format. Expected: CWE-x...');
@ -583,6 +583,28 @@ class AttributeValidationTool
throw new InvalidArgumentException("Unknown type $type.");
}
/**
* This method will generate all valid types for given value.
* @param array $types Typos to check
* @param array $compositeTypes Composite types
* @param string $value Values to check
* @return array
*/
public static function validTypesForValue(array $types, array $compositeTypes, $value)
{
$possibleTypes = [];
foreach ($types as $type) {
if (in_array($type, $compositeTypes, true) && substr_count($value, '|') !== 1) {
continue; // value is not in composite format
}
$modifiedValue = AttributeValidationTool::modifyBeforeValidation($type, $value);
if (AttributeValidationTool::validate($type, $modifiedValue) === true) {
$possibleTypes[] = $type;
}
}
return $possibleTypes;
}
/**
* @param string $value
* @return bool

View File

@ -57,6 +57,12 @@
$event['Attribute'] = array();
}
if (!empty($fullevent[0]['Sighting'])) {
$event['Sighting'] = $fullevent[0]['Sighting'];
} else {
$event['Sighting'] = array();
}
return $event;
}
@ -81,6 +87,11 @@
$attribute = array();
}
$sightingsAttributeMap = [];
foreach ($event['Sighting'] as $sighting) {
$sightingsAttributeMap[$sighting['attribute_id']][] = $sighting['date_sighting'];
}
// extract links and node type
foreach ($attribute as $attr) {
$toPush = array(
@ -93,6 +104,7 @@
'first_seen' => $attr['first_seen'],
'last_seen' => $attr['last_seen'],
'attribute_type' => $attr['type'],
'date_sighting' => $sightingsAttributeMap[$attr['id']] ?? [],
'is_image' => $this->__eventModel->Attribute->isImage($attr),
);
$this->__json['items'][] = $toPush;
@ -134,6 +146,7 @@
'group' => 'object_attribute',
'timestamp' => $obj_attr['timestamp'],
'attribute_type' => $obj_attr['type'],
'date_sighting' => $sightingsAttributeMap[$attr['id']] ?? [],
'is_image' => $this->__eventModel->Attribute->isImage($obj_attr),
);
$toPush_obj['Attribute'][] = $toPush_attr;

View File

@ -107,8 +107,14 @@ class FileAccessTool
}
if (file_put_contents($file, $content, LOCK_EX | (!empty($append) ? FILE_APPEND : 0)) === false) {
$freeSpace = disk_free_space($dir);
throw new Exception("An error has occurred while attempt to write to file `$file`. Maybe not enough space? ($freeSpace bytes left)");
if (file_exists($file) && !is_writable($file)) {
$errorMessage = 'File is not writeable.';
} else {
$freeSpace = disk_free_space($dir);
$errorMessage = "Maybe not enough space? ($freeSpace bytes left)";
}
throw new Exception("An error has occurred while attempt to write to file `$file`. $errorMessage");
}
}

View File

@ -26,12 +26,18 @@ class RedisTool
}
$host = Configure::read('MISP.redis_host') ?: '127.0.0.1';
$port = Configure::read('MISP.redis_port') ?: 6379;
$socket = false;
if ($host[0] === '/') {
$socket = $host;
} else {
$port = Configure::read('MISP.redis_port') ?: 6379;
}
$database = Configure::read('MISP.redis_database') ?: 13;
$pass = Configure::read('MISP.redis_password');
$redis = new Redis();
if (!$redis->connect($host, (int) $port)) {
$connection = empty($socket) ? $redis->connect($host, (int) $port) : $redis->connect($host);
if (!$connection) {
throw new Exception("Could not connect to Redis: {$redis->getLastError()}");
}
if (!empty($pass)) {

View File

@ -57,6 +57,9 @@ class AccessLog extends AppModel
$result['AccessLog']['request'] = false;
}
}
if (!empty($result['AccessLog']['query_log'])) {
$result['AccessLog']['query_log'] = JsonTool::decode($this->decompress($result['AccessLog']['query_log']));
}
if (!empty($result['AccessLog']['memory_usage'])) {
$result['AccessLog']['memory_usage'] = $result['AccessLog']['memory_usage'] * 1024;
}
@ -90,8 +93,12 @@ class AccessLog extends AppModel
$accessLog['request_method'] = $requestMethodIds[$accessLog['request_method']] ?? 0;
}
if (isset($accessLog['request'])) {
$accessLog['request'] = $this->encodeRequest($accessLog['request']);
if (!empty($accessLog['request'])) {
$accessLog['request'] = $this->compress($accessLog['request']);
}
if (!empty($accessLog['query_log'])) {
$accessLog['query_log'] = $this->compress(JsonTool::encode($accessLog['query_log']));
}
// In database save size in kb to avoid overflow signed int type
@ -110,12 +117,16 @@ class AccessLog extends AppModel
*/
public function logRequest(array $user, $remoteIp, CakeRequest $request, $includeRequestBody = true)
{
$requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true);
$now = DateTime::createFromFormat('U.u', $requestTime);
$requestTime = $this->requestTime();
$logClientIp = Configure::read('MISP.log_client_ip');
$includeSqlQueries = Configure::read('MISP.log_paranoid_include_sql_queries');
if ($includeSqlQueries) {
$this->getDataSource()->fullDebug = true; // Enable SQL logging
}
$dataToSave = [
'created' => $now->format('Y-m-d H:i:s.u'),
'created' => $requestTime->format('Y-m-d H:i:s.u'),
'request_id' => $_SERVER['HTTP_X_REQUEST_ID'] ?? null,
'user_id' => (int)$user['id'],
'org_id' => (int)$user['org_id'],
@ -133,14 +144,32 @@ class AccessLog extends AppModel
}
// Save data on shutdown
register_shutdown_function(function () use ($dataToSave, $requestTime) {
register_shutdown_function(function () use ($dataToSave, $requestTime, $includeSqlQueries) {
session_write_close(); // close session to allow concurrent requests
$this->saveOnShutdown($dataToSave, $requestTime);
$this->saveOnShutdown($dataToSave, $requestTime, $includeSqlQueries);
});
return true;
}
/**
* @param DateTime $duration
* @return int Number of deleted entries
*/
public function deleteOldLogs(DateTime $duration)
{
$this->deleteAll([
['created <' => $duration->format('Y-m-d H:i:s.u')],
], false);
$deleted = $this->getAffectedRows();
if ($deleted > 100) {
$dataSource = $this->getDataSource();
$dataSource->query('OPTIMISE TABLE ' . $dataSource->name($this->table));
}
return $deleted;
}
/**
* @param CakeRequest $request
* @return string
@ -161,18 +190,29 @@ class AccessLog extends AppModel
/**
* @param array $data
* @param float $requestTime
* @param DateTime $requestTime
* @param bool $includeSqlQueries
* @return bool
* @throws Exception
*/
private function saveOnShutdown(array $data, $requestTime)
private function saveOnShutdown(array $data, DateTime $requestTime, $includeSqlQueries)
{
$queryCount = $this->getDataSource()->getLog(false, false)['count'];
$sqlLog = $this->getDataSource()->getLog(false, false);
$queryCount = $sqlLog['count'];
if ($includeSqlQueries && !empty($sqlLog['log'])) {
foreach ($sqlLog['log'] as &$log) {
$log['query'] = $this->escapeNonUnicode($log['query']);
unset($log['affected']); // affected is the same as numRows
unset($log['params']); // no need to save for your use case
}
$data['query_log'] = ['time' => $sqlLog['time'], 'log' => $sqlLog['log']];
}
$data['response_code'] = http_response_code();
$data['memory_usage'] = memory_get_peak_usage();
$data['query_count'] = $queryCount;
$data['duration'] = (int)((microtime(true) - $requestTime) * 1000); // in milliseconds
$data['duration'] = (int)((microtime(true) - $requestTime->format('U.u')) * 1000); // in milliseconds
try {
return $this->save($data, ['atomic' => false]);
@ -196,23 +236,31 @@ class AccessLog extends AppModel
// In future add support for sending logs to elastic
}
/**
* @return DateTime
*/
private function requestTime()
{
$requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true);
$requestTime = (string) $requestTime;
// Fix string if float value doesnt contain decimal part
if (strpos($requestTime, '.') === false) {
$requestTime .= '.0';
}
return DateTime::createFromFormat('U.u', $requestTime);
}
/**
* @param string $request
* @return array|bool
* @return array|false
*/
private function decodeRequest($request)
{
$header = substr($request, 0, 4);
if ($header === self::BROTLI_HEADER) {
if (function_exists('brotli_uncompress')) {
$request = brotli_uncompress(substr($request, 4));
if ($request === false) {
return false;
}
} else {
return false;
}
$request = $this->decompress($request);
if ($request === false) {
return false;
}
list($contentType, $encoding, $data) = explode("\n", $request, 3);
if ($encoding === 'gzip') {
@ -229,17 +277,69 @@ class AccessLog extends AppModel
}
/**
* @param string $request
* @param string $data
* @return false|string
*/
private function decompress($data)
{
$header = substr($data, 0, 4);
if ($header === self::BROTLI_HEADER) {
if (function_exists('brotli_uncompress')) {
$data = brotli_uncompress(substr($data, 4));
if ($data === false) {
return false;
}
} else {
return false;
}
}
return $data;
}
/**
* @param string $data
* @return string
*/
private function encodeRequest($request)
private function compress($data)
{
$compressionEnabled = Configure::read('MISP.log_new_audit_compress') &&
function_exists('brotli_compress');
if ($compressionEnabled && strlen($request) >= self::COMPRESS_MIN_LENGTH) {
return self::BROTLI_HEADER . brotli_compress($request, 4, BROTLI_TEXT);
if ($compressionEnabled && strlen($data) >= self::COMPRESS_MIN_LENGTH) {
return self::BROTLI_HEADER . brotli_compress($data, 4, BROTLI_TEXT);
}
return $request;
return $data;
}
/**
* @param $string
* @return string
*/
private function escapeNonUnicode($string)
{
if (json_encode($string, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS) !== false) {
return $string; // string is valid unicode
}
if (function_exists('mb_str_split')) {
$result = mb_str_split($string);
} else {
$result = [];
$length = mb_strlen($string);
for ($i = 0; $i < $length; $i++) {
$result[] = mb_substr($string, $i, 1);
}
}
$string = '';
foreach ($result as $char) {
if (strlen($char) === 1 && !preg_match('/[[:print:]]/', $char)) {
$string .= '\x' . bin2hex($char);
} else {
$string .= $char;
}
}
return $string;
}
}

View File

@ -83,7 +83,8 @@ class AppModel extends Model
81 => false, 82 => false, 83 => false, 84 => false, 85 => false, 86 => false,
87 => false, 88 => false, 89 => false, 90 => false, 91 => false, 92 => false,
93 => false, 94 => false, 95 => true, 96 => false, 97 => true, 98 => false,
99 => false, 100 => false, 101 => false
99 => false, 100 => false, 101 => false, 102 => false, 103 => false, 104 => false,
105 => false
);
const ADVANCED_UPDATES_DESCRIPTION = array(
@ -1920,6 +1921,26 @@ class AppModel extends Model
INDEX `baseurl` (`baseurl`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
break;
case 102:
$sqlArray[] = "UPDATE roles SET perm_audit = 1;";
break;
case 103:
$sqlArray[] = "ALTER TABLE `taxonomies` ADD `highlighted` tinyint(1) DEFAULT 0;";
break;
case 104:
$sqlArray[] = "ALTER TABLE `access_logs` ADD `query_log` blob DEFAULT NULL";
break;
case 105:
// set a default role if there is none
if (!$this->AdminSetting->getSetting('default_role')) {
$role = ClassRegistry::init('Role')->findByName('User');
if ($role) {
$sqlArray[] = "INSERT INTO `admin_settings` (setting, value) VALUES ('default_role', '".$role['Role']['id']."');";
} else {
// there is no role called User, do nothing
}
}
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;';
@ -3050,6 +3071,16 @@ class AppModel extends Model
return [$subQuery];
}
/**
* Returns estimated number of table rows
* @return int
*/
public function tableRows()
{
$rows = $this->query("SELECT TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '{$this->table}';");
return $rows[0]['TABLES']['TABLE_ROWS'];
}
// start a benchmark run for the given bench name
public function benchmarkInit($name = 'default')
{
@ -3912,8 +3943,10 @@ class AppModel extends Model
*/
public function _remoteIp()
{
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
return isset($_SERVER[$ipHeader]) ? trim($_SERVER[$ipHeader]) : $_SERVER['REMOTE_ADDR'];
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: null;
if ($ipHeader && isset($_SERVER[$ipHeader])) {
return trim($_SERVER[$ipHeader]);
}
return $_SERVER['REMOTE_ADDR'] ?? null;
}
}

View File

@ -3233,20 +3233,20 @@ class Attribute extends AppModel
private function generateTypeDefinitions()
{
return array(
'md5' => array('desc' => __('A checksum in md5 format'), 'formdesc' => __("You are encouraged to use filename|md5 instead. A checksum in md5 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha1' => array('desc' => __('A checksum in sha1 format'), 'formdesc' => __("You are encouraged to use filename|sha1 instead. A checksum in sha1 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha256' => array('desc' => __('A checksum in sha256 format'), 'formdesc' => __("You are encouraged to use filename|sha256 instead. A checksum in sha256 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'md5' => array('desc' => __('A checksum in MD5 format'), 'formdesc' => __("You are encouraged to use filename|md5 instead. A checksum in md5 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha1' => array('desc' => __('A checksum in SHA1 format'), 'formdesc' => __("You are encouraged to use filename|sha1 instead. A checksum in sha1 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha256' => array('desc' => __('A checksum in SHA256 format'), 'formdesc' => __("You are encouraged to use filename|sha256 instead. A checksum in sha256 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename' => array('desc' => __('Filename'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'pdb' => array('desc' => __('Microsoft Program database (PDB) path information'), 'default_category' => 'Artifacts dropped', 'to_ids' => 0),
'filename|md5' => array('desc' => __('A filename and an md5 hash separated by a |'), 'formdesc' => __("A filename and an md5 hash separated by a | (no spaces)"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha1' => array('desc' => __('A filename and an sha1 hash separated by a |'), 'formdesc' => __("A filename and an sha1 hash separated by a | (no spaces)"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha256' => array('desc' => __('A filename and an sha256 hash separated by a |'), 'formdesc' => __("A filename and an sha256 hash separated by a | (no spaces)"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|md5' => array('desc' => __('A filename and an MD5 hash separated by a |'), 'formdesc' => __("A filename and an md5 hash separated by a | (no spaces)"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha1' => array('desc' => __('A filename and an SHA1 hash separated by a |'), 'formdesc' => __("A filename and an sha1 hash separated by a | (no spaces)"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha256' => array('desc' => __('A filename and an SHA256 hash separated by a |'), 'formdesc' => __("A filename and an sha256 hash separated by a | (no spaces)"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'ip-src' => array('desc' => __("A source IP address of the attacker"), 'default_category' => 'Network activity', 'to_ids' => 1),
'ip-dst' => array('desc' => __('A destination IP address of the attacker or C&C server'), 'formdesc' => __("A destination IP address of the attacker or C&C server. Also set the IDS flag on when this IP is hardcoded in malware"), 'default_category' => 'Network activity', 'to_ids' => 1),
'hostname' => array('desc' => __('A full host/dnsname of an attacker'), 'formdesc' => __("A full host/dnsname of an attacker. Also set the IDS flag on when this hostname is hardcoded in malware"), 'default_category' => 'Network activity', 'to_ids' => 1),
'domain' => array('desc' => __('A domain name used in the malware'), 'formdesc' => __("A domain name used in the malware. Use this instead of hostname when the upper domain is important or can be used to create links between events."), 'default_category' => 'Network activity', 'to_ids' => 1),
'domain|ip' => array('desc' => __('A domain name and its IP address (as found in DNS lookup) separated by a |'),'formdesc' => __("A domain name and its IP address (as found in DNS lookup) separated by a | (no spaces)"), 'default_category' => 'Network activity', 'to_ids' => 1),
'email' => array('desc' => ('An e-mail address'), 'default_category' => 'Social network', 'to_ids' => 1),
'email' => array('desc' => ('An email address'), 'default_category' => 'Social network', 'to_ids' => 1),
'email-src' => array('desc' => __("The source email address. Used to describe the sender when describing an e-mail."), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'eppn' => array('desc' => __("eduPersonPrincipalName - eppn - the NetId of the person for the purposes of inter-institutional authentication. Should be stored in the form of user@univ.edu, where univ.edu is the name of the local security domain."), 'default_category' => 'Network activity', 'to_ids' => 1),
'email-dst' => array('desc' => __("The destination email address. Used to describe the recipient when describing an e-mail."), 'default_category' => 'Network activity', 'to_ids' => 1),
@ -3254,8 +3254,8 @@ class Attribute extends AppModel
'email-attachment' => array('desc' => __("File name of the email attachment."), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'email-body' => array('desc' => __('Email body'), 'default_category' => 'Payload delivery', 'to_ids' => 0),
'float' => array('desc' => __("A floating point value."), 'default_category' => 'Other', 'to_ids' => 0),
'git-commit-id' => array('desc' => __("A git commit ID."), 'default_category' => 'Internal reference', 'to_ids' => 0),
'url' => array('desc' => __('url'), 'default_category' => 'Network activity', 'to_ids' => 1),
'git-commit-id' => array('desc' => __("A Git commit ID."), 'default_category' => 'Internal reference', 'to_ids' => 0),
'url' => array('desc' => __('Uniform Resource Locator'), 'default_category' => 'Network activity', 'to_ids' => 1),
'http-method' => array('desc' => __("HTTP method used by the malware (e.g. POST, GET, ...)."), 'default_category' => 'Network activity', 'to_ids' => 0),
'user-agent' => array('desc' => __("The user-agent used by the malware in the HTTP request."), 'default_category' => 'Network activity', 'to_ids' => 0),
'ja3-fingerprint-md5' => array('desc' => __("JA3 is a method for creating SSL/TLS client fingerprints that should be easy to produce on any platform and can be easily shared for threat intelligence."), 'default_category' => 'Network activity', 'to_ids' => 1),
@ -3269,7 +3269,7 @@ class Attribute extends AppModel
'snort' => array('desc' => __('An IDS rule in Snort rule-format'), 'formdesc' => __("An IDS rule in Snort rule-format. This rule will be automatically rewritten in the NIDS exports."), 'default_category' => 'Network activity', 'to_ids' => 1),
'bro' => array('desc' => __('An NIDS rule in the Bro rule-format'), 'formdesc' => __("An NIDS rule in the Bro rule-format."), 'default_category' => 'Network activity', 'to_ids' => 1),
'zeek' => array('desc' => __('An NIDS rule in the Zeek rule-format'), 'formdesc' => __("An NIDS rule in the Zeek rule-format."), 'default_category' => 'Network activity', 'to_ids' => 1),
'community-id' => array('desc' => __('a community ID flow hashing algorithm to map multiple traffic monitors into common flow id'), 'formdesc' => __("a community ID flow hashing algorithm to map multiple traffic monitors into common flow id"), 'default_category' => 'Network activity', 'to_ids' => 1),
'community-id' => array('desc' => __('A community ID flow hashing algorithm to map multiple traffic monitors into common flow id'), 'formdesc' => __("a community ID flow hashing algorithm to map multiple traffic monitors into common flow id"), 'default_category' => 'Network activity', 'to_ids' => 1),
'pattern-in-file' => array('desc' => __('Pattern in file that identifies the malware'), 'default_category' => 'Payload installation', 'to_ids' => 1),
'pattern-in-traffic' => array('desc' => __('Pattern in network traffic that identifies the malware'), 'default_category' => 'Network activity', 'to_ids' => 1),
'pattern-in-memory' => array('desc' => __('Pattern in memory dump that identifies the malware'), 'default_category' => 'Payload installation', 'to_ids' => 1),
@ -3277,7 +3277,7 @@ class Attribute extends AppModel
'pgp-public-key' => array('desc' => __('A PGP public key'), 'default_category' => 'Person', 'to_ids' => 0),
'pgp-private-key' => array('desc' => __('A PGP private key'), 'default_category' => 'Person', 'to_ids' => 0),
'ssh-fingerprint' => array('desc' => __('A fingerprint of SSH key material'), 'default_category' => 'Network activity', 'to_ids' => 0),
'yara' => array('desc' => __('Yara signature'), 'default_category' => 'Payload installation', 'to_ids' => 1),
'yara' => array('desc' => __('YARA signature'), 'default_category' => 'Payload installation', 'to_ids' => 1),
'stix2-pattern' => array('desc' => __('STIX 2 pattern'), 'default_category' => 'Payload installation', 'to_ids' => 1),
'sigma' => array('desc' => __('Sigma - Generic Signature Format for SIEM Systems'), 'default_category' => 'Payload installation', 'to_ids' => 1),
'gene' => array('desc' => __('GENE - Go Evtx sigNature Engine'), 'default_category' => 'Artifacts dropped', 'to_ids' => 0),
@ -3287,7 +3287,7 @@ class Attribute extends AppModel
'cookie' => array('desc' => __('HTTP cookie as often stored on the user web client. This can include authentication cookie or session cookie.'), 'default_category' => 'Network activity', 'to_ids' => 0),
'vulnerability' => array('desc' => __('A reference to the vulnerability used in the exploit'), 'default_category' => 'External analysis', 'to_ids' => 0),
'cpe' => array('desc' => __('Common Platform Enumeration - structured naming scheme for information technology systems, software, and packages.'), 'default_category' => 'External analysis', 'to_ids' => 0),
'weakness' => array('desc'=> __('A reference to the weakness used in the exploit'), 'default_category' => 'External analysis', 'to_ids' => 0),
'weakness' => array('desc'=> __('A reference to the weakness (CWE) used in the exploit'), 'default_category' => 'External analysis', 'to_ids' => 0),
'attachment' => array('desc' => __('Attachment with external information'), 'formdesc' => __("Please upload files using the <em>Upload Attachment</em> button."), 'default_category' => 'External analysis', 'to_ids' => 0),
'malware-sample' => array('desc' => __('Attachment containing encrypted malware sample'), 'formdesc' => __("Please upload files using the <em>Upload Attachment</em> button."), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'link' => array('desc' => __('Link to an external information'), 'default_category' => 'External analysis', 'to_ids' => 0),
@ -3325,34 +3325,34 @@ class Attribute extends AppModel
'ssdeep' => array('desc' => __('A checksum in ssdeep format'), 'formdesc' => __("You are encouraged to use filename|ssdeep instead. A checksum in the SSDeep format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'imphash' => array('desc' => __('Import hash - a hash created based on the imports in the sample.'), 'formdesc' => __("You are encouraged to use filename|imphash instead. A hash created based on the imports in the sample, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'telfhash' => array('desc' => __('telfhash is symbol hash for ELF files, just like imphash is imports hash for PE files.'), 'formdesc' => __("You are encouraged to use a file object with telfash"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'pehash' => array('desc' => __('PEhash - a hash calculated based of certain pieces of a PE executable file'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'pehash' => array('desc' => __('peHash - a hash calculated based of certain pieces of a PE executable file'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'impfuzzy' => array('desc' => __('A fuzzy hash of import table of Portable Executable format'), 'formdesc' => __("You are encouraged to use filename|impfuzzy instead. A fuzzy hash created based on the imports in the sample, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha224' => array('desc' => __('A checksum in sha-224 format'), 'formdesc' => __("You are encouraged to use filename|sha224 instead. A checksum in sha224 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha384' => array('desc' => __('A checksum in sha-384 format'), 'formdesc' => __("You are encouraged to use filename|sha384 instead. A checksum in sha384 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha512' => array('desc' => __('A checksum in sha-512 format'), 'formdesc' => __("You are encouraged to use filename|sha512 instead. A checksum in sha512 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha512/224' => array('desc' => __('A checksum in the sha-512/224 format'), 'formdesc' => __("You are encouraged to use filename|sha512/224 instead. A checksum in sha512/224 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha512/256' => array('desc' => __('A checksum in the sha-512/256 format'), 'formdesc' => __("You are encouraged to use filename|sha512/256 instead. A checksum in sha512/256 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-224' => array('desc' => __('A checksum in sha3-224 format'), 'formdesc' => __("You are encouraged to use filename|sha3-224 instead. A checksum in sha3-224 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-256' => array('desc' => __('A checksum in sha3-256 format'), 'formdesc' => __("You are encouraged to use filename|sha3-256 instead. A checksum in sha3-256 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-384' => array('desc' => __('A checksum in sha3-384 format'), 'formdesc' => __("You are encouraged to use filename|sha3-384 instead. A checksum in sha3-384 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-512' => array('desc' => __('A checksum in sha3-512 format'), 'formdesc' => __("You are encouraged to use filename|sha3-512 instead. A checksum in sha3-512 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha224' => array('desc' => __('A checksum in SHA-224 format'), 'formdesc' => __("You are encouraged to use filename|sha224 instead. A checksum in sha224 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha384' => array('desc' => __('A checksum in SHA-384 format'), 'formdesc' => __("You are encouraged to use filename|sha384 instead. A checksum in sha384 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha512' => array('desc' => __('A checksum in SHA-512 format'), 'formdesc' => __("You are encouraged to use filename|sha512 instead. A checksum in sha512 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha512/224' => array('desc' => __('A checksum in the SHA-512/224 format'), 'formdesc' => __("You are encouraged to use filename|sha512/224 instead. A checksum in sha512/224 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha512/256' => array('desc' => __('A checksum in the SHA-512/256 format'), 'formdesc' => __("You are encouraged to use filename|sha512/256 instead. A checksum in sha512/256 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-224' => array('desc' => __('A checksum in SHA3-224 format'), 'formdesc' => __("You are encouraged to use filename|sha3-224 instead. A checksum in sha3-224 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-256' => array('desc' => __('A checksum in SHA3-256 format'), 'formdesc' => __("You are encouraged to use filename|sha3-256 instead. A checksum in sha3-256 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-384' => array('desc' => __('A checksum in SHA3-384 format'), 'formdesc' => __("You are encouraged to use filename|sha3-384 instead. A checksum in sha3-384 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha3-512' => array('desc' => __('A checksum in SHA3-512 format'), 'formdesc' => __("You are encouraged to use filename|sha3-512 instead. A checksum in sha3-512 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'tlsh' => array('desc' => __('A checksum in the Trend Micro Locality Sensitive Hash format'), 'formdesc' => __("You are encouraged to use filename|tlsh instead. A checksum in the Trend Micro Locality Sensitive Hash format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'cdhash' => array('desc' => __('An Apple Code Directory Hash, identifying a code-signed Mach-O executable file'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|authentihash' => array('desc' => __('A checksum in md5 format'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|authentihash' => array('desc' => __('A filename and Authenticode executable signature hash'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|vhash' => array('desc' => __('A filename and a VirusTotal hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|ssdeep' => array('desc' => __('A checksum in ssdeep format'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|imphash' => array('desc' => __('Import hash - a hash created based on the imports in the sample.'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|impfuzzy' => array('desc' => __('Import fuzzy hash - a fuzzy hash created based on the imports in the sample.'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|pehash' => array('desc' => __('A filename and a PEhash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha224' => array('desc' => __('A filename and a sha-224 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha384' => array('desc' => __('A filename and a sha-384 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha512' => array('desc' => __('A filename and a sha-512 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha512/224' => array('desc' => __('A filename and a sha-512/224 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha512/256' => array('desc' => __('A filename and a sha-512/256 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-224' => array('desc' => __('A filename and an sha3-224 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-256' => array('desc' => __('A filename and an sha3-256 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-384' => array('desc' => __('A filename and an sha3-384 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-512' => array('desc' => __('A filename and an sha3-512 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|pehash' => array('desc' => __('A filename and a peHash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha224' => array('desc' => __('A filename and a SHA-224 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha384' => array('desc' => __('A filename and a SHA-384 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha512' => array('desc' => __('A filename and a SHA-512 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha512/224' => array('desc' => __('A filename and a SHa-512/224 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha512/256' => array('desc' => __('A filename and a SHA-512/256 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-224' => array('desc' => __('A filename and an SHA3-224 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-256' => array('desc' => __('A filename and an SHA3-256 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-384' => array('desc' => __('A filename and an SHA3-384 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|sha3-512' => array('desc' => __('A filename and an SHA3-512 hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'filename|tlsh' => array('desc' => __('A filename and a Trend Micro Locality Sensitive Hash separated by a |'), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'windows-scheduled-task' => array('desc' => __('A scheduled task in windows'), 'default_category' => 'Artifacts dropped', 'to_ids' => 0),
'windows-service-name' => array('desc' => __('A windows service name. This is the name used internally by windows. Not to be confused with the windows-service-displayname.'), 'default_category' => 'Artifacts dropped', 'to_ids' => 0),
@ -3370,7 +3370,7 @@ class Attribute extends AppModel
'x509-fingerprint-sha1' => array('desc' => __('X509 fingerprint in SHA-1 format'), 'default_category' => 'Network activity', 'to_ids' => 1),
'x509-fingerprint-md5' => array('desc' => __('X509 fingerprint in MD5 format'), 'default_category' => 'Network activity', 'to_ids' => 1),
'x509-fingerprint-sha256' => array('desc' => __('X509 fingerprint in SHA-256 format'), 'default_category' => 'Network activity', 'to_ids' => 1),
'dns-soa-email' => array('desc' => __('RFC1035 mandates that DNS zones should have a SOA (Statement Of Authority) record that contains an email address where a PoC for the domain could be contacted. This can sometimes be used for attribution/linkage between different domains even if protected by whois privacy'), 'default_category' => 'Attribution', 'to_ids' => 0),
'dns-soa-email' => array('desc' => __('RFC 1035 mandates that DNS zones should have a SOA (Statement Of Authority) record that contains an email address where a PoC for the domain could be contacted. This can sometimes be used for attribution/linkage between different domains even if protected by whois privacy'), 'default_category' => 'Attribution', 'to_ids' => 0),
'size-in-bytes' => array('desc' => __('Size expressed in bytes'), 'default_category' => 'Other', 'to_ids' => 0),
'counter' => array('desc' => __('An integer counter, generally to be used in objects'), 'default_category' => 'Other', 'to_ids' => 0),
'datetime' => array('desc' => __('Datetime in the ISO 8601 format'), 'default_category' => 'Other', 'to_ids' => 0),
@ -3378,8 +3378,8 @@ class Attribute extends AppModel
'ip-dst|port' => array('desc' => __('IP destination and port number separated by a |'), 'default_category' => 'Network activity', 'to_ids' => 1),
'ip-src|port' => array('desc' => __('IP source and port number separated by a |'), 'default_category' => 'Network activity', 'to_ids' => 1),
'hostname|port' => array('desc' => __('Hostname and port number separated by a |'), 'default_category' => 'Network activity', 'to_ids' => 1),
'mac-address' => array('desc' => __('Mac address'), 'default_category' => 'Network activity', 'to_ids' => 0),
'mac-eui-64' => array('desc' => __('Mac EUI-64 address'), 'default_category' => 'Network activity', 'to_ids' => 0),
'mac-address' => array('desc' => __('MAC address'), 'default_category' => 'Network activity', 'to_ids' => 0),
'mac-eui-64' => array('desc' => __('MAC EUI-64 address'), 'default_category' => 'Network activity', 'to_ids' => 0),
// verify IDS flag defaults for these
'email-dst-display-name' => array('desc' => __('Email destination display name'), 'default_category' => 'Payload delivery', 'to_ids' => 0),
'email-src-display-name' => array('desc' => __('Email source display name'), 'default_category' => 'Payload delivery', 'to_ids' => 0),
@ -3389,9 +3389,9 @@ class Attribute extends AppModel
'email-mime-boundary' => array('desc' => __('The email mime boundary separating parts in a multipart email'), 'default_category' => 'Payload delivery', 'to_ids' => 0),
'email-thread-index' => array('desc' => __('The email thread index header'), 'default_category' => 'Payload delivery', 'to_ids' => 0),
'email-message-id' => array('desc' => __('The email message ID'), 'default_category' => 'Payload delivery', 'to_ids' => 0),
'github-username' => array('desc' => __('A github user name'), 'default_category' => 'Social network', 'to_ids' => 0),
'github-repository' => array('desc' => __('A github repository'), 'default_category' => 'Social network', 'to_ids' => 0),
'github-organisation' => array('desc' => __('A github organisation'), 'default_category' => 'Social network', 'to_ids' => 0),
'github-username' => array('desc' => __('A GitHub user name'), 'default_category' => 'Social network', 'to_ids' => 0),
'github-repository' => array('desc' => __('A Github repository'), 'default_category' => 'Social network', 'to_ids' => 0),
'github-organisation' => array('desc' => __('A GitHub organisation'), 'default_category' => 'Social network', 'to_ids' => 0),
'jabber-id' => array('desc' => __('Jabber ID'), 'default_category' => 'Social network', 'to_ids' => 0),
'twitter-id' => array('desc' => __('Twitter ID'), 'default_category' => 'Social network', 'to_ids' => 0),
'dkim' => array('desc' => __('DKIM public key'), 'default_category' => 'Network activity', 'to_ids' => 0),

View File

@ -12,25 +12,43 @@ class Bruteforce extends AppModel
$ip = $this->_remoteIp();
$expire = Configure::check('SecureAuth.expire') ? Configure::read('SecureAuth.expire') : 300;
$amount = Configure::check('SecureAuth.amount') ? Configure::read('SecureAuth.amount') : 5;
$expire = time() + $expire;
$expire = date('Y-m-d H:i:s', $expire);
$expireTime = time() + $expire;
$expireTime = date('Y-m-d H:i:s', $expireTime);
$bruteforceEntry = array(
'ip' => $ip,
'username' => trim(strtolower($username)),
'expire' => $expire
'expire' => $expireTime
);
$this->save($bruteforceEntry);
$title = 'Failed login attempt using username ' . $username . ' from IP: ' . $ip . '.';
if ($this->isBlocklisted($username)) {
$title .= 'This has tripped the bruteforce protection after ' . $amount . ' failed attempts. The user is now blocklisted for ' . $expire . ' seconds.';
$change = 'This has tripped the bruteforce protection after ' . $amount . ' failed attempts. The source IP/username is now blocklisted for ' . $expire . ' seconds.';
} else {
$change = '';
}
// lookup the real user details
$this->User = ClassRegistry::init('User');
$user = $this->User->find('first', array(
'conditions' => array('User.email' => $username),
'fields' => array('User.id', 'Organisation.name'),
'recursive' => 0));
if ($user) {
$org = $user['Organisation']['name'];
$userId = $user['User']['id'];
} else {
$org = 'SYSTEM';
$userId = 0;
}
$log = array(
'org' => 'SYSTEM',
'org' => $org,
'model' => 'User',
'model_id' => 0,
'model_id' => $userId,
'email' => $username,
'user_id' => $userId,
'action' => 'login_fail',
'title' => $title
'title' => $title,
'change' => $change
);
$this->Log->save($log);
}

View File

@ -4,37 +4,20 @@ class Community extends AppModel
{
public $useTable = false;
public $recursive = -1;
public $actsAs = array(
'Containable',
);
public $validate = array(
);
public function beforeValidate($options = array())
{
parent::beforeValidate();
return true;
}
/**
* @param string $context
* @param string|null $value
* @return array
*/
public function getCommunityList($context, $value)
{
$community_file = new File(APP . 'files/community-metadata/defaults.json');
if (!$community_file->exists()) {
throw new NotFoundException(__('Default community list not found.'));
}
$community_list = $community_file->read();
if (empty($community_list)) {
throw new NotFoundException(__('Default community list empty.'));
}
try {
$community_list = json_decode($community_list, true);
$community_list = FileAccessTool::readJsonFromFile(APP . 'files/community-metadata/defaults.json');
} catch (Exception $e) {
throw new NotFoundException(__('Default community list not in the expected format.'));
}
$fieldsToCheck = array('name', 'uuid', 'description', 'url', 'sector', 'nationality', 'type', 'org_uuid', 'org_name');
$fieldsToCheck = ['name', 'uuid', 'description', 'url', 'sector', 'nationality', 'type', 'org_uuid', 'org_name'];
foreach ($community_list as $k => $v) {
if ($v['misp_project_vetted'] === ($context === 'vetted')) {
$community_list[$k]['id'] = $k + 1;
@ -44,11 +27,12 @@ class Community extends AppModel
continue;
}
if (!empty($value)) {
$value = mb_strtolower($value);
$found = false;
foreach ($fieldsToCheck as $field) {
if (strpos(strtolower($v[$field]), $value) !== false) {
if (strpos(mb_strtolower($v[$field]), $value) !== false) {
$found = true;
continue;
break;
}
}
if (!$found) {
@ -56,42 +40,32 @@ class Community extends AppModel
}
}
}
$community_list = array_values($community_list);
return $community_list;
return array_values($community_list);
}
/**
* @param int|string $id Community ID or UUID
* @return array
*/
public function getCommunity($id)
{
$community_file = new File(APP . 'files/community-metadata/defaults.json');
if (!$community_file->exists()) {
throw new NotFoundException(__('Default community list not found.'));
}
$community_list = $community_file->read();
if (empty($community_list)) {
throw new NotFoundException(__('Default community list empty.'));
}
try {
$community_list = json_decode($community_list, true);
$community_list = FileAccessTool::readJsonFromFile(APP . 'files/community-metadata/defaults.json');
} catch (Exception $e) {
throw new NotFoundException(__('Default community list not in the expected format.'));
}
foreach ($community_list as $k => $v) {
$community_list[$k]['id'] = $k + 1;
$community_list[$k]['Org'] = array('uuid' => $v['org_uuid'], 'name' => $v['org_name']);
}
$community = false;
$lookupField = 'id';
if (Validation::uuid($id)) {
$lookupField = 'uuid';
}
$lookupField = Validation::uuid($id) ? 'uuid' : 'id';
foreach ($community_list as $s) {
if ($s[$lookupField === 'uuid' ? 'uuid' : 'id'] === $id) {
$community = $s;
if ($s[$lookupField === 'uuid' ? 'uuid' : 'id'] == $id) {
return $s;
}
}
if (empty($community)) {
throw new NotFoundException(__('Community not found.'));
}
return $community;
throw new NotFoundException(__('Community not found.'));
}
}

View File

@ -97,6 +97,7 @@ class Dashboard extends AppModel
}
}
}
ksort($widgets);
return $widgets;
}

View File

@ -18,7 +18,7 @@ class PolynomialExtended extends Polynomial
} else {
$retention_taxonomy_id = $retention_taxonomy_id['Taxonomy']['id'];
}
$taxonomy = $this->Taxonomy->getTaxonomy($retention_taxonomy_id, array('full' => true));
$taxonomy = $this->Taxonomy->getTaxonomy($retention_taxonomy_id);
$this->retention_taxonomy = array();
foreach ($taxonomy['entries'] as $k => $entry) {
$this->retention_taxonomy[$entry['tag']] = $entry['numerical_value'];

View File

@ -5594,6 +5594,10 @@ class Event extends AppModel
return $resultArray;
}
/**
* @param array $result
* @return array
*/
public function handleMispFormatFromModuleResult(&$result)
{
$defaultDistribution = $this->Attribute->defaultDistribution();
@ -5607,7 +5611,7 @@ class Event extends AppModel
$event['Attribute'] = $attributes;
}
if (!empty($result['results']['Object'])) {
$object = array();
$objects = array();
foreach ($result['results']['Object'] as $tmp_object) {
$tmp_object['distribution'] = (isset($tmp_object['distribution']) ? (int)$tmp_object['distribution'] : $defaultDistribution);
$tmp_object['sharing_group_id'] = (isset($tmp_object['sharing_group_id']) ? (int)$tmp_object['sharing_group_id'] : 0);
@ -5631,6 +5635,11 @@ class Event extends AppModel
return $event;
}
/**
* @param array $attribute
* @param int $defaultDistribution
* @return array
*/
private function __fillAttribute($attribute, $defaultDistribution)
{
if (is_array($attribute['type'])) {
@ -6327,11 +6336,33 @@ class Event extends AppModel
return $message;
}
public function processModuleResultsData($user, $resolved_data, $id, $default_comment = '', $jobId = false, $adhereToWarninglists = false, $event_level = false)
/**
* @param array $user
* @param array $resolved_data
* @param int $id
* @param string $default_comment
* @param int|false $jobId
* @param bool $adhereToWarninglists
* @param bool $event_level
* @return int|string
* @throws JsonException
*/
public function processModuleResultsData(array $user, $resolved_data, $id, $default_comment = '', $jobId = false, $adhereToWarninglists = false, $event_level = false)
{
$event = $this->find('first', [
'recursive' => -1,
'conditions' => ['id' => $id],
]);
if (empty($event)) {
throw new Exception("Event with ID `$id` not found.");
}
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
$this->Job->id = $jobId;
/** @var EventLock $eventLock */
$eventLock = ClassRegistry::init('EventLock');
$eventLock->insertLockBackgroundJob($event['Event']['id'], $jobId);
}
$failed_attributes = $failed_objects = $failed_object_attributes = $failed_reports = 0;
$saved_attributes = $saved_objects = $saved_object_attributes = $saved_reports = 0;
@ -6377,6 +6408,7 @@ class Event extends AppModel
}
}
} else {
$this->Attribute->logDropped($user, $attribute);
$failed_attributes++;
$lastAttributeError = $this->Attribute->validationErrors;
$original_uuid = $this->__findOriginalUUID(
@ -6392,8 +6424,7 @@ class Event extends AppModel
}
if ($jobId) {
$processedAttributes++;
$this->Job->saveField('message', 'Attribute ' . $processedAttributes . '/' . $total_attributes);
$this->Job->saveField('progress', ($processedAttributes * 100 / $items_count));
$this->Job->saveProgress($jobId, "Attribute $processedAttributes/$total_attributes", $processedAttributes * 100 / $items_count);
}
}
} else {
@ -6438,7 +6469,7 @@ class Event extends AppModel
if (isset($initial_attributes[$object_relation]) && in_array($object_attribute['value'], $initial_attributes[$object_relation])) {
continue;
}
if ($this->__saveObjectAttribute($object_attribute, $default_comment, $id, $initial_object_id, $user)) {
if ($this->__saveObjectAttribute($object_attribute, null, $event, $initial_object_id, $user)) {
$saved_object_attributes++;
} else {
$failed_object_attributes++;
@ -6471,7 +6502,7 @@ class Event extends AppModel
if ($this->Object->save($object)) {
$object_id = $this->Object->id;
foreach ($object['Attribute'] as $object_attribute) {
if ($this->__saveObjectAttribute($object_attribute, $default_comment, $id, $object_id, $user)) {
if ($this->__saveObjectAttribute($object_attribute, null, $event, $object_id, $user)) {
$saved_object_attributes++;
} else {
$failed_object_attributes++;
@ -6506,8 +6537,7 @@ class Event extends AppModel
}
if ($jobId) {
$processedObjects++;
$this->Job->saveField('message', 'Object ' . $processedObjects . '/' . $total_objects);
$this->Job->saveField('progress', (($processedObjects + $total_attributes) * 100 / $items_count));
$this->Job->saveProgress($jobId, "Object $processedObjects/$total_objects", ($processedObjects + $total_attributes) * 100 / $items_count);
}
}
@ -6574,14 +6604,13 @@ class Event extends AppModel
}
if ($jobId) {
$current = ($i + 1);
$this->Job->saveField('message', 'EventReport ' . $current . '/' . $total_reports);
$this->Job->saveField('progress', ($current * 100 / $items_count));
$this->Job->saveProgress($jobId, "EventReport $current/$total_reports", $current * 100 / $items_count);
}
}
}
if ($saved_attributes > 0 || $saved_objects > 0 || $saved_reports > 0) {
$this->unpublishEvent($id);
$this->unpublishEvent($event);
}
if ($event_level) {
return $saved_attributes + $saved_object_attributes + $saved_reports;
@ -6642,8 +6671,8 @@ class Event extends AppModel
$message .= $failed_reports . $reason;
}
if ($jobId) {
$this->Job->saveField('message', 'Processing complete. ' . $message);
$this->Job->saveField('progress', 100);
$this->Job->saveStatus($jobId, true, 'Processing complete. ' . $message);
$eventLock->deleteBackgroundJobLock($event['Event']['id'], $jobId);
}
return $message;
}
@ -6730,28 +6759,39 @@ class Event extends AppModel
return (!empty($original_uuid)) ? $original_uuid['Object']['uuid'] : $original_uuid;
}
private function __saveObjectAttribute($attribute, $default_comment, $event_id, $object_id, $user)
/**
* @param array $attribute
* @param string|null $default_comment
* @param array $event
* @param int $object_id
* @param array $user
* @return array|bool|mixed
* @throws Exception
*/
private function __saveObjectAttribute(array $attribute, $default_comment, array $event, $object_id, array $user)
{
$attribute['object_id'] = $object_id;
$attribute['event_id'] = $event_id;
if (empty($attribute['comment'])) {
$attribute['event_id'] = $event['Event']['id'];
if (empty($attribute['comment']) && $default_comment) {
$attribute['comment'] = $default_comment;
}
if (!empty($attribute['data']) && !empty($attribute['encrypt'])) {
$attribute = $this->Attribute->onDemandEncrypt($attribute);
}
$this->Attribute->create();
$attribute_save = $this->Attribute->save($attribute);
$attribute_save = $this->Attribute->save($attribute, ['parentEvent' => $event]);
if ($attribute_save) {
if (!empty($attribute['Tag'])) {
foreach ($attribute['Tag'] as $tag) {
$tag_id = $this->Attribute->AttributeTag->Tag->captureTag($tag, $user);
$relationship_type = empty($tag['relationship_type']) ? false : $tag['relationship_type'];
if ($tag_id) {
$this->Attribute->AttributeTag->attachTagToAttribute($this->Attribute->id, $event_id, $tag_id, !empty($tag['local']), $relationship_type);
$this->Attribute->AttributeTag->attachTagToAttribute($this->Attribute->id, $event['Event']['id'], $tag_id, !empty($tag['local']), $relationship_type);
}
}
}
} else {
$this->Attribute->logDropped($user, $attribute);
}
return $attribute_save;
}

View File

@ -91,7 +91,7 @@ class EventTag extends AppModel
/**
* @param int $event_id
* @param int $tagId
* @param array $tag
* @param bool $nothingToChange
* @return bool
* @throws Exception

View File

@ -380,16 +380,16 @@ class Galaxy extends AppModel
/**
* @param array $user
* @param string $target_type
* @param string $targetType Can be 'event', 'attribute' or 'tag_collection'
* @param array $target
* @param int $cluster_id
* @param bool $local
* @return string
* @throws Exception
*/
public function attachCluster(array $user, $target_type, array $target, $cluster_id, $local = false)
public function attachCluster(array $user, $targetType, array $target, $cluster_id, $local = false)
{
$connectorModel = Inflector::camelize($target_type) . 'Tag';
$connectorModel = Inflector::camelize($targetType) . 'Tag';
$local = $local == 1 || $local === true ? 1 : 0;
$cluster_alias = $this->GalaxyCluster->alias;
$galaxy_alias = $this->alias;
@ -409,36 +409,36 @@ class Galaxy extends AppModel
}
$this->Tag = ClassRegistry::init('Tag');
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc', 'exportable' => 1, 'local_only' => $local_only), $user, true);
if ($target_type === 'event') {
if ($targetType === 'event') {
$target_id = $target['Event']['id'];
} elseif ($target_type === 'attribute') {
} elseif ($targetType === 'attribute') {
$target_id = $target['Attribute']['id'];
} else {
$target_id = $target['TagCollection']['id'];
}
$existingTag = $this->Tag->$connectorModel->hasAny(array($target_type . '_id' => $target_id, 'tag_id' => $tag_id));
$existingTag = $this->Tag->$connectorModel->hasAny(array($targetType . '_id' => $target_id, 'tag_id' => $tag_id));
if ($existingTag) {
return 'Cluster already attached.';
}
$this->Tag->$connectorModel->create();
$toSave = array($target_type . '_id' => $target_id, 'tag_id' => $tag_id, 'local' => $local);
if ($target_type === 'attribute') {
$toSave = array($targetType . '_id' => $target_id, 'tag_id' => $tag_id, 'local' => $local);
if ($targetType === 'attribute') {
$toSave['event_id'] = $target['Attribute']['event_id'];
}
$result = $this->Tag->$connectorModel->save($toSave);
if ($result) {
if (!$local) {
if ($target_type === 'attribute') {
if ($targetType === 'attribute') {
$this->Tag->AttributeTag->Attribute->touch($target);
} elseif ($target_type === 'event') {
} elseif ($targetType === 'event') {
$this->Tag->EventTag->Event->unpublishEvent($target);
}
}
if ($target_type === 'attribute' || $target_type === 'event') {
if ($targetType === 'attribute' || $targetType === 'event') {
$this->Tag->EventTag->Event->insertLock($user, $target['Event']['id']);
}
$logTitle = 'Attached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') to ' . $target_type . ' (' . $target_id . ')';
$this->loadLog()->createLogEntry($user, 'galaxy', ucfirst($target_type), $target_id, $logTitle);
$logTitle = 'Attached ' . $cluster['GalaxyCluster']['value'] . ' (' . $cluster['GalaxyCluster']['id'] . ') to ' . $targetType . ' (' . $target_id . ')';
$this->loadLog()->createLogEntry($user, 'galaxy', ucfirst($targetType), $target_id, $logTitle);
return 'Cluster attached.';
}
return 'Could not attach the cluster';

View File

@ -1,5 +1,9 @@
<?php
App::uses('AppModel', 'Model');
/**
* @property GalaxyCluster $GalaxyCluster
*/
class GalaxyElement extends AppModel
{
public $useTable = 'galaxy_elements';

View File

@ -452,7 +452,37 @@ class MispObject extends AppModel
return false;
}
public function saveObject(array $object, $eventId, $template = false, $user, $errorBehaviour = 'drop', $breakOnDuplicate = false)
/**
* @param array $object
* @param array $template
* @return array
*/
public function fillObjectDataFromTemplate(array $object, array $template)
{
$templateFields = array(
'name' => 'name',
'meta-category' => 'meta-category',
'description' => 'description',
'template_version' => 'version',
'template_uuid' => 'uuid'
);
foreach ($templateFields as $objectField => $templateField) {
$object['Object'][$objectField] = $template['ObjectTemplate'][$templateField];
}
return $object;
}
/**
* @param array $object
* @param int $eventId
* @param array $template
* @param array $user
* @param string $errorBehaviour
* @param bool $breakOnDuplicate
* @return array|array[]|bool|int|mixed|string
* @throws Exception
*/
public function saveObject(array $object, $eventId, $template = false, array $user, $errorBehaviour = 'drop', $breakOnDuplicate = false)
{
$templateFields = array(
'name' => 'name',
@ -562,7 +592,7 @@ class MispObject extends AppModel
// conditions
// order
// group
public function fetchObjects($user, $options = array())
public function fetchObjects(array $user, array $options = array())
{
$attributeConditions = array();
if (!$user['Role']['perm_site_admin']) {
@ -608,8 +638,6 @@ class MispObject extends AppModel
}
if (isset($options['contain'])) {
$params['contain'] = array_merge_recursive($params['contain'], $options['contain']);
} else {
$option['contain']['Event']['fields'] = array('id', 'info', 'org_id', 'orgc_id');
}
if (
empty($options['metadata']) &&
@ -662,7 +690,6 @@ class MispObject extends AppModel
if ($options['enforceWarninglist'] && !isset($this->Warninglist)) {
$this->Warninglist = ClassRegistry::init('Warninglist');
}
$results = array_values($results);
$proposals_block_attributes = Configure::read('MISP.proposals_block_attributes');
if (empty($options['metadata'])) {
foreach ($results as $key => $object) {
@ -764,7 +791,7 @@ class MispObject extends AppModel
/**
* Clean the attribute list up from artifacts introduced by the object form
* @param array $attributes
* @return string|array
* @return array
* @throws InternalErrorException
* @throws Exception
*/
@ -812,6 +839,70 @@ class MispObject extends AppModel
return $attributes;
}
/**
* @param array $user
* @param int $eventId
* @param array $attributes
* @param array $template
* @param int $threshold
* @return array
*/
public function findSimilarObjects(array $user, $eventId, array $attributes, array $template, $threshold = 15)
{
$attributeValues = array_column($attributes, 'value');
$conditions = array(
'event_id' => $eventId,
'value1' => $attributeValues,
'object_id !=' => 0,
);
$similarObjects = $this->Attribute->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'fields' => 'object_id, count(object_id) as similarity_amount',
'group' => 'object_id',
'order' => 'similarity_amount DESC'
));
if (empty($similarObjects)) {
return [0, [], [], []];
}
$similar_object_ids = array();
$similar_object_similarity_amount = array();
foreach ($similarObjects as $obj) {
$similar_object_ids[] = $obj['Attribute']['object_id'];
$similar_object_similarity_amount[$obj['Attribute']['object_id']] = (int)$obj[0]['similarity_amount'];
}
$similar_objects_count = count($similar_object_ids);
$similar_object_ids = array_slice($similar_object_ids, 0, $threshold); // slice to honor the threshold
$similar_objects = $this->fetchObjects($user, array(
'conditions' => array(
'Object.id' => $similar_object_ids,
'Object.template_uuid' => $template['ObjectTemplate']['uuid']
)
));
foreach ($similar_objects as $key => $obj) {
$similar_objects[$key]['Object']['similarity_amount'] = $similar_object_similarity_amount[$obj['Object']['id']]; // sorting function cannot use external variables
}
usort($similar_objects, function ($a, $b) { // fetch Object returns object sorted by IDs, force the sort by the similarity amount
if ($a['Object']['similarity_amount'] == $b['Object']['similarity_amount']) {
return 0;
}
return ($a['Object']['similarity_amount'] > $b['Object']['similarity_amount']) ? -1 : 1;
});
$simple_flattened_attribute = [];
$simple_flattened_attribute_noval = [];
foreach ($attributes as $k => $attribute) {
$curFlat = $attribute['object_relation'] . '.' . $attribute['type'] . '.' .$attribute['value'];
$simple_flattened_attribute[$curFlat] = $k;
$curFlatNoval = $attribute['object_relation'] . '.' . $attribute['type'];
$simple_flattened_attribute_noval[$curFlatNoval] = $k;
}
return [$similar_objects_count, $similar_objects, $simple_flattened_attribute, $simple_flattened_attribute_noval];
}
// Set Object's *-seen (and ObjectAttribute's *-seen and ObjectAttribute's value if requested) to the provided *-seen value
// Therefore, synchronizing the 3 values
public function syncObjectAndAttributeSeen($object, $forcedSeenOnElements, $applyOnAttribute=True) {
@ -851,6 +942,14 @@ class MispObject extends AppModel
return $object;
}
/**
* @param array $object
* @param array $objectToSave
* @param bool $onlyAddNewAttribute
* @param array $user
* @return array|int
* @throws JsonException
*/
public function deltaMerge(array $object, array $objectToSave, $onlyAddNewAttribute=false, array $user)
{
if (!isset($objectToSave['Object'])) {
@ -965,7 +1064,6 @@ class MispObject extends AppModel
}
} else { // we only add the new attribute
$newAttribute = $objectToSave['Attribute'][0];
$this->Event->Attribute->create();
$newAttribute['event_id'] = $object['Object']['event_id'];
$newAttribute['object_id'] = $object['Object']['id'];
// Set seen of object at attribute level
@ -980,10 +1078,9 @@ class MispObject extends AppModel
(!array_key_exists('last_seen', $object['Object']) && !is_null($object['Object']['last_seen']))
) {
$newAttribute['last_seen'] = $object['Object']['last_seen'];
$different = true;
}
$saveAttributeResult = $this->Attribute->saveAttributes(array($newAttribute), $user);
return $saveAttributeResult ? $this->id : $this->validationErrors;
return $saveAttributeResult ? $this->id : $this->Attribute->validationErrors;
}
return $this->id;
}
@ -1232,51 +1329,14 @@ class MispObject extends AppModel
'Attribute.event_id' => $eventId,
'Attribute.object_id' => 0,
],
'fields' => ['Attribute.type'],
]);
if (empty($attributes)) {
return array('templates' => array(), 'types' => array());
}
$attributeTypes = array();
foreach ($attributes as $i => $attribute) {
$attributeTypes[$attribute['Attribute']['type']] = true;
$attributes[$i]['Attribute']['object_relation'] = $attribute['Attribute']['type'];
}
$attributeTypes = array_keys($attributeTypes);
$potentialTemplateIds = $this->ObjectTemplate->find('column', array(
'recursive' => -1,
'fields' => array(
'ObjectTemplate.id',
),
'conditions' => array(
'ObjectTemplate.active' => true,
'ObjectTemplateElement.type' => $attributeTypes,
),
'joins' => array(
array(
'table' => 'object_template_elements',
'alias' => 'ObjectTemplateElement',
'type' => 'RIGHT',
'fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type'),
'conditions' => array('ObjectTemplate.id = ObjectTemplateElement.object_template_id')
)
),
'group' => 'ObjectTemplate.id',
));
$templates = $this->ObjectTemplate->find('all', [
'recursive' => -1,
'conditions' => ['id' => $potentialTemplateIds],
'contain' => ['ObjectTemplateElement' => ['fields' => ['object_relation', 'type', 'multiple']]]
]);
foreach ($templates as $i => $template) {
$res = $this->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $attributes);
$templates[$i]['ObjectTemplate']['compatibility'] = $res['valid'] ? true : $res['missingTypes'];
$templates[$i]['ObjectTemplate']['invalidTypes'] = $res['invalidTypes'];
$templates[$i]['ObjectTemplate']['invalidTypesMultiple'] = $res['invalidTypesMultiple'];
}
return array('templates' => $templates, 'types' => $attributeTypes);
$attributeTypes = array_column(array_column($attributes, 'Attribute'), 'type');
return $this->ObjectTemplate->fetchPossibleTemplatesBasedOnTypes($attributeTypes);
}
public function groupAttributesIntoObject(array $user, $event_id, array $object, $template, array $selected_attribute_ids, array $selected_object_relation_mapping, $hard_delete_attribute)

View File

@ -6,7 +6,8 @@ class Module extends AppModel
{
public $useTable = false;
private $__validTypes = array(
// private
const VALID_TYPES = array(
'Enrichment' => array('hover', 'expansion'),
'Import' => array('import'),
'Export' => array('export'),
@ -14,6 +15,7 @@ class Module extends AppModel
'Cortex' => array('cortex')
);
// private
const TYPE_TO_FAMILY = array(
'Import' => 'Import',
'Export' => 'Export',
@ -23,7 +25,7 @@ class Module extends AppModel
'Cortex' => 'Cortex'
);
public $configTypes = array(
const CONFIG_TYPES = array(
'IP' => array(
'validation' => 'validateIPField',
'field' => 'text',
@ -351,7 +353,7 @@ class Module extends AppModel
$result = array();
if (is_array($modules)) {
foreach ($modules as $module) {
if (array_intersect($this->__validTypes[$moduleFamily], $module['meta']['module-type'])) {
if (array_intersect(self::VALID_TYPES[$moduleFamily], $module['meta']['module-type'])) {
$moduleSettings = [
[
'name' => 'enabled',

View File

@ -207,11 +207,69 @@ class ObjectTemplate extends AppModel
}
/**
* @param array $template
* @param array $attributes
* @param array $attributeTypes Array of attribute types to check, can contains multiple types
* @return array
*/
public function checkTemplateConformityBasedOnTypes(array $template, array $attributes)
public function fetchPossibleTemplatesBasedOnTypes(array $attributeTypes)
{
$uniqueAttributeTypes = array_unique($attributeTypes, SORT_REGULAR);
$potentialTemplateIds = $this->find('column', array(
'recursive' => -1,
'fields' => array(
'ObjectTemplate.id',
),
'conditions' => array(
'ObjectTemplate.active' => true,
'ObjectTemplateElement.type' => $uniqueAttributeTypes,
),
'joins' => array(
array(
'table' => 'object_template_elements',
'alias' => 'ObjectTemplateElement',
'type' => 'RIGHT',
'fields' => array('ObjectTemplateElement.object_relation', 'ObjectTemplateElement.type'),
'conditions' => array('ObjectTemplate.id = ObjectTemplateElement.object_template_id')
)
),
'group' => 'ObjectTemplate.id',
));
$templates = $this->find('all', [
'recursive' => -1,
'conditions' => ['id' => $potentialTemplateIds],
'contain' => ['ObjectTemplateElement' => ['fields' => ['object_relation', 'type', 'multiple']]]
]);
foreach ($templates as $i => $template) {
$res = $this->checkTemplateConformityBasedOnTypes($template, $attributeTypes);
$templates[$i]['ObjectTemplate']['compatibility'] = $res['valid'] ? true : $res['missingTypes'];
$templates[$i]['ObjectTemplate']['invalidTypes'] = $res['invalidTypes'];
$templates[$i]['ObjectTemplate']['invalidTypesMultiple'] = $res['invalidTypesMultiple'];
}
usort($templates, function($a, $b) {
if ($a['ObjectTemplate']['id'] == $b['ObjectTemplate']['id']) {
return 0;
} else if (is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) {
return count($a['ObjectTemplate']['compatibility']) > count($b['ObjectTemplate']['compatibility']) ? 1 : -1;
} else if (is_array($a['ObjectTemplate']['compatibility']) && !is_array($b['ObjectTemplate']['compatibility'])) {
return 1;
} else if (!is_array($a['ObjectTemplate']['compatibility']) && is_array($b['ObjectTemplate']['compatibility'])) {
return -1;
} else { // sort based on invalidTypes count
return count($a['ObjectTemplate']['invalidTypes']) > count($b['ObjectTemplate']['invalidTypes']) ? 1 : -1;
}
});
return array('templates' => $templates, 'types' => $uniqueAttributeTypes);
}
/**
* @param array $template
* @param array $attributeTypes Array of attribute types to check, can contains multiple types
* @return array
*/
public function checkTemplateConformityBasedOnTypes(array $template, array $attributeTypes)
{
$to_return = array('valid' => true, 'missingTypes' => array());
if (!empty($template['ObjectTemplate']['requirements'])) {
@ -222,13 +280,7 @@ class ObjectTemplate extends AppModel
if (!empty($template['ObjectTemplate']['requirements']['required'])) {
foreach ($template['ObjectTemplate']['requirements']['required'] as $requiredField) {
$requiredType = $elementsByObjectRelationName[$requiredField]['type'];
$found = false;
foreach ($attributes as $attribute) {
if ($attribute['Attribute']['type'] === $requiredType) {
$found = true;
break;
}
}
$found = in_array($requiredType, $attributeTypes, true);
if (!$found) {
$to_return = array('valid' => false, 'missingTypes' => array($requiredType));
}
@ -241,11 +293,8 @@ class ObjectTemplate extends AppModel
foreach ($template['ObjectTemplate']['requirements']['requiredOneOf'] as $requiredField) {
$requiredType = $elementsByObjectRelationName[$requiredField]['type'] ?? null;
$allRequiredTypes[] = $requiredType;
foreach ($attributes as $attribute) {
if ($attribute['Attribute']['type'] === $requiredType) {
$found = true;
break;
}
if (!$found) {
$found = in_array($requiredType, $attributeTypes, true);
}
}
if (!$found) {
@ -262,17 +311,17 @@ class ObjectTemplate extends AppModel
$valid_types[$templateElement['type']] = $templateElement['multiple'];
}
$check_for_multiple_type = array();
foreach ($attributes as $attribute) {
if (isset($valid_types[$attribute['Attribute']['type']])) {
if (!$valid_types[$attribute['Attribute']['type']]) { // is not multiple
if (isset($check_for_multiple_type[$attribute['Attribute']['type']])) {
$to_return['invalidTypesMultiple'][] = $attribute['Attribute']['type'];
foreach ($attributeTypes as $attributeType) {
if (isset($valid_types[$attributeType])) {
if (!$valid_types[$attributeType]) { // is not multiple
if (isset($check_for_multiple_type[$attributeType])) {
$to_return['invalidTypesMultiple'][] = $attributeType;
} else {
$check_for_multiple_type[$attribute['Attribute']['type']] = 1;
$check_for_multiple_type[$attributeType] = 1;
}
}
} else {
$to_return['invalidTypes'][] = $attribute['Attribute']['type'];
$to_return['invalidTypes'][] = $attributeType;
}
}
$to_return['invalidTypes'] = array_unique($to_return['invalidTypes'], SORT_REGULAR);

View File

@ -5539,7 +5539,7 @@ class Server extends AppModel
),
'log_client_ip_header' => array(
'level' => 1,
'description' => __('If log_client_ip is enabled, you can customize which header field contains the client\'s IP address. This is generally used when you have a reverse proxy infront of your MISP instance.'),
'description' => __('If log_client_ip is enabled, you can customize which header field contains the client\'s IP address. This is generally used when you have a reverse proxy in front of your MISP instance. Prepend the variable with "HTTP_", for example "HTTP_X_FORWARDED_FOR".'),
'value' => 'REMOTE_ADDR',
'test' => 'testForEmpty',
'type' => 'string',
@ -5595,7 +5595,7 @@ class Server extends AppModel
),
'log_paranoid_skip_db' => array(
'level' => 0,
'description' => __('You can decide to skip the logging of the paranoid logs to the database.'),
'description' => __('You can decide to skip the logging of the paranoid logs to the database. Logs will be just published to ZMQ or Kafka.'),
'value' => false,
'test' => 'testParanoidSkipDb',
'type' => 'boolean',
@ -5609,6 +5609,14 @@ class Server extends AppModel
'type' => 'boolean',
'null' => true
),
'log_paranoid_include_sql_queries' => [
'level' => 0,
'description' => __('If paranoid logging is enabled, include the SQL queries in the entries.'),
'value' => false,
'test' => 'testBool',
'type' => 'boolean',
'null' => true
],
'log_user_ips' => array(
'level' => 0,
'description' => __('Log user IPs on each request. 30 day retention for lookups by IP to get the last authenticated user ID for the given IP, whilst on the reverse, indefinitely stores all associated IPs for a user ID.'),
@ -5649,6 +5657,14 @@ class Server extends AppModel
'type' => 'boolean',
'null' => true
),
'discussion_disable' => [
'level' => 1,
'description' => __('Completely disable ability for user to add discussion to events.'),
'value' => false,
'test' => 'testBool',
'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.'),

View File

@ -459,7 +459,7 @@ class Tag extends AppModel
$tags_temp = $this->find('all', $tag_params);
$tags = array();
foreach ($tags_temp as $temp) {
$tags[strtoupper($temp['Tag']['name'])] = $temp;
$tags[mb_strtolower($temp['Tag']['name'])] = $temp;
}
return $tags;
}

View File

@ -118,7 +118,7 @@ class Taxonomy extends AppModel
$current = $this->find('first', array(
'conditions' => array('namespace' => $vocab['namespace']),
'recursive' => -1,
'fields' => array('version', 'enabled', 'namespace')
'fields' => array('version', 'enabled', 'namespace', 'highlighted')
));
$current = empty($current) ? [] : $current['Taxonomy'];
$result = $this->__updateVocab($vocab, $current);
@ -147,6 +147,7 @@ class Taxonomy extends AppModel
'version' => $vocab['version'],
'exclusive' => !empty($vocab['exclusive']),
'enabled' => $enabled,
'highlighted' => !empty($vocab['highlighted']),
]];
$predicateLookup = array();
foreach ($vocab['predicates'] as $k => $predicate) {
@ -176,15 +177,10 @@ class Taxonomy extends AppModel
/**
* @param int|string $id Taxonomy ID or namespace
* @param string|null $options
* @return array|false
*/
private function __getTaxonomy($id, $options = array('full' => false, 'filter' => false))
private function __getTaxonomy($id)
{
$filter = false;
if (isset($options['filter'])) {
$filter = $options['filter'];
}
if (!is_numeric($id)) {
$conditions = ['Taxonomy.namespace' => trim(mb_strtolower($id))];
} else {
@ -236,17 +232,10 @@ class Taxonomy extends AppModel
$entries[] = $temp;
}
}
$taxonomy = array('Taxonomy' => $taxonomy['Taxonomy']);
if ($filter) {
$filter = mb_strtolower($filter);
$namespaceLength = strlen($taxonomy['Taxonomy']['namespace']);
foreach ($entries as $k => $entry) {
if (strpos(substr(mb_strtolower($entry['tag']), $namespaceLength), $filter) === false) {
unset($entries[$k]);
}
}
}
$taxonomy['entries'] = $entries;
$taxonomy = [
'Taxonomy' => $taxonomy['Taxonomy'],
'entries' => $entries,
];
return $taxonomy;
}
@ -264,8 +253,13 @@ class Taxonomy extends AppModel
{
$taxonomies = $this->find('all', [
'fields' => ['namespace'],
'contain' => ['TaxonomyPredicate' => ['TaxonomyEntry']],
'recursive' => -1,
'contain' => ['TaxonomyPredicate' => [
'fields' => ['value'],
'TaxonomyEntry' => ['fields' => ['value']]],
],
]);
$allTaxonomyTags = [];
foreach ($taxonomies as $taxonomy) {
$namespace = $taxonomy['Taxonomy']['namespace'];
@ -326,7 +320,7 @@ class Taxonomy extends AppModel
public function getTaxonomyTags($id, $upperCase = false, $existingOnly = false)
{
$taxonomy = $this->__getTaxonomy($id, array('full' => true, 'filter' => false));
$taxonomy = $this->__getTaxonomy($id);
if ($existingOnly) {
$this->Tag = ClassRegistry::init('Tag');
$tags = $this->Tag->find('list', array('fields' => array('name'), 'order' => array('UPPER(Tag.name) ASC')));
@ -352,45 +346,31 @@ class Taxonomy extends AppModel
/**
* @param int|string $id Taxonomy ID or namespace
* @param array|null $options
* @param bool $full Add tag information to entries
* @return array|false
*/
public function getTaxonomy($id, $options = array('full' => true))
public function getTaxonomy($id, $full = true)
{
$taxonomy = $this->__getTaxonomy($id, $options);
$taxonomy = $this->__getTaxonomy($id);
if (empty($taxonomy)) {
return false;
}
$this->Tag = ClassRegistry::init('Tag');
if (isset($options['full']) && $options['full']) {
if ($full) {
$this->Tag = ClassRegistry::init('Tag');
$tagNames = array_column($taxonomy['entries'], 'tag');
$tags = $this->Tag->getTagsByName($tagNames, false);
$filterActive = false;
if (isset($options['enabled'])) {
$filterActive = true;
$enabledTag = isset($options['enabled']) ? $options['enabled'] : null;
}
if (isset($taxonomy['entries'])) {
foreach ($taxonomy['entries'] as $key => $temp) {
if (isset($tags[strtoupper($temp['tag'])])) {
$existingTag = $tags[strtoupper($temp['tag'])];
if ($filterActive && $options['enabled'] == $existingTag['Tag']['hide_tag']) {
unset($taxonomy['entries'][$key]);
continue;
}
$taxonomy['entries'][$key]['existing_tag'] = $existingTag;
// numerical_value is overridden at tag level. Propagate the override further up
if (isset($existingTag['Tag']['original_numerical_value'])) {
$taxonomy['entries'][$key]['original_numerical_value'] = $existingTag['Tag']['original_numerical_value'];
$taxonomy['entries'][$key]['numerical_value'] = $existingTag['Tag']['numerical_value'];
}
} else {
if ($filterActive) {
unset($taxonomy['entries'][$key]);
} else {
$taxonomy['entries'][$key]['existing_tag'] = false;
}
foreach ($taxonomy['entries'] as $key => $temp) {
$tagLower = mb_strtolower($temp['tag']);
if (isset($tags[$tagLower])) {
$existingTag = $tags[$tagLower];
$taxonomy['entries'][$key]['existing_tag'] = $existingTag;
// numerical_value is overridden at tag level. Propagate the override further up
if (isset($existingTag['Tag']['original_numerical_value'])) {
$taxonomy['entries'][$key]['original_numerical_value'] = $existingTag['Tag']['original_numerical_value'];
$taxonomy['entries'][$key]['numerical_value'] = $existingTag['Tag']['numerical_value'];
}
} else {
$taxonomy['entries'][$key]['existing_tag'] = false;
}
}
}
@ -401,7 +381,7 @@ class Taxonomy extends AppModel
{
App::uses('ColourPaletteTool', 'Tools');
$paletteTool = new ColourPaletteTool();
$taxonomy = $this->__getTaxonomy($id, array('full' => true));
$taxonomy = $this->__getTaxonomy($id);
$colours = $paletteTool->generatePaletteFromString($taxonomy['Taxonomy']['namespace'], count($taxonomy['entries']));
$this->Tag = ClassRegistry::init('Tag');
$tags = $this->Tag->getTagsForNamespace($taxonomy['Taxonomy']['namespace'], false);
@ -440,7 +420,7 @@ class Taxonomy extends AppModel
$this->Tag = ClassRegistry::init('Tag');
App::uses('ColourPaletteTool', 'Tools');
$paletteTool = new ColourPaletteTool();
$taxonomy = $this->__getTaxonomy($id, array('full' => true));
$taxonomy = $this->__getTaxonomy($id);
if (empty($taxonomy)) {
return false;
}
@ -486,7 +466,7 @@ class Taxonomy extends AppModel
if ($tagList) {
$tags = $tagList;
} else {
$taxonomy = $this->__getTaxonomy($id, array('full' => true));
$taxonomy = $this->__getTaxonomy($id);
foreach ($taxonomy['entries'] as $entry) {
$tags[] = $entry['tag'];
}
@ -513,7 +493,7 @@ class Taxonomy extends AppModel
$this->Tag = ClassRegistry::init('Tag');
App::uses('ColourPaletteTool', 'Tools');
$paletteTool = new ColourPaletteTool();
$taxonomy = $this->__getTaxonomy($id, array('full' => true));
$taxonomy = $this->__getTaxonomy($id);
$tags = $this->Tag->getTagsForNamespace($taxonomy['Taxonomy']['namespace']);
$colours = $paletteTool->generatePaletteFromString($taxonomy['Taxonomy']['namespace'], count($taxonomy['entries']));
foreach ($taxonomy['entries'] as $k => $entry) {
@ -546,7 +526,7 @@ class Taxonomy extends AppModel
$this->Tag = ClassRegistry::init('Tag');
App::uses('ColourPaletteTool', 'Tools');
$paletteTool = new ColourPaletteTool();
$taxonomy = $this->__getTaxonomy($id, array('full' => true));
$taxonomy = $this->__getTaxonomy($id);
$tags = $this->Tag->getTagsForNamespace($taxonomy['Taxonomy']['namespace']);
$colours = $paletteTool->generatePaletteFromString($taxonomy['Taxonomy']['namespace'], count($taxonomy['entries']));
foreach ($taxonomy['entries'] as $k => $entry) {
@ -699,6 +679,12 @@ class Taxonomy extends AppModel
// at this point, we have a duplicated namespace(-predicate)
$taxonomy = $this->getTaxonomyForTag($newTagName);
if (!empty($taxonomy['Taxonomy']['exclusive'])) {
if (
($newTagName === 'tlp:white' && in_array('tlp:clear', $tagNameList)) ||
($newTagName === 'tlp:clear' && in_array('tlp:white', $tagNameList))
) {
return true;
}
return false; // only one tag of this taxonomy is allowed
} elseif (!empty($taxonomy['TaxonomyPredicate'][0]['exclusive'])) {
return false; // only one tag belonging to this predicate is allowed
@ -877,4 +863,46 @@ class Taxonomy extends AppModel
{
return $this->Tag->mergeTag($source_id, $target_id);
}
/**
* @return array
*/
public function getHighlightedTaxonomies()
{
return $this->find('all', [
'conditions' => [
'highlighted' => 1,
]
]);
}
/**
*
* @param array $highlightedTaxonomies
* @param array $tags
* @return array
*/
public function getHighlightedTags($highlightedTaxonomies, $tags)
{
$highlightedTags = [];
if (is_array($highlightedTaxonomies) && !empty($highlightedTaxonomies)) {
foreach ($highlightedTaxonomies as $k => $taxonomy) {
$highlightedTags[$k] = [
'taxonomy' => $taxonomy,
'tags' => []
];
foreach ($tags as $tag) {
$splits = $this->splitTagToComponents($tag['Tag']['name']);
if (!empty($splits) && $splits['namespace'] === $taxonomy['Taxonomy']['namespace']) {
$highlightedTags[$k]['tags'][] = $tag;
}
}
}
return $highlightedTags;
}
return $highlightedTags;
}
}

View File

@ -849,7 +849,7 @@ class User extends AppModel
return true;
}
$this->loadLog();
$log = $this->loadLog();
$replyToLog = $replyToUser ? ' from ' . $replyToUser['User']['email'] : '';
$gpg = $this->initializeGpg();
@ -859,8 +859,8 @@ class User extends AppModel
} catch (SendEmailException $e) {
$this->logException("Exception during sending e-mail", $e);
$this->Log->create();
$this->Log->save(array(
$log->create();
$log->save(array(
'org' => 'SYSTEM',
'model' => 'User',
'model_id' => $user['User']['id'],
@ -876,8 +876,8 @@ class User extends AppModel
// Intentional two spaces to pass test :)
$logTitle .= $replyToLog . ' to ' . $user['User']['email'] . ' sent, titled "' . $result['subject'] . '".';
$this->Log->create();
$this->Log->save(array(
$log->create();
$log->save(array(
'org' => 'SYSTEM',
'model' => 'User',
'model_id' => $user['User']['id'],
@ -1458,18 +1458,23 @@ class User extends AppModel
*/
public function checkIfUserIsValid(array $user)
{
$auth = Configure::read('Security.auth');
if (!$auth) {
return true;
static $oidc;
if ($oidc === null) {
$auth = Configure::read('Security.auth');
if (!$auth) {
return true;
}
if (!is_array($auth)) {
throw new Exception("`Security.auth` config value must be array.");
}
if (!in_array('OidcAuth.Oidc', $auth, true)) {
return true; // this method currently makes sense just for OIDC auth provider
}
App::uses('Oidc', 'OidcAuth.Lib');
$oidc = new Oidc($this);
}
if (!is_array($auth)) {
throw new Exception("`Security.auth` config value must be array.");
}
if (!in_array('OidcAuth.Oidc', $auth, true)) {
return true; // this method currently makes sense just for OIDC auth provider
}
App::uses('Oidc', 'OidcAuth.Lib');
$oidc = new Oidc($this);
return $oidc->isUserValid($user);
}
@ -1971,4 +1976,30 @@ class User extends AppModel
}
return $users;
}
public function checkForSessionDestruction($id)
{
if (empty(CakeSession::read('creation_timestamp'))) {
return false;
}
$redis = $this->setupRedis();
if ($redis) {
$cutoff = $redis->get('misp:session_destroy:' . $id);
$allcutoff = $redis->get('misp:session_destroy:all');
if (
empty($cutoff) ||
(
!empty($cutoff) &&
!empty($allcutoff) &&
$allcutoff < $cutoff
)
) {
$cutoff = $allcutoff;
}
if ($cutoff && CakeSession::read('creation_timestamp') < $cutoff) {
return true;
}
}
return false;
}
}

View File

@ -621,16 +621,20 @@ class Workflow extends AppModel
'id' => Configure::read('MISP.host_org_id')
],
]);
$this->User = ClassRegistry::init('User');
if (!empty($hostOrg)) {
$perms = array_keys($this->User->Role->permFlags);
$allPermEnabled = array_map(function($perm) {
return true;
}, array_flip($perms));
$userForWorkflow = [
'email' => 'SYSTEM',
'id' => 0,
'org_id' => $hostOrg['Organisation']['id'],
'Role' => ['perm_site_admin' => 1],
'Role' => $allPermEnabled,
'Organisation' => $hostOrg['Organisation']
];
} else {
$this->User = ClassRegistry::init('User');
$userForWorkflow = $this->User->find('first', [
'recursive' => -1,
'conditions' => [

View File

@ -110,6 +110,20 @@ class AttributeValidationToolTest extends TestCase
]);
}
public function testValidateAs(): void
{
$this->shouldBeValid('AS', [
'0',
0,
1,
'1',
4294967295,
]);
$this->shouldBeInvalid('AS', [
'1.2.3.4',
]);
}
public function testCompressIpv6(): void
{
$this->assertEquals('1234:fd2:5621:1:89::4500', AttributeValidationTool::modifyBeforeValidation('ip-src', '1234:0fd2:5621:0001:0089:0000:0000:4500'));

View File

@ -315,13 +315,14 @@
</td>
<td class="short" data-search="request_method" data-search-value="<?= h($item['AccessLog']['request_method']) ?>">
<?= h($item['AccessLog']['request_method']) ?>
<?= in_array($item['AccessLog']['request_method'], ['POST', 'PUT']) ? ' <a href="#" class="far fa-file request" data-log-id="' . h($item['AccessLog']['id']) . '"></i>' : '' ?>
<?= in_array($item['AccessLog']['request_method'], ['POST', 'PUT']) ? ' <a href="#" class="far fa-file request" title="' . __('Show HTTP request') . '" data-log-id="' . h($item['AccessLog']['id']) . '"></i>' : '' ?>
</td>
<td class="short" data-search="controller:action" data-search-value="<?= h($item['AccessLog']['controller']) . ':' . h($item['AccessLog']['action']) ?>" title="<?= __('Controller: %s, action: %s', h($item['AccessLog']['controller']), h($item['AccessLog']['action'])) ?>"><?= h($item['AccessLog']['url']) ?></td>
<td class="short" data-search="response_code" data-search-value="<?= h($item['AccessLog']['response_code']) ?>"><?= h($item['AccessLog']['response_code']) ?></td>
<td class="short"><?= CakeNumber::toReadableSize($item['AccessLog']['memory_usage']) ?></td>
<td class="short"><?= $item['AccessLog']['duration'] ?> ms</td>
<td class="short"><?= $item['AccessLog']['query_count'] ?></td>
<td class="short"><?= $item['AccessLog']['query_count'] . ($item['AccessLog']['has_query_log'] ? ' <a href="#" class="fas fa-database query-log" title="' . __('Show SQL queries') . '" data-log-id="' . h($item['AccessLog']['id']) . '"></i>' : '') ?>
</td>
</tr>
<?php endforeach; ?>
</table>
@ -347,6 +348,17 @@
return false;
});
$('.query-log').click(function (e) {
e.preventDefault();
var id = $(this).data('log-id');
$.get(baseurl + "/admin/access_logs/queryLog/" + id, function(data) {
var $popoverFormLarge = $('#popover_form_large');
$popoverFormLarge.html(data);
openPopup($popoverFormLarge);
}).fail(xhrFailCallback);
return false;
});
$(function() {
filterSearch(function (e, searchKey, searchValue) {
if (searchKey === 'controller:action') {

View File

@ -0,0 +1,14 @@
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?= __('Query') ?></th>
<th><?= __('Num. rows') ?></th>
<th><?= __('Took (ms)') ?></th>
</tr>
<?php foreach ($queryLog['log'] as $query): ?>
<tr>
<td><?= h($query['query']) ?></td>
<td><?= h($query['numRows']) ?></td>
<td><?= h($query['took']) ?></td>
</tr>
<?php endforeach; ?>
</table>

View File

@ -52,16 +52,18 @@
'div' => 'input clear',
'label' => __("Contextual Comment")
),
array(
'field' => 'batch_import',
'type' => 'checkbox',
'requirements' => $action === 'add',
'label' => __('Batch import') . ' <span class="fas fa-info-circle" data-toggle="popover" data-trigger="hover" data-content="' . __('Insert multiple attributes to value field separated by new line') .'"></span>',
),
array(
'field' => 'to_ids',
'type' => 'checkbox',
'label' => __("For Intrusion Detection System"),
//'stayInLine' => 1
),
array(
'field' => 'batch_import',
'type' => 'checkbox'
),
array(
'field' => 'disable_correlation',
'type' => 'checkbox'
@ -89,7 +91,7 @@
),
'metaFields' => array(
'<div id="notice_message" style="display: none;"></div>',
'<div id="bothSeenSliderContainer" style="height: 170px;"></div>'
'<div id="bothSeenSliderContainer"' . ($ajax ? '' : ' style="height: 170px;"') . '></div>'
)
)
));

View File

@ -1,12 +1,12 @@
<?php
echo $this->Form->create('Attribute', array('class' => 'inline-form inline-field-form', 'id' => 'Attribute_' . $object['id'] . '_category_form', 'url' => $baseurl . '/attributes/editField/' . $object['id']));
?>
<div class='inline-input inline-input-container'>
<div class="inline-input inline-input-container">
<div class="inline-input-accept inline-input-button inline-input-passive"><span class="fas fa-check" role="button" tabindex="0" aria-label="<?php echo __('Accept change'); ?>"></span></div>
<div class="inline-input-decline inline-input-button inline-input-passive"><span class="fas fa-times" role="button" tabindex="0" aria-label="<?php echo __('Discard change'); ?>"></span></div>
<?php
echo $this->Form->input('category', array(
'options' => array(array_combine($typeCategory[$object['type']], $typeCategory[$object['type']])),
'options' => array_combine($possibleCategories, $possibleCategories),
'label' => false,
'selected' => $object['category'],
'error' => array('escape' => false),

View File

@ -1,12 +1,12 @@
<?php
echo $this->Form->create('Attribute', array('class' => 'inline-form inline-field-form', 'id' => 'Attribute_' . $object['id'] . '_type_form', 'url' => $baseurl . '/attributes/editField/' . $object['id']));
?>
<div class='inline-input inline-input-container'>
<div class="inline-input inline-input-container">
<div class="inline-input-accept inline-input-button inline-input-passive"><span class="fas fa-check" role="button" tabindex="0" aria-label="<?php echo __('Accept change'); ?>"></span></div>
<div class="inline-input-decline inline-input-button inline-input-passive"><span class="fas fa-times" role="button" tabindex="0" aria-label="<?php echo __('Discard change'); ?>"></span></div>
<?php
echo $this->Form->input('type', array(
'options' => array(array_combine($categoryDefinitions[$object['category']]['types'], $categoryDefinitions[$object['category']]['types'])),
'options' => $options,
'label' => false,
'selected' => $object['type'],
'error' => array('escape' => false),

View File

@ -3,12 +3,12 @@ if ($field === 'value') {
echo $this->element('Events/View/value_field', ['object' => $object['Attribute']]);
} elseif ($field === 'timestamp') {
echo $this->Time->date($value);
} else {
if ($value === 'No') {
echo '<input type="checkbox" disabled>';
} else if ($value === 'Yes') {
echo '<input type="checkbox" checked disabled>';
} elseif ($field === 'distribution') {
if ($value == 0) {
echo '<span class="red">' . $shortDist[$value] . '</span>';
} else {
echo nl2br(h($value), false);
echo $shortDist[$value];
}
} else {
echo nl2br(h($value), false);
}

View File

@ -140,22 +140,19 @@ echo $this->element('/genericElements/IndexTable/index_table', [
'Attribute.id'
],
'icon' => 'comment',
'complex_requirement' => [
'function' => function ($object) use ($isSiteAdmin, $me) {
return $isSiteAdmin || ($object['Event']['orgc_id'] !== $me['org_id']);
}
]
'title' => __('Add proposal'),
'complex_requirement' => function ($object) use ($isSiteAdmin, $me) {
return $isSiteAdmin || ($object['Event']['orgc_id'] !== $me['org_id']);
},
],
[
'onclick' => "deleteObject('shadow_attributes', 'delete', '[onclick_params_data_path]');",
'onclick_params_data_path' => 'Attribute.id',
'icon' => 'trash',
'title' => __('Propose deletion'),
'complex_requirement' => [
'function' => function ($object) use ($isSiteAdmin, $me) {
return $isSiteAdmin || ($object['Event']['orgc_id'] !== $me['org_id']);
}
]
'complex_requirement' => function ($object) use ($isSiteAdmin, $me) {
return $isSiteAdmin || ($object['Event']['orgc_id'] !== $me['org_id']);
}
],
[
'title' => __('Propose enrichment'),
@ -272,7 +269,6 @@ $class = $isSearch ? 'searchAttributes' : 'listAttributes';
echo $this->element('/genericElements/SideMenu/side_menu', ['menuList' => 'event-collection', 'menuItem' => $class]);
?>
<script>
// tooltips
$(function() {

View File

@ -15,7 +15,8 @@
'label' => __('From the following organisation(s)'),
'div' => 'input clear',
'rows' => 2,
'class' => 'input-xxlarge'));
'class' => 'input-xxlarge'
));
$typeFormInfo = $this->element('genericElements/Form/formInfo', [
'field' => [
'field' => 'type'
@ -44,7 +45,8 @@
<?php
echo $this->Form->input('to_ids', array(
'type' => 'checkbox',
'label' => __('Only find IOCs flagged as to IDS')
'label' => __('Only find IOCs flagged as to IDS'),
'div' => ['style' => 'margin-top:1em'],
));
echo $this->Form->input('first_seen', array(
'type' => 'text',
@ -58,13 +60,13 @@
));
?>
<div class="clear">
<h3><?php echo __('First seen and Last seen'); ?></h3>
<p><?php echo __('Attributes not having first seen or last seen set might not appear in the search'); ?></p>
</div>
<h3><?php echo __('First seen and Last seen'); ?></h3>
<p><?php echo __('Attributes not having first seen or last seen set might not appear in the search'); ?></p>
</div>
</fieldset>
<div id="bothSeenSliderContainer"></div>
<div class="clear"></div>
<button class="btn btn-primary" type="submit"><?= __("Search") ?></button>
<button class="btn btn-primary" style="margin-top: 1em" type="submit"><?= __("Search") ?></button>
<?php echo $this->Form->end(); ?>
</div>
<?php echo $this->element('form_seen_input'); ?>
@ -73,7 +75,7 @@ var category_type_mapping = <?= json_encode(array_map(function(array $value) {
return $value['types'];
}, $categoryDefinitions)); ?>;
function formTypeChanged() {
function searchFormTypeChanged() {
var $categorySelect = $('#AttributeCategory');
var alreadySelected = $categorySelect.val();
// empty the categories
@ -100,19 +102,13 @@ $(function() {
$("#AttributeCategory").change(function () {
formCategoryChanged("Attribute");
$("#AttributeType").chosen('destroy').chosen();
$("#AttributeType").trigger("chosen:updated");
}).change();
$("#AttributeType").change(function () {
formTypeChanged();
$("#AttributeCategory").chosen('destroy').chosen();
searchFormTypeChanged();
$("#AttributeCategory").trigger("chosen:updated");
}).change();
$('.input-xxlarge').keydown(function (e) {
if (e.ctrlKey && e.keyCode == 13) {
$('#AttributeSearchForm').submit();
}
});
});
</script>
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event-collection', 'menuItem' => 'searchAttributes'));

View File

@ -278,7 +278,7 @@
<td class="short" data-search="model" data-search-value="<?= h($item['AuditLog']['model']) . ':' . h($item['AuditLog']['model_id']) ?>">
<?php $title = isset($item['AuditLog']['event_info']) ? ' title="' . __('Event #%s: %s', $item['AuditLog']['event_id'], h($item['AuditLog']['event_info'])) . '"' : '' ?>
<?= isset($item['AuditLog']['model_link']) ? '<a href="' . h($item['AuditLog']['model_link']) . '"' . $title . '>' : '' ?>
<?= h($item['AuditLog']['model']) . ' #' . h($item['AuditLog']['model_id']) ?>
<?= h($item['AuditLog']['model']) . ($item['AuditLog']['model_id'] ? ' #' . h($item['AuditLog']['model_id']) : '') ?>
<?= isset($item['AuditLog']['model_link']) ? '</a>' : '' ?>
</td>
<td class="limitedWidth"><?= h($item['AuditLog']['title']) ?></td>

View File

@ -1,22 +1,21 @@
<div class="logs index">
<h2><?= __('Audit logs for event #%s', $event['Event']['id']) ?></h2>
<h2><?= __('Audit logs for event #%s', intval($event['Event']['id'])) ?></h2>
<div class="pagination">
<ul>
<?php
$paginator = $this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
$paginator .= $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
$paginator .= $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
$paginator = $this->LightPaginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
$paginator .= $this->LightPaginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
echo $paginator;
?>
<li><a href="<?= $baseurl . '/logs/event_index/' . h($event['Event']['id']) ?>"><?= __('Older logs') ?></a></li>
<li><a href="<?= $baseurl . '/logs/event_index/' . intval($event['Event']['id']) ?>"><?= __('Older logs') ?></a></li>
</ul>
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?= $this->Paginator->sort('created') ?></th>
<th><?= $this->Paginator->sort('user_id', __('User')) ?></th>
<th><?= $this->Paginator->sort('org_id', __('Org')) ?></th>
<th><?= $this->Paginator->sort('action') ?></th>
<th><?= $this->LightPaginator->sort('created') ?></th>
<th><?= $this->LightPaginator->sort('user_id', __('User')) ?></th>
<th><?= $this->LightPaginator->sort('org_id', __('Org')) ?></th>
<th><?= $this->LightPaginator->sort('action') ?></th>
<th><?= __('Model') ?></th>
<th><?= __('Title') ?></th>
<th><?= __('Change') ?></th>
@ -32,22 +31,16 @@
} ?></td>
<td class="short"><?= isset($item['Organisation']) ? $this->OrgImg->getOrgLogo($item, 24) : '' ?></td>
<td class="short"><?= h($item['AuditLog']['action_human']) ?></td>
<td class="short"><?= h($item['AuditLog']['model']) . ' #' . h($item['AuditLog']['model_id']) ?></td>
<td class="short"><?= h($item['AuditLog']['model']) . ' #' . intval($item['AuditLog']['model_id']) ?></td>
<td class="limitedWidth"><?= h($item['AuditLog']['title']) ?></td>
<td><?= $this->element('AuditLog/change', ['item' => $item]) ?></td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?= $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
));
?>
</p>
<div class="pagination">
<ul>
<?= $paginator ?>
<li><a href="<?= $baseurl . '/logs/event_index/' . h($event['Event']['id']) ?>"><?= __('Older logs') ?></a></li>
<li><a href="<?= $baseurl . '/logs/event_index/' . intval($event['Event']['id']) ?>"><?= __('Older logs') ?></a></li>
</ul>
</div>
</div>

View File

@ -43,6 +43,7 @@
'element' => empty($user_id) ? 'links' : 'generic_field',
'url' => $baseurl . '/users/view',
'url_params_data_paths' => ['User.id'],
'requirement' => $me['Role']['perm_admin'] || $me['Role']['perm_site_admin'],
],
[
'name' => __('Auth Key'),

View File

@ -31,7 +31,7 @@
),
'fields' => array(
array(
'name' => __('Id'),
'name' => __('ID'),
'sort' => 'id',
'class' => 'short',
'data_path' => 'id',
@ -76,14 +76,16 @@
'url_params_data_paths' => array(
'uuid'
),
'icon' => 'eye'
'icon' => 'eye',
'title' => __('View'),
),
array(
'url' => $baseurl . '/communities/requestAccess',
'url_params_data_paths' => array(
'uuid'
),
'icon' => 'comments'
'icon' => 'comments',
'title' => __('Request access'),
)
)
)
@ -91,12 +93,12 @@
echo '</div>';
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'sync', 'menuItem' => 'list_communities'));
?>
<script type="text/javascript">
<script>
var passedArgsArray = <?php echo $passedArgs; ?>;
if (passedArgsArray['context'] === undefined) {
passedArgsArray['context'] = 'vetted';
}
$(document).ready(function() {
$(function() {
$('#quickFilterButton').click(function() {
runIndexQuickFilter('/context:' + passedArgsArray['context']);
});

View File

@ -1,10 +1,10 @@
<div class="communities view">
<?php
$table_data = array();
$table_data[] = array('key' => __('Id'), 'value' => $community['id']);
$table_data[] = array('key' => __('ID'), 'value' => $community['id']);
$table_data[] = array('key' => __('UUID'), 'value' => $community['uuid']);
$table_data[] = array('key' => __('Name'), 'value' => $community['name']);
$table_data[] = array('key' => __('Url'), 'url' => $community['url']);
$table_data[] = array('key' => __('URL'), 'url' => $community['url']);
$table_data[] = array('key' => __('Host organisation'), 'value' => $community['org_name'] . ' (' . $community['org_uuid'] . ')');
$table_data[] = array(
'key' => __('Vetted by MISP-project'),
@ -24,7 +24,7 @@
}
if (!empty($community['pgp_key'])) {
$table_data[] = array(
'key' => __('GnuPG key'),
'key' => __('PGP key'),
'element' => 'genericElements/key',
'element_params' => array('key' => $community['pgp_key']),
);
@ -34,12 +34,13 @@
sprintf(
'%s<h2>%s</h2>%s',
sprintf(
'<img src="https://misp-project.org/org-logos/%s.png" title="%s" aria-label="%s" style="max-height: 100px;"/>',
'<img src="https://misp-project.org/org-logos/%s.png" title="%s" alt="%s" aria-label="%s" style="max-height: 100px;">',
h($community['org_uuid']),
h($community['org_name']),
h($community['org_name']),
h($community['org_name'])
),
__('Community ') . h($community['name']),
__('Community %s', h($community['name'])),
$this->element('genericElements/viewMetaTable', array('table_data' => $table_data))
)
);

View File

@ -30,7 +30,7 @@
);
$popover = '';
foreach ($relatedData as $k => $v) {
$popover .= '<span class="bold black">' . h($k) . '</span>: <span class="blue">' . h($v) . '</span><br>';
$popover .= '<b class="black">' . h($k) . '</b>: <span class="blue">' . h($v) . '</span><br>';
}
$link = $this->Html->link(
$relatedAttribute['id'],
@ -51,7 +51,7 @@
}
if ($i > 5) {
echo sprintf(
'<li class="no-side-padding correlation-collapse-button useCursorPointer linkButton %s" style="display:none;">%s</li>',
'<li class="no-side-padding correlation-collapse-button useCursorPointer linkButton %s" style="display:none;">%s</li> ',
$linkColour,
__('Collapse…')
);

View File

@ -1,3 +1,4 @@
<?php $canAccessDiscussion = $this->Acl->canAccess('threads', 'view') ?>
<div id="eventToggleButtons">
<button class="btn btn-inverse toggle-left qet" id="pivots_toggle" data-toggle-type="pivots">
<span class="fas fa-minus" title="<?php echo __('Toggle pivot graph');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle pivot graph');?>"></span><?php echo __('Pivots');?>
@ -20,12 +21,14 @@
<button class="btn btn-inverse toggle qet" id="eventreport_toggle" data-toggle-type="eventreport">
<span class="fas fa-plus" title="<?php echo __('Toggle reports');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle reports');?>"></span><?php echo __('Event reports');?>
</button>
<button class="btn btn-inverse toggle qet" id="attributes_toggle" data-toggle-type="attributes">
<button class="btn btn-inverse <?= $canAccessDiscussion ? 'toggle' : 'toggle-right' ?> qet" id="attributes_toggle" data-toggle-type="attributes">
<span class="fas fa-minus" title="<?php echo __('Toggle attributes');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle attributes');?>"></span><?php echo __('Attributes');?>
</button>
<?php if ($canAccessDiscussion): ?>
<button class="btn btn-inverse toggle-right qet" id="discussions_toggle" data-toggle-type="discussions">
<span class="fas fa-minus" title="<?php echo __('Toggle discussions');?>" role="button" tabindex="0" aria-label="<?php echo __('Toggle discussions');?>"></span><?php echo __('Discussion');?>
</button>
<?php endif; ?>
</div>
<br>
<br>
@ -83,9 +86,11 @@ $(document.body).tooltip({
$('.tooltip').not(":last").remove();
});
<?php if ($this->Acl->canAccess('threads', 'view')): ?>
$.get("<?php echo $baseurl; ?>/threads/view/<?php echo h($event['Event']['id']); ?>/true", function(data) {
$("#discussions_div").html(data);
});
<?php endif; ?>
$.get("<?php echo $baseurl; ?>/eventReports/index/event_id:<?= h($event['Event']['id']); ?>/index_for_event:1<?= $extended ? '/extended_event:1' : ''?>", function(data) {
$("#eventreport_content").html(data);

View File

@ -85,6 +85,7 @@
<?php
endif;
?>
<?php if ($includeOrgColumn): ?>
<td class="short">
<?php
if (!empty($extended)):
@ -92,6 +93,7 @@
endif;
?>
</td>
<?php endif; ?>
<td class="short"<?= $quickEdit('category') ?>>
<div class="inline-field-solid">
<?php echo h($object['category']); ?>
@ -218,7 +220,7 @@
h($feed['id']),
sprintf(
'<input type="hidden" name="data[Feed][eventid]" value="%s">',
h(json_encode($feed['event_uuids']))
h(json_encode($feed['event_uuids'] ?? []))
),
sprintf(
'<input type="submit" class="linkButton useCursorPointer" value="%s" data-toggle="popover" data-content="%s" data-trigger="hover" style="margin-right:3px;line-height:normal;vertical-align: text-top;">',
@ -287,14 +289,18 @@
<input type="checkbox" class="toids-toggle" id="toids_toggle_<?= $objectId ?>" aria-label="<?= __('Toggle IDS flag') ?>" title="<?= __('Toggle IDS flag') ?>"<?= $object['to_ids'] ? ' checked' : ''; ?><?= $mayModify ? '' : ' disabled' ?>>
</td>
<td class="short"<?= $quickEdit('distribution') ?>>
<div class="inline-field-solid<?= $object['distribution'] == 0 ? ' red' : '' ?>">
<div class="inline-field-solid">
<?php
if ($object['distribution'] == 4):
?>
<a href="<?php echo $baseurl;?>/sharing_groups/view/<?php echo h($object['sharing_group_id']); ?>"><?php echo h($object['SharingGroup']['name']);?></a>
<?php
else:
echo h($shortDist[$object['distribution']]);
if ($object['distribution'] == 0) {
echo '<span class="red">' . h($shortDist[$object['distribution']]) . '</span>';
} else {
echo h($shortDist[$object['distribution']]);
}
endif;
?>
</div>

View File

@ -43,6 +43,7 @@ $objectId = intval($object['id']);
<?php
endif;
?>
<?php if ($includeOrgColumn): ?>
<td class="short">
<?php
if ($extended):
@ -50,6 +51,7 @@ $objectId = intval($object['id']);
endif;
?>
</td>
<?php endif; ?>
<td colspan="<?= $includeRelatedTags ? 6 : 5 ?>">
<span class="bold"><?php echo __('Object name: ');?></span><?php echo h($object['name']);?>
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo $objectId ?>_collapsible"></span>
@ -81,14 +83,18 @@ $objectId = intval($object['id']);
</td>
<td colspan="4"></td>
<td class="shortish"<?= $quickEdit('distribution') ?>>
<div class="inline-field-solid<?= $object['distribution'] == 0 ? ' red' : '' ?>">
<div class="inline-field-solid">
<?php
if ($object['distribution'] == 4):
?>
<a href="<?php echo $baseurl; ?>/sharing_groups/view/<?php echo h($object['sharing_group_id']); ?>"><?php echo h($object['SharingGroup']['name']);?></a>
<?php
else:
echo h($shortDist[$object['distribution']]);
if ($object['distribution'] == 0) {
echo '<span class="red">' . h($shortDist[$object['distribution']]) . '</span>';
} else {
echo h($shortDist[$object['distribution']]);
}
endif;
?>
</div>
@ -136,17 +142,19 @@ $objectId = intval($object['id']);
</td>
</tr>
<?php
if (!empty($object['Attribute'])) {
if (!empty($object['Attribute'])) {
end($object['Attribute']);
$lastElement = key($object['Attribute']);
foreach ($object['Attribute'] as $attrKey => $attribute) {
echo $this->element('/Events/View/row_' . $attribute['objectType'], array(
'object' => $attribute,
'mayModify' => $mayModify,
'mayChangeCorrelation' => $mayChangeCorrelation,
'fieldCount' => $fieldCount,
'child' => $attrKey == $lastElement ? 'last' : true
));
echo $this->element('/Events/View/row_' . $attribute['objectType'], array(
'object' => $attribute,
'mayModify' => $mayModify,
'mayChangeCorrelation' => $mayChangeCorrelation,
'fieldCount' => $fieldCount,
'child' => $attrKey === $lastElement ? 'last' : true,
));
}
echo '<tr class="objectAddFieldTr"><td><span class="fa fa-plus-circle objectAddField" title="' . __('Add an Object Attribute') .'" data-popover-popup="' . $baseurl . '/objects/quickFetchTemplateWithValidObjectAttributes/' . $objectId .'"></span></td></tr>';
}
if ($mayModify) {
echo '<tr class="objectAddFieldTr"><td><span class="fa fa-plus-circle objectAddField" title="' . __('Add an Object Attribute') . '" data-popover-popup="' . $baseurl . '/objects/quickFetchTemplateWithValidObjectAttributes/' . $objectId . '"></span></td></tr>';
}
}

View File

@ -64,6 +64,7 @@
<?php
endif;
?>
<?php if ($includeOrgColumn): ?>
<td class="short">
<?php
if (isset($object['Org']['name'])) {
@ -71,6 +72,7 @@
}
?>
</td>
<?php endif; ?>
<td class="short">
<?php echo h($object['category']); ?>
</td>

View File

@ -65,13 +65,15 @@ switch ($object['type']) {
} else {
$confirm = __('According to AV scan, this file contains %s malware. Do you really want to download it?', $object['infected']);
}
} else if ($object['type'] === 'malware-sample') {
$confirm = __('You are going to download file that is probably malware. For your safety, the file is compressed in encrypted ZIP file. To decrypt use password `infected`.');
} else {
$confirm = null;
}
$controller = $object['objectType'] === 'proposal' ? 'shadow_attributes' : 'attributes';
$url = array('controller' => $controller, 'action' => 'download', $object['id']);
echo $this->Html->link($filename, $url, array('class' => $linkClass), $confirm);
$url = ['controller' => $controller, 'action' => 'download', $object['id']];
echo $this->Html->link($filename, $url, ['class' => $linkClass], $confirm);
} else {
echo $filename;
}

View File

@ -94,6 +94,7 @@
'columnised' => true,
'static_tags_only' => 1,
'tag_display_style' => Configure::check('MISP.full_tags_on_event_index') ? Configure::read('MISP.full_tags_on_event_index') : 1,
'highlightedTags' => $event['Event']['highlightedTags'] ?? [],
]);
?>
</td>

View File

@ -13,14 +13,13 @@
</td>
<td class="short" title="<?php echo h($element['description']); ?>">
<?php
$formSettings = array(
'type' => 'hidden',
'value' => $element['object_relation'],
'label' => false,
'div' => false
);
echo $this->Form->input('Attribute.' . $k . '.object_relation', $formSettings);
if ($action == 'edit') {
echo $this->Form->input('Attribute.' . $k . '.object_relation', array(
'type' => 'hidden',
'value' => $element['object_relation'],
'label' => false,
'div' => false
));
if ($action === 'edit') {
echo $this->Form->input('Attribute.' . $k . '.uuid', array(
'type' => 'hidden',
'label' => false,
@ -28,15 +27,14 @@
'value' => !empty($element['uuid']) ? $element['uuid'] : ''
));
}
$formSettings = array(
'type' => 'hidden',
'value' => $element['type'],
'label' => false,
'div' => false
);
echo $this->Form->input('Attribute.' . $k . '.type', $formSettings);
echo $this->Form->input('Attribute.' . $k . '.type', array(
'type' => 'hidden',
'value' => $element['type'],
'label' => false,
'div' => false
));
echo '<span class="bold">' . Inflector::humanize(h($element['object_relation'])) . '</span>';
if (!empty($template['ObjectTemplate']['requirements']['required']) && in_array($element['object_relation'], $template['ObjectTemplate']['requirements']['required'])) {
if (!empty($template['ObjectTemplate']['requirements']['required']) && in_array($element['object_relation'], $template['ObjectTemplate']['requirements']['required'], true)) {
echo '<span class="red" style="vertical-align: super;font-size: 8px;margin-left: 2px;" title="' . __('Required') . '"><i class="fas fa-asterisk"></i></span>';
}
echo '<br>' . h($element['type']);
@ -47,14 +45,13 @@
</td>
<td class="short">
<?php
$formSettings = array(
'options' => array_combine($element['categories'], $element['categories']),
'default' => $element['default_category'],
'style' => 'margin-bottom:0px;',
'label' => false,
'div' => false
);
echo $this->Form->input('Attribute.' . $k . '.category', $formSettings);
echo $this->Form->input('Attribute.' . $k . '.category', array(
'options' => array_combine($element['categories'], $element['categories']),
'default' => $element['default_category'],
'style' => 'margin-bottom:0px;width:180px',
'label' => false,
'div' => false
));
?>
</td>
<td class="short">
@ -85,7 +82,8 @@
'type' => 'checkbox',
'checked' => $element['disable_correlation'],
'label' => false,
'div' => false
'div' => false,
'disabled' => in_array($element['type'], Attribute::NON_CORRELATING_TYPES, true),
));
?>
</td>

View File

@ -4,6 +4,7 @@
Required Args:
- object => The object to be drawed
- attributes
Optional Args:
- template => The template used to compare the object with
@ -14,8 +15,6 @@
- meta_fields => The fields to be displayed from the object meta.
Default: [`id`, `name`, `description`, `distribution`, `template_version`]
- similar_object_similarity_amount => The amount of attributes both contained in `object` and the object to compare to
- simple_flattened_attribute => array containing the aggregate of multiple fields used for the comparison. Has the format:
array(
'object_relation1.type1.val1' => attribute_id1,
@ -47,8 +46,8 @@ if (!isset($simple_flattened_attribute_noval) || !isset($simple_flattened_attrib
$simple_flattened_attribute_noval = array();
$simple_flattened_attribute = array();
foreach ($target_comparison_object['Attribute'] as $id => $attribute) {
$cur_flat = h($attribute['object_relation']) . '.' . h($attribute['type']) . '.' .h($attribute['value']);
$cur_flat_noval = h($attribute['object_relation']) . '.' . h($attribute['type']);
$cur_flat = $attribute['object_relation'] . '.' . $attribute['type'] . '.' .$attribute['value'];
$cur_flat_noval = $attribute['object_relation'] . '.' . $attribute['type'];
$simple_flattened_attribute[$cur_flat] = $id;
$simple_flattened_attribute_noval[$cur_flat_noval] = $id;
}
@ -88,18 +87,16 @@ if (!isset($simple_flattened_attribute_noval) || !isset($simple_flattened_attrib
<?php if (isset($merge_button_functionname)): ?>
<input type="button" class="btn <?php echo $btn_style; ?>" onclick="<?php echo h($merge_button_functionname); ?>(this)" data-objectid="<?php echo h($object['Object']['id']) ?>" data-updatetemplate="<?php echo $temp_comparison == 'below' ? 'true' : 'false'; ?>" value="<?php echo $temp_text; ?>" <?php echo $temp_comparison == 'above' ? 'disabled' : ''; ?>>
<?php endif; ?>
<?php if (isset($similar_object_similarity_amount[$object['Object']['id']])): ?>
<span class="badge badge-inverse" style="position: absolute; right: 0;" title="<?php echo __('Similarity amount') ?>">
<?php echo number_format(intval($similar_object_similarity_amount[$object['Object']['id']]) / count($data['Attribute']), 2)*100 . '%'; ?>
</span>
<?php endif; ?>
<span class="badge badge-inverse" style="position: absolute; right: 0;" title="<?php echo __('Similarity amount') ?>">
<?php echo number_format(intval($object['Object']['similarity_amount']) / count($attributes), 2)*100 . '%'; ?>
</span>
</div>
<?php foreach ($meta_fields as $field): ?>
<?php if (isset($object['Object'][$field])): ?>
<?php switch ($field):
case 'id': ?>
<div>
<span class="bold"><?php echo h(Inflector::humanize($field)) . ':'; ?></span>
<span class="bold">ID</span>
<a href="<?php echo $baseurl . '/objects/edit/' . h($object['Object'][$field]); ?>" style="color: white;"><?php echo h($object['Object'][$field]); ?></a>
</div>
<?php break; ?>
@ -147,8 +144,8 @@ if (!isset($simple_flattened_attribute_noval) || !isset($simple_flattened_attrib
$classname = '';
$title = '';
if ($flag_comparison_enabled) { // Comparison enabled
$simple_flattened_similar_attribute = h($attribute['object_relation']) . '.' . h($attribute['type']) . '.' .h($attribute['value']);
$simple_flattened_similar_attribute_noval = h($attribute['object_relation']) . '.' . h($attribute['type']);
$simple_flattened_similar_attribute = $attribute['object_relation'] . '.' . $attribute['type'] . '.' .$attribute['value'];
$simple_flattened_similar_attribute_noval = $attribute['object_relation'] . '.' . $attribute['type'];
$flattened_ids_in_similar_object[$simple_flattened_similar_attribute_noval] = $attribute['id'];
if (
isset($simple_flattened_attribute_noval[$simple_flattened_similar_attribute_noval])
@ -199,7 +196,7 @@ if (!isset($simple_flattened_attribute_noval) || !isset($simple_flattened_attrib
?>
<?php if (!empty($attribute_ids_to_inject)): ?>
<?php foreach ($attribute_ids_to_inject as $i => $attribute_id): ?>
<?php $attribute = $data['Attribute'][$attribute_id]; ?>
<?php $attribute = $attributes[$attribute_id]; ?>
<tr class="success" title="<?php echo __('This attribute will be added to this similar object during the merge.'); ?>" style="<?php echo $i == 0 ? 'border-top: 2px dashed #3465a4' : ''; ?>">
<?php foreach ($attribute_fields as $field): ?>
<?php if (isset($attribute[$field])): ?>

View File

@ -1,6 +1,6 @@
<div class="object_value_field">
<?php
if ($element['type'] == 'malware-sample' || $element['type'] == 'attachment'):
if ($element['type'] === 'malware-sample' || $element['type'] === 'attachment'):
if ($action != 'edit'):
echo $this->Form->file('Attribute.' . $k . '.Attachment', array(
'class' => 'Attribute_attachment'

View File

@ -24,100 +24,9 @@
$full = $isAclTagger && $tagAccess && empty($static_tags_only);
$fullLocal = $isAclTagger && $localTagAccess && empty($static_tags_only);
$tagData = "";
foreach ($tags as $tag) {
if (empty($tag['Tag'])) {
$tag['Tag'] = $tag;
}
if (empty($tag['Tag']['colour'])) {
$tag['Tag']['colour'] = '#0088cc';
}
$aStyle = 'background-color:' . h($tag['Tag']['colour']) . ';color:' . $this->TextColour->getTextColour($tag['Tag']['colour']);
$aClass = 'tag nowrap';
$aText = trim($tag['Tag']['name']);
$aTextModified = null;
if (isset($tag_display_style)) {
if ($tag_display_style == 1) {
// default behaviour, do nothing for now
} else if ($tag_display_style == 2) {
$separator_pos = strpos($aText, ':');
if ($separator_pos !== false) {
$aTextModified = substr($aText, $separator_pos + 1);
$value_pos = strpos($aTextModified, '=');
if ($value_pos !== false) {
$aTextModified = substr($aTextModified, $value_pos + 1);
$aTextModified = trim($aTextModified, '"');
}
$aTextModified = h($aTextModified);
}
} else if ($tag_display_style === 0 || $tag_display_style === '0') {
$aTextModified = '&nbsp;';
}
}
$aText = h($aText);
$span_scope = !empty($hide_global_scope) ? '' : sprintf(
'<span class="%s" title="%s" aria-label="%s"><i class="fas fa-%s"></i></span>',
'black-white tag',
!empty($tag['local']) ? __('Local tag') : __('Global tag'),
!empty($tag['local']) ? __('Local tag') : __('Global tag'),
!empty($tag['local']) ? 'user' : 'globe-americas'
);
$span_relationship_type = empty($tag['relationship_type']) ? '' : sprintf(
'<span class="tag nowrap white" style="background-color:black" title="%s" aria-label="%s">%s:</span>',
h($tag['relationship_type']),
h($tag['relationship_type']),
h($tag['relationship_type'])
);
if (!empty($tag['Tag']['id'])) {
$span_tag = sprintf(
'<a href="%s" style="%s" class="%s"%s data-tag-id="%s">%s</a>',
$baseurl . $searchUrl . intval($tag['Tag']['id']),
$aStyle,
$aClass,
isset($aTextModified) ? ' title="' . $aText . '"' : '',
intval($tag['Tag']['id']),
isset($aTextModified) ? $aTextModified : $aText
);
} else {
$span_tag = sprintf(
'<span style="%s" class="%s">%s</span>',
$aStyle,
$aClass,
$aText
);
}
$span_delete = '';
$span_relationship = '';
if ($full || ($fullLocal && $tag['Tag']['local'])) {
$span_relationship = sprintf(
'<a class="%s" title="%s" role="button" tabindex="0" aria-label="%s" href="%s"><i class="fas fa-project-diagram"></i></a>',
'black-white tag noPrint modal-open',
__('Modify Tag Relationship'),
__('Modify relationship for tag %s', h($tag['Tag']['name'])),
sprintf(
'%s/tags/modifyTagRelationship/%s/%s',
$baseurl,
h($scope),
h($tag['id'])
)
);
$span_delete = sprintf(
'<span class="%s" title="%s" role="%s" tabindex="%s" aria-label="%s" onclick="%s">x</span>',
'black-white tag useCursorPointer noPrint',
__('Remove tag'),
"button",
"0",
__('Remove tag %s', h($tag['Tag']['name'])),
sprintf(
"removeObjectTagPopup(this, '%s', %s, %s)",
$scope,
$id,
intval($tag['Tag']['id'])
)
);
}
$tagData .= '<span class="tag-container nowrap">' . $span_scope . $span_relationship_type . $span_tag . $span_relationship . $span_delete . '</span> ';
}
$buttonData = array();
$tag_display_style = $tag_display_style ?? 1;
$buttonData = [];
if ($full) {
$buttonData[] = sprintf(
'<button title="%s" role="button" tabindex="0" aria-label="%s" class="%s" data-popover-popup="%s">%s</button>',
@ -138,6 +47,66 @@
'<i class="fas fa-user"></i> <i class="fas fa-plus"></i>'
);
}
$highlightedTagsString = "";
if (isset($highlightedTags) && $scope === 'event') {
foreach ($highlightedTags as $hTaxonomy) {
$hButtonData = [];
if ($full) {
$hButtonData[] = sprintf(
'<button title="%s" role="button" tabindex="0" aria-label="%s" class="%s" data-popover-popup="%s">%s</button>',
__('Add a tag'),
__('Add a tag'),
'addTagButton addButton btn btn-inverse noPrint',
sprintf($baseurl . '/tags/selectTag/%u/%u/event', $id, $hTaxonomy['taxonomy']['Taxonomy']['id']),
'<i class="fas fa-globe-americas"></i> <i class="fas fa-plus"></i>'
);
}
$hTags = "";
foreach ($hTaxonomy['tags'] as $hTag) {
$hTags .= $this->element('rich_tag', [
'tag' => $hTag,
'tagAccess' => $tagAccess,
'localTagAccess' => $localTagAccess,
'searchUrl' => $searchUrl,
'scope' => $scope,
'id' => $id,
'tag_display_style' => 2
]);
}
$highlightedTagsString .= sprintf(
'<tr><td style="font-weight: bold;text-transform: uppercase;">%s</td></td><td>%s</td><td>%s</td></tr>',
$hTaxonomy['taxonomy']['Taxonomy']['namespace'],
$hTags,
$hButtonData ? '<span style="white-space:nowrap">' . implode('', $hButtonData) . '</span>' : ''
);
foreach ($tags as $k => $tag) {
foreach ($hTaxonomy['tags'] as $hTag) {
if ($tag['Tag']['name'] === $hTag['Tag']['name']) {
unset($tags[$k]);
}
}
}
}
if (!empty($highlightedTagsString)) {
$tagData .= sprintf('<table>%s</table>', $highlightedTagsString);
}
}
foreach ($tags as $tag) {
$tagData .= $this->element('rich_tag', [
'tag' => $tag,
'tagAccess' => $tagAccess,
'localTagAccess' => $localTagAccess,
'searchUrl' => $searchUrl,
'scope' => $scope,
'id' => $id ?? null,
'tag_display_style' => $tag_display_style
]);
}
if (!empty($buttonData)) {
$tagData .= '<span style="white-space:nowrap">' . implode('', $buttonData) . '</span>';
}

View File

@ -2,7 +2,7 @@
$mayChangeCorrelation = $this->Acl->canDisableCorrelation($event);
$possibleAction = $mayModify ? 'attribute' : 'shadow_attribute';
$all = isset($this->params->params['paging']['Event']['page']) && $this->params->params['paging']['Event']['page'] == 0;
$fieldCount = 11;
$fieldCount = 10;
?>
<div class="pagination">
<ul>
@ -81,7 +81,7 @@
<tr>
<?php
if ($extended || ($mayModify && !empty($event['objects']))):
$fieldCount += 1;
$fieldCount++;
?>
<th><input class="select_all" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all attributes/proposals on current page');?>" onclick="toggleAllAttributeCheckboxes()"></th>
<?php
@ -94,7 +94,9 @@
<?php if ($extended): ?>
<th class="event_id"><?php echo $this->Paginator->sort('event_id', __('Event'));?></th>
<?php endif; ?>
<?php if ($includeOrgColumn): $fieldCount++; ?>
<th><?php echo $this->Paginator->sort('Org.name', __('Org')); ?>
<?php endif; ?>
<th><?php echo $this->Paginator->sort('category');?></th>
<th><?php echo $this->Paginator->sort('type');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
@ -103,7 +105,7 @@
if ($includeRelatedTags) {
echo sprintf('<th>%s</th>', __('Related Tags'));
}
$fieldCount += 1;
$fieldCount++;
?>
<th><?php echo __('Galaxies');?></th>
<th><?php echo $this->Paginator->sort('comment');?></th>
@ -120,7 +122,7 @@
'<th>%s</th>',
__('SightingDB')
);
$fieldCount += 1;
$fieldCount++;
}
if ($includeDecayScore) {
echo sprintf(
@ -128,7 +130,7 @@
__('Decaying Score'),
__('Score')
);
$fieldCount += 1;
$fieldCount++;
}
?>
<th class="actions"><?php echo __('Actions');?></th>

View File

@ -55,9 +55,18 @@
'id' => 'create-button',
'title' => $possibleAction === 'attribute' ? __('Add attribute') : __('Add proposal'),
'fa-icon' => 'plus',
'class' => 'last modal-open',
'class' => $mayModify ? 'modal-open' : 'modal-open last',
'url' => $baseurl . '/' . $possibleAction . 's/add/' . $eventId,
),
array(
'id' => 'object-button',
'title' => __('Add Object'),
'fa-icon' => 'list',
'class' => 'last',
'onClick' => 'popoverPopupNew',
'onClickParams' => ['this', "$baseurl/objectTemplates/objectMetaChoice/$eventId"],
'requirement' => $mayModify,
),
array(
'id' => 'multi-edit-button',
'title' => __('Edit selected Attributes'),
@ -147,14 +156,6 @@
),
array(
'children' => array(
array(
'id' => 'template-button',
'title' => __('Populate using a template'),
'fa-icon' => 'list',
'onClick' => 'getPopup',
'onClickParams' => array($eventId, 'templates', 'templateChoices'),
'requirement' => $mayModify
),
array(
'id' => 'freetext-button',
'title' => __('Populate using the freetext import tool'),
@ -206,9 +207,10 @@
'title' => __('Show SightingDB lookup results'),
'fa-icon' => 'binoculars',
'text' => __('SightingDB'),
'active' => empty($includeSightingdb) ? false : true,
'active' => !empty($includeSightingdb),
'onClick' => 'toggleBoolFilter',
'onClickParams' => array('includeSightingdb')
'onClickParams' => array('includeSightingdb'),
'requirement' => $sightingsDbEnabled,
),
array(
'id' => 'show_attribute_context',

View File

@ -1,11 +1,13 @@
<?php
$seed = 's-' . mt_rand();
$fieldData['type'] = 'select';
if (empty($fieldData['class'])) {
$fieldData['class'] = $seed;
} else {
$fieldData['class'] .= ' ' . $seed;
if (!empty($fieldData['picker'])) {
$seed = 's-' . mt_rand();
if (empty($fieldData['class'])) {
$fieldData['class'] = $seed;
} else {
$fieldData['class'] .= ' ' . $seed;
}
}
echo $this->Form->input($fieldData['field'], $fieldData);
@ -13,8 +15,7 @@ if (!empty($params['description'])) {
echo sprintf('<small class="clear form-field-description apply_css_arrow">%s</small>', h($params['description']));
}
?>
<?php if (!empty($fieldData['picker'])) : ?>
<?php if (!empty($fieldData['picker'])): ?>
<script>
var chosenOptions = <?= JsonTool::encode($fieldData['_chosenOptions'] ?? []) ?>;
$('select.<?= $seed ?>').chosen(chosenOptions)

View File

@ -105,9 +105,9 @@
$extracted_value = Hash::extract($row, $path);
if (!empty($extracted_value)) {
if (is_string($k)) { // associative array, use cake's parameter
$temp[] = h($k) . ':' . h($extracted_value[0]);
$temp[] = h($k) . ':' . urlencode(h($extracted_value[0]));
} else {
$temp[] = h($extracted_value[0]);
$temp[] = urlencode(h($extracted_value[0]));
}
}
}

View File

@ -2,14 +2,13 @@
$quickedit = isset($field['quickedit']) && $field['quickedit'];
if ($quickedit) {
$object = Hash::extract($row, $field['data']['object']['value_path']);
$event = Hash::extract($row, 'Event');
$objectId = h($object['id']);
$scope = $field['data']['scope'];
}
$distributionLevel = (Hash::extract($row, $field['data_path'])[0]);
$distributionLevel = Hash::extract($row, $field['data_path'])[0];
echo sprintf('<div %s>', $quickedit ? sprintf(
echo sprintf('<div%s>', $quickedit ? sprintf(
" onmouseenter=\"quickEditHover(this, '%s', %s, 'distribution');\"",
$scope,
$objectId
@ -20,8 +19,8 @@ if ($quickedit) {
}
echo sprintf(
'<span class="%s bold">%s</span>',
$distributionLevel == 0 ? 'red' : '',
'<span class="%s">%s</span>',
$distributionLevel == 0 ? 'red bold' : '',
$distributionLevel != 4 ? $distributionLevels[$distributionLevel] :
sprintf(
'<a href="%s/sharing_groups/view/%s">%s</a>',

View File

@ -4,9 +4,20 @@
foreach ($fields as $k => $header) {
if (!isset($header['requirement']) || $header['requirement']) {
$header_data = '';
if (!empty($header['icon'])) {
$header['name'] = sprintf(
'<i class="fas fa-%s"></i> %s',
h($header['icon']),
empty($header['name']) ? '' : h($header['name'])
);
} else {
if (!empty($header['name'])) {
$header['name'] = h($header['name']);
}
}
if (!empty($header['sort'])) {
if (!empty($header['name'])) {
$header_data = $paginator->sort($header['sort'], $header['name']);
$header_data = $paginator->sort($header['sort'], $header['name'], ['escape' => false]);
} else {
$header_data = $paginator->sort($header['sort']);
}
@ -19,7 +30,7 @@
empty($header['select_all_function']) ? 'onclick="toggleAllAttributeCheckboxes();"' : 'onclick="' . $header['select_all_function'] . '"'
);
} else {
$header_data = h($header['name']);
$header_data = $header['name'];
}
}
$classes = [];

View File

@ -1,6 +1,6 @@
<?php
if (!isset($data['requirement']) || $data['requirement']) {
if (!empty($data['onClick']) || empty($data['url'])) {
if (!empty($data['onClick'])) {
$onClickParams = array();
if (!empty($data['onClickParams'])) {
foreach ($data['onClickParams'] as $param) {
@ -15,11 +15,11 @@
$onClick = sprintf(
'onclick="%s%s"',
(empty($data['url'])) ? 'event.preventDefault();' : '',
(!empty($data['onClick']) ? sprintf(
sprintf(
'%s(%s)',
h($data['onClick']),
$onClickParams
) : '')
)
);
}
$dataFields = array();

View File

@ -1,13 +1,13 @@
<?php
if (!isset($data['requirement']) || $data['requirement']) {
$elements = '';
foreach ($data['children'] as $element) {
$elements .= $this->element('/genericElements/ListTopBar/element_' . (empty($element['type']) ? 'simple' : h($element['type'])), array('data' => $element));
}
echo sprintf(
'<div %s class="btn-group">%s</div>',
(!empty($data['id'])) ? 'id="' . h($data['id']) . '"' : '',
$elements
);
if (!isset($data['requirement']) || $data['requirement']) {
$elements = [];
foreach ($data['children'] as $element) {
$elements[] = $this->element('/genericElements/ListTopBar/element_' . (empty($element['type']) ? 'simple' : $element['type']), array('data' => $element));
}
?>
echo sprintf(
'<div%s class="btn-group">%s</div>',
(!empty($data['id'])) ? ' id="' . h($data['id']) . '"' : '',
implode('', $elements)
);
}

View File

@ -1,10 +1,7 @@
<div class="btn-toolbar" style="margin:0 10px;">
<?php
$groups = '';
foreach ($data['children'] as $group) {
$groups .= $this->element('/genericElements/ListTopBar/group_' . (empty($group['type']) ? 'simple' : h($group['type'])), array('data' => $group));
echo $this->element('/genericElements/ListTopBar/group_' . (empty($group['type']) ? 'simple' : $group['type']), array('data' => $group));
}
echo sprintf(
'<div class="btn-toolbar" style="margin:0px 10px;">%s</div>',
$groups
);
?>
</div>

View File

@ -1,6 +1,6 @@
<?php
$this->set('menuItem', $menuItem);
$divider = $this->element('/genericElements/SideMenu/side_menu_divider');
$divider = '<li class="divider"></li>';
?>
<div class="actions sideMenu">
<ul class="nav nav-list">
@ -119,7 +119,7 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'add',
'url' => '/eventReports/add/' . h($event['Event']['id']),
'url' => '/eventReports/add/' . $eventId,
'text' => __('Add Event Report')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
@ -163,34 +163,34 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
));
}
echo $divider;
$publishButtons = ' hidden';
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && $mayPublish) {
$publishButtons = "";
if ($isSiteAdmin || $mayPublish) {
echo '<div id="hiddenSideMenuData" class="hidden" data-event-id="' . $eventId . '"></div>';
$isPublished = isset($event['Event']['published']) && 0 == $event['Event']['published'];
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($eventId, 'alert')
),
'class' => 'publishButtons not-published' . ($isPublished ? '' : ' hidden'),
'text' => __('Publish Event')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($eventId, 'publish')
),
'class' => 'publishButtons not-published' . ($isPublished ? '' : ' hidden'),
'text' => __('Publish (no email)')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($eventId, 'unpublish')
),
'class' => (isset($event['Event']['published']) && (1 == $event['Event']['published'] && $mayModify)) ? '' : 'hidden',
'text' => __('Unpublish')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($eventId, 'alert')
),
'class' => 'publishButtons not-published' . $publishButtons,
'text' => __('Publish Event')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($eventId, 'publish')
),
'class' => 'publishButtons not-published' . $publishButtons,
'text' => __('Publish (no email)')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($eventId, 'unpublish')
),
'class' => (isset($event['Event']['published']) && (1 == $event['Event']['published'] && $mayModify)) ? '' : 'hidden',
'text' => __('Unpublish')
));
if (!empty($event['Event']['published']) && $me['Role']['perm_sighting']) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
@ -652,10 +652,6 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
'url' => $baseurl . '/user_settings/setSetting',
'text' => __('Set Setting')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => $baseurl . '/dashboards',
'text' => __('Dashboard')
));
if ($this->Acl->canAccess('organisations', 'index')) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'indexOrg',
@ -734,6 +730,11 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
'url' => $baseurl . '/pages/display/doc/general',
'text' => __('User Guide')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'categoriesAndTypes',
'url' => $baseurl . '/pages/display/doc/categories_and_types',
'text' => __('Categories & Types'),
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => $baseurl . '/users/terms',
'text' => __('Terms & Conditions')
@ -1093,25 +1094,29 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
case 'logs':
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => $baseurl . '/admin/logs/index',
'url' => $baseurl . '/logs/index',
'text' => __('Application Logs')
));
if (Configure::read('MISP.log_new_audit')) {
if (Configure::read('MISP.log_new_audit') && $isAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'listAuditLogs',
'url' => $baseurl . '/admin/audit_logs/index',
'text' => __('Audit Logs'),
));
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'listAccessLogs',
'url' => $baseurl . '/admin/access_logs/index',
'text' => __('Access Logs'),
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => $baseurl . '/admin/logs/search',
'text' => __('Search Logs')
));
if ($isSiteAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'listAccessLogs',
'url' => $baseurl . '/admin/access_logs/index',
'text' => __('Access Logs'),
));
}
if ($isAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => $baseurl . '/admin/logs/search',
'text' => __('Search Logs')
));
}
break;
case 'threads':
@ -1726,7 +1731,6 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
}
}
break;
}
?>
</ul>

View File

@ -1 +0,0 @@
<li class="divider"></li>

View File

@ -23,7 +23,7 @@
sprintf(
'<input type="hidden" name="data[Feed][eventid]" value="%s">
<input type="submit" class="linkButton useCursorPointer" value="%s" data-toggle="popover" data-content="%s" data-trigger="hover">',
h(json_encode($relatedFeed['event_uuids'])),
h(json_encode($relatedFeed['event_uuids'] ?? [])),
h($relatedFeed['name']) . ' (' . $relatedFeed['id'] . ')',
h($popover)
)

View File

@ -1,11 +1,14 @@
<div class="alert alert-error" style="margin-bottom: 0">
<?php
foreach ($field['warnings'] as $key => $values) {
$values = is_array($values) ? $values : [$values];
foreach ($values as $value) {
echo sprintf(
'<span class="bold">%s</span>: <p style="margin-left:10px;">%s</p>',
h($key),
h($value)
);
}
foreach ($field['warnings'] as $key => $values) {
$values = is_array($values) ? $values : [$values];
foreach ($values as $value) {
echo sprintf(
'<b>%s</b>: <p style="margin-left:10px;">%s</p>',
h($key),
h($value)
);
}
}
?>
</div>

View File

@ -78,8 +78,7 @@ function setupChosen(id, redrawChosen) {
fn = window[fn];
submitFunction(this, fn);
} else {
select = this;
$select = $(select);
var $select = $(this);
var endpoint;
if (selected !== undefined) {
endpoint = selected.selected;
@ -87,7 +86,7 @@ function setupChosen(id, redrawChosen) {
endpoint = $(event.target).val();
}
if (endpoint === '') {
$wrapper = $select.closest('div').find('div.generic-picker-wrapper');
var $wrapper = $select.closest('div').find('div.generic-picker-wrapper');
$wrapper.hide(0);
} else {
$select.data('endpoint', endpoint);
@ -112,6 +111,13 @@ function setupChosen(id, redrawChosen) {
} else {
$elem.filter('[autofocus]').trigger('chosen:activate');
}
// Hide popover when pressing ESC on closed chosen
$chosenContainer.on('keydown', function (e) {
if (e.keyCode === 27 && !$chosenContainer.hasClass('chosen-with-drop')) {
execAndClose($elem);
}
});
}
var debounceTimer;

View File

@ -253,15 +253,18 @@
'url' => $baseurl . '/users/statistics'
),
array(
'type' => 'separator'
'type' => 'separator',
'requirement' => $this->Acl->canAccess('threads', 'index'),
),
array(
'text' => __('List Discussions'),
'url' => $baseurl . '/threads/index'
'url' => $baseurl . '/threads/index',
'requirement' => $this->Acl->canAccess('threads', 'index'),
),
array(
'text' => __('Start Discussion'),
'url' => $baseurl . '/posts/add'
'url' => $baseurl . '/posts/add',
'requirement' => $this->Acl->canAccess('posts', 'add'),
)
)
),
@ -281,12 +284,12 @@
'requirement' => $this->Acl->canAccess('servers', 'import'),
),
array(
'text' => __('List Servers'),
'text' => __('Remote Servers'),
'url' => $baseurl . '/servers/index',
'requirement' => $this->Acl->canAccess('servers', 'index'),
),
array(
'text' => __('List Feeds'),
'text' => __('Feeds'),
'url' => $baseurl . '/feeds/index',
'requirement' => $this->Acl->canAccess('feeds', 'index'),
),
@ -296,17 +299,12 @@
'requirement' => $this->Acl->canAccess('feeds', 'searchCaches'),
),
array(
'text' => __('List SightingDB Connections'),
'text' => __('SightingDB'),
'url' => $baseurl . '/sightingdb/index',
'requirement' => $this->Acl->canAccess('sightingdb', 'index'),
),
array(
'text' => __('Add SightingDB Connection'),
'url' => $baseurl . '/sightingdb/add',
'requirement' => $this->Acl->canAccess('sightingdb', 'add'),
),
array(
'text' => __('List Communities'),
'text' => __('Communities'),
'url' => $baseurl . '/communities/index',
'requirement' => $this->Acl->canAccess('communities', 'index'),
),
@ -398,31 +396,18 @@
),
array(
'type' => 'separator',
'requirement' => Configure::read('MISP.background_jobs') && $isSiteAdmin
'requirement' => $isSiteAdmin
),
array(
'text' => __('Jobs'),
'url' => $baseurl . '/jobs/index',
'requirement' => Configure::read('MISP.background_jobs') && $isSiteAdmin
),
array(
'type' => 'separator',
'requirement' => Configure::read('MISP.background_jobs') && $isSiteAdmin
),
array(
'text' => __('Scheduled Tasks'),
'url' => $baseurl . '/tasks',
'requirement' => Configure::read('MISP.background_jobs') && $isSiteAdmin
),
array(
'text' => __('Event Block Rules'),
'url' => $baseurl . '/servers/eventBlockRule',
'requirement' => $isSiteAdmin
),
array(
'type' => 'separator',
'requirement' => Configure::read('MISP.enableEventBlocklisting') !== false && $isSiteAdmin
),
array(
'html' => sprintf(
'<span style="display: flex;"><span>%s</span><span class="label label-info" style="margin-left: auto;">%s</span></span>',
@ -434,29 +419,20 @@
),
array(
'type' => 'separator',
'requirement' => Configure::read('MISP.enableEventBlocklisting') !== false && $isSiteAdmin
'requirement' => $isSiteAdmin
),
array(
'text' => __('Blocklist Event'),
'url' => $baseurl . '/eventBlocklists/add',
'requirement' => Configure::read('MISP.enableEventBlocklisting') !== false && $isSiteAdmin
'text' => __('Event Block Rules'),
'url' => $baseurl . '/servers/eventBlockRule',
'requirement' => $isSiteAdmin
),
array(
'text' => __('Manage Event Blocklists'),
'text' => __('Event Blocklists'),
'url' => $baseurl . '/eventBlocklists',
'requirement' => Configure::read('MISP.enableEventBlocklisting') !== false && $isSiteAdmin
),
array(
'type' => 'separator',
'requirement' => Configure::read('MISP.enableEventBlocklisting') !== false && $isSiteAdmin
),
array(
'text' => __('Blocklist Organisation'),
'url' => $baseurl . '/orgBlocklists/add',
'requirement' => Configure::read('MISP.enableOrgBlocklisting') !== false && $isSiteAdmin
),
array(
'text' => __('Manage Org Blocklists'),
'text' => __('Org Blocklists'),
'url' => $baseurl . '/orgBlocklists',
'requirement' => Configure::read('MISP.enableOrgBlocklisting') !== false && $isSiteAdmin
),
@ -487,20 +463,22 @@
'children' => array(
array(
'text' => __('Application Logs'),
'url' => $baseurl . '/admin/logs/index'
'url' => $baseurl . '/logs/index'
),
array(
'text' => __('Audit Logs'),
'url' => $baseurl . '/admin/audit_logs/index',
'requirement' => Configure::read('MISP.log_new_audit'),
'requirement' => Configure::read('MISP.log_new_audit') && $isAdmin,
),
array(
'text' => __('Access Logs'),
'url' => $baseurl . '/admin/access_logs/index',
'requirement' => $isSiteAdmin
),
array(
'text' => __('Search Logs'),
'url' => $baseurl . '/admin/logs/search',
'requirement' => $isAdmin
)
)
),

View File

@ -2,7 +2,7 @@
echo '<div style="border:1px solid #dddddd; margin-top:1px; width:100%; padding:10px">';
echo sprintf(
'<p>%s</p><p>%s</p>',
__('This is the correlation management interface. Its goal is to provide youwith information about the currently used correlation engine as well as the data stores of currently dormant engines.'),
__('This is the correlation management interface. Its goal is to provide you with information about the currently used correlation engine as well as the data stores of currently dormant engines.'),
__('You will also find management tools for the various engines below, make sure that you keep an eye on the disk requirements as well as the exhaustion of IDs and recorrelate the instance when needed.')
);
echo sprintf(

View File

@ -19,32 +19,28 @@
),
[...]
);
*/
function highlightAndSanitize($dirty, $toHighlight, $colorType = 'success')
{
if (is_array($dirty)) {
$arraySane = array();
foreach ($dirty as $i => $item) {
if (in_array($item, $toHighlight)) {
$arraySane[] = sprintf('<span class="label label-%s">', $colorType) . h($item) . '</span>';
} else {
$arraySane[] = h($item);
}
function highlightAndSanitize($dirty, $toHighlight, $colorType = 'success')
{
if (is_array($dirty)) {
$arraySane = array();
foreach ($dirty as $i => $item) {
if (in_array($item, $toHighlight)) {
$arraySane[] = sprintf('<span class="label label-%s">', $colorType) . h($item) . '</span>';
} else {
$arraySane[] = h($item);
}
return $arraySane;
} else {
$sane = h($dirty);
$sane = str_replace($toHighlight, sprintf('<span class="label label-%s">', $colorType) . h($toHighlight) . '</span>', $sane);
return $sane;
}
return $arraySane;
} else {
$sane = h($dirty);
$sane = str_replace($toHighlight, sprintf('<span class="label label-%s">', $colorType) . h($toHighlight) . '</span>', $sane);
return $sane;
}
?>
}
<?php
$hasAtLeastOneCriticalWarning = false;
foreach ($dbSchemaDiagnostics as $tableName => $tableDiagnostic) {
foreach ($tableDiagnostic as $i => $columnDiagnostic) {
@ -171,12 +167,13 @@
__('Updates are locked due to to many update fails') : sprintf(__('Updates unlocked in %s'), h($humanReadableTime)))
: __('Updates are not locked'),
$updateLocked ? 'times' : 'check'
);
);
$validDataSource = in_array($dataSource, ['Database/Mysql', 'Database/MysqlExtended'], true);
echo sprintf('<span class="label label-%s" title="%s" style="margin-left: 5px;">%s <i class="fas fa-%s"></i></span>',
$dataSource != 'Database/Mysql' ? 'important' : 'success',
$validDataSource ? 'success' : 'important',
__('DataSource: ') . h($dataSource),
__('DataSource: ') . h($dataSource),
$dataSource != 'Database/Mysql' ? 'times' : 'check'
$validDataSource ? 'check' : 'times'
);
if ($expectedDbVersion == $actualDbVersion) {
echo $this->element('/healthElements/db_indexes_diagnostic', array(
@ -198,7 +195,7 @@ function adjustRowSpan() {
})
}
$(document).ready(function() {
$(function() {
// hide non-critical issues
if ($('#dbSchemaDiagnosticCheckbox').prop('checked')) {
$('#dbSchemaDiagnosticTable').find('tr.noncritical').show();

View File

@ -0,0 +1,99 @@
<?php
if (!isset($canModifyAllTags)) {
$canModifyAllTags = $isAclTagger && $tagAccess && empty($static_tags_only);
}
if (!isset($canModifyLocalTags)) {
$canModifyLocalTags = $isAclTagger && $localTagAccess && empty($static_tags_only);
}
if (empty($tag['Tag'])) {
$tag['Tag'] = $tag;
}
if (empty($tag['Tag']['colour'])) {
$tag['Tag']['colour'] = '#0088cc';
}
$aStyle = 'background-color:' . h($tag['Tag']['colour']) . ';color:' . $this->TextColour->getTextColour($tag['Tag']['colour']);
$aClass = 'tag nowrap';
$aText = trim($tag['Tag']['name']);
$aTextModified = null;
if (isset($tag_display_style)) {
if ($tag_display_style == 1) {
// default behaviour, do nothing for now
} else if ($tag_display_style == 2) {
$separator_pos = strpos($aText, ':');
if ($separator_pos !== false) {
$aTextModified = substr($aText, $separator_pos + 1);
$value_pos = strpos($aTextModified, '=');
if ($value_pos !== false) {
$aTextModified = substr($aTextModified, $value_pos + 1);
$aTextModified = trim($aTextModified, '"');
}
$aTextModified = h($aTextModified);
}
} else if ($tag_display_style === 0 || $tag_display_style === '0') {
$aTextModified = '&nbsp;';
}
}
$aText = h($aText);
$span_scope = !empty($hide_global_scope) ? '' : sprintf(
'<span class="%s" title="%s" aria-label="%s"><i class="fas fa-%s"></i></span>',
'black-white tag',
!empty($tag['local']) ? __('Local tag') : __('Global tag'),
!empty($tag['local']) ? __('Local tag') : __('Global tag'),
!empty($tag['local']) ? 'user' : 'globe-americas'
);
$span_relationship_type = empty($tag['relationship_type']) ? '' : sprintf(
'<span class="tag nowrap white" style="background-color:black" title="%s" aria-label="%s">%s:</span>',
h($tag['relationship_type']),
h($tag['relationship_type']),
h($tag['relationship_type'])
);
if (!empty($tag['Tag']['id'])) {
$span_tag = sprintf(
'<a href="%s" style="%s" class="%s"%s data-tag-id="%s">%s</a>',
$baseurl . $searchUrl . intval($tag['Tag']['id']),
$aStyle,
$aClass,
isset($aTextModified) ? ' title="' . $aText . '"' : '',
intval($tag['Tag']['id']),
isset($aTextModified) ? $aTextModified : $aText
);
} else {
$span_tag = sprintf(
'<span style="%s" class="%s">%s</span>',
$aStyle,
$aClass,
$aText
);
}
$span_delete = '';
$span_relationship = '';
if ($canModifyAllTags || ($canModifyLocalTags && $tag['Tag']['local'])) {
$span_relationship = sprintf(
'<a class="%s" title="%s" role="button" tabindex="0" aria-label="%s" href="%s"><i class="fas fa-project-diagram"></i></a>',
'black-white tag noPrint modal-open',
__('Modify Tag Relationship'),
__('Modify relationship for tag %s', h($tag['Tag']['name'])),
sprintf(
'%s/tags/modifyTagRelationship/%s/%s',
$baseurl,
h($scope),
h($tag['id'])
)
);
$span_delete = sprintf(
'<span class="%s" title="%s" role="%s" tabindex="%s" aria-label="%s" onclick="%s">x</span>',
'black-white tag useCursorPointer noPrint',
__('Remove tag'),
"button",
"0",
__('Remove tag %s', h($tag['Tag']['name'])),
sprintf(
"removeObjectTagPopup(this, '%s', %s, %s)",
$scope,
$id,
intval($tag['Tag']['id'])
)
);
}
echo '<span class="tag-container nowrap">' . $span_scope . $span_relationship_type . $span_tag . $span_relationship . $span_delete . '</span> ';

View File

@ -1,6 +1,6 @@
<?php if (!empty($csv)): ?>
<div id="spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>"></div>
<div id="spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>" data-csv="<?= $csv ?>"></div>
<script>
sparkline('#spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>', "<?= $csv ?>");
sparkline('#spark_<?php echo (isset($scope) ? h($scope) . '_' : ''); ?><?php echo h($id); ?>');
</script>
<?php endif; ?>

View File

@ -65,7 +65,7 @@
?>
</div>
<div class="error-message populateTemplateErrorField" <?php if (!isset($errors[$element_id])) echo 'style="display:none;"';?>>
<?php echo __('Error: %s', $errors[$element_id]); ?>
<?= isset($errors[$element_id]) ? __('Error: %s', $errors[$element_id]) : ''; ?>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
<div id="distribution_graph_container">
<div class="loadingPopover">
<div class="spinner"></div>
<div class="loadingText"><?php echo __('Loading');?></div>
<div class="loadingText"><?php echo __('Loading'); ?></div>
</div>
<div id="eventdistri_graph" data-event-id="<?php echo h($event['Event']['id']); ?>" data-event-distribution="<?php echo h($event['Event']['distribution']); ?>" data-event-distribution-text="<?php echo $event['Event']['distribution'] == 4 ? h($event['SharingGroup']['name']) : h($distributionLevels[$event['Event']['distribution']]); ?>" data-user-manipulation="<?php echo $mayModify || $isSiteAdmin ? 'true' : 'false'; ?>" data-extended="<?php echo $extended; ?>">

View File

@ -1,4 +1,4 @@
<div>
<div class="sub-container">
<div id="timeline-header" class="eventgraph_header">
<label id="timeline-scope" class="btn center-in-network-header network-control-btn">
<span class="useCursorPointer fa fa-object-group" style="margin-right: 3px;"></span><?php echo __('Time scope')?>
@ -22,11 +22,13 @@
<span class="timeline-help shortcut-help btn btn-xs btn-info">?</span>
</div>
<?= $this->element('genericElements/assetLoader', [
'js' => [
'moment.min',
'event-timeline',
],
'css' => [
'event-timeline',
],
]);
'js' => [
'moment.min',
'Chart.min',
'chartjs-adapter-moment.min',
'event-timeline',
],
'css' => [
'event-timeline',
],
]);

View File

@ -2,9 +2,9 @@
<legend><?php echo __('Choose the format that you would like to use for the import'); ?></legend>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<?php foreach ($imports as $k => $import): ?>
<?php foreach ($imports as $import): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td class="<?php echo !empty($import['bold']) ? 'bold' : ''; ?>" role="button" tabindex="0" aria-label="<?php echo __('Import %s', h($import['text'])); ?>" style="padding-left:10px; text-align:center;width:100%;" onClick="importChoiceSelect('<?php echo h($import['url']); ?>', '<?php echo h($k); ?>', '<?php echo $import['ajax'] ? h($import['target']) : "false"; ?>')"><?php echo h($import['text']); ?></td>
<td class="<?php echo !empty($import['bold']) ? 'bold' : ''; ?>" role="button" tabindex="0" aria-label="<?php echo __('Import %s', h($import['text'])); ?>" style="padding-left:10px; text-align:center;width:100%;" onClick="importChoiceSelect('<?php echo h($import['url']); ?>', '<?php echo $import['ajax'] ? h($import['target']) : "false"; ?>')"><?php echo h($import['text']); ?></td>
</tr>
<?php endforeach; ?>
</table>
@ -12,7 +12,7 @@
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$(function() {
resizePopoverBody();
});

View File

@ -1,4 +1,4 @@
<div class="events form">
<div class="events form" style="font-size: 14px">
<?php echo $this->Form->create('', array('type' => 'file'));?>
<fieldset>
<legend><?= h(Inflector::humanize($module['name'])) ?></legend>
@ -18,7 +18,7 @@
if (isset($configTypes[$config['type']]['field'])) {
$settings['type'] = $configTypes[$config['type']]['field'];
}
switch($settings['type']) {
switch ($settings['type']) {
case 'select':
if (isset($config['options'])) {
$settings['options'] = $config['options'];
@ -34,13 +34,12 @@
<span class="bold"><?= ucfirst(h($configName)) ?></span><br>
<?php
if ($settings['type'] === 'checkbox'):
echo '<label class="checkbox">';
echo $this->Form->input('Event.config.' . $configName, $settings);
if (isset($config['message']) && !empty($config['message'])):
echo ' ' . h($config['message']);
?>
<br>
<?php
endif;
if (isset($config['message']) && !empty($config['message'])) {
echo ' ' . h($config['message']) . '<br>';
}
echo '</label>';
else:
if (isset($config['message']) && !empty($config['message'])):
?>
@ -54,17 +53,18 @@
<?php
}
}
$source = 'paste';
if (in_array('paste', $module['mispattributes']['inputSource']) && in_array('file', $module['mispattributes']['inputSource'])) {
$source = 'both';
} else if (in_array('file', $module['mispattributes']['inputSource'])) {
$source = 'file';
} else {
$source = 'paste';
}
if (!empty($module['mispattributes']['inputSource'])):
echo $this->Form->input('Event.source', array(
'label' => false,
'checked' => $source === 'file' ? true : false,
'disabled' => $source === 'both' ? false : true,
'checked' => $source === 'file',
'disabled' => !($source === 'both'),
'div' => false,
'style' => 'margin-bottom:5px;'
));
@ -110,7 +110,7 @@ echo $this->Form->end();
</div>
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'populateFrom', 'event' => $event)); ?>
<script type="text/javascript">
<script>
$(function() {
changeImportSource();
$('#EventSource').change(function() {

View File

@ -10,14 +10,6 @@
}
?>
<?php
$instanceDefault = 5;
if (!empty(Configure::read('MISP.default_attribute_distribution'))) {
if (Configure::read('MISP.default_attribute_distribution') == 'event') {
$instanceDefault = 5;
} else {
$instanceDefault = Configure::read('MISP.default_attribute_distribution');
}
}
echo $this->Form->create('Attribute', array('url' => $baseurl . '/events/saveFreeText/' . $event['Event']['id'], 'class' => 'mainForm'));
if ($isSiteAdmin) {
echo $this->Form->input('force', array(
@ -56,7 +48,7 @@
$options = array();
foreach ($resultArray as $k => $item):
?>
<tr id="row_<?php echo $k; ?>" class="freetext_row">
<tr data-row="<?= $k ?>" class="freetext_row">
<?php
echo $this->Form->input('Attribute' . $k . 'Save', array(
'label' => false,
@ -79,7 +71,7 @@
echo $this->Form->input('Attribute' . $k . 'Value', array(
'label' => false,
'value' => $item['value'],
'style' => 'padding:0px;height:20px;margin-bottom:0px;width:90%;min-width:400px;',
'style' => 'width:90%;min-width:400px;',
'div' => false
));
?>
@ -123,14 +115,14 @@
else $default = array_search($item['categories'][0], $typeCategoryMapping[$item['default_type']]);
}
?>
<select id="<?php echo 'Attribute' . $k . 'Category'; ?>" style='padding:0px;height:20px;margin-bottom:0px;' class="categoryToggle">
<select id="<?php echo 'Attribute' . $k . 'Category'; ?>" style="width: 180px" class="categoryToggle">
<?php
foreach ($typeCategoryMapping[$item['default_type']] as $category) {
if (isset($item['categories']) && !in_array($category, $item['categories'])) {
if (isset($item['categories']) && !in_array($category, $item['categories'], true)) {
continue;
}
echo '<option';
if ($category == $default) echo ' selected="selected"';
if ($category == $default) echo ' selected';
echo '>' . $category . '</option>';
}
?>
@ -150,12 +142,12 @@
}
?>
<div id="<?php echo 'Attribute' . $k . 'TypeStatic'; ?>" <?php echo $divVisibility; ?> ><?php echo h($item['default_type']); ?></div>
<select id="<?php echo 'Attribute' . $k . 'Type'; ?>" class='typeToggle' style='padding:0px;height:20px;margin-bottom:0px;<?php echo $selectVisibility; ?>'>
<select id="<?php echo 'Attribute' . $k . 'Type'; ?>" class='typeToggle' style='<?php echo $selectVisibility; ?>'>
<?php
if (!empty($item['types'])) {
foreach ($item['types'] as $type) {
echo '<option';
echo ($type === $item['default_type'] ? ' selected="selected"' : '') . '>' . h($type) . '</option>';
echo ($type === $item['default_type'] ? ' selected' : '') . '>' . h($type) . '</option>';
}
}
?>
@ -168,17 +160,17 @@
<input type="checkbox" id="<?php echo 'Attribute' . $k . 'Disable_correlation'; ?>" <?php if (!empty($item['disable_correlation'])) echo 'checked'; ?> class="dcCheckbox">
</td>
<td class="short" style="width:40px;text-align:center;">
<select id="<?php echo 'Attribute' . $k . 'Distribution'; ?>" class='distributionToggle' style='padding:0px;height:20px;margin-bottom:0px;'>
<select id="<?php echo 'Attribute' . $k . 'Distribution'; ?>" class='distributionToggle'>
<?php
foreach ($distributions as $distKey => $distValue) {
$default = isset($item['distribution']) ? $item['distribution'] : $instanceDefault;
$default = $item['distribution'] ?? $defaultAttributeDistribution;
echo '<option value="' . $distKey . '" ';
echo ($distKey == $default ? 'selected="selected"' : '') . '>' . $distValue . '</option>';
}
?>
</select>
<div style="display:none;">
<select id="<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<select id="<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='margin-top:3px;'>
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '">' . h($sgValue) . '</option>';
@ -188,13 +180,13 @@
</div>
</td>
<td class="short">
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>>
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>>
</td>
<td class="short">
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>>
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" <?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>>
</td>
<td class="action short">
<span class="fa fa-times useCursorPointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onclick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
<span class="fa fa-times useCursorPointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onclick="freetextRemoveRow(<?php echo $k; ?>, <?php echo $event['Event']['id']; ?>);"></span>
</td>
</tr>
<?php
@ -211,7 +203,24 @@
?>
</table>
<span>
<button class="btn btn-primary" style="float:left;" onclick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', <?= count($resultArray) ?>);"><?php echo __('Submit %s', $scope);?></button>
<div class="btn-toolbar" style="float:left;">
<button class="btn btn-primary" onclick="freetextImportResultsSubmit(<?= $event['Event']['id']; ?>);"><?= __('Submit %s', $scope);?></button>
<div class="btn-group createObject" style="display: none">
<?php
echo $this->Form->create('Object', ['url' => $baseurl . '/objects/createFromFreetext/' . $event['Event']['id'], 'class' => 'hidden']);
echo $this->Form->input('selectedTemplateId', ['label' => false]);
echo $this->Form->input('attributes', ['label' => false]);
echo $this->Form->end();
?>
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<?= __('Create object') ?>
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
</ul>
</div>
</div>
<span style="float:right">
<?php
if (!empty($optionsRearranged)):
@ -236,7 +245,7 @@
endforeach;
?>
</select>
<span role="button" tabindex="0" aria-label="<?php echo __('Apply changes to all applicable resolved attributes');?>" title="<?php echo __('Apply changes to all applicable resolved attributes');?>" class="btn btn-inverse" onClick="changeFreetextImportExecute();"><?php echo __('Change all');?></span><br />
<span role="button" tabindex="0" aria-label="<?php echo __('Apply changes to all applicable resolved attributes');?>" title="<?php echo __('Apply changes to all applicable resolved attributes');?>" class="btn btn-inverse" onClick="changeFreetextImportExecute();"><?php echo __('Change all');?></span><br>
<?php endif; ?>
<input type="text" id="changeComments" style="margin-left:50px;margin-top:10px;width:446px;" placeholder="<?php echo __('Update all comment fields');?>">
<span role="button" tabindex="0" aria-label="<?php echo __('Change all');?>" title="<?php echo __('Change all');?>" class="btn btn-inverse" onClick="changeFreetextImportCommentExecute();"><?php echo __('Change all');?></span>
@ -247,12 +256,16 @@
var options = <?php echo json_encode($optionsRearranged);?>;
var typeCategoryMapping = <?php echo json_encode($typeCategoryMapping); ?>;
$(function() {
freetextPossibleObjectTemplates();
popoverStartup();
$('.typeToggle').on('change', function() {
var currentId = $(this).attr('id');
var selected = $(this).val();
currentId = currentId.replace('Type', 'Category');
var currentOptions = typeCategoryMapping[selected];
freetextPossibleObjectTemplates();
/*
// Coming soon - restrict further if a list of categories is passed by the modules / freetext import tool
if ($('#' + currentId)).data('category-restrictions') {

View File

@ -1,27 +1,25 @@
<div class="index" style="margin-bottom: 2em">
<div class="index">
<h2><?php echo h($title); ?></h2>
<?php
$event_id = $event['Event']['id'];
$url = $baseurl . '/events/handleModuleResults/' . $event_id;
echo $this->Form->create('Event', array('url' => $url, 'class' => 'mainForm'));
$formSettings = array(
echo $this->Form->create('Event', array('url' => $url, 'class' => 'mainForm hidden'));
echo $this->Form->input('data', array(
'type' => 'hidden',
'value' => json_encode($event, true)
);
echo $this->Form->input('data', $formSettings);
'value' => JsonTool::encode($event)
));
echo $this->Form->input('JsonObject', array(
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => ''
'label' => false,
'type' => 'text',
'value' => ''
));
echo $this->Form->input('default_comment', array(
'label' => false,
'type' => 'text',
'style' => 'display:none;',
'value' => $importComment
'label' => false,
'type' => 'text',
'value' => $importComment
));
echo $this->Form->end();
$objects_array = array();
foreach (array('Attribute', 'Object') as $field) {
if (!empty($event[$field])) {
@ -101,7 +99,7 @@
<?php foreach($event['EventReport'] as $report): ?>
<tr class="MISPEventReport">
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" class="ImportMISPEventReport" checked />
<input type="checkbox" class="ImportMISPEventReport" checked>
</td>
<td class="EventReportName"><?= h($report['name']); ?></td>
<td class="EventReportUUID hidden"><?= h($report['uuid']); ?></td>
@ -109,7 +107,7 @@
<?= h($report['content']); ?>
</td>
<td class="short" style="width:40px;text-align:center;">
<select class='EventReportDistribution' style='padding:0px;height:20px;margin-bottom:0px;'>
<select class="EventReportDistribution" style="padding:0;height:20px;margin-bottom:0;">
<?php
foreach ($distributions as $distKey => $distValue) {
echo '<option value="' . h($distKey) . '" ' . ($distKey == $report['distribution'] ? 'selected="selected"' : '') . '>' . h($distValue) . '</option>';
@ -117,7 +115,7 @@
?>
</select>
<div style="display:none;">
<select class='EventReportSharingGroup' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<select class="EventReportSharingGroup" style="padding:0;height:20px;margin-top:3px;margin-bottom:0;">
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '" ' . ($sgKey == $report['sharing_group_id'] ? 'selected="selected"' : '') . '>' . h($sgValue) . '</option>';
@ -156,41 +154,41 @@
<tbody class="MISPObject">
<tr class="tableHighlightBorderTop borderBlue blueRow" tabindex="0">
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" class="ImportMISPObject" checked />
<input type="checkbox" class="ImportMISPObject" checked>
</td>
<td colspan="6">
<?php if(!empty($object['id'])) { ?>
<span class="bold"><?php echo __('ID: ');?></span><span class="ObjectID"><?php echo h($object['id']); ?></span><br />
<span class="bold"><?php echo __('ID: ');?></span><span class="ObjectID"><?php echo h($object['id']); ?></span><br>
<?php } ?>
<span class="bold"><?php echo __('Name: ');?></span><span class="ObjectName"><?php echo h($object['name']); ?></span>
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo $o; ?>_collapsible"></span><br />
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo $o; ?>_collapsible"></span><br>
<div id="Object_<?php echo $o; ?>_collapsible" class="collapse">
<?php
if (!empty($object['description'])) {
echo '<span class="bold">Description: </span><span class="ObjectDescription">' . h($object['description']) . '</span><br/>';
echo '<span class="bold">Description: </span><span class="ObjectDescription">' . h($object['description']) . '</span><br>';
}
if (!empty($object['template_uuid'])) {
echo '<span class="bold">Template UUID: </span><span class="TemplateUUID">' . h($object['template_uuid']) . '</span><br/>';
echo '<span class="bold">Template UUID: </span><span class="TemplateUUID">' . h($object['template_uuid']) . '</span><br>';
}
if (!empty($object['template_version'])) {
echo '<span class="bold">Template version: </span><span class="TemplateVersion">' . h($object['template_version']) . '</span><br/>';
echo '<span class="bold">Template version: </span><span class="TemplateVersion">' . h($object['template_version']) . '</span><br>';
}
?>
<span class="bold"><?php echo __('UUID: ');?></span><span class="ObjectUUID"><?php echo h($object['uuid']); ?></span><br />
<span class="bold"><?php echo __('Meta Category: ');?></span><span class="ObjectMetaCategory"><?php echo h($object['meta-category']); ?></span><br />
<span class="bold"><?php echo __('UUID: ');?></span><span class="ObjectUUID"><?php echo h($object['uuid']); ?></span><br>
<span class="bold"><?php echo __('Meta Category: ');?></span><span class="ObjectMetaCategory"><?php echo h($object['meta-category']); ?></span><br>
<?php
if (!empty($object['first_seen'])) {
echo '<span class="bold">First seen: </span><span class="ObjectFirstSeen">' . h($object['first_seen']) . '</span><br/>';
echo '<span class="bold">First seen: </span><span class="ObjectFirstSeen">' . h($object['first_seen']) . '</span><br>';
}
if (!empty($object['last_seen'])) {
echo '<span class="bold">Last seen: </span><span class="ObjectLastSeen">' . h($object['last_seen']) . '</span><br/>';
echo '<span class="bold">Last seen: </span><span class="ObjectLastSeen">' . h($object['last_seen']) . '</span><br>';
}
?>
</div>
<span class="bold"><?php echo __('References: ')?></span>
<?php
if (!empty($object['ObjectReference'])) {
echo sizeof($object['ObjectReference']);
echo count($object['ObjectReference']);
?>
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo $o; ?>_references_collapsible"></span>
<div id="Object_<?php echo $o; ?>_references_collapsible" class="collapse">
@ -222,7 +220,7 @@
$objectType = '';
}
}
echo $objectType . ' <span class="ReferencedUUID">' . $referenced_uuid . '</span> (' . $name . ': ' . $category . ')</span><br />';
echo $objectType . ' <span class="ReferencedUUID">' . $referenced_uuid . '</span> (' . $name . ': ' . $category . ')</span><br>';
unset($name);
}
echo '</div>';
@ -232,21 +230,21 @@
?>
</td>
<td class="short">
<input type="text" class="ObjectComment" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (!empty($object['comment'])) echo 'value="' . h($object['comment']) . '"';?>/>
<input type="text" class="ObjectComment" style="padding:0;height:20px;margin-bottom:0;" placeholder="<?php echo h($importComment); ?>"<?php if (!empty($object['comment'])) echo ' value="' . h($object['comment']) . '"';?>>
</td>
<td style="width:60px;text-align:center;">
<select class="ObjectDistribution" style="padding:0px;height:20px;margin-bottom:0px;">
<select class="ObjectDistribution" style="padding:0;height:20px;margin-bottom:0;">
<?php
foreach ($distributions as $distKey => $distValue) {
echo '<option value="' . h($distKey) . '" ' . ($distKey == $object['distribution'] ? 'selected="selected"' : '') . '>' . h($distValue) . '</option>';
echo '<option value="' . h($distKey) . '"' . ($distKey == $object['distribution'] ? ' selected' : '') . '>' . h($distValue) . '</option>';
}
?>
</select>
<div style="display:none;">
<select class='ObjectSharingGroup' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<select class="ObjectSharingGroup" style="padding:0;height:20px;margin-top:3px;margin-bottom:0;">
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '" ' . ($sgKey == $object['sharing_group_id'] ? 'selected="selected"' : '') . '>' . h($sgValue) . '</option>';
echo '<option value="' . h($sgKey) . '"' . ($sgKey == $object['sharing_group_id'] ? ' selected' : '') . '>' . h($sgValue) . '</option>';
}
?>
</select>
@ -256,24 +254,24 @@
<?php
if (!empty($object['Attribute'])) {
$last_attribute = end($object['Attribute']);
foreach ($object['Attribute'] as $a => $attribute) {
foreach ($object['Attribute'] as $attribute) {
$border_position = ($attribute == $last_attribute ? 'Bottom' : 'Center');
?>
<tr class="ObjectAttribute tableHighlightBorder<?php echo $border_position; ?> borderBlue">
<td class="short" style="width:40px;text-align:center;"><input type="checkbox" class="ImportMISPObjectAttribute" checked /></td>
<td class="short" style="width:40px;text-align:center;"><input type="checkbox" class="ImportMISPObjectAttribute" checked></td>
<td class="ObjectCategory"><?php echo (isset($attribute['category']) ? h($attribute['category']) : ''); ?></td>
<td class="short">
<span class="ObjectRelation bold"><?php echo h($attribute['object_relation']); ?></span>
<span class="AttributeType"><?php echo h($attribute['type']); ?></span>
</td>
<td class="AttributeValue limitedWidth"><?= $this->element('Events/View/value_field', ['object' => $attribute]); ?></td>
<td class="AttributeValue limitedWidth" data-value="<?= h($attribute['value']) ?>"><?= $this->element('Events/View/value_field', ['object' => $attribute]); ?></td>
<?php
if (in_array($attribute['type'], $typesWithData)) {
if (in_array($attribute['type'], $typesWithData, true)) {
if (!empty($attribute['data'])) {
echo "<input class='AttributeData' type='hidden' value='" . h($attribute['data']) . "'/>";
echo "<input class='AttributeData' type='hidden' value='" . h($attribute['data']) . "'>";
}
if (!empty($attribute['encrypt'])) {
echo "<input class='AttributeEncrypt' type='hidden' value='" . h($attribute['encrypt']) . "'/>";
echo "<input class='AttributeEncrypt' type='hidden' value='" . h($attribute['encrypt']) . "'>";
}
}
?>
@ -299,34 +297,34 @@
<?php } ?>
</td>
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" class="AttributeToIds" <?php if (!empty($attribute['to_ids'])) echo 'checked'; ?>/>
<input type="checkbox" class="AttributeToIds"<?php if (!empty($attribute['to_ids'])) echo ' checked'; ?>>
</td>
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" class="AttributeDisableCorrelation" <?php if (!empty($attribute['disable_correlation'])) echo 'checked'; ?>/>
<input type="checkbox" class="AttributeDisableCorrelation"<?php if (!empty($attribute['disable_correlation'])) echo ' checked'; ?>>
</td>
<td class="short">
<input type="text" class="AttributeComment" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (!empty($attribute['comment'])) echo 'value="' . h($attribute['comment']) . '"';?>/>
<input type="text" class="AttributeComment" style="padding:0;height:20px;margin-bottom:0;"<?php if (!empty($attribute['comment'])) echo ' value="' . h($attribute['comment']) . '"';?>>
</td>
<td class="short" style="width:40px;text-align:center;">
<select class='AttributeDistribution' style='padding:0px;height:20px;margin-bottom:0px;'>
<select class="AttributeDistribution" style="padding:0;height:20px;margin-bottom:0;">
<?php
foreach ($distributions as $distKey => $distValue) {
echo '<option value="' . h($distKey) . '" ' . ($distKey == $attribute['distribution'] ? 'selected="selected"' : '') . '>' . h($distValue) . '</option>';
}
foreach ($distributions as $distKey => $distValue) {
echo '<option value="' . h($distKey) . '"' . ($distKey == $attribute['distribution'] ? ' selected' : '') . '>' . h($distValue) . '</option>';
}
?>
</select>
<div style="display:none;">
<select class='AttributeSharingGroup' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<select class="AttributeSharingGroup" style="padding:0;height:20px;margin-top:3px;margin-bottom:0;">
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '" ' . ($sgKey == $attribute['sharing_group_id'] ? 'selected="selected"' : '') . '>' . h($sgValue) . '</option>';
}
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '"' . ($sgKey == $attribute['sharing_group_id'] ? ' selected' : '') . '>' . h($sgValue) . '</option>';
}
?>
</select>
</div>
</td>
</tr>
<?php
echo '</tr>';
}
}
echo '<tr><td colspan="9"></td></tr>';
@ -354,17 +352,17 @@
</tr>
<?php
}
foreach ($event['Attribute'] as $a => $attribute) {
foreach ($event['Attribute'] as $attribute) {
?>
<tr class="MISPAttribute">
<td class="short" style="width:40px;text-align:center;"><input type="checkbox" class="ImportMISPAttribute" checked /></td>
<td class="short" style="width:40px;text-align:center;"><input type="checkbox" class="ImportMISPAttribute" checked></td>
<?php
foreach (array('category', 'type') as $field) {
$field_header = 'class="Attribute' . ucfirst($field);
if (isset($attribute[$field])) {
if (is_array($attribute[$field])) {
echo '<td class="short" style="width:40px;text-align:center;"><select ' . $field_header . 'Select" style="padding:0px;height:20px;margin-bottom:0px;">';
foreach ($attribute[$field] as $v => $value) {
foreach ($attribute[$field] as $value) {
echo '<option value="' . h($value) . '">' . h($value) . '</option>';
}
echo '</select></td>';
@ -376,14 +374,14 @@
}
}
?>
<td class="AttributeValue limitedWidth"><?= $this->element('Events/View/value_field', ['object' => $attribute]); ?></td>
<td class="AttributeValue limitedWidth" data-value="<?= h($attribute['value']) ?>"><?= $this->element('Events/View/value_field', ['object' => $attribute]); ?></td>
<?php
if (in_array($attribute['type'], $typesWithData)) {
if (in_array($attribute['type'], $typesWithData, true)) {
if (!empty($attribute['data'])) {
echo "<input class='AttributeData' type='hidden' value='" . h($attribute['data']) . "'/>";
echo "<input class='AttributeData' type='hidden' value='" . h($attribute['data']) . "'>";
}
if (!empty($attribute['encrypt'])) {
echo "<input class='AttributeEncrypt' type='hidden' value='" . h($attribute['encrypt']) . "'/>";
echo "<input class='AttributeEncrypt' type='hidden' value='" . h($attribute['encrypt']) . "'>";
}
}
?>
@ -409,44 +407,44 @@
<?php } ?>
</td>
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" class="AttributeToIds" <?php if (isset($attribute['to_ids']) && $attribute['to_ids']) echo 'checked'; ?>/>
<input type="checkbox" class="AttributeToIds"<?php if (isset($attribute['to_ids']) && $attribute['to_ids']) echo ' checked'; ?>>
</td>
<td class="short" style="width:40px;text-align:center;">
<input type="checkbox" class="AttributeDisableCorrelation" <?php if (isset($attribute['disable_correlation']) && $attribute['disable_correlation']) echo 'checked'; ?>/>
<input type="checkbox" class="AttributeDisableCorrelation"<?php if (isset($attribute['disable_correlation']) && $attribute['disable_correlation']) echo ' checked'; ?>>
</td>
<td class="short">
<input type="text" class="AttributeComment" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (!empty($attribute['comment'])) echo 'value="' . h($attribute['comment']) . '"';?>/>
<input type="text" class="AttributeComment" style="padding:0;height:20px;margin-bottom:0;" placeholder="<?php echo h($importComment); ?>"<?php if (!empty($attribute['comment'])) echo ' value="' . h($attribute['comment']) . '"';?>>
</td>
<td class="short" style="width:40px;text-align:center;">
<select class='AttributeDistribution' style='padding:0px;height:20px;margin-bottom:0px;'>
<select class="AttributeDistribution" style="padding:0;height:20px;margin-bottom:0;">
<?php
foreach ($distributions as $distKey => $distValue) {
echo '<option value="' . h($distKey) . '" ' . ($distKey == $attribute['distribution'] ? 'selected="selected"' : '') . '>' . h($distValue) . '</option>';
echo '<option value="' . h($distKey) . '"' . ($distKey == $attribute['distribution'] ? ' selected' : '') . '>' . h($distValue) . '</option>';
}
?>
</select>
<div style="display:none;">
<select class='AttributeSharingGroup' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<select class="AttributeSharingGroup" style="padding:0;height:20px;margin-top:3px;margin-bottom:0;">
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . h($sgKey) . '" ' . ($sgKey == $attribute['sharing_group_id'] ? 'selected="selected"' : '') . '>' . h($sgValue) . '</option>';
echo '<option value="' . h($sgKey) . '"' . ($sgKey == $attribute['sharing_group_id'] ? ' selected' : '') . '>' . h($sgValue) . '</option>';
}
?>
</select>
</div>
</td>
</tr>
<?php
echo '</tr>';
}
}
?>
</tbody>
</table>
<button class="btn btn-primary" style="float:left;" onClick="moduleResultsSubmit('<?php echo h($event_id); ?>');"><?php echo __('Submit'); ?></button>
<button class="btn btn-primary" style="float:left;" onclick="moduleResultsSubmit('<?php echo h($event_id); ?>');"><?php echo __('Submit'); ?></button>
<a href="<?php echo $baseurl . '/events/view/' . h($event['Event']['id']); ?>" style="margin-left:10px;" class="btn btn-inverse"><?php echo __('Cancel');?></a>
</div>
<script type="text/javascript">
<script>
$(function() {
$('.AttributeDistribution, .ObjectDistribution, .EventReportDistribution').change(function() {
if ($(this).val() == 4) {

View File

@ -3,25 +3,25 @@
echo $this->Form->create('Event', array('type' => 'file'));
?>
<fieldset>
<legend><?php echo __('Import %s file', $stix_version); ?></legend>
<legend><?= __('Import STIX %s file', $stix_version); ?></legend>
<?php
echo $this->Form->input('Event.stix', array(
'label' => '<b>' . __('%s file', $stix_version) . '</b>',
'type' => 'file',
'label' => '<b>' . __('%s file', $stix_version) . '</b>',
'type' => 'file',
));
?>
<div class="input clear"></div>
<?php
echo $this->Form->input('publish', array(
'checked' => false,
'label' => __('Publish imported events'),
'checked' => false,
'label' => __('Publish imported events'),
));
?>
<div class="input clear"></div>
<?php
echo $this->Form->input('original_file', array(
'checked' => true,
'label' => __('Include the original imported file as attachment')
'checked' => true,
'label' => __('Include the original imported file as attachment')
));
?>
</fieldset>

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