Merge branch '2.4' of github.com:MISP/MISP into relatedEventUI

pull/4570/head
mokaddem 2019-06-21 09:20:57 +02:00
commit 1c6b9d0c6b
63 changed files with 1863 additions and 591 deletions

View File

@ -120,9 +120,11 @@ MISPvars () {
# GPG configuration
GPG_REAL_NAME='Autogenerated Key'
# On a REAL install, please do not set a comment, see here for why: https://www.debian-administration.org/users/dkg/weblog/97
GPG_COMMENT='WARNING: MISP AutoGenerated Key consider this Key VOID!'
GPG_EMAIL_ADDRESS='admin@admin.test'
GPG_KEY_LENGTH='2048'
# 3072 bits used as per suggestions here: https://riseup.net/en/security/message-security/openpgp/best-practices
GPG_KEY_LENGTH='3072'
GPG_PASSPHRASE="$(openssl rand -hex 32)"
# debug alias to make sure people are not confused when blindly copy pasting blobs of code
@ -247,7 +249,7 @@ checkCoreOS () {
if [[ -f "/etc/redhat-release" ]]; then
echo "This is some redhat flavour"
REDHAT=1
RHfla=$(cat /etc/redhat-release | cut -f 1 -d\ | tr [A-Z] [a-z])
RHfla=$(cat /etc/redhat-release | cut -f 1 -d\ | tr '[:upper:]' '[:lower:]')
fi
}
@ -259,7 +261,7 @@ checkFlavour () {
sudo apt install lsb-release dialog -y
fi
FLAVOUR=$(lsb_release -s -i |tr [A-Z] [a-z])
FLAVOUR=$(lsb_release -s -i |tr '[:upper:]' '[:lower:]')
if [ FLAVOUR == "ubuntu" ]; then
RELEASE=$(lsb_release -s -r)
debug "We detected the following Linux flavour: ${YELLOW}$(tr '[:lower:]' '[:upper:]' <<< ${FLAVOUR:0:1})${FLAVOUR:1} ${RELEASE}${NC}"
@ -377,6 +379,27 @@ checkFail () {
fi
}
ask_o () {
ANSWER=""
if [ -z "${1}" ]; then
echo "This function needs at least 1 parameter."
exit 1
fi
[ -z "${2}" ] && OPT1="y" || OPT1="${2}"
[ -z "${3}" ] && OPT2="n" || OPT2="${3}"
while true; do
case "${ANSWER}" in "${OPT1}" | "${OPT2}") break ;; esac
echo -e -n "${1} (${OPT1}/${OPT2}) "
read ANSWER
ANSWER=$(echo "${ANSWER}" | tr '[:upper:]' '[:lower:]')
done
}
# Check if misp user is present and if run as root
checkID () {
debug "Checking if run as root and $MISP_USER is present"
@ -387,7 +410,7 @@ checkID () {
if [[ "$UNATTENDED" != "1" ]]; then
echo "There is NO user called '$MISP_USER' create a user '$MISP_USER' (y) or continue as $USER (n)? (y/n) "
read ANSWER
ANSWER=$(echo $ANSWER |tr [A-Z] [a-z])
ANSWER=$(echo $ANSWER |tr '[:upper:]' '[:lower:]')
else
ANSWER="y"
fi
@ -530,7 +553,7 @@ setBaseURL () {
echo "You can now enter your own MISP_BASEURL, if you wish to NOT do that, the MISP_BASEURL will be empty, which will work, but ideally you configure it afterwards."
echo "Do you want to change it now? (y/n) "
read ANSWER
ANSWER=$(echo $ANSWER |tr [A-Z] [a-z])
ANSWER=$(echo $ANSWER |tr '[:upper:]' '[:lower:]')
if [[ "$ANSWER" == "y" ]]; then
if [[ ! -z $IP ]]; then
echo "It seems you have an interface called $IFACE UP with the following IP: $IP - FYI"
@ -854,6 +877,7 @@ genRCLOCAL () {
sed -i -e '$i \echo never > /sys/kernel/mm/transparent_hugepage/enabled\n' /etc/rc.local
sed -i -e '$i \echo 1024 > /proc/sys/net/core/somaxconn\n' /etc/rc.local
sed -i -e '$i \sysctl vm.overcommit_memory=1\n' /etc/rc.local
sed -i -e '$i \[ -f /etc/init.d/firstBoot ] && bash /etc/init.d/firstBoot\n' /etc/rc.local
}
# Run PyMISP tests
@ -943,7 +967,16 @@ aptUpgrade () {
debug "Upgrading system"
checkAptLock
sudo apt-get update
sudo apt-get upgrade -qy
# If we run in non-interactive mode, make sure we do not stop all of a sudden
if [[ "${PACKER}" == "1" || "${UNATTENDED}" == "1" ]]; then
export DEBIAN_FRONTEND=noninteractive
export DEBIAN_PRIORITY=critical
sudo -E apt-get -qy -o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold" upgrade
sudo -E apt-get -qy autoclean
else
sudo apt-get upgrade -qy
fi
}
# check if sudo is installed
@ -1172,6 +1205,9 @@ installCore () {
# install lief
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install https://github.com/lief-project/packages/raw/lief-master-latest/pylief-0.9.0.dev.zip
# install zmq needed by mispzmq
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install zmq
# install python-magic
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install python-magic
@ -1269,7 +1305,8 @@ coreCAKE () {
$SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "MISP.python_bin" "${PATH_TO_MISP}/venv/bin/python"
# Set default role
$SUDO_WWW $RUN_PHP -- $CAKE setDefaultRole 3
# TESTME: The following seem defunct, please test.
# $SUDO_WWW $RUN_PHP -- $CAKE setDefaultRole 3
# Tune global time outs
$SUDO_WWW $RUN_PHP -- $CAKE Admin setSetting "Session.autoRegenerate" 0
@ -2113,6 +2150,12 @@ installMISPonKali () {
# install python-magic
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install python-magic 2> /dev/null > /dev/null
# install plyara
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install plyara 2> /dev/null > /dev/null
# install zmq needed by mispzmq
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install zmq 2> /dev/null > /dev/null
# Install Crypt_GPG and Console_CommandLine
debug "Installing pear Console_CommandLine"
pear install ${PATH_TO_MISP}/INSTALL/dependencies/Console_CommandLine/package.xml
@ -2311,7 +2354,7 @@ fi
# If Ubuntu is detected, figure out which release it is and run the according scripts
if [ "${FLAVOUR}" == "ubuntu" ]; then
RELEASE=$(lsb_release -s -r| tr [A-Z] [a-z])
RELEASE=$(lsb_release -s -r| tr '[:upper:]' '[:lower:]')
if [ "${RELEASE}" == "18.04" ]; then
echo "Install on Ubuntu 18.04 LTS fully supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
@ -2337,7 +2380,7 @@ fi
# If Debian is detected, figure out which release it is and run the according scripts
if [ "${FLAVOUR}" == "debian" ]; then
CODE=$(lsb_release -s -c| tr [A-Z] [a-z])
CODE=$(lsb_release -s -c| tr '[:upper:]' '[:lower:]')
if [ "${CODE}" == "buster" ]; then
echo "Install on Debian testing fully supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
@ -2359,7 +2402,7 @@ fi
# If Tsurugi is detected, figure out which release it is and run the according scripts
if [ "${FLAVOUR}" == "tsurugi" ]; then
CODE=$(lsb_release -s -c| tr [A-Z] [a-z])
CODE=$(lsb_release -s -c| tr '[:upper:]' '[:lower:]')
if [ "${CODE}" == "bamboo" ]; then
echo "Install on Tsurugi Lab partially supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"

View File

@ -1,5 +1,5 @@
; Generated by RHash v1.3.8 on 2019-05-30 at 14:36.25
; Generated by RHash v1.3.8 on 2019-06-20 at 14:00.36
; Written by Kravchenko Aleksey (Akademgorodok) - http://rhash.sf.net/
;
; 93871 14:36.25 2019-05-30 INSTALL.sh
INSTALL.sh DE23B5D224757A8AB2941D8E15D73F10872D5106 ABEE81992478478406197EEC1891FA7CBDC5B32575447DD6865511B1DE48EC6F D7B9CA78779343C0CD47C9184DCA17DEFA24FA1B6BB35441F574AC40ED5A5AD68738BA91676E528AFC2488B44EC935C6 1FFDD293EF9FD53F80813B33839187ECF00B68FDDECA11327508ACABB99B45F45017CFF4AF2B70CF82D27B4AEEB75C34434B3AA00AD52D3AFC8405E77B8CF348
; 95437 14:00.36 2019-06-20 INSTALL.sh
INSTALL.sh 8CFDF8FC14572C9AA51673D7449C354257C6CE67 61B8976709B44B3F2C0491EDB6FA013AC15BA4833F074929810C65C93C274FCB 75D5538717565401F180E7C777BE41A167B2365473806141C9357E75220DD198BE68DC2B59452F39396B42FB50208194 460D731E91EAA0F589B96D13CC451BCB7014C683A357099B13492E7683A459ECB7C2A43AFFB237C966CE67DD06140199686E968B518A33ED73C84135948E0749

View File

@ -1 +1 @@
de23b5d224757a8ab2941d8e15d73f10872d5106 INSTALL.sh
8cfdf8fc14572c9aa51673d7449c354257c6ce67 INSTALL.sh

View File

@ -1 +1 @@
abee81992478478406197eec1891fa7cbdc5b32575447dd6865511b1de48ec6f INSTALL.sh
61b8976709b44b3f2c0491edb6fa013ac15ba4833f074929810c65c93c274fcb INSTALL.sh

View File

@ -1 +1 @@
d7b9ca78779343c0cd47c9184dca17defa24fa1b6bb35441f574ac40ed5a5ad68738ba91676e528afc2488b44ec935c6 INSTALL.sh
75d5538717565401f180e7c777be41a167b2365473806141c9357e75220dd198be68dc2b59452f39396b42fb50208194 INSTALL.sh

View File

@ -1 +1 @@
1ffdd293ef9fd53f80813b33839187ecf00b68fddeca11327508acabb99b45f45017cff4af2b70cf82d27b4aeeb75c34434b3aa00ad52d3afc8405e77b8cf348 INSTALL.sh
460d731e91eaa0f589b96d13cc451bcb7014c683a357099b13492e7683a459ecb7c2a43affb237c966ce67dd06140199686e968b518a33ed73c84135948e0749 INSTALL.sh

View File

@ -465,6 +465,12 @@ installMISPonKali () {
# install python-magic
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install python-magic 2> /dev/null > /dev/null
# install plyara
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install plyara 2> /dev/null > /dev/null
# install zmq needed by mispzmq
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install zmq 2> /dev/null > /dev/null
# Install Crypt_GPG and Console_CommandLine
debug "Installing pear Console_CommandLine"
pear install ${PATH_TO_MISP}/INSTALL/dependencies/Console_CommandLine/package.xml
@ -663,7 +669,7 @@ fi
# If Ubuntu is detected, figure out which release it is and run the according scripts
if [ "${FLAVOUR}" == "ubuntu" ]; then
RELEASE=$(lsb_release -s -r| tr [A-Z] [a-z])
RELEASE=$(lsb_release -s -r| tr '[:upper:]' '[:lower:]')
if [ "${RELEASE}" == "18.04" ]; then
echo "Install on Ubuntu 18.04 LTS fully supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
@ -689,7 +695,7 @@ fi
# If Debian is detected, figure out which release it is and run the according scripts
if [ "${FLAVOUR}" == "debian" ]; then
CODE=$(lsb_release -s -c| tr [A-Z] [a-z])
CODE=$(lsb_release -s -c| tr '[:upper:]' '[:lower:]')
if [ "${CODE}" == "buster" ]; then
echo "Install on Debian testing fully supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"
@ -711,7 +717,7 @@ fi
# If Tsurugi is detected, figure out which release it is and run the according scripts
if [ "${FLAVOUR}" == "tsurugi" ]; then
CODE=$(lsb_release -s -c| tr [A-Z] [a-z])
CODE=$(lsb_release -s -c| tr '[:upper:]' '[:lower:]')
if [ "${CODE}" == "bamboo" ]; then
echo "Install on Tsurugi Lab partially supported."
echo "Please report bugs/issues here: https://github.com/MISP/MISP/issues"

View File

@ -1269,13 +1269,13 @@ INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modi
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, 0);
INSERT 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`, `default_role`)
VALUES (3, 'User', NOW(), NOW(), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1);
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);
INSERT 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`, `default_role`)
VALUES (4, 'Publisher', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0);
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, 0);
INSERT 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`, `default_role`)
VALUES (5, 'Sync user', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0);
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, 0);
INSERT 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`, `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);

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":108}
{"major":2, "minor":4, "hotfix":109}

View File

@ -46,10 +46,11 @@ class AppController extends Controller
public $helpers = array('Utility', 'OrgImg', 'FontAwesome');
private $__queryVersion = '71';
private $__queryVersion = '77';
public $pyMispVersion = '2.4.106';
public $phpmin = '7.0';
public $phprec = '7.2';
public $isApiAuthed = false;
public $baseurl = '';
public $sql_dump = false;
@ -251,6 +252,7 @@ class AppController extends Controller
}
$this->Session->renew();
$this->Session->write(AuthComponent::$sessionKey, $user['User']);
$this->isApiAuthed = true;
} else {
// User not authenticated correctly
// reset the session information
@ -502,6 +504,9 @@ class AppController extends Controller
$this->Log = ClassRegistry::init('Log');
echo json_encode($this->Log->getDataSource()->getLog(false, false), JSON_PRETTY_PRINT);
}
if ($this->isApiAuthed && $this->_isRest()) {
session_destroy();
}
}
public function queryACL($debugType='findMissingFunctionNames', $content = false)
@ -520,7 +525,7 @@ class AppController extends Controller
private function __convertEmailToName($email)
{
$name = explode('@', $email);
$name = explode('@', (string)$email);
$name = explode('.', $name[0]);
foreach ($name as $key => $value) {
$name[$key] = ucfirst($value);
@ -663,7 +668,7 @@ class AppController extends Controller
foreach ($options['paramArray'] as $p) {
if (
isset($options['ordered_url_params'][$p]) &&
(!in_array(strtolower($options['ordered_url_params'][$p]), array('null', '0', false, 'false', null)))
(!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]);

View File

@ -1277,7 +1277,7 @@ class AttributesController extends AppController
}
if ($this->request->is('ajax')) {
if ($this->request->is('post')) {
if ($this->__delete($id, $hard)) {
if ($this->Attribute->deleteAttribute($id, $this->Auth->user(), $hard)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Attribute deleted.')), 'status'=>200, 'type' => 'json'));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Attribute was not deleted.')), 'status'=>200, 'type' => 'json'));
@ -1291,7 +1291,7 @@ class AttributesController extends AppController
if (!$this->request->is('post') && !$this->_isRest()) {
throw new MethodNotAllowedException();
}
if ($this->__delete($id, $hard)) {
if ($this->Attribute->deleteAttribute($id, $this->Auth->user(), $hard)) {
if ($this->_isRest() || $this->response->type() === 'application/json') {
$this->set('message', 'Attribute deleted.');
$this->set('_serialize', array('message'));
@ -1360,77 +1360,6 @@ class AttributesController extends AppController
}
}
// unification of the actual delete for the multi-select
private function __delete($id, $hard = false)
{
$this->Attribute->id = $id;
if (!$this->Attribute->exists()) {
return false;
}
$result = $this->Attribute->find('first', array(
'conditions' => array('Attribute.id' => $id),
'fields' => array('Attribute.*'),
'contain' => array('Event' => array(
'fields' => array('Event.*')
)),
));
if (empty($result)) {
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
}
// check for permissions
if (!$this->_isSiteAdmin()) {
if ($result['Event']['locked']) {
if ($this->Auth->user('org_id') != $result['Event']['org_id'] || !$this->userRole['perm_sync']) {
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
}
} else {
if ($this->Auth->user('org_id') != $result['Event']['orgc_id']) {
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
}
}
}
$date = new DateTime();
if ($hard) {
$save = $this->Attribute->delete($id);
} else {
if (Configure::read('Security.sanitise_attribute_on_delete')) {
$result['Attribute']['category'] = 'Other';
$result['Attribute']['type'] = 'comment';
$result['Attribute']['value'] = 'deleted';
$result['Attribute']['comment'] = '';
$result['Attribute']['to_ids'] = 0;
}
$result['Attribute']['deleted'] = 1;
$result['Attribute']['timestamp'] = $date->getTimestamp();
$save = $this->Attribute->save($result);
$object_refs = $this->Attribute->Object->ObjectReference->find('all', array(
'conditions' => array(
'ObjectReference.referenced_type' => 0,
'ObjectReference.referenced_id' => $id,
),
'recursive' => -1
));
foreach ($object_refs as $ref) {
$ref['ObjectReference']['deleted'] = 1;
$this->Attribute->Object->ObjectReference->save($ref);
}
}
// attachment will be deleted with the beforeDelete() function in the Model
if ($save) {
// We have just deleted the attribute, let's also check if there are any shadow attributes that were attached to it and delete them
$this->loadModel('ShadowAttribute');
$this->ShadowAttribute->deleteAll(array('ShadowAttribute.old_id' => $id), false);
// remove the published flag from the event
$this->Attribute->Event->unpublishEvent($result['Event']['id']);
return true;
} else {
return false;
}
}
public function deleteSelected($id = false, $hard = false)
{
if (!$this->request->is('post')) {
@ -1497,11 +1426,11 @@ class AttributesController extends AppController
$successes = array();
foreach ($attributes as $a) {
if ($hard) {
if ($this->__delete($a['Attribute']['id'], true)) {
if ($this->Attribute->deleteAttribute($a['Attribute']['id'], $this->Auth->user(), true)) {
$successes[] = $a['Attribute']['id'];
}
} else {
if ($this->__delete($a['Attribute']['id'], $a['Attribute']['deleted'] == 1 ? true : false)) {
if ($this->Attribute->deleteAttribute($a['Attribute']['id'], $this->Auth->user(), $a['Attribute']['deleted'] == 1 ? true : false)) {
$successes[] = $a['Attribute']['id'];
}
}

View File

@ -75,6 +75,7 @@ class ACLComponent extends Component
'delete' => array(),
'edit' => array(),
'index' => array(),
'massDelete' => array()
),
'eventDelegations' => array(
'acceptDelegation' => array('perm_add'),
@ -250,6 +251,8 @@ class ACLComponent extends Component
'edit' => array('perm_add'),
'get_row' => array('perm_add'),
'orphanedObjectDiagnostics' => array(),
'proposeObjectsFromAttributes' => array('*'),
'groupAttributesIntoObject' => array('perm_add'),
'revise_object' => array('perm_add'),
'view' => array('*'),
),
@ -340,6 +343,7 @@ class ACLComponent extends Component
'getPyMISPVersion' => array('*'),
'getSubmodulesStatus' => array('perm_site_admin'),
'getSubmoduleQuickUpdateForm' => array('perm_site_admin'),
'getWorkers' => array(),
'getVersion' => array('*'),
'import' => ('perm_site_admin'),
'index' => array('OR' => array('perm_sync', 'perm_admin')),

View File

@ -47,7 +47,7 @@ class RestResponseComponent extends Component
Besides the parameters listed, other, format specific ones can be passed along (for example: requested_attributes and includeContext for the CSV export).
This API allows pagination via the page and limit parameters.",
'mandatory' => array('returnFormat'),
'optional' => array('page', 'limit', 'value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'includeEventTags', 'event_timestamp', 'threat_level_id', 'eventinfo', 'includeProposals'),
'optional' => array('page', 'limit', 'value' , 'type', 'category', 'org', 'tags', 'date', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'includeEventTags', 'event_timestamp', 'threat_level_id', 'eventinfo', 'includeProposals'),
'params' => array()
)
),
@ -75,7 +75,7 @@ class RestResponseComponent extends Component
Besides the parameters listed, other, format specific ones can be passed along (for example: requested_attributes and includeContext for the CSV export).
This API allows pagination via the page and limit parameters.",
'mandatory' => array('returnFormat'),
'optional' => array('page', 'limit', 'value', 'type', 'category', 'org', 'tag', 'tags', 'searchall', 'from', 'to', 'last', 'eventid', 'withAttachments', 'metadata', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'sgReferenceOnly', 'eventinfo'),
'optional' => array('page', 'limit', 'value', 'type', 'category', 'org', 'tag', 'tags', 'searchall', 'date', 'last', 'eventid', 'withAttachments', 'metadata', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'sgReferenceOnly', 'eventinfo'),
'params' => array()
)
),
@ -679,6 +679,7 @@ class RestResponseComponent extends Component
'todayHighlight' => true,
'autoclose' => true
),
'help' => 'The user set date field on the event level. If you are using restSearch, you can use any of the valid time related filters (examples: 7d, timestamps, [14d, 7d] for ranges, etc.)'
),
'datefrom' => array(
'type' => 'date',
@ -838,7 +839,7 @@ class RestResponseComponent extends Component
'autoclose' => true
),
'help' => 'The date from which the event was published'
),
),
'gpgkey' => array(
'input' => 'text',
'type' => 'string',
@ -1537,6 +1538,7 @@ class RestResponseComponent extends Component
break;
}
}
private function __overwriteCategory($scope, &$field) {
$field['values'] = array_keys(ClassRegistry::init("Attribute")->categoryDefinitions);
}

View File

@ -27,13 +27,25 @@ class EventBlacklistsController extends AppController
public function index()
{
$passedArgsArray = array();
$passedArgs = $this->passedArgs;
$params = array();
$validParams = array('event_uuid', 'comment');
$validParams = array('event_uuid', 'comment', 'event_info', 'event_orgc');
foreach ($validParams as $validParam) {
if (!empty($this->params['named'][$validParam])) {
$params[$validParam] = $this->params['named'][$validParam];
}
}
if (!empty($this->params['named']['searchall'])) {
$params['AND']['OR'] = array(
'event_uuid' => $this->params['named']['searchall'],
'comment' => $this->params['named']['searchall'],
'event_info' => $this->params['named']['searchall'],
'event_orgc' => $this->params['named']['searchall']
);
}
$this->set('passedArgs', json_encode($passedArgs));
$this->set('passedArgsArray', $passedArgsArray);
$this->BlackList->index($this->_isRest(), $params);
}
@ -51,4 +63,39 @@ class EventBlacklistsController extends AppController
{
$this->BlackList->delete($this->_isRest(), $id);
}
public function massDelete()
{
if ($this->request->is('post') || $this->request->is('put')) {
$ids = $this->request->data['EventBlacklist']['ids'];
$event_ids = json_decode($ids, true);
if (empty($event_ids)) {
throw new NotFoundException(__('Invalid event IDs.'));
}
$result = $this->EventBlacklist->deleteAll(array('EventBlacklist.id' => $event_ids));
if ($result) {
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('EventBlacklist', 'Deleted', $ids, $this->response->type());
} else {
$this->Flash->success('Blacklist entry removed');
$this->redirect(array('controller' => 'eventBlacklists', 'action' => 'index'));
}
} else {
$error = __('Failed to delete Event from EventBlacklist. Error: ') . PHP_EOL . h($result);
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('EventBlacklist', 'Deleted', false, $error, $this->response->type());
} else {
$this->Flash->error($error);
$this->redirect(array('controller' => 'eventBlacklists', 'action' => 'index'));
}
}
} else {
$ids = json_decode($this->request->query('ids'), true);
if (empty($ids)) {
throw new NotFoundException(__('Invalid event IDs.'));
}
$this->set('event_ids', $ids);
}
}
}

View File

@ -1549,6 +1549,8 @@ class EventsController extends AppController
$conditions['includeFeedCorrelations'] = 1;
if (!$this->_isRest()) {
$conditions['includeGranularCorrelations'] = 1;
} else if (!empty($this->params['named']['includeGranularCorrelations'])) {
$conditions['includeGranularCorrelations'] = 1;
}
if (!isset($this->params['named']['includeServerCorrelations'])) {
$conditions['includeServerCorrelations'] = 1;
@ -1559,6 +1561,28 @@ class EventsController extends AppController
$conditions['includeServerCorrelations'] = $this->params['named']['includeServerCorrelations'];
}
$results = $this->Event->fetchEvent($this->Auth->user(), $conditions);
if (!empty($this->params['named']['includeGranularCorrelations'])) {
foreach ($results as $k => $event) {
if (!empty($event['RelatedAttribute'])) {
foreach ($event['RelatedAttribute'] as $attribute_id => $relation) {
foreach ($event['Attribute'] as $k2 => $attribute) {
if ((int)$attribute['id'] == $attribute_id) {
$results[$k]['Attribute'][$k2]['RelatedAttribute'][] = $relation;
break 2;
}
}
foreach ($event['Object'] as $k2 => $object) {
foreach ($object['Attribute'] as $k3 => $attribute) {
if ((int)$attribute['id'] == $attribute_id) {
$results[$k]['Object'][$k2]['Attribute'][$k3]['RelatedAttribute'][] = $relation;
break 3;
}
}
}
}
}
}
}
if (empty($results)) {
throw new NotFoundException(__('Invalid event'));
}
@ -4913,7 +4937,12 @@ class EventsController extends AppController
throw new Exception("Invalid options.");
}
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores($eventId, $matrixTags);
$event = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $eventId, 'metadata' => true));
if (empty($event)) {
throw new NotFoundException(__('Event not found or you are not authorised to view it.'));
}
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores($this->Auth->user(), $eventId, $matrixTags);
$scoresDataEvent = $this->Event->EventTag->getTagScores($eventId, $matrixTags);
$maxScore = 0;
$scoresData = array();
@ -4967,6 +4996,7 @@ class EventsController extends AppController
}
// end FIXME
$this->Galaxy->sortMatrixByScore($tabs, $scores);
if ($this->_isRest()) {
$json = array('matrix' => $tabs, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
$this->response->type('json');

View File

@ -450,7 +450,7 @@ class GalaxyClustersController extends AppController
}
$maxScore = count($scores) > 0 ? max(array_values($scores)) : 0;
$matrixData = $this->GalaxyCluster->Galaxy->getMatrix($mitreAttackGalaxyId);
$matrixData = $this->GalaxyCluster->Galaxy->getMatrix($mitreAttackGalaxyId, $scores);
$tabs = $matrixData['tabs'];
$matrixTags = $matrixData['matrixTags'];
$killChainOrders = $matrixData['killChain'];

View File

@ -343,7 +343,11 @@ class LogsController extends AppController
'conditions' => $conditions,
'order' => array('Log.id' => 'DESC')
);
$this->set('list', $this->paginate());
$list = $this->paginate();
if (empty($this->Auth->user('Role')['perm_site_admin'])) {
$list = $this->Log->filterSiteAdminSensitiveLogs($list);
}
$this->set('list', $list);
// and store into session
$this->Session->write('paginate_conditions_log', $this->paginate);
@ -394,7 +398,11 @@ class LogsController extends AppController
}
$conditions = $this->__buildSearchConditions($filters);
$this->paginate['conditions'] = $conditions;
$this->set('list', $this->paginate());
$list = $this->paginate();
if (empty($this->Auth->user('Role')['perm_site_admin'])) {
$list = $this->Log->filterSiteAdminSensitiveLogs($list);
}
$this->set('list', $list);
// set the same view as the index page
$this->render('admin_index');

View File

@ -163,12 +163,22 @@ class ObjectTemplatesController extends AppController
public function index($all = false)
{
$passedArgsArray = array();
$passedArgs = $this->passedArgs;
if (!$all || !$this->_isSiteAdmin()) {
$this->paginate['conditions'][] = array('ObjectTemplate.active' => 1);
$this->set('all', false);
} else {
$this->set('all', true);
}
if (!empty($this->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']) . '%'
);
}
if ($this->_isRest()) {
$rules = $this->paginate;
unset($rules['limit']);
@ -180,6 +190,8 @@ class ObjectTemplatesController extends AppController
$objectTemplates = $this->paginate();
$this->set('list', $objectTemplates);
}
$this->set('passedArgs', json_encode($passedArgs));
$this->set('passedArgsArray', $passedArgsArray);
}
public function update($type = false, $force = false)

View File

@ -989,4 +989,154 @@ class ObjectsController extends AppController
$this->set('captured', $capturedObjects);
$this->set('unmapped', $unmappedAttributes);
}
function proposeObjectsFromAttributes($event_id, $selected_attributes='[]')
{
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This action can only be reached via AJAX.'));
}
$selected_attributes = json_decode($selected_attributes, true);
$res = $this->MispObject->validObjectsFromAttributeTypes($this->Auth->user(), $event_id, $selected_attributes);
$potential_templates = $res['templates'];
$attribute_types = $res['types'];
usort($potential_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;
}
});
$this->set('potential_templates', $potential_templates);
$this->set('selected_types', $attribute_types);
$this->set('event_id', $event_id);
}
function groupAttributesIntoObject($event_id, $selected_template, $selected_attribute_ids='[]')
{
$event = $this->MispObject->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.uuid', 'Event.orgc_id', 'Event.publish_timestamp'),
'conditions' => array('Event.id' => $event_id)
));
if (empty($event) || (!$this->_isSiteAdmin() && $event['Event']['orgc_id'] != $this->Auth->user('org_id'))) {
throw new NotFoundException(__('Invalid event.'));
}
$hard_delete_attribute = $event['Event']['publish_timestamp'] == 0;
if (!$this->request->is('ajax')) {
throw new MethodNotAllowedException(__('This action can only be reached via AJAX.'));
}
if ($this->request->is('post')) {
$template = $this->MispObject->ObjectTemplate->find('first', array(
'recursive' => -1,
'conditions' => array('ObjectTemplate.id' => $selected_template, 'ObjectTemplate.active' => true)
));
if (empty($template)) {
throw new NotFoundException(__('Invalid template.'));
}
$distribution = $this->request->data['Object']['distribution'];
$sharing_group_id = $this->request->data['Object']['sharing_group_id'];
$comment = $this->request->data['Object']['comment'];
$selected_attribute_ids = json_decode($this->request->data['Object']['selectedAttributeIds'], true);
$selected_object_relation_mapping = json_decode($this->request->data['Object']['selectedObjectRelationMapping'], true);
if ($distribution == 4) {
$sg = $this->MispObject->SharingGroup->find('first', array(
'conditions' => array('SharingGroup.id' => $sharing_group_id),
'recursive' => -1,
'fields' => array('SharingGroup.id', 'SharingGroup.name'),
'order' => false
));
if (empty($sg)) {
throw new NotFoundException(__('Invalid sharing group.'));
}
} else {
$sharing_group_id = 0;
}
$object = array(
'Object' => array(
'distribution' => $distribution,
'sharing_group_id' => $sharing_group_id,
'comment' => $comment,
),
'Attribute' => array()
);
$result = $this->MispObject->groupAttributesIntoObject($this->Auth->user(), $event_id, $object, $template, $selected_attribute_ids, $selected_object_relation_mapping, $hard_delete_attribute);
if (is_numeric($result)) {
$this->MispObject->Event->unpublishEvent($event_id);
return $this->RestResponse->saveSuccessResponse('Objects', 'Created from Attributes', $result, $this->response->type());
} else {
$error = __('Failed to create an Object from Attributes. Error: ') . PHP_EOL . h($result);
return $this->RestResponse->saveFailResponse('Objects', 'Created from Attributes', false, $error, $this->response->type());
}
} else {
$selected_attribute_ids = json_decode($selected_attribute_ids, true);
$selected_attributes = $this->MispObject->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array(
'Attribute.id' => $selected_attribute_ids,
'Attribute.event_id' => $event_id,
'Attribute.object_id' => 0
)));
if (empty($selected_attributes)) {
throw new MethodNotAllowedException(__('No Attribute selected.'));
}
$template = $this->MispObject->ObjectTemplate->find('first', array(
'recursive' => -1,
'conditions' => array('ObjectTemplate.id' => $selected_template, 'ObjectTemplate.active' => true),
'contain' => 'ObjectTemplateElement'
));
if (empty($template)) {
throw new NotFoundException(__('Invalid template.'));
}
$conformity_result = $this->MispObject->ObjectTemplate->checkTemplateConformityBasedOnTypes($template, $selected_attributes);
$skipped_attributes = 0;
foreach ($selected_attributes as $i => $attribute) {
if (in_array($attribute['Attribute']['type'], $conformity_result['invalidTypes'])) {
unset($selected_attributes[$i]);
$array_position = array_search($attribute['Attribute']['id'], $selected_attribute_ids);
unset($selected_attribute_ids[$array_position]);
$skipped_attributes++;
}
}
$object_relations = array();
foreach ($template['ObjectTemplateElement'] as $template_element) {
$object_relations[$template_element['type']][] = $template_element;
}
$object_references = $this->MispObject->ObjectReference->find('all', array(
'conditions' => array(
'ObjectReference.referenced_id' => $selected_attribute_ids,
),
'recursive' => -1
));
foreach ($object_references as $i => $object_reference) {
$temp_object = $this->MispObject->find('first', array('id' => $object_reference['ObjectReference']['object_id'], 'recursive' => -1));
$temp_attribute = $this->MispObject->Attribute->find('first', array('id' => $object_reference['ObjectReference']['referenced_id'], 'recursive' => -1));
if (!empty($temp_object) && !empty($temp_attribute)) {
$temp_object = $temp_object['Object'];
$temp_attribute = $temp_attribute['Attribute'];
$object_references[$i]['ObjectReference']['object_name'] = $temp_object['name'];
$object_references[$i]['ObjectReference']['attribute_name'] = sprintf('%s/%s: "%s"', $temp_attribute['category'], $temp_attribute['type'], $temp_attribute['value']);
}
}
$distributionData = $this->MispObject->Event->Attribute->fetchDistributionData($this->Auth->user());
$this->set('event_id', $event_id);
$this->set('hard_delete_attribute', $hard_delete_attribute);
$this->set('distributionData', $distributionData);
$this->set('distributionLevels', $this->MispObject->Attribute->distributionLevels);
$this->set('selectedTemplateTd', $selected_template);
$this->set('selectedAttributeIds', $selected_attribute_ids);
$this->set('template', $template);
$this->set('object_relations', $object_relations);
$this->set('attributes', $selected_attributes);
$this->set('skipped_attributes', $skipped_attributes);
$this->set('object_references', $object_references);
}
}
}

View File

@ -1103,7 +1103,13 @@ class ServersController extends AppController
} else {
shell_exec($prepend . APP . 'Console' . DS . 'cake CakeResque.CakeResque startscheduler -i 5 > /dev/null 2>&1 &');
}
$this->redirect('/servers/serverSettings/workers');
$message = __('Worker start signal sent');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Servers', 'startWorker', $type, $this->response->type(), $message);
} else {
$this->Flash->info($message);
$this->redirect('/servers/serverSettings/workers');
}
}
public function stopWorker($pid)
@ -1112,7 +1118,20 @@ class ServersController extends AppController
throw new MethodNotAllowedException();
}
$this->Server->killWorker($pid, $this->Auth->user());
$this->redirect('/servers/serverSettings/workers');
$message = __('Worker stop signal sent');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Servers', 'stopWorker', $pid, $this->response->type(), $message);
} else {
$this->Flash->info($message);
$this->redirect('/servers/serverSettings/workers');
}
}
public function getWorkers()
{
$issues = 0;
$worker_array = $this->Server->workerDiagnostics($issues);
return $this->RestResponse->viewData($worker_array);
}
private function __checkVersion()
@ -1168,6 +1187,9 @@ class ServersController extends AppController
}
$setting = $this->Server->getSettingData($setting_name);
if (!empty($setting['cli_only'])) {
throw new MethodNotAllowedException(__('This setting can only be edited via the CLI.'));
}
if ($this->request->is('get')) {
if ($setting != null) {
$value = Configure::read($setting['name']);

View File

@ -19,7 +19,7 @@ class UsersController extends AppController
),
'contain' => array(
'Organisation' => array('id', 'name'),
'Role' => array('id', 'name', 'perm_auth')
'Role' => array('id', 'name', 'perm_auth', 'perm_site_admin')
)
);
@ -350,11 +350,16 @@ class UsersController extends AppController
),
'contain' => array(
'Organisation' => array('id', 'name'),
'Role' => array('id', 'name', 'perm_auth')
'Role' => array('id', 'name', 'perm_auth', 'perm_site_admin')
)
));
foreach ($users as $key => $value) {
unset($users['User']['password']);
if (empty($this->Auth->user('Role')['perm_site_admin'])) {
if ($value['Role']['perm_site_admin']) {
$users[$key]['User']['authkey'] = __('Redacted');
}
}
unset($users[$key]['User']['password']);
}
return $this->RestResponse->viewData($users, $this->response->type());
} else {
@ -366,7 +371,13 @@ class UsersController extends AppController
} else {
$conditions['User.org_id'] = $this->Auth->user('org_id');
$this->paginate['conditions']['AND'][] = $conditions;
$this->set('users', $this->paginate());
$users = $this->paginate();
foreach ($users as $key => $value) {
if ($value['Role']['perm_site_admin']) {
$users[$key]['User']['authkey'] = __('Redacted');
}
}
$this->set('users', $users);
}
if ($this->request->is('ajax')) {
$this->autoRender = false;
@ -462,6 +473,9 @@ class UsersController extends AppController
$user['User']['fingerprint'] = !empty($pgpDetails[4]) ? $pgpDetails[4] : 'N/A';
}
$user['User']['orgAdmins'] = $this->User->getOrgAdminsForOrg($user['User']['org_id'], $user['User']['id']);
if (empty($this->Auth->user('Role')['perm_site_admin']) && !(empty($user['Role']['perm_site_admin']))) {
$user['User']['authkey'] = __('Redacted');
}
$this->set('user', $user);
if (!$this->_isSiteAdmin() && !($this->_isAdmin() && $this->Auth->user('org_id') == $user['User']['org_id'])) {
throw new MethodNotAllowedException();
@ -694,9 +708,10 @@ class UsersController extends AppController
$params = array();
$allowedRole = '';
$userToEdit = $this->User->find('first', array(
'conditions' => array('id' => $id),
'conditions' => array('User.id' => $id),
'recursive' => -1,
'fields' => array('id', 'role_id', 'email', 'org_id'),
'fields' => array('User.id', 'User.role_id', 'User.email', 'User.org_id', 'Role.perm_site_admin'),
'contain' => array('Role')
));
if (!$this->_isSiteAdmin()) {
// Org admins should be able to select the role that is already assigned to an org user when editing them.
@ -706,8 +721,8 @@ class UsersController extends AppController
// MISP automatically chooses the first available option for the user as the selected setting (usually user)
// Org admin is downgraded to a user
// Now we make an exception for the already assigned role, both in the form and the actual edit.
if ($userToEdit['User']['org_id'] != $this->Auth->user('org_id')) {
throw new Exception('Invalid user');
if ($userToEdit['User']['org_id'] != $this->Auth->user('org_id') || !empty($userToEdit['Role']['perm_site_admin'])) {
throw new NotFoundException(__('Invalid user'));
}
$allowedRole = $userToEdit['User']['role_id'];
$params = array('conditions' => array(
@ -1906,94 +1921,149 @@ class UsersController extends AppController
} else {
$galaxy_id = $mitre_galaxy_id;
}
$matrixData = $this->Galaxy->getMatrix($galaxy_id);
$tabs = $matrixData['tabs'];
$matrixTags = $matrixData['matrixTags'];
$killChainOrders = $matrixData['killChain'];
$instanceUUID = $matrixData['instance-uuid'];
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores(0, $matrixTags);
$scoresDataEvent = $this->Event->EventTag->getTagScores(0, $matrixTags);
$scoresData = array();
foreach (array_keys($scoresDataAttr['scores'] + $scoresDataEvent['scores']) as $key) {
$scoresData[$key] = (isset($scoresDataAttr['scores'][$key]) ? $scoresDataAttr['scores'][$key] : 0) + (isset($scoresDataEvent['scores'][$key]) ? $scoresDataEvent['scores'][$key] : 0);
$organisations = $this->User->Organisation->find('all', array(
'recursive' => -1,
));
array_unshift($organisations, array('Organisation' => array('id' => 0, 'name' => 'All')));
$this->set('organisations', $organisations);
$picked_organisation = 0;
if (isset($params['organisation']) && $params['organisation'] != 0) {
$org = $this->User->Organisation->find('first', array(
'recursive' => -1,
'conditions' => array('id' => $params['organisation']),
));
if (!empty($org)) {
$picked_organisation = $org;
$this->set('picked_organisation', $picked_organisation);
} else {
$this->set('picked_organisation', array('Organisation' => array('id' => '')));
}
} else {
$this->set('picked_organisation', array('Organisation' => array('id' => '')));
}
$maxScore = max($scoresDataAttr['maxScore'], $scoresDataEvent['maxScore']);
$scores = $scoresData;
// FIXME: temporary fix: add the score of deprecated mitre galaxies to the new one (for the stats)
if ($matrixData['galaxy']['id'] == $mitre_galaxy_id) {
$mergedScore = array();
foreach ($scoresData as $tag => $v) {
$predicateValue = explode(':', $tag, 2)[1];
$predicateValue = explode('=', $predicateValue, 2);
$predicate = $predicateValue[0];
$clusterValue = $predicateValue[1];
$mappedTag = '';
$mappingWithoutExternalId = array();
if ($predicate == 'mitre-attack-pattern') {
$mappedTag = $tag;
$name = explode(" ", $tag);
$name = join(" ", array_slice($name, 0, -2)); // remove " - external_id"
$mappingWithoutExternalId[$name] = $tag;
} else {
$name = explode(" ", $clusterValue);
$name = join(" ", array_slice($name, 0, -2)); // remove " - external_id"
if (isset($mappingWithoutExternalId[$name])) {
$mappedTag = $mappingWithoutExternalId[$name];
$rest_response_empty = true;
$ignore_score = false;
if (
isset($params['dateFrom'])
|| isset($params['dateTo'])
|| isset($params['organisation']) && $params['organisation'] != 0
) { // use restSearch
$ignore_score = true;
$filters = array();
if (isset($params['dateFrom'])) {
$filters['from'] = $params['dateFrom'];
$this->set('dateFrom', $params['dateFrom']);
}
if (isset($params['dateTo'])) {
$filters['to'] = $params['dateTo'];
$this->set('dateTo', $params['dateTo']);
}
if (isset($params['organisation'])) {
$filters['org'] = $params['organisation'];
}
$elementCounter = 0;
$renderView = '';
$final = $this->Event->restSearch($this->Auth->user(), 'attack', $filters, false, false, $elementCounter, $renderView);
$final = json_decode($final, true);
if (!empty($final)) {
$rest_response_empty = false;
foreach ($final as $key => $data) {
$this->set($key, $data);
}
}
}
// No need for restSearch or result is empty
if ($rest_response_empty) {
$matrixData = $this->Galaxy->getMatrix($galaxy_id);
$tabs = $matrixData['tabs'];
$matrixTags = $matrixData['matrixTags'];
$killChainOrders = $matrixData['killChain'];
$instanceUUID = $matrixData['instance-uuid'];
if ($ignore_score) {
$scores_uniform = array('scores' => array(), 'maxScore' => 0);
} else {
$scores_uniform = $this->Event->EventTag->getTagScoresUniform(0, $matrixTags);
}
$scores = $scores_uniform['scores'];
$maxScore = $scores_uniform['maxScore'];
// FIXME: temporary fix: add the score of deprecated mitre galaxies to the new one (for the stats)
if ($matrixData['galaxy']['id'] == $mitre_galaxy_id) {
$mergedScore = array();
foreach ($scores as $tag => $v) {
$predicateValue = explode(':', $tag, 2)[1];
$predicateValue = explode('=', $predicateValue, 2);
$predicate = $predicateValue[0];
$clusterValue = $predicateValue[1];
$mappedTag = '';
$mappingWithoutExternalId = array();
if ($predicate == 'mitre-attack-pattern') {
$mappedTag = $tag;
$name = explode(" ", $tag);
$name = join(" ", array_slice($name, 0, -2)); // remove " - external_id"
$mappingWithoutExternalId[$name] = $tag;
} else {
$adjustedTagName = $this->Galaxy->GalaxyCluster->find('list', array(
'group' => array('GalaxyCluster.id', 'GalaxyCluster.tag_name'),
'conditions' => array('GalaxyCluster.tag_name LIKE' => 'misp-galaxy:mitre-attack-pattern=' . $name . '% T%'),
'fields' => array('GalaxyCluster.tag_name')
));
$adjustedTagName = array_values($adjustedTagName)[0];
$mappingWithoutExternalId[$name] = $adjustedTagName;
$mappedTag = $mappingWithoutExternalId[$name];
$name = explode(" ", $clusterValue);
$name = join(" ", array_slice($name, 0, -2)); // remove " - external_id"
if (isset($mappingWithoutExternalId[$name])) {
$mappedTag = $mappingWithoutExternalId[$name];
} else {
$adjustedTagName = $this->Galaxy->GalaxyCluster->find('list', array(
'group' => array('GalaxyCluster.id', 'GalaxyCluster.tag_name'),
'conditions' => array('GalaxyCluster.tag_name LIKE' => 'misp-galaxy:mitre-attack-pattern=' . $name . '% T%'),
'fields' => array('GalaxyCluster.tag_name')
));
if (!empty($adjustedTagName)) {
$adjustedTagName = array_values($adjustedTagName)[0];
$mappingWithoutExternalId[$name] = $adjustedTagName;
$mappedTag = $mappingWithoutExternalId[$name];
}
}
}
if (isset($mergedScore[$mappedTag])) {
$mergedScore[$mappedTag] += $v;
} else {
$mergedScore[$mappedTag] = $v;
}
}
$scores = $mergedScore;
$maxScore = !empty($mergedScore) ? max(array_values($mergedScore)) : 0;
}
// end FIXME
if (isset($mergedScore[$mappedTag])) {
$mergedScore[$mappedTag] += $v;
} else {
$mergedScore[$mappedTag] = $v;
$this->Galaxy->sortMatrixByScore($tabs, $scores);
if ($this->_isRest()) {
$json = array('matrix' => $tabs, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
return $this->RestResponse->viewData($json, $this->response->type());
} else {
App::uses('ColourGradientTool', 'Tools');
$gradientTool = new ColourGradientTool();
$colours = $gradientTool->createGradientFromValues($scores);
$this->set('target_type', 'attribute');
$this->set('columnOrders', $killChainOrders);
$this->set('tabs', $tabs);
$this->set('scores', $scores);
$this->set('maxScore', $maxScore);
if (!empty($colours)) {
$this->set('colours', $colours['mapping']);
$this->set('interpolation', $colours['interpolation']);
}
$this->set('pickingMode', false);
if ($matrixData['galaxy']['id'] == $mitre_galaxy_id) {
$this->set('defaultTabName', "mitre-attack");
$this->set('removeTrailling', 2);
}
$this->set('galaxyName', $matrixData['galaxy']['name']);
$this->set('galaxyId', $matrixData['galaxy']['id']);
$matrixGalaxies = $this->Galaxy->getAllowedMatrixGalaxies();
$this->set('matrixGalaxies', $matrixGalaxies);
}
$scores = $mergedScore;
$maxScore = max(array_values($mergedScore));
}
// end FIXME
if ($this->_isRest()) {
$json = array('matrix' => $tabs, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
return $this->RestResponse->viewData($json, $this->response->type());
} else {
App::uses('ColourGradientTool', 'Tools');
$gradientTool = new ColourGradientTool();
$colours = $gradientTool->createGradientFromValues($scores);
$this->set('target_type', 'attribute');
$this->set('columnOrders', $killChainOrders);
$this->set('tabs', $tabs);
$this->set('scores', $scores);
$this->set('maxScore', $maxScore);
if (!empty($colours)) {
$this->set('colours', $colours['mapping']);
$this->set('interpolation', $colours['interpolation']);
}
$this->set('pickingMode', false);
if ($matrixData['galaxy']['id'] == $mitre_galaxy_id) {
$this->set('defaultTabName', "mitre-attack");
$this->set('removeTrailling', 2);
}
$this->set('galaxyName', $matrixData['galaxy']['name']);
$this->set('galaxyId', $matrixData['galaxy']['id']);
$matrixGalaxies = $this->Galaxy->getAllowedMatrixGalaxies();
$this->set('matrixGalaxies', $matrixGalaxies);
$this->render('statistics_galaxymatrix');
}
$this->render('statistics_galaxymatrix');
}
public function verifyGPG($full = false)

View File

@ -11,6 +11,7 @@ class AttackExport
public $non_restrictive_export = true;
public $renderView = 'attack_view';
private $__matrixData = null;
private $__clusterCounts = array();
private $__attackGalaxy = 'mitre-attack-pattern';
private $__galaxy_id = 0;
@ -20,7 +21,6 @@ class AttackExport
private $__matrixTags = false;
private $__killChainOrders = false;
private $__instanceUUID = false;
private $__scope = 'Event';
public function handler($data, $options = array())
{
@ -28,35 +28,34 @@ class AttackExport
$this->__GalaxyModel = ClassRegistry::init('Galaxy');
}
$this->__attackGalaxy = empty($options['filters']['attackGalaxy']) ? $this->__attackGalaxy : $options['filters']['attackGalaxy'];
$temp = $this->__GalaxyModel->find('first', array(
if (empty($this->__galaxy_id)) {
$temp = $this->__GalaxyModel->find('first', array(
'recursive' => -1,
'fields' => array('id', 'name'),
'conditions' => array('Galaxy.type' => $this->__attackGalaxy, 'Galaxy.namespace !=' => 'deprecated'),
));
if (empty($temp)) {
return '';
} else {
$this->__galaxy_id = $temp['Galaxy']['id'];
$this->__galaxy_name = $temp['Galaxy']['name'];
}
$matrixData = $this->__GalaxyModel->getMatrix($this->__galaxy_id);
if (empty($this->__tabs)) {
$this->__tabs = $matrixData['tabs'];
$this->__matrixTags = $matrixData['matrixTags'];
$this->__killChainOrders = $matrixData['killChain'];
$this->__instanceUUID = $matrixData['instance-uuid'];
}
$this->__scope = empty($options['scope']) ? 'Event' : $options['scope'];
$clusterData = array();
if ($this->__scope === 'Event') {
$clusterData = $this->__aggregate($data, $clusterData);
if (!empty($data['Attribute'])) {
foreach ($data['Attribute'] as $attribute) {
$clusterData = $this->__aggregate($attribute, $clusterData);
}
));
if (empty($temp)) {
return '';
} else {
$this->__galaxy_id = $temp['Galaxy']['id'];
$this->__galaxy_name = $temp['Galaxy']['name'];
}
}
if (empty($this->__matrixData)) {
$this->__matrixData = $this->__GalaxyModel->getMatrix($this->__galaxy_id);
}
if (empty($this->__tabs)) {
$this->__tabs = $this->__matrixData['tabs'];
$this->__matrixTags = $this->__matrixData['matrixTags'];
$this->__killChainOrders = $this->__matrixData['killChain'];
$this->__instanceUUID = $this->__matrixData['instance-uuid'];
}
$clusterData = $this->__aggregate($data, array());
if (!empty($data['Attribute'])) {
foreach ($data['Attribute'] as $attribute) {
$clusterData = $this->__aggregate($attribute, $clusterData);
}
} else {
$clusterData = $this->__aggregate($data, $clusterData);
}
foreach ($clusterData as $key => $value) {
@ -99,11 +98,12 @@ class AttackExport
$maxScore = $clusterCount;
}
}
$this->__GalaxyModel->sortMatrixByScore($this->__tabs, $this->__clusterCounts);
App::uses('ColourGradientTool', 'Tools');
$gradientTool = new ColourGradientTool();
$colours = $gradientTool->createGradientFromValues($this->__clusterCounts);
$result = array(
'target_type' => strtolower($this->__scope),
'target_type' => 'event',
'columnOrders' => $this->__killChainOrders,
'tabs' => $this->__tabs,
'scores' => $this->__clusterCounts,
@ -114,6 +114,10 @@ class AttackExport
$result['colours'] = $colours['mapping'];
$result['interpolation'] = $colours['interpolation'];
}
if ($this->__galaxy_id == $this->__GalaxyModel->getMitreAttackGalaxyId()) {
$result['defaultTabName'] = 'mitre-attack';
$result['removeTrailling'] = 2;
}
$result['galaxyName'] = $this->__galaxy_name;
$result['galaxyId'] = $this->__galaxy_id;
$matrixGalaxies = $this->__GalaxyModel->getAllowedMatrixGalaxies();

View File

@ -392,8 +392,7 @@ class Attribute extends AppModel
'yara-json' => array('json', 'YaraExport', 'json'),
'rpz' => array('txt', 'RPZExport', 'rpz'),
'csv' => array('csv', 'CsvExport', 'csv'),
'cache' => array('txt', 'CacheExport', 'cache'),
'attack' => array('html', 'AttackExport', 'html')
'cache' => array('txt', 'CacheExport', 'cache')
);
// FIXME we need a better way to list the defaultCategories knowing that new attribute types will continue to appear in the future. We should generate this dynamically or use a function using the default_category of the $typeDefinitions
@ -1478,9 +1477,6 @@ class Attribute extends AppModel
$value = strtolower($value);
str_replace(':', '|', $value);
break;
case 'float':
$value = floatval($value);
break;
case 'hex':
$value = strtoupper($value);
break;
@ -3168,8 +3164,10 @@ class Attribute extends AppModel
}
if (!empty($results[$key])) {
if (!empty($options['includeGalaxy'])) {
$results[$key] = $this->Event->massageTags($results[$key], 'Attribute');
$results[$key] = $this->Event->massageTags($results[$key], 'Event');
$massaged_attribute = $this->Event->massageTags($results[$key], 'Attribute');
$massaged_event = $this->Event->massageTags($results[$key], 'Event');
$massaged_attribute['Galaxy'] = array_merge_recursive($massaged_attribute['Galaxy'], $massaged_event['Galaxy']);
$results[$key] = $massaged_attribute;
}
$attributes[] = $results[$key];
}
@ -3470,7 +3468,7 @@ class Attribute extends AppModel
return $conditions;
}
public function setTimestampConditions($timestamp, $conditions, $scope = 'Event.timestamp')
public function setTimestampConditions($timestamp, $conditions, $scope = 'Event.timestamp', $returnRaw = false)
{
if (is_array($timestamp)) {
$timestamp[0] = intval($this->Event->resolveTimeDelta($timestamp[0]));
@ -3486,6 +3484,9 @@ class Attribute extends AppModel
$timestamp = intval($this->Event->resolveTimeDelta($timestamp));
$conditions['AND'][] = array($scope . ' >=' => $timestamp);
}
if ($returnRaw) {
return $timestamp;
}
return $conditions;
}
@ -3800,7 +3801,6 @@ class Attribute extends AppModel
} else {
$date = new DateTime();
$attribute['timestamp'] = $date->getTimestamp();
;
}
} else {
$this->create();
@ -3906,6 +3906,72 @@ class Attribute extends AppModel
return true;
}
public function deleteAttribute($id, $user, $hard = false)
{
$this->id = $id;
if (!$this->exists()) {
return false;
}
$result = $this->find('first', array(
'conditions' => array('Attribute.id' => $id),
'recursive' => -1,
'contain' => array('Event')
));
if (empty($result)) {
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
}
// check for permissions
if (!$user['Role']['perm_site_admin']) {
if ($result['Event']['locked']) {
if ($user['org_id'] != $result['Event']['org_id'] || !$user['Role']['perm_sync']) {
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
}
} else {
if ($user['org_id'] != $result['Event']['orgc_id']) {
throw new MethodNotAllowedException(__('Attribute not found or not authorised.'));
}
}
}
$date = new DateTime();
if ($hard) {
$save = $this->delete($id);
} else {
if (Configure::read('Security.sanitise_attribute_on_delete')) {
$result['Attribute']['category'] = 'Other';
$result['Attribute']['type'] = 'comment';
$result['Attribute']['value'] = 'deleted';
$result['Attribute']['comment'] = '';
$result['Attribute']['to_ids'] = 0;
}
$result['Attribute']['deleted'] = 1;
$result['Attribute']['timestamp'] = $date->getTimestamp();
$save = $this->save($result);
$object_refs = $this->Object->ObjectReference->find('all', array(
'conditions' => array(
'ObjectReference.referenced_type' => 0,
'ObjectReference.referenced_id' => $id,
),
'recursive' => -1
));
foreach ($object_refs as $ref) {
$ref['ObjectReference']['deleted'] = 1;
$this->Object->ObjectReference->save($ref);
}
}
// attachment will be deleted with the beforeDelete() function in the Model
if ($save) {
// We have just deleted the attribute, let's also check if there are any shadow attributes that were attached to it and delete them
$this->Event->ShadowAttribute->deleteAll(array('ShadowAttribute.old_id' => $id), false);
// remove the published flag from the event
$this->Event->unpublishEvent($result['Event']['id']);
return true;
} else {
return false;
}
}
public function attachValidationWarnings($adata)
{
if (!$this->__fTool) {
@ -3955,6 +4021,7 @@ class Attribute extends AppModel
'ignore' => array('function' => 'set_filter_ignore'),
'from' => array('function' => 'set_filter_timestamp'),
'to' => array('function' => 'set_filter_timestamp'),
'date' => array('function' => 'set_filter_date'),
'tags' => array('function' => 'set_filter_tags'),
'last' => array('function' => 'set_filter_timestamp', 'pop' => true),
'timestamp' => array('function' => 'set_filter_timestamp', 'pop' => true),

View File

@ -111,45 +111,58 @@ class AttributeTag extends AppModel
));
}
public function getTagScores($eventId=0, $allowedTags=array())
// Fetch all tags attached to attribute belonging to supplied event. No ACL if user not provided
public function getTagScores($user=false, $eventId=0, $allowedTags=array())
{
// get score of galaxy
$db = $this->getDataSource();
$statementArray = array(
'fields' => array('attr_tag.tag_id as id', 'count(attr_tag.tag_id) as value'),
'table' => $db->fullTableName($this),
'alias' => 'attr_tag',
'group' => 'tag_id'
);
if ($eventId != 0) {
$statementArray['conditions'] = array('event_id' => $eventId);
}
// tag along with its occurence in the event
$subQuery = $db->buildStatement(
$statementArray,
$this
);
$subQueryExpression = $db->expression($subQuery)->value;
// get related galaxies
$attributeTagScores = $this->query("SELECT name, value FROM (" . $subQueryExpression . ") AS score, tags WHERE tags.id=score.id;");
// arrange data
$scores = array();
$maxScore = 0;
foreach ($attributeTagScores as $item) {
$score = $item['score']['value'];
$name = $item['tags']['name'];
if (in_array($name, $allowedTags)) {
$maxScore = $score > $maxScore ? $score : $maxScore;
$scores[$name] = $score;
if ($user === false) {
$conditions = array('Tag.id !=' => null);
if ($eventId != 0) {
$conditions['event_id'] = $eventId;
}
$attribute_tag_scores = $this->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'contain' => array(
'Tag' => array(
'conditions' => array('name' => $allowedTags)
)
),
'fields' => array('Tag.name', 'AttributeTag.event_id')
));
$scores = array('scores' => array(), 'maxScore' => 0);
foreach ($attribute_tag_scores as $attribute_tag_score) {
$tag_name = $attribute_tag_score['Tag']['name'];
if (!isset($scores['scores'][$tag_name])) {
$scores['scores'][$tag_name] = 0;
}
$scores['scores'][$tag_name]++;
$scores['maxScore'] = $scores['scores'][$tag_name] > $scores['maxScore'] ? $scores['scores'][$tag_name] : $scores['maxScore'];
}
} else {
$allowed_tag_lookup_table = array_flip($allowedTags);
$attributes = $this->Attribute->fetchAttributes($user, array('conditions' => array(
'Attribute.event_id' => $eventId
)));
$scores = array('scores' => array(), 'maxScore' => 0);
foreach ($attributes as $attribute) {
foreach ($attribute['AttributeTag'] as $tag) {
$tag_name = $tag['Tag']['name'];
if (isset($allowed_tag_lookup_table[$tag_name])) {
if (!isset($scores['scores'][$tag_name])) {
$scores['scores'][$tag_name] = 0;
}
$scores['scores'][$tag_name]++;
$scores['maxScore'] = $scores['scores'][$tag_name] > $scores['maxScore'] ? $scores['scores'][$tag_name] : $scores['maxScore'];
}
}
}
}
return array('scores' => $scores, 'maxScore' => $maxScore);
return $scores;
}
// find all tags that belong to a list of attributes (contained in the same event)
public function getAttributesTags($user, $requestedEventId, $attributeIds=false) {
public function getAttributesTags($user, $requestedEventId, $attributeIds=false, $includeGalaxies=false) {
$conditions = array('Attribute.event_id' => $requestedEventId);
if (is_array($attributeIds) && $attributeIds !== false) {
$conditions['Attribute.id'] = $attributeIds;
@ -169,12 +182,11 @@ class AttributeTag extends AppModel
'recursive' => -1,
'fields' => array('GalaxyCluster.tag_name', 'GalaxyCluster.id'),
));
$allTags = array();
foreach ($attributes as $attribute) {
$attributeTags = $attribute['AttributeTag'];
foreach ($attributeTags as $k => $attributeTag) {
if (!isset($cluster_names[$attributeTag['Tag']['name']])) {
if ($includeGalaxies || !isset($cluster_names[$attributeTag['Tag']['name']])) {
$allTags[$attributeTag['Tag']['id']] = $attributeTag['Tag'];
}
}

View File

@ -1590,6 +1590,7 @@ class Event extends AppModel
'tags' => array('function' => 'set_filter_tags'),
'from' => array('function' => 'set_filter_timestamp', 'pop' => true),
'to' => array('function' => 'set_filter_timestamp', 'pop' => true),
'date' => array('function' => 'set_filter_date', 'pop' => true),
'last' => array('function' => 'set_filter_timestamp', 'pop' => true),
'timestamp' => array('function' => 'set_filter_timestamp', 'pop' => true),
'event_timestamp' => array('function' => 'set_filter_timestamp', 'pop' => true),
@ -2637,6 +2638,18 @@ class Event extends AppModel
return $conditions;
}
public function set_filter_date(&$params, $conditions, $options)
{
$timestamp = $this->Attribute->setTimestampConditions($params[$options['filter']], $conditions, 'Event.date', true);
if (!is_array($timestamp)) {
$conditions['AND']['Event.date >='] = date('Y-m-d', $timestamp);
} else {
$conditions['AND']['Event.date >='] = date('Y-m-d', $timestamp[0]);
$conditions['AND']['Event.date <='] = date('Y-m-d', $timestamp[1]);
}
return $conditions;
}
public function csv($user, $params, $search = false, &$continue = true)
{
$conditions = array();

View File

@ -154,7 +154,7 @@ class EventTag extends AppModel
}
return $tags;
}
public function countForTag($tag_id, $user)
{
return $this->find('count', array(
@ -163,39 +163,96 @@ class EventTag extends AppModel
));
}
public function getTagScores($eventId=0, $allowedTags=array())
public function getTagScores($eventId=0, $allowedTags=array(), $propagateToAttribute=false)
{
// get score of galaxy
$db = $this->getDataSource();
$statementArray = array(
'fields' => array('event_tag.tag_id as id', 'count(event_tag.tag_id) as value'),
'table' => $db->fullTableName($this),
'alias' => 'event_tag',
'group' => 'tag_id'
);
if ($eventId != 0) {
$statementArray['conditions'] = array('event_id' => $eventId);
if ($propagateToAttribute) {
$eventTagScores = $this->find('all', array(
'recursive' => -1,
'conditions' => array('Tag.id !=' => null),
'contain' => array(
'Event',
'Tag' => array(
'conditions' => array('name' => $allowedTags)
)
),
'fields' => array('Tag.name', 'Event.attribute_count')
));
} else {
$conditions = array('Tag.id !=' => null);
if ($eventId != 0) {
$conditions['event_id'] = $eventId;
}
$eventTagScores = $this->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'contain' => array(
'Tag' => array(
'conditions' => array('name' => $allowedTags)
)
),
'group' => 'tag_id',
'fields' => array('Tag.name', 'EventTag.tag_id', 'count(EventTag.tag_id) as score')
));
}
// tag along with its occurence in the event
$subQuery = $db->buildStatement(
$statementArray,
$this
);
$subQueryExpression = $db->expression($subQuery)->value;
// get related galaxies
$attributeTagScores = $this->query("SELECT name, value FROM (" . $subQueryExpression . ") AS score, tags WHERE tags.id=score.id;");
// arrange data
$scores = array();
$maxScore = 0;
foreach ($attributeTagScores as $item) {
$score = $item['score']['value'];
$name = $item['tags']['name'];
foreach ($eventTagScores as $item) {
$score = isset($item['Event']) ? $item['Event']['attribute_count'] : $item[0]['score'];
$name = $item['Tag']['name'];
if (in_array($name, $allowedTags)) {
$maxScore = $score > $maxScore ? $score : $maxScore;
$scores[$name] = $score;
if (!isset($scores[$name])) {
$scores[$name] = 0;
}
$scores[$name] += $score;
}
}
return array('scores' => $scores, 'maxScore' => $maxScore);
}
// Fetch all tags contained in an event (both event and attributes) ignoring the occurence. No ACL
public function getTagScoresUniform($eventId=0, $allowedTags=array())
{
$conditions = array('Tag.id !=' => null);
if ($eventId != 0) {
$conditions['event_id'] = $eventId;
}
$event_tag_scores = $this->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'contain' => array(
'Tag' => array(
'conditions' => array('name' => $allowedTags)
)
),
'fields' => array('Tag.name', 'EventTag.event_id')
));
$attribute_tag_scores = $this->Event->Attribute->AttributeTag->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'contain' => array(
'Tag' => array(
'conditions' => array('name' => $allowedTags)
)
),
'fields' => array('Tag.name', 'AttributeTag.event_id')
));
$score_aggregation = array();
foreach ($event_tag_scores as $event_tag_score) {
$score_aggregation[$event_tag_score['Tag']['name']][$event_tag_score['EventTag']['event_id']] = 1;
}
foreach ($attribute_tag_scores as $attribute_tag_score) {
$score_aggregation[$attribute_tag_score['Tag']['name']][$attribute_tag_score['AttributeTag']['event_id']] = 1;
}
$scores = array('scores' => array(), 'maxScore' => 0);
foreach ($score_aggregation as $name => $array_ids) {
$event_count = count($array_ids);
$scores['scores'][$name] = $event_count;
$scores['maxScore'] = $event_count > $scores['maxScore'] ? $event_count : $scores['maxScore'];
}
return $scores;
}
}

View File

@ -397,7 +397,7 @@ class Galaxy extends AppModel
return $galaxies;
}
public function getMatrix($galaxy_id)
public function getMatrix($galaxy_id, $scores=array())
{
$conditions = array('Galaxy.id' => $galaxy_id);
$contains = array(
@ -454,18 +454,7 @@ class Galaxy extends AppModel
}
$matrixData['tabs'] = $cols;
foreach ($matrixData['tabs'] as $k => $v) {
foreach ($matrixData['tabs'][$k] as $kc => $v2) {
// sort clusters in the kill chains
usort(
$matrixData['tabs'][$k][$kc],
function($a, $b) {
return strcmp($a['value'], $b['value']);
}
);
}
}
$this->sortMatrixByScore($matrixData['tabs'], $scores);
// #FIXME temporary fix: retreive tag name of deprecated mitre galaxies (for the stats)
if ($galaxy['Galaxy']['id'] == $this->getMitreAttackGalaxyId()) {
$names = array('Enterprise Attack - Attack Pattern', 'Pre Attack - Attack Pattern', 'Mobile Attack - Attack Pattern');
@ -486,4 +475,34 @@ class Galaxy extends AppModel
$matrixData['matrixTags'] = array_keys($matrixData['matrixTags']);
return $matrixData;
}
public function sortMatrixByScore(&$tabs, $scores)
{
foreach (array_keys($tabs) as $i) {
foreach (array_keys($tabs[$i]) as $j) {
// major ordering based on score, minor based on alphabetical
usort($tabs[$i][$j], function ($a, $b) use($scores) {
if ($a['tag_name'] == $b['tag_name']) {
return 0;
}
if (isset($scores[$a['tag_name']]) && isset($scores[$b['tag_name']])) {
if ($scores[$a['tag_name']] < $scores[$b['tag_name']]) {
$ret = 1;
} else if ($scores[$a['tag_name']] == $scores[$b['tag_name']]) {
$ret = strcmp($a['value'], $b['value']);
} else {
$ret = -1;
}
} else if (isset($scores[$a['tag_name']])) {
$ret = -1;
} else if (isset($scores[$b['tag_name']])) {
$ret = 1;
} else { // none are set
$ret = strcmp($a['value'], $b['value']);
}
return $ret;
});
}
}
}
}

View File

@ -295,4 +295,31 @@ class Log extends AppModel
}
return true;
}
public function filterSiteAdminSensitiveLogs($list)
{
$this->User = ClassRegistry::init('User');
$site_admin_roles = $this->User->Role->find('list', array(
'recursive' => -1,
'conditions' => array('Role.perm_site_admin' => 1),
'fields' => array('Role.id', 'Role.id')
));
$site_admins = $this->User->find('list', array(
'recursive' => -1,
'conditions' => array(
'User.role_id' => array_values($site_admin_roles)
),
'fields' => array('User.id', 'User.id')
));
foreach ($list as $k => $v) {
if (
$v['Log']['model'] === 'User' &&
in_array($v['Log']['model_id'], array_values($site_admins)) &&
in_array($v['Log']['action'], array('add', 'edit', 'reset_auth_key'))
) {
$list[$k]['Log']['change'] = __('Redacted');
}
}
return $list;
}
}

View File

@ -725,4 +725,113 @@ class MispObject extends AppModel
}
return count($orphans);
}
public function validObjectsFromAttributeTypes($user, $event_id, $selected_attribute_ids)
{
$attributes = $this->Attribute->fetchAttributes($user,
array(
'conditions' => array(
'Attribute.id' => $selected_attribute_ids,
'Attribute.event_id' => $event_id,
'Attribute.object_id' => 0
),
)
);
if (empty($attributes)) {
return array('templates' => array(), 'types' => array());
}
$attribute_types = array();
foreach ($attributes as $i => $attribute) {
$attribute_types[$attribute['Attribute']['type']] = 1;
$attributes[$i]['Attribute']['object_relation'] = $attribute['Attribute']['type'];
}
$attribute_types = array_keys($attribute_types);
$potential_templates = $this->ObjectTemplate->find('list', array(
'recursive' => -1,
'fields' => array(
'ObjectTemplate.id',
'COUNT(ObjectTemplateElement.type) as type_count'
),
'conditions' => array(
'ObjectTemplate.active' => true,
'ObjectTemplateElement.type' => $attribute_types
),
'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',
'order' => 'type_count DESC'
));
$potential_template_ids = array_keys($potential_templates);
$templates = $this->ObjectTemplate->find('all', array(
'recursive' => -1,
'conditions' => array('id' => $potential_template_ids),
'contain' => 'ObjectTemplateElement'
));
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' => $attribute_types);
}
public function groupAttributesIntoObject($user, $event_id, $object, $template, $selected_attribute_ids, $selected_object_relation_mapping, $hard_delete_attribute)
{
$saved_object_id = $this->saveObject($object, $event_id, $template, $user);
if (!is_numeric($saved_object_id)) {
return $saved_object_id;
}
$saved_object = $this->find('first', array(
'recursive' => -1,
'conditions' => array('Object.id' => $saved_object_id)
));
$existing_attributes = $this->Attribute->fetchAttributes($user, array('conditions' => array(
'Attribute.id' => $selected_attribute_ids,
'Attribute.event_id' => $event_id,
'Attribute.object_id' => 0
)));
if (empty($existing_attributes)) {
return __('Selected Attributes do not exist.');
}
$event = array('Event' => $existing_attributes[0]['Event']);
// Duplicate the attribute and its context, otherwise connected instances will drop the duplicated UUID
foreach ($existing_attributes as $i => $existing_attribute) {
if (isset($selected_object_relation_mapping[$existing_attribute['Attribute']['id']])) {
$sightings = $this->Event->Sighting->attachToEvent($event, $user, $existing_attribute['Attribute']['id']);
$object_relation = $selected_object_relation_mapping[$existing_attribute['Attribute']['id']];
$created_attribute = $existing_attribute['Attribute'];
unset($created_attribute['timestamp']);
unset($created_attribute['id']);
unset($created_attribute['uuid']);
$created_attribute['object_relation'] = $object_relation;
$created_attribute['object_id'] = $saved_object['Object']['id'];
if (isset($existing_attribute['AttributeTag'])) {
$created_attribute['AttributeTag'] = $existing_attribute['AttributeTag'];
}
if (!empty($sightings)) {
$created_attribute['Sighting'] = $sightings;
}
$saved_object['Attribute'][$i] = $created_attribute;
$this->Attribute->captureAttribute($created_attribute, $event_id, $user, $saved_object['Object']['id']);
$this->Attribute->deleteAttribute($existing_attribute['Attribute']['id'], $user, $hard_delete_attribute);
}
}
return $saved_object['Object']['id'];
}
}

View File

@ -204,6 +204,74 @@ class ObjectTemplate extends AppModel
return true;
}
public function checkTemplateConformityBasedOnTypes($template, $attributes)
{
$to_return = array('valid' => true, 'missingTypes' => array());
if (!empty($template['ObjectTemplate']['requirements'])) {
// check for all required attributes
if (!empty($template['ObjectTemplate']['requirements']['required'])) {
foreach ($template['ObjectTemplate']['requirements']['required'] as $requiredField) {
$requiredType = Hash::extract($template['ObjectTemplateElement'], sprintf('{n}[object_relation=%s].type', $requiredField))[0];
$found = false;
foreach ($attributes as $attribute) {
if ($attribute['Attribute']['type'] == $requiredType) {
$found = true;
}
}
if (!$found) {
$to_return = array('valid' => false, 'missingTypes' => array($requiredType));
}
}
}
// check for all required one of attributes
if (!empty($template['ObjectTemplate']['requirements']['requiredOneOf'])) {
$found = false;
$all_required_type = array();
foreach ($template['ObjectTemplate']['requirements']['requiredOneOf'] as $requiredField) {
$requiredType = Hash::extract($template['ObjectTemplateElement'], sprintf('{n}[object_relation=%s].type', $requiredField));
$requiredType = empty($requiredType) ? NULL : $requiredType[0];
$all_required_type[] = $requiredType;
foreach ($attributes as $attribute) {
if ($attribute['Attribute']['type'] == $requiredType) {
$found = true;
}
}
}
if (!$found) {
$to_return = array('valid' => false, 'missingTypes' => $all_required_type);
}
}
}
// at this point, an object could created; checking if all attribute are valids
$valid_types = array();
$to_return['invalidTypes'] = array();
$to_return['invalidTypesMultiple'] = array();
foreach ($template['ObjectTemplateElement'] as $templateElement) {
$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'];
} else {
$check_for_multiple_type[$attribute['Attribute']['type']] = 1;
}
}
} else {
$to_return['invalidTypes'][] = $attribute['Attribute']['type'];
}
}
$to_return['invalidTypes'] = array_unique($to_return['invalidTypes']);
$to_return['invalidTypesMultiple'] = array_unique($to_return['invalidTypesMultiple']);
if (!empty($to_return['invalidTypesMultiple'])) {
$to_return['valid'] = false;
}
return $to_return;
}
// simple test to see if there are any object templates - if not trigger update
public function populateIfEmpty($user)
{

View File

@ -192,6 +192,15 @@ class Server extends AppModel
'type' => 'boolean',
'null' => true
),
'server_settings_skip_backup_rotate' => array(
'level' => 1,
'description' => __('Enable this setting to directly save the config.php file without first creating a temporary file and moving it to avoid concurency issues. Generally not recommended, but useful when for example other tools modify/maintain the config.php file.'),
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
'type' => 'boolean',
'null' => true
),
'python_bin' => array(
'level' => 1,
'description' => __('It is highly recommended to install all the python dependencies in a virtualenv. The recommended location is: %s/venv', ROOT),
@ -201,6 +210,7 @@ class Server extends AppModel
'test' => 'testForBinExec',
'beforeHook' => 'beforeHookBinExec',
'type' => 'string',
'cli_only' => 1
),
'disable_auto_logout' => array(
'level' => 1,
@ -456,6 +466,7 @@ class Server extends AppModel
'null' => false,
'test' => 'testForWritableDir',
'type' => 'string',
'cli_only' => 1
),
'cached_attachments' => array(
'level' => 1,
@ -847,6 +858,7 @@ class Server extends AppModel
'test' => 'testForPath',
'type' => 'string',
'null' => true,
'cli_only' => 1
),
'custom_css' => array(
'level' => 2,
@ -970,6 +982,7 @@ class Server extends AppModel
'errorMessage' => '',
'test' => 'testForGPGBinary',
'type' => 'string',
'cli_only' => 1
),
'onlyencrypted' => array(
'level' => 0,
@ -2649,7 +2662,7 @@ class Server extends AppModel
'event_uuid' => $eventUuid,
'includeAttachments' => true,
'includeAllTags' => true,
'deleted' => true,
'deleted' => array(0,1),
'excludeGalaxy' => 1
));
$event = $this->Event->fetchEvent($user, $params);
@ -3076,6 +3089,9 @@ class Server extends AppModel
public function testForBinExec($value)
{
if (substr($value, 0, 7) === "phar://") {
return 'Phar protocol not allowed.';
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
if ($value === '') {
return true;
@ -3094,6 +3110,9 @@ class Server extends AppModel
public function testForWritableDir($value)
{
if (substr($value, 0, 7) === "phar://") {
return 'Phar protocol not allowed.';
}
if (!is_dir($value)) {
return 'Not a valid directory.';
}
@ -3724,26 +3743,30 @@ class Server extends AppModel
if (function_exists('opcache_reset')) {
opcache_reset();
}
$randomFilename = $this->generateRandomFileName();
// To protect us from 2 admin users having a concurent file write to the config file, solar flares and the bogeyman
file_put_contents(APP . 'Config' . DS . $randomFilename, $settingsString);
rename(APP . 'Config' . DS . $randomFilename, APP . 'Config' . DS . 'config.php');
$config_saved = file_get_contents(APP . 'Config' . DS . 'config.php');
// if the saved config file is empty, restore the backup.
if (strlen($config_saved) < 20) {
copy(APP . 'Config' . DS . 'config.php.bk', APP . 'Config' . DS . 'config.php');
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Server',
'model_id' => $id,
'email' => 'SYSTEM',
'action' => 'error',
'user_id' => 0,
'title' => 'Error: Something went wrong saving the config file, reverted to backup file.',
));
return false;
if (empty(Configure::read('MISP.server_settings_skip_backup_rotate'))) {
$randomFilename = $this->generateRandomFileName();
// To protect us from 2 admin users having a concurent file write to the config file, solar flares and the bogeyman
file_put_contents(APP . 'Config' . DS . $randomFilename, $settingsString);
rename(APP . 'Config' . DS . $randomFilename, APP . 'Config' . DS . 'config.php');
$config_saved = file_get_contents(APP . 'Config' . DS . 'config.php');
// if the saved config file is empty, restore the backup.
if (strlen($config_saved) < 20) {
copy(APP . 'Config' . DS . 'config.php.bk', APP . 'Config' . DS . 'config.php');
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Server',
'model_id' => $id,
'email' => 'SYSTEM',
'action' => 'error',
'user_id' => 0,
'title' => 'Error: Something went wrong saving the config file, reverted to backup file.',
));
return false;
}
} else {
file_put_contents(APP . 'Config' . DS . 'config.php', $settingsString);
}
return true;
}

View File

@ -21,14 +21,24 @@
?>
<span style="display:inline-block;">
<?php
$full = $isAclTagger && $tagAccess;
$full = $isAclTagger && $tagAccess && 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 = 'display:inline-block; background-color:' . h($tag['Tag']['colour']) . ';color:' . $this->TextColour->getTextColour($tag['Tag']['colour']) . ';';
$aClass = $full ? 'tagFirstHalf' : 'tag';
$aText = h($tag['Tag']['name']);
$aSearchTagUrl = $baseurl . '/events/index/searchtag: ' . h($tag['Tag']['id']);
$span1 = sprintf('<a href="%s" style="%s" class="%s">%s</a>', $aSearchTagUrl, $aStyle, $aClass, $aText);
if (!empty($tag['Tag']['id'])) {
$aSearchTagUrl = $baseurl . '/events/index/searchtag: ' . h($tag['Tag']['id']);
$span1 = sprintf('<a href="%s" style="%s" class="%s">%s</a>', $aSearchTagUrl, $aStyle, $aClass, $aText);
} else {
$span1 = sprintf('<span style="%s" class="%s">%s</span>', $aStyle, $aClass, $aText);
}
$span2 = '';
if ($full) {
$spanClass = "tagSecondHalf useCursorPointer noPrint";

View File

@ -315,6 +315,32 @@ attributes or the appropriate distribution level. If you think there is a mistak
url = "<?php echo $baseurl; ?>" + "/sightings/advanced/" + object_id + "/" + object_context;
genericPopup(url, '#popover_box');
});
$(".eventViewAttributeHover").mouseenter(function() {
$('#' + currentPopover).popover('destroy');
var type = $(this).attr('data-object-type');
var id = $(this).attr('data-object-id');
if (type + "_" + id in ajaxResults["hover"]) {
var element = $('#' + type + '_' + id + '_container');
element.popover({
title: attributeHoverTitle(id, type),
content: ajaxResults["hover"][type + "_" + id],
placement: attributeHoverPlacement(element),
html: true,
trigger: 'manual',
container: 'body'
}).popover('show');
currentPopover = type + '_' + id + '_container';
} else {
timer = setTimeout(function () {
runHoverLookup(type, id)
},
500
);
}
}).mouseout(function() {
clearTimeout(timer);
});
});
$('#attributesFilterField').bind("keydown", function(e) {
var eventid = $('#attributesFilterField').data("eventid");

View File

@ -79,6 +79,15 @@
'onClick' => 'popoverPopup',
'onClickParams' => array('this', 'selected/attribute', 'galaxies', 'selectGalaxyNamespace')
),
array(
'id' => 'group-into-object-button',
'title' => __('Group selected Attributes into an Object'),
'class' => 'mass-select hidden',
'fa-icon' => 'object-group',
'fa-source' => 'fa',
'onClick' => 'proposeObjectsFromSelectedAttributes',
'onClickParams' => array('this', $event['Event']['id'])
),
array(
'id' => 'multi-delete-button',
'title' => __('Delete selected Attributes'),

View File

@ -28,7 +28,7 @@
'value_passive' => array(
'html' => nl2br(h($setting['value'])),
'class' => 'inline-field-solid live_filter_target',
'requirement' => ((isset($setting['editable']) && !$setting['editable'])),
'requirement' => ((isset($setting['editable']) && !$setting['editable']) || !empty($setting['cli_only'])),
'style' => 'width:500px;',
'id' => sprintf(
'setting_%s_%s_passive',
@ -39,7 +39,7 @@
'value_solid' => array(
'html' => nl2br(h($setting['value'])),
'class' => 'inline-field-solid live_filter_target',
'requirement' => ((!isset($setting['editable']) || $setting['editable'])),
'requirement' => ((!isset($setting['editable']) || $setting['editable']) && empty($setting['cli_only'])),
'style' => 'width:500px;',
'id' => sprintf(
'setting_%s_%s_solid',
@ -51,7 +51,7 @@
),
'value_placeholder' => array(
'class' => 'inline-field-placeholder hidden',
'requirement' => ((!isset($setting['editable']) || $setting['editable'])),
'requirement' => ((!isset($setting['editable']) || $setting['editable']) && empty($setting['cli_only'])),
'style' => 'width:500px;',
'id' => sprintf(
'setting_%s_%s_placeholder',
@ -60,7 +60,11 @@
)
),
'description' => array(
'html' => h($setting['description']),
'html' => sprintf(
'%s%s',
!empty($setting['cli_only']) ? sprintf('<span class="bold">[<span class="red">%s</span>]</span> ', __('CLI only')) : '',
h($setting['description'])
),
'class' => 'live_filter_target'
),
'error' => array(

View File

@ -101,12 +101,12 @@ foreach($tabs as $tabName => $column):
</div>
<?php endif; ?>
<div id="matrix_container" class="fixed-table-container-inner" style="max-height: 670px;" data-picking-mode="<?php echo $pickingMode ? 'true' : 'false'; ?>">
<div id="matrix_container" class="fixed-table-container-inner" style="" data-picking-mode="<?php echo $pickingMode ? 'true' : 'false'; ?>">
<div class="tab-content">
<?php foreach($tabs as $tabName => $column): ?>
<div class="tab-pane <?php echo $tabName==$defaultTabName ? "active" : ""; ?>" id="tabMatrix-<?php echo h($tabName); ?>">
<div class="header-background"></div>
<div class="fixed-table-container-inner" style="max-height: 670px;">
<div class="fixed-table-container-inner" style="">
<table class="table table-condensed matrix-table">
<thead>
<tr>
@ -116,7 +116,10 @@ foreach($tabs as $tabName => $column):
?>
<th>
<?php echo h(ucfirst($name)); ?>
<div class="th-inner"><?php echo h(ucfirst($name)); ?></div>
<div class="th-inner" style="flex-direction: column; align-items: flex-start; padding-top: 3px;">
<span><?php echo h(ucfirst($name)); ?></span>
<i style="font-size: smaller;"><?php echo sprintf(__('(%s items)'), isset($column[$co]) ? count($column[$co]) : 0); ?></i>
</div>
</th>
<?php endforeach; ?>
@ -197,5 +200,5 @@ foreach($tabs as $tabName => $column):
</select>
</div>
<div class="templateChoiceButton btn-matrix-submit submit-container hide"><?php echo __('Submit'); ?></div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm('#popover_form_large');"><?php echo __('Cancel'); ?></div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm('#popover_matrix');"><?php echo __('Cancel'); ?></div>
<?php endif; ?>

View File

@ -16,8 +16,36 @@
?>
</ul>
</div>
<div>
<?php
$data = array(
'children' => array(
array(
'children' => array(
array(
'class' => 'hidden mass-select',
'fa-icon' => 'trash',
'onClick' => "multiSelectDeleteEventBlacklist",
'onClickParams' => array('1', '0')
)
)
),
array(
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
)
)
);
echo $this->element('/genericElements/ListTopBar/scaffold', array('data' => $data));
?>
</div>
<table class="table table-striped table-hover table-condensed">
<tr>
<th>
<input class="select_all select" type="checkbox" title="<?php echo __('Select all');?>" role="button" tabindex="0" aria-label="<?php echo __('Select all events on current page');?>" onClick="toggleAllCheckboxes();" />&nbsp;
</th>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('org');?></th>
<th><?php echo $this->Paginator->sort('event_uuid', __('Event UUID'));?></th>
@ -28,6 +56,9 @@
</tr><?php
foreach ($response as $item): ?>
<tr>
<td style="width:10px;">
<input class="select" type="checkbox" data-id="<?php echo h($item['EventBlacklist']['id']); ?>" aria-label="select <?php echo h($item['EventBlacklist']['id'])?>" />
</td>
<td class="short"><?php echo h($item['EventBlacklist']['id']); ?>&nbsp;</td>
<td class="short"><?php echo (isset($item['EventBlacklist']['event_orgc']) ? h($item['EventBlacklist']['event_orgc']) : '&nbsp;'); ?></td>
<td class="short"><?php echo h($item['EventBlacklist']['event_uuid']); ?>&nbsp;</td>
@ -35,7 +66,7 @@ foreach ($response as $item): ?>
<td class="short"><?php echo (isset($item['EventBlacklist']['event_info']) ? h($item['EventBlacklist']['event_info']) : '&nbsp;'); ?></td>
<td class="short"><?php echo (isset($item['EventBlacklist']['comment']) ? h($item['EventBlacklist']['comment']) : '&nbsp;'); ?></td>
<td class="short action-links">
<a href="<?php echo $baseurl;?>/eventBlacklists/edit/<?php echo h($item['EventBlacklist']['id']); ?>"><span class="fa fa-edit" title=<?php echo __('Edit')?> role="button" tabindex="0" aria-label="Edit blacklist entry">&nbsp;</span></a>
<a href="<?php echo $baseurl;?>/eventBlacklists/edit/<?php echo h($item['EventBlacklist']['id']); ?>"><span class="fa fa-edit black" title=<?php echo __('Edit')?> role="button" tabindex="0" aria-label="Edit blacklist entry">&nbsp;</span></a>
<?php echo $this->Form->postLink('', array('action' => 'delete', h($item['EventBlacklist']['id'])), array('class' => 'fa fa-trash', 'title' => __('Delete'), 'aria-label' => __('Delete')), __('Are you sure you want to delete the blacklist entry for the event UUID %s?', h($item['EventBlacklist']['event_uuid']))); ?>
</td>
</tr><?php
@ -59,6 +90,25 @@ endforeach; ?>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
popoverStartup();
$('.select').on('change', function() {
listCheckboxesChecked();
});
$('.select').on('change', function() {
listCheckboxesChecked();
});
$('#quickFilterButton').click(function() {
runIndexQuickFilter();
});
$('#quickFilterField').on('keypress', function (e) {
if(e.which === 13) {
runIndexQuickFilter();
}
});
});
</script>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'admin', 'menuItem' => 'eventBlacklists'));
?>

View File

@ -0,0 +1,29 @@
<div class="confirmation">
<?php
echo $this->Form->create('EventBlacklist', array('style' => 'margin:0px;', 'id' => 'PromptForm'));
echo $this->Form->input('ids', array(
'type' => 'hidden',
'div' => 'hidden',
'value' => json_encode($event_ids)
));
?>
<legend><?php echo __('Delete blacklisted events'); ?></legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<p><?php echo __('Are you sure you want to delete from the blacklist the selected events?'); ?></p>
<table>
<tr>
<td style="vertical-align:top">
<span role="button" tabindex="0" aria-label="Publish" title="Publish" id="PromptYesButton" class="btn btn-primary" onClick="submitPublish()">Yes</span>
</td>
<td style="width:540px;">
</td>
<td style="vertical-align:top;">
<span role="button" tabindex="0" aria-label="Cancel" title="Cancel" class="btn btn-inverse" id="PromptNoButton" onClick="cancelPrompt();">No</span>
</td>
</tr>
</table>
</div>
<?php
echo $this->Form->end();
?>
</div>

View File

@ -329,6 +329,17 @@
echo sprintf('<h3>%s</h3>', $data['title']);
echo sprintf('<p>%s</p>', implode(" ", $data['description']));
echo sprintf("<pre>%s</pre>", implode("\n", $data['url']));
$data = array(
'title' => __('Administering the background workers via the API.'),
'description' => array(
__('You can start/stop and view the bacground workers via the API.'),
sprintf('<br /><span class="bold">%s</span>: <code>%s/servers/%s</code><br />', __('Add worker'), $baseurl, 'startWorker/[queue_name]'),
sprintf('<span class="bold">%s</span>: <code>%s/servers/%s</code><br />', __('Stop worker'), $baseurl, 'stopWorker/[worker_pid]'),
sprintf('<span class="bold">%s</span>: <code>%s/servers/%s</code><br />', __('Get worker info'), $baseurl, 'getWorkers')
)
);
echo sprintf('<h3>%s</h3>', $data['title']);
echo sprintf('<p>%s</p>', implode(" ", $data['description']));
foreach ($command_line_functions as $clusterRef => $cluster) {
echo sprintf('<a id="%s"></a><h3>%s</h3>', $clusterRef, $cluster['header']);
echo sprintf('<p>%s:<br />', $cluster['description']);

View File

@ -12,7 +12,7 @@
<?php
if (!$ajax):
?>
<div class="view">
<div class="graph-view">
<?php endif; ?>
<span id="fullscreen-btn-correlation" class="fullscreen-btn-correlation btn btn-xs btn-primary" data-toggle="tooltip" data-placement="top" data-title="<?php echo __('Toggle fullscreen');?>"><span class="fa fa-desktop"></span></span>
<div id="chart" style="width:100%;height:100%"></div>
@ -30,6 +30,7 @@
<li id="expand"><?php echo __('Expand');?></li>
<li id="context-delete"><?php echo __('Delete');?></li>
</ul>
<button class="correlation-stop-btn btn btn-inverse" onClick="togglePhysics();" title="<?php echo __('Toggle the physics engine on/off.');?> ">Toggle physics</button>
<?php
if (!$ajax):
?>

View File

@ -10,7 +10,7 @@ App::uses('AppHelper', 'View/Helper');
$g = hexdec(substr($RGB, 3, 2));
$b = hexdec(substr($RGB, 5, 2));
$average = ((2 * $r) + $b + (3 * $g))/6;
if ($average < 128) {
if ($average < 127) {
return 'white';
} else {
return 'black';

View File

@ -40,6 +40,7 @@
<body>
<div id="popover_form" class="ajax_popover_form"></div>
<div id="popover_form_large" class="ajax_popover_form ajax_popover_form_large"></div>
<div id="popover_matrix" class="ajax_popover_form ajax_popover_matrix"></div>
<div id="popover_box" class="popover_box"></div>
<div id="screenshot_box" class="screenshot_box"></div>
<div id="confirmation_box" class="confirmation_box"></div>

View File

@ -41,6 +41,12 @@
'active' => $all
)
)
),
array(
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
)
)
);
@ -141,5 +147,17 @@ endforeach; ?>
</ul>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#quickFilterButton').click(function() {
runIndexQuickFilter();
});
$('#quickFilterField').on('keypress', function (e) {
if(e.which === 13) {
runIndexQuickFilter();
}
});
});
</script>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'objectTemplates', 'menuItem' => 'index'));

View File

@ -0,0 +1,179 @@
<button class="btn btn-inverse" onclick="showObjectProposition()"><i class="fas fa-chevron-left"></i></button>
<?php
echo $this->Form->create('Object', array('url' => $baseurl . '/objects/groupAttributesIntoObject/' . $event_id . '/' . $selectedTemplateTd));
?>
<dl style="margin-top: 10px;">
<dt><?php echo __('Object Template');?></dt>
<dd><a href="<?php echo $baseurl . '/ObjectTemplates/view/' . h($template['ObjectTemplate']['id']) ?>"><?php echo Inflector::humanize(h($template['ObjectTemplate']['name'])) . ' v' . h($template['ObjectTemplate']['version']); ?></a></dd>
<dt><?php echo __('Description');?></dt>
<dd><?php echo h($template['ObjectTemplate']['description']); ?></dd>
<dt><?php echo __('Meta category');?></dt>
<dd><?php echo h($template['ObjectTemplate']['meta-category']); ?></dd>
<dt><?php echo __('Distribution');?></dt>
<dd>
<?php echo $this->Form->input('Object.distribution', array(
'class' => 'Object_distribution_select',
'options' => $distributionData['levels'],
'default' => $distributionData['initial'],
'label' => false,
'style' => 'margin-bottom:5px;',
'div' => false
)); ?>
<?php echo $this->Form->input('Object.sharing_group_id', array(
'class' => 'Object_sharing_group_id_select',
'options' => $distributionData['sgs'],
'label' => false,
'div' => false,
'style' => 'display:none;margin-bottom:5px;',
'value' => 0
)); ?>
<dt><?php echo __('Comment');?></dt>
<dd>
<?php echo $this->Form->input('Object.comment', array(
'type' => 'textarea',
'style' => 'height:20px;width:400px;',
'required' => false,
'allowEmpty' => true,
'label' => false,
'div' => false
)); ?>
<div class="hidden">
<?php
echo $this->Form->input('selectedTemplateId', array('type' => 'hidden', 'value' => $selectedTemplateTd));
echo $this->Form->input('selectedAttributeIds', array('type' => 'hidden', 'value' => json_encode($selectedAttributeIds)));
echo $this->Form->input('selectedObjectRelationMapping', array('value' => ''));
echo $this->Form->end();
?>
</div>
</dl>
<div style="border: 2px solid #3465a4 ; border-radius: 3px; overflow: hidden;">
<table class="table table-striped table-condensed" style="margin-bottom: 0px;">
<thead>
<tr>
<th><?php echo __('ID'); ?></th>
<th><?php echo __('Name :: Type'); ?></th>
<th><?php echo __('Date'); ?></th>
<th><?php echo __('Category'); ?></th>
<th><?php echo __('Value'); ?></th>
<th><?php echo __('Distribution'); ?></th>
</tr>
</thead>
<tbody id='attributeMappingBody'>
<?php foreach ($attributes as $attribute): ?>
<tr>
<td id="isAttributeId"><?php echo h($attribute['Attribute']['id']); ?></td>
<td>
<span style="display: block;">
<select id="isAttributeMapping" style="margin-bottom: 5px;" onchange="updateObjectRelationDescription(this);">
<?php foreach ($object_relations[$attribute['Attribute']['type']] as $object_relation): ?>
<option value="<?php echo h($object_relation['object_relation']); ?>" title="<?php echo h($object_relation['description']); ?>"><?php echo h($object_relation['object_relation']); ?></option>
<?php endforeach; ?>
</select>
:: <?php echo h($attribute['Attribute']['type']); ?>
</span>
<i id="objectRelationDescription" class="apply_css_arrow"><?php echo h($object_relations[$attribute['Attribute']['type']][0]['description']); ?></i>
</td>
<td style="min-width: 75px;"><?php echo h(date('Y-m-d', $attribute['Attribute']['timestamp'])); ?></td>
<td><?php echo h($attribute['Attribute']['category']); ?></td>
<td style="white-space: nowrap;"><?php echo h($attribute['Attribute']['value']); ?></td>
<td><?php echo h($distributionLevels[$attribute['Attribute']['distribution']]); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if ($skipped_attributes > 0): ?>
<div class="alert" style="margin-top: 15px;">
<strong><?php echo __('Skipped'); ?></strong> <?php echo h($skipped_attributes) . __(' Attribute(s)') ?>
</div>
<?php endif; ?>
<?php if (!empty($object_references)): ?>
<div class="alert alert-danger" style="margin-top: 15px;">
<strong><?php echo __('Dropped Object references'); ?></strong>
<div><?php echo __('As these Attributes are converted into an Objects, the meaning of the Refences might change. If you whish to preserve the References, you will have to created them after the merge. Take note of them!') ?></div>
<div><?php echo __('The following References will be dropped after the merge:') ?></div>
<div style="max-height: 170px; overflow-y: auto; border: 1px solid #e6cace; border-radius: 4px; padding: 5px;">
<table style="margin: 2px;">
<?php foreach ($object_references as $object_reference): ?>
<?php $object_reference = $object_reference['ObjectReference']; ?>
<tr>
<td><span style="margin-right: 5px;">&#8226;</span></td>
<td><?php echo sprintf('<strong>%s</strong> (%s)', h($object_reference['object_name']), h($object_reference['object_id'])); ?></td>
<td style="text-align: center;">
<div style="display: inline-block; position: relative; margin: 10px 10px 0px 10px; top: -8px;">
<span style=""><?php echo h($object_reference['relationship_type']); ?></span>
<i class="fas fa-long-arrow-alt-right" style="font-size: x-large; position: absolute; left: calc(50% - 10px); top: 10px;"></i>
</div>
</td>
<td><?php echo sprintf('<strong>%s</strong> (%s)', h($object_reference['attribute_name']), h($object_reference['referenced_id'])); ?></td>
<?php if ($object_reference['comment'] !== ''): ?>
<td><span style="margin: 0px 10px;">-</span></td>
<td style="margin-left: 10px"><?php echo h($object_reference['comment']); ?></td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
<?php endif; ?>
<div style="margin-top: 15px; text-align: center;">
<div>
<button class="btn btn-primary" onclick="submitMergeAttributeIntoObjectForm(this);"><?php echo __('Merge above Attributes into an Object'); ?></button>
</div>
<span class="red bold" data-original-title="" title="">
<?php echo sprintf(__('Selected Attributes will be %s deleted'), '<strong style="font-size: medium">' . ($hard_delete_attribute ? __('hard') : __('soft')) . '</strong>'); ?>
</span>
</div>
<script>
$(".Object_distribution_select").change(function() {
checkAndEnable($(this).parent().find('.Object_sharing_group_id_select'), $(this).val() == 4);
});
function submitMergeAttributeIntoObjectForm(btn) {
var $btn = $(btn);
var $form = $('#ObjectGroupAttributesIntoObjectForm');
var attribute_mapping = {};
$('#attributeMappingBody').find('tr').each(function() {
var $tr = $(this);
var attr_id = $tr.find('#isAttributeId').text();
var attr_mapping = $tr.find('#isAttributeMapping').val();
attribute_mapping[attr_id] = attr_mapping;
});
$('#ObjectSelectedObjectRelationMapping').val(JSON.stringify(attribute_mapping));
var btn_text_backup = '';
$.ajax({
data: $form.serialize(),
beforeSend: function (XMLHttpRequest) {
btn_text_backup = $btn.text();
$btn.html('<it class="fa fa-spinner fa-spin"></it>');
},
success:function (data, textStatus) {
if (data.errors !== undefined) {
showMessage('fail', responseArray.errors);
$btn.text(btn_text_backup);
return false;
} else {
location.reload();
}
},
error:function() {
showMessage('fail', 'Could not merge Attributes into an Object.');
showObjectProposition();
},
type:"post",
url: $form.attr('action')
});
}
function updateObjectRelationDescription(changed) {
var $select = $(changed);
var text = $select.find(":selected").attr('title');
$select.parent().parent().find('#objectRelationDescription').text(text);
}
</script>

View File

@ -0,0 +1,85 @@
<div style="max-width: 1000px; max-height: 800px; overflow-y: auto; min-height: 400px; min-width: 700px;">
<div>
<?php echo !empty($selected_types) ? '<strong>' . __('Selected types: ') . '</strong>' : ''; ?>
<?php foreach ($selected_types as $type): ?>
<span class="label label-info"><?php echo h($type) ?></span>
<?php endforeach; ?>
</div>
<?php if (empty($potential_templates)): ?>
<?php echo __('No matching Object.'); ?>
<?php else: ?>
<table id="tableGroupAttributeIntoObject" class="table table-condensed table-hover">
<thead>
<tr>
<th><?php echo __('Template'); ?></th>
<th><?php echo __('Object name'); ?></th>
<th><?php echo __('Category'); ?></th>
<th><?php echo __('Description'); ?></th>
<th title="<?php echo __('Compatiblity or Attribute type missing from the selection'); ?>"><?php echo __('Compatiblity'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($potential_templates as $i => $potential_template): ?>
<tr class="useCursorPointer" style="<?php echo $potential_template['ObjectTemplate']['compatibility'] === true ? '' : 'cursor: not-allowed;' ?>" data-objecttemplateid="<?php echo h($potential_template['ObjectTemplate']['id']); ?>" data-enabled="<?php echo $potential_template['ObjectTemplate']['compatibility'] === true ? 'true' : 'false'; ?>">
<td class="ignoreSelection">
<a href="<?php echo $baseurl . '/ObjectTemplates/view/' . h($potential_template['ObjectTemplate']['id']) ?>"><?php echo h($potential_template['ObjectTemplate']['id']); ?></a>
</td>
<td><?php echo h($potential_template['ObjectTemplate']['name']); ?></td>
<td><?php echo h($potential_template['ObjectTemplate']['meta-category']); ?></td>
<?php
$v = h($potential_template['ObjectTemplate']['description']);
$v = strlen($v) > 100 ? substr($v, 0, 100) . '...' : $v;
?>
<td style="max-width: 500px;" title="<?php echo h($potential_template['ObjectTemplate']['description']); ?>">
<?php echo $v; ?>
</td>
<?php if ($potential_template['ObjectTemplate']['compatibility'] === true): ?>
<td>
<i class="fa fa-check" style="font-size: medium;" title="<?php echo __('This Object is compatible for the merge'); ?>"></i>
<?php if (!empty($potential_template['ObjectTemplate']['invalidTypes'])): ?>
<?php foreach ($potential_template['ObjectTemplate']['invalidTypes'] as $type): ?>
<span class="label label-warning" title="<?php echo __('This Attribute type cannot be part of this Object template. If you merge the selected Attributes into this object, all Attribute having this type will be ignored.'); ?>"><?php echo h($type); ?></span>
<?php endforeach; ?>
<?php endif; ?>
</td>
<?php else: ?>
<td style="max-width: 500px;">
<?php foreach ($potential_template['ObjectTemplate']['compatibility'] as $type): ?>
<span class="label label-important" title="<?php echo __('This Attribute type is missing from the selection. Add it to the selection to be able to merge the selected Attributes into this Object.'); ?>"><?php echo h($type); ?></span>
<?php endforeach; ?>
<?php foreach ($potential_template['ObjectTemplate']['invalidTypesMultiple'] as $type): ?>
<span class="label" title="<?php echo __('This Attribute type is not allowed to be present multiple time in this Object. Consider only picking one.'); ?>"><?php echo h($type); ?></span>
<?php endforeach; ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div id="resultPreview" class="hidden" style="height: calc(100% - 20px);"></div>
<?php endif; ?>
</div>
<script>
$('#tableGroupAttributeIntoObject > tbody > tr[data-enabled="true"] > td:not(.ignoreSelection)').click(function() {
var object_template_id = $(this).parent().data('objecttemplateid');
if (object_template_id !== undefined) {
var $parentDIV = $('#tableGroupAttributeIntoObject').parent();
var bb = $parentDIV[0].getBoundingClientRect();
$parentDIV.css({height: bb.height, width: bb.width});
$('#tableGroupAttributeIntoObject').toggle('slide');
$('#resultPreview').show().html('<div style="align-items: center; justify-content: center; display: flex; height: 100%; width: 100%"><i class="fas fa-spinner fa-spin" style="font-size: xx-large;"></i></div>');
$.get('<?php echo $baseurl . '/objects/groupAttributesIntoObject/' . h($event_id) . '/' ?>' + object_template_id + '/' + getSelected(), function(data) {
$('#resultPreview').html(data);
});
}
});
function showObjectProposition() {
$('#resultPreview').html('');
$('#tableGroupAttributeIntoObject').toggle('slide', {
direction: 'left',
});
$('#resultPreview').hide();
}
</script>

View File

@ -20,7 +20,7 @@
?>
<div class="input clear"></div>
<?php
echo $this->Form->input('gpgkey', array('label' => __('GnuPG key'), 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('gpgkey', array('label' => __('GnuPG key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s GnuPG key here or try to retrieve it from the MIT key server by clicking on "Fetch GnuPG key" below.')));
?>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch GnuPG key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GnuPG key');?></span></div>
<?php

View File

@ -5,19 +5,65 @@
?>
<p style="margin-bottom: 40px;"><?php echo sprintf(__('A heatmap showing the usage of %s.'), $galaxyName);?></p>
<select id="galaxyMatrixPicker" onchange="this.options[this.selectedIndex].value && (window.location = window.location.pathname.replace(/\/*galaxy_id:\d+/, '') + '/' + 'galaxy_id:' + this.options[this.selectedIndex].value);" >
<?php foreach ($matrixGalaxies as $k => $galaxy): ?>
<option value="<?php echo h($galaxy['Galaxy']['id']); ?>" <?php echo $galaxy['Galaxy']['id'] == $galaxyId ? 'selected' : ''; ?> ><?php echo h($galaxy['Galaxy']['name']); ?></option>
<?php endforeach; ?>
</select>
<div style="height: 80px;">
<div class="input select">
<label>Galaxy</label>
<select id="galaxyMatrixPicker" data-toggle="chosen">
<?php foreach ($matrixGalaxies as $k => $galaxy): ?>
<option value="<?php echo h($galaxy['Galaxy']['id']); ?>" <?php echo $galaxy['Galaxy']['id'] == $galaxyId ? 'selected' : ''; ?> ><?php echo h($galaxy['Galaxy']['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input select">
<label>Organisation</label>
<select id="organisationPicker" data-toggle="chosen">
<?php foreach ($organisations as $k => $org): ?>
<option value="<?php echo isset($org['Organisation']['id']) ? h($org['Organisation']['id']) : ''; ?>" <?php echo $org['Organisation']['id'] == $picked_organisation['Organisation']['id'] ? 'selected' : ''; ?> ><?php echo h($org['Organisation']['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div style="display: inline-block;">
<label>Dates</label>
<input id="dateFrom" class="datepicker" placeholder="from" value="<?php echo isset($dateFrom) ? h($dateFrom) : ''; ?>"></input>
<i class="fas fa-arrow-right"></i>
<input id="dateTo" class="datepicker" placeholder="to" value="<?php echo isset($dateTo) ? h($dateTo) : ''; ?>"></input>
</div>
<button id="btnSubmit" class="btn btn-primary"><?php echo __('Submit') ?></button>
</div>
<div id="attackmatrix_div" style="position: relative; border: solid 1px;" class="statistics_attack_matrix">
<?php
echo $this->element('view_galaxy_matrix');
?>
<div id="attackmatrix_div" style="position: relative; border: solid 1px;" class="statistics_attack_matrix">
<?php
echo $this->element('view_galaxy_matrix');
?>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$('#btnSubmit').click(function() {
var value = $('#galaxyMatrixPicker').val();
var organisation = $('#organisationPicker').val();
var dateFrom = $('#dateFrom').val();
var dateTo = $('#dateTo').val();
var eventTagsOnAttributes = $('#eventTagsOnAttributes').is(':checked');
var url = '<?php echo $baseurl; ?>/users/statistics/galaxyMatrix/galaxy_id:' + value
if (organisation) {
url += '/' + 'organisation:' + organisation;
}
if (dateFrom) {
url += '/' + 'dateFrom:' + dateFrom;
}
if (dateTo) {
url += '/' + 'dateTo:' + dateTo;
}
$(this).text('').append('<i class="fas fa-spinner fa-spin"></i>')
window.location = url;
});
$('[data-toggle="chosen"]').chosen();
})
</script>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'globalActions', 'menuItem' => 'statistics'));

@ -1 +1 @@
Subproject commit 9eac2a3923a546fdf555b5eca57f85840dea6298
Subproject commit 0ebe2c50a7a04ae2108e0c32da058826cf15387c

View File

@ -27,6 +27,10 @@ from mixbox.namespaces import NamespaceNotFoundError
from operator import attrgetter
from stix.core import STIXPackage
from collections import defaultdict
try:
import stix_edh
except ModuleNotFoundError:
pass
_MISP_dir = "/".join([p for p in os.path.dirname(os.path.realpath(__file__)).split('/')[:-3]])
_PyMISP_dir = '{_MISP_dir}/PyMISP'.format(_MISP_dir=_MISP_dir)
@ -206,11 +210,13 @@ class StixParser():
# Return type & value of an ip address attribute
@staticmethod
def handle_address(properties):
if properties.is_source:
ip_type = "ip-src"
if properties.category == 'e-mail':
attribute_type = 'email-src'
relation = 'from'
else:
ip_type = "ip-dst"
return ip_type, properties.address_value.value, "ip"
attribute_type = "ip-src" if properties.is_source else "ip-dst"
relation = 'ip'
return attribute_type, properties.address_value.value, relation
def handle_as(self, properties):
attributes = self.fetch_attributes_with_partial_key_parsing(properties, stix2misp_mapping._as_mapping)
@ -1099,12 +1105,14 @@ class ExternalStixParser(StixParser):
self.handle_object_case(attribute_type, attribute_value, compl_data, to_ids=True, object_uuid=uuid)
except AttributeError:
self.parse_description(indicator)
elif hasattr(observable, 'observable_composition') and observable.observable_composition:
self.parse_external_observable(observable.observable_composition.observables, to_ids=True)
if hasattr(indicator, 'related_indicators') and indicator.related_indicators:
for related_indicator in indicator.related_indicators:
self.parse_external_single_indicator(related_indicator.item)
# Parse observables of an external STIX document
def parse_external_observable(self, observables):
def parse_external_observable(self, observables, to_ids=False):
for observable in observables:
title = observable.title
observable_object = observable.object_
@ -1122,7 +1130,7 @@ class ExternalStixParser(StixParser):
object_uuid = self.fetch_uuid(observable_object.id_)
if isinstance(attribute_value, (str, int)):
# if the returned value is a simple value, we build an attribute
attribute = {'to_ids': False, 'uuid': object_uuid}
attribute = {'to_ids': to_ids, 'uuid': object_uuid}
if hasattr(observable, 'handling') and observable.handling:
attribute['Tag'] = []
for handling in observable.handling:
@ -1207,7 +1215,9 @@ def _update_namespaces():
# can add additional ones whenever it is needed
ADDITIONAL_NAMESPACES = [
Namespace('http://us-cert.gov/ciscp', 'CISCP',
'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ciscp_vocab_v1.1.1.xsd')
'http://www.us-cert.gov/sites/default/files/STIX_Namespace/ciscp_vocab_v1.1.1.xsd'),
Namespace('http://taxii.mitre.org/messages/taxii_xml_binding-1.1', 'TAXII',
'http://docs.oasis-open.org/cti/taxii/v1.1.1/cs01/schemas/TAXII-XMLMessageBinding-Schema.xsd')
]
for namespace in ADDITIONAL_NAMESPACES:
register_namespace(namespace)
@ -1222,13 +1232,16 @@ def generate_event(filename, tries=0):
sys.exit()
_update_namespaces()
return generate_event(filename, 1)
except NotImplementedError:
print('ERROR - Missing python library: stix_edh', file=sys.stderr)
except Exception:
try:
import maec
print(2)
except ImportError:
print('ERROR - Missing python library: maec', file=sys.stderr)
print(3)
sys.exit(0)
sys.exit(0)
def main(args):
filename = '{}/tmp/{}'.format(os.path.dirname(args[0]), args[1])

View File

@ -49,6 +49,9 @@ td.matrix-interaction.cell-picked {
overflow-y: auto;
max-height: 670px;
}
#popover_matrix div.fixed-table-container-inner {
max-height: calc(80vh - 100px);
}
.extra-wrap {
width: 100%;

View File

@ -88,4 +88,15 @@ line.link {
cursor: nesw-resize;
}
.graph-view {
float: right;
width: calc(100% - 216px);
border-left: 1px solid #666;
padding: 0px 10px;
}
.correlation-stop-btn {
position: absolute;
top: 60px;
right:10px;
}

View File

@ -853,6 +853,14 @@ a.proposal_link_red:hover {
left: calc(50% - 700px);
}
.ajax_popover_matrix {
width: 96vw;
min-width: 1400px;
left: 2vw;
max-height: 80vh;
position: absolute;
}
.popover_box {
display:none;
position: fixed;

View File

@ -1,6 +1,4 @@
(function () {
var minWidth = 1400;
var savedTopOffset;
var clusterNameToIdMapping = new Map();
var typeaheadDataMatrixSearch;
var pickedGalaxies = [];
@ -13,13 +11,6 @@
$('#attack-matrix-tabscontroller span').off('click.tab').on('click.tab', function (e) {
$(this).tab('show');
var jfilter = '.info_container_eventgraph_network';
var colNum = $(jfilter+' .matrix-table > thead > tr > th :visible').length;
$('#attackmatrix_div').css('min-width', 100*colNum);
jfilter = '.ajax_popover_form';
var colNum = $(jfilter+' .matrix-table > thead > tr > th :visible').length;
$('#popover_form_large').css('min-width', 100*colNum);
adapt_position_from_viewport(100*colNum);
});
// form
@ -31,7 +22,7 @@
$('.ajax_popover_form .btn-matrix-submit').click(function() {
makeTagging(pickedGalaxies);
cancelPopoverForm('#popover_form_large');
cancelPopoverForm('#popover_matrix');
});
var scoredCells = $('.ajax_popover_form .heatCell').filter(function() {
return $(this).attr('data-score') > 0;
@ -177,24 +168,8 @@
$(jfilter + ' #matrix-heatmap-legend-caret-value').text(score);
}
function adapt_position_from_viewport(minOverwrite) {
minOverwrite = minOverwrite !== undefined ? minOverwrite : minWidth;
minOverwrite = minWidth > minOverwrite ? minWidth : minOverwrite;
if($(window).width()*0.5+700 <= minOverwrite) {
var topOff = $('#popover_form_large').offset().top;
savedTopOffset = topOff >= $(document).scrollTop() ? topOff - $(document).scrollTop() : topOff;
$('#popover_form_large').css({
position: 'absolute',
left: '10px',
top: savedTopOffset+$(document).scrollTop()+'px'
});
} else {
$('#popover_form_large').css({
position: 'absolute',
left: '',
top: savedTopOffset
});
}
function adapt_position_from_viewport() {
$('#popover_matrix').css('top', document.documentElement.scrollTop + 120 + 'px');
}
function matrixContextualMenu(cell, x, y, tagName, tagId, func_name) {

View File

@ -1,13 +1,24 @@
var pinNodes = true;
function togglePhysics() {
d3.selectAll(".node").each(
function(d) {
d.fixed = pinNodes;
}
);
pinNodes = !pinNodes;
}
$(document).ready( function() {
var currentMousePos = { x: -1, y: -1 };
$(document).mousemove(function(event) {
currentMousePos.x = event.pageX;
currentMousePos .x = event.pageX;
currentMousePos.y = event.pageY;
});
var margin = {top: -5, right: -5, bottom: -5, left: -5},
width = $(window).width() - margin.left - margin.right,
height = $(window).height() - 160 - margin.top - margin.bottom;
height = $(window).height() - 115 - margin.top - margin.bottom;
var menu_x_buffer_ = width - 150;
var menu_y_buffer = height - 100;
@ -524,5 +535,6 @@ $(document).ready( function() {
}
}
}
});
});

View File

@ -604,105 +604,105 @@ function submitForm(type, id, field, context) {
function quickSubmitTagForm(selected_tag_ids, addData) {
var event_id = addData.id;
var formData = fetchFormDataAjax("/events/addTag/" + event_id);
$('#temp').html(formData);
$('#EventTag').val(JSON.stringify(selected_tag_ids));
$.ajax({
data: $('#EventAddTagForm').serialize(),
cache: false,
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
loadEventTags(event_id);
loadGalaxies(event_id, 'event');
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadEventTags(event_id);
loadGalaxies(event_id, 'event');
},
complete:function() {
$('#temp').empty();
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
},
type:"post",
url:"/events/addTag/" + event_id
fetchFormDataAjax("/events/addTag/" + event_id, function(formData) {
$('body').append($('<div id="temp"/>').html(formData));
$('#temp #EventTag').val(JSON.stringify(selected_tag_ids));
$.ajax({
data: $('#EventAddTagForm').serialize(),
cache: false,
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
loadEventTags(event_id);
loadGalaxies(event_id, 'event');
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadEventTags(event_id);
loadGalaxies(event_id, 'event');
},
complete:function() {
$('#temp').remove();
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
$('#temp').remove();
},
type:"post",
url:"/events/addTag/" + event_id
});
});
$('#temp').remove();
return false;
}
function quickSubmitAttributeTagForm(selected_tag_ids, addData) {
var attribute_id = addData.id;
var formData = fetchFormDataAjax("/attributes/addTag/" + attribute_id);
$('#temp').html(formData);
$('#AttributeTag').val(JSON.stringify(selected_tag_ids));
if (attribute_id == 'selected') {
$('#AttributeAttributeIds').val(getSelected());
}
$.ajax({
data: $('#AttributeAddTagForm').serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
if (attribute_id == 'selected') {
updateIndex(0, 'event');
} else {
fetchFormDataAjax("/attributes/addTag/" + attribute_id, function(formData) {
$('body').append($('<div id="temp"/>').html(formData));
$('#temp #AttributeTag').val(JSON.stringify(selected_tag_ids));
if (attribute_id == 'selected') {
$('#AttributeAttributeIds').val(getSelected());
}
$.ajax({
data: $('#AttributeAddTagForm').serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
if (attribute_id == 'selected') {
updateIndex(0, 'event');
} else {
loadAttributeTags(attribute_id);
loadGalaxies(attribute_id, 'attribute');
}
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadAttributeTags(attribute_id);
loadGalaxies(attribute_id, 'attribute');
}
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadAttributeTags(attribute_id);
loadGalaxies(attribute_id, 'attribute');
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
},
type:"post",
url:"/attributes/addTag/" + attribute_id
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
$('#temp').remove();
},
type:"post",
url:"/attributes/addTag/" + attribute_id
});
});
$('#temp').remove();
return false;
}
function quickSubmitTagCollectionTagForm(selected_tag_ids, addData) {
var tag_collection_id = addData.id;
var formData = fetchFormDataAjax("/tag_collections/addTag/" + tag_collection_id);
$('#temp').html(formData);
$('#TagCollectionTag').val(JSON.stringify(selected_tag_ids));
$.ajax({
data: $('#TagCollectionAddTagForm').serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
handleGenericAjaxResponse(data);
refreshTagCollectionRow(tag_collection_id);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadTagCollectionTags(tag_collection_id);
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
},
type:"post",
url:"/tag_collections/addTag/" + tag_collection_id
fetchFormDataAjax("/tag_collections/addTag/" + tag_collection_id, function(formData) {
$('body').append($('<div id="temp"/>').html(formData));
$('#temp #TagCollectionTag').val(JSON.stringify(selected_tag_ids));
$.ajax({
data: $('#TagCollectionAddTagForm').serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
handleGenericAjaxResponse(data);
refreshTagCollectionRow(tag_collection_id);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadTagCollectionTags(tag_collection_id);
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
$('#temp').remove();
},
type:"post",
url:"/tag_collections/addTag/" + tag_collection_id
});
});
$('#temp').remove();
return false;
}
function refreshTagCollectionRow(tag_collection_id) {
@ -845,6 +845,22 @@ function multiSelectToggleFeeds(on, cache) {
});
}
function multiSelectDeleteEventBlacklist(on, cache) {
var selected = [];
$(".select").each(function() {
if ($(this).is(":checked")) {
var temp = $(this).data("id");
if (temp != null) {
selected.push(temp);
}
}
});
$.get("/eventBlacklists/massDelete?ids=" + JSON.stringify(selected), function(data) {
$("#confirmation_box").html(data);
openPopup("#confirmation_box");
});
}
function multiSelectAction(event, context) {
var settings = {
deleteAttributes: {
@ -913,6 +929,11 @@ function addSelectedTaxonomies(taxonomy) {
});
}
function proposeObjectsFromSelectedAttributes(clicked, event_id) {
var selectedAttributeIds = getSelected();
popoverPopup(clicked, event_id + '/' + selectedAttributeIds, 'objects', 'proposeObjectsFromAttributes');
}
function hideSelectedTags(taxonomy) {
$.get("/taxonomies/taxonomyMassHide/"+taxonomy, function(data) {
$("#confirmation_box").html(data);
@ -1456,20 +1477,23 @@ function templateElementFileCategoryChange(category) {
}
}
function openPopup(id) {
var window_height = $(window).height();
var popup_height = $(id).height();
if (window_height < popup_height) {
$(id).css("top", 50);
$(id).css("height", window_height);
$(id).addClass('vertical-scroll');
} else {
if (window_height > (300 + popup_height)) {
var top_offset = ((window_height - popup_height) / 2) - 150;
function openPopup(id, adjust_layout) {
adjust_layout = adjust_layout === undefined ? true : adjust_layout;
if (adjust_layout) {
var window_height = $(window).height();
var popup_height = $(id).height();
if (window_height < popup_height) {
$(id).css("top", 50);
$(id).css("height", window_height);
$(id).addClass('vertical-scroll');
} else {
var top_offset = (window_height - popup_height) / 2;
if (window_height > (300 + popup_height)) {
var top_offset = ((window_height - popup_height) / 2) - 150;
} else {
var top_offset = (window_height - popup_height) / 2;
}
$(id).css("top", top_offset + 'px');
}
$(id).css("top", top_offset + 'px');
}
$("#gray_out").fadeIn();
$(id).fadeIn();
@ -1555,7 +1579,7 @@ function openPopover(clicked, data, hover, placement) {
function getMatrixPopup(scope, scope_id, galaxy_id) {
cancelPopoverForm();
getPopup(scope_id + '/' + galaxy_id + '/' + scope, 'events', 'viewGalaxyMatrix', '', '#popover_form_large');
getPopup(scope_id + '/' + galaxy_id + '/' + scope, 'events', 'viewGalaxyMatrix', '', '#popover_matrix');
}
function getPopup(id, context, target, admin, popupType) {
@ -1578,7 +1602,7 @@ function getPopup(id, context, target, admin, popupType) {
success:function (data, textStatus) {
$(".loading").hide();
$(popupType).html(data);
openPopup(popupType);
openPopup(popupType, false);
},
error:function() {
$(".loading").hide();
@ -3640,43 +3664,43 @@ function addGalaxyListener(id) {
function quickSubmitGalaxyForm(cluster_ids, additionalData) {
var target_id = additionalData['target_id'];
var scope = additionalData['target_type'];
var formData = fetchFormDataAjax("/galaxies/attachMultipleClusters/" + target_id + "/" + scope);
$('#temp').html(formData);
$('#temp #GalaxyTargetIds').val(JSON.stringify(cluster_ids));
if (target_id == 'selected') {
$('#AttributeAttributeIds, #GalaxyAttributeIds').val(getSelected());
}
$.ajax({
data: $('#GalaxyAttachMultipleClustersForm').serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
if (target_id === 'selected') {
location.reload();
} else {
if (scope == 'tag_collection') {
fetchFormDataAjax("/galaxies/attachMultipleClusters/" + target_id + "/" + scope, function(formData) {
$('body').append($('<div id="temp"/>').html(formData));
$('#temp #GalaxyTargetIds').val(JSON.stringify(cluster_ids));
if (target_id == 'selected') {
$('#AttributeAttributeIds, #GalaxyAttributeIds').val(getSelected());
}
$.ajax({
data: $('#GalaxyAttachMultipleClustersForm').serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
if (target_id === 'selected') {
location.reload();
} else {
loadGalaxies(target_id, scope);
handleGenericAjaxResponse(data);
if (scope == 'tag_collection') {
location.reload();
} else {
loadGalaxies(target_id, scope);
handleGenericAjaxResponse(data);
}
}
}
},
error:function() {
showMessage('fail', 'Could not add cluster.');
loadGalaxies(target_id, scope);
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
},
type:"post",
url: "/galaxies/attachMultipleClusters/" + target_id + "/" + scope
},
error:function() {
showMessage('fail', 'Could not add cluster.');
loadGalaxies(target_id, scope);
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
$('#temp').remove();
},
type:"post",
url: "/galaxies/attachMultipleClusters/" + target_id + "/" + scope
});
});
$('#temp').remove();
return false;
}
function checkAndSetPublishedInfo(skip_reload) {
@ -3702,6 +3726,7 @@ $(document).keyup(function(e){
$("#gray_out").fadeOut();
$("#popover_form").fadeOut();
$("#popover_form_large").fadeOut();
$("#popover_matrix").fadeOut();
$("#screenshot_box").fadeOut();
$("#popover_box").fadeOut();
$("#confirmation_box").fadeOut();
@ -3990,32 +4015,6 @@ $(document).ready(function() {
$('#quickFilterButton').trigger("click");
}
});
$(".eventViewAttributeHover").mouseenter(function() {
$('#' + currentPopover).popover('destroy');
var type = $(this).attr('data-object-type');
var id = $(this).attr('data-object-id');
if (type + "_" + id in ajaxResults["hover"]) {
var element = $('#' + type + '_' + id + '_container');
element.popover({
title: attributeHoverTitle(id, type),
content: ajaxResults["hover"][type + "_" + id],
placement: attributeHoverPlacement(element),
html: true,
trigger: 'manual',
container: 'body'
}).popover('show');
currentPopover = type + '_' + id + '_container';
} else {
timer = setTimeout(function () {
runHoverLookup(type, id)
},
500
);
}
}).mouseout(function() {
clearTimeout(timer);
});
$(".queryPopover").click(function() {
url = $(this).data('url');
id = $(this).data('id');
@ -4123,6 +4122,8 @@ function checkIfLoggedIn() {
if (data.slice(-2) !== 'OK') {
window.location.replace(baseurl + "/users/login");
}
}).fail(function() {
window.location.replace(baseurl + "/users/login");
});
}
setTimeout(function() { checkIfLoggedIn(); }, 5000);
@ -4271,30 +4272,30 @@ function submit_feed_overlap_tool(feedId) {
function changeTaxonomyRequiredState(checkbox) {
var checkbox_state = $(checkbox).is(":checked");
var taxonomy_id = $(checkbox).data('taxonomy-id');
var formData = fetchFormDataAjax('/taxonomies/toggleRequired/' + taxonomy_id);
$.ajax({
data: $(formData).serialize(),
success:function (data, textStatus) {
handleGenericAjaxResponse({'saved':true, 'success':['Taxonomy\'s required state toggled.']});
},
error:function() {
$(checkbox).prop('checked', !$(checkbox).prop('checked'));
handleGenericAjaxResponse({'saved':false, 'errors':['Could not toggle the required state of the taxonomy.']});
},
async:"false",
type:"post",
cache: false,
url: '/taxonomies/toggleRequired/' + taxonomy_id,
fetchFormDataAjax('/taxonomies/toggleRequired/' + taxonomy_id, function(formData) {
$.ajax({
data: $(formData).serialize(),
success:function (data, textStatus) {
handleGenericAjaxResponse({'saved':true, 'success':['Taxonomy\'s required state toggled.']});
},
error:function() {
$(checkbox).prop('checked', !$(checkbox).prop('checked'));
handleGenericAjaxResponse({'saved':false, 'errors':['Could not toggle the required state of the taxonomy.']});
},
async:"false",
type:"post",
cache: false,
url: '/taxonomies/toggleRequired/' + taxonomy_id,
});
});
formData = false;
}
function fetchFormDataAjax(url) {
function fetchFormDataAjax(url, callback) {
var formData = false;
$.ajax({
data: '[]',
success:function (data, textStatus) {
formData = data;
callback(data);
},
error:function() {
handleGenericAjaxResponse({'saved':false, 'errors':['Request failed due to an unexpected error.']});
@ -4304,7 +4305,6 @@ function fetchFormDataAjax(url) {
cache: false,
url: url
});
return formData;
}
(function(){

View File

@ -703,7 +703,7 @@ sudo systemctl enable --now misp-workers.service
## 9.07/ misp-modules (WIP!)
```bash
# some misp-modules dependencies
sudo yum install openjpeg-devel gcc-c++ poppler-cpp-devel -y
sudo yum install openjpeg-devel gcc-c++ poppler-cpp-devel pkgconfig python-devel redhat-rpm-config -y
sudo chmod 2777 /usr/local/src
sudo chown root:users /usr/local/src

View File

@ -46,7 +46,16 @@ aptUpgrade () {
debug "Upgrading system"
checkAptLock
sudo apt-get update
sudo apt-get upgrade -qy
# If we run in non-interactive mode, make sure we do not stop all of a sudden
if [[ "${PACKER}" == "1" || "${UNATTENDED}" == "1" ]]; then
export DEBIAN_FRONTEND=noninteractive
export DEBIAN_PRIORITY=critical
sudo -E apt-get -qy -o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold" upgrade
sudo -E apt-get -qy autoclean
else
sudo apt-get upgrade -qy
fi
}
# <snippet-end 0_apt-upgrade.sh>
```
@ -173,6 +182,9 @@ installCore () {
# install lief
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install https://github.com/lief-project/packages/raw/lief-master-latest/pylief-0.9.0.dev.zip
# install zmq needed by mispzmq
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install zmq
# install python-magic
$SUDO_WWW ${PATH_TO_MISP}/venv/bin/pip install python-magic

View File

@ -57,9 +57,11 @@ MISPvars () {
# GPG configuration
GPG_REAL_NAME='Autogenerated Key'
# On a REAL install, please do not set a comment, see here for why: https://www.debian-administration.org/users/dkg/weblog/97
GPG_COMMENT='WARNING: MISP AutoGenerated Key consider this Key VOID!'
GPG_EMAIL_ADDRESS='admin@admin.test'
GPG_KEY_LENGTH='2048'
# 3072 bits used as per suggestions here: https://riseup.net/en/security/message-security/openpgp/best-practices
GPG_KEY_LENGTH='3072'
GPG_PASSPHRASE="$(openssl rand -hex 32)"
# debug alias to make sure people are not confused when blindly copy pasting blobs of code

View File

@ -95,7 +95,7 @@ checkCoreOS () {
if [[ -f "/etc/redhat-release" ]]; then
echo "This is some redhat flavour"
REDHAT=1
RHfla=$(cat /etc/redhat-release | cut -f 1 -d\ | tr [A-Z] [a-z])
RHfla=$(cat /etc/redhat-release | cut -f 1 -d\ | tr '[:upper:]' '[:lower:]')
fi
}
@ -107,7 +107,7 @@ checkFlavour () {
sudo apt install lsb-release dialog -y
fi
FLAVOUR=$(lsb_release -s -i |tr [A-Z] [a-z])
FLAVOUR=$(lsb_release -s -i |tr '[:upper:]' '[:lower:]')
if [ FLAVOUR == "ubuntu" ]; then
RELEASE=$(lsb_release -s -r)
debug "We detected the following Linux flavour: ${YELLOW}$(tr '[:lower:]' '[:upper:]' <<< ${FLAVOUR:0:1})${FLAVOUR:1} ${RELEASE}${NC}"
@ -225,6 +225,27 @@ checkFail () {
fi
}
ask_o () {
ANSWER=""
if [ -z "${1}" ]; then
echo "This function needs at least 1 parameter."
exit 1
fi
[ -z "${2}" ] && OPT1="y" || OPT1="${2}"
[ -z "${3}" ] && OPT2="n" || OPT2="${3}"
while true; do
case "${ANSWER}" in "${OPT1}" | "${OPT2}") break ;; esac
echo -e -n "${1} (${OPT1}/${OPT2}) "
read ANSWER
ANSWER=$(echo "${ANSWER}" | tr '[:upper:]' '[:lower:]')
done
}
# Check if misp user is present and if run as root
checkID () {
debug "Checking if run as root and $MISP_USER is present"
@ -235,7 +256,7 @@ checkID () {
if [[ "$UNATTENDED" != "1" ]]; then
echo "There is NO user called '$MISP_USER' create a user '$MISP_USER' (y) or continue as $USER (n)? (y/n) "
read ANSWER
ANSWER=$(echo $ANSWER |tr [A-Z] [a-z])
ANSWER=$(echo $ANSWER |tr '[:upper:]' '[:lower:]')
else
ANSWER="y"
fi
@ -378,7 +399,7 @@ setBaseURL () {
echo "You can now enter your own MISP_BASEURL, if you wish to NOT do that, the MISP_BASEURL will be empty, which will work, but ideally you configure it afterwards."
echo "Do you want to change it now? (y/n) "
read ANSWER
ANSWER=$(echo $ANSWER |tr [A-Z] [a-z])
ANSWER=$(echo $ANSWER |tr '[:upper:]' '[:lower:]')
if [[ "$ANSWER" == "y" ]]; then
if [[ ! -z $IP ]]; then
echo "It seems you have an interface called $IFACE UP with the following IP: $IP - FYI"
@ -706,6 +727,7 @@ genRCLOCAL () {
sed -i -e '$i \echo never > /sys/kernel/mm/transparent_hugepage/enabled\n' /etc/rc.local
sed -i -e '$i \echo 1024 > /proc/sys/net/core/somaxconn\n' /etc/rc.local
sed -i -e '$i \sysctl vm.overcommit_memory=1\n' /etc/rc.local
sed -i -e '$i \[ -f /etc/init.d/firstBoot ] && bash /etc/init.d/firstBoot\n' /etc/rc.local
}
# Run PyMISP tests

View File

@ -26,11 +26,14 @@
## vi misp-backup.conf # adjust values
## sudo bash misp-backup.sh 2>&1 | tee misp-backup.log
##
## TODO: Target directory, rudimentary free space check: stat -f --format="%a" OutputDirName
## TODO: Make sure no directories are blank
## TODO: Make sure no directories are blank, $OutputDirName==Done
## TODO: Review how much sense it makes to ask fo MySQL credentials when most of the script does auto detection anyway.
##
# This makes use of the standard variables used by the installer
eval "$(curl -fsSL https://raw.githubusercontent.com/MISP/MISP/2.4/docs/generic/globalVariables.md | grep -v \`\`\`)"
MISPvars > /dev/null 2>&1
# Leave empty for NO debug messages, if run with set -x or bash -x it will enable DEBUG by default
DEBUG=
@ -59,6 +62,10 @@ checkDiskFree () {
if [[ ! -e $1 ]]; then
echo "$1 does not exist, creating"
mkdir -p $1
if [[ $? != 0 ]]; then
echo "Could not create $1, please fix permissions."
exit 126
fi
fi
threshhold=90
free=$(df -l --sync --output=pcent $1 |tail -1|cut -f 1 -d% | tr -d \ )

View File

@ -27,6 +27,10 @@
# TODO: Move DB, check DB?
# TODO: Check db user exists.
# This makes use of the standard variables used by the installer
eval "$(curl -fsSL https://raw.githubusercontent.com/MISP/MISP/2.4/docs/generic/globalVariables.md | grep -v \`\`\`)"
MISPvars > /dev/null 2>&1
# Leave empty for NO debug messages, if run with set -x or bash -x it will enable DEBUG by default
DEBUG=

View File

@ -1 +1 @@
MISPPath=/var/www/MISP
PATH_TO_MISP=/var/www/MISP

View File

@ -25,6 +25,10 @@
## Time to set some variables
##
# This makes use of the standard variables used by the installer
eval "$(curl -fsSL https://raw.githubusercontent.com/MISP/MISP/2.4/docs/generic/globalVariables.md | grep -v \`\`\`)"
MISPvars > /dev/null 2>&1
LUSER_ID="$(id -u)"
if [[ "${LUSER_ID}" > "0" ]]; then
@ -54,17 +58,17 @@ fi
# Fill in any missing values with defaults
# MISP path
MISPPath=${MISPPath:-$(locate MISP/app/webroot/index.php|sed 's/\/app\/webroot\/index\.php//')}
PATH_TO_MISP=${PATH_TO_MISP:-$(locate MISP/app/webroot/index.php|sed 's/\/app\/webroot\/index\.php//')}
# database.php
MySQLUUser=$(grep -o -P "(?<='login' => ').*(?=')" $MISPPath/app/Config/database.php)
MySQLUPass=$(grep -o -P "(?<='password' => ').*(?=')" $MISPPath/app/Config/database.php)
MISPDB=$(grep -o -P "(?<='database' => ').*(?=')" $MISPPath/app/Config/database.php)
DB_Port=$(grep -o -P "(?<='port' => ).*(?=,)" $MISPPath/app/Config/database.php)
MISPDBHost=$(grep -o -P "(?<='host' => ').*(?=')" $MISPPath/app/Config/database.php)
MySQLUUser=$(grep -o -P "(?<='login' => ').*(?=')" $PATH_TO_MISP/app/Config/database.php)
MySQLUPass=$(grep -o -P "(?<='password' => ').*(?=')" $PATH_TO_MISP/app/Config/database.php)
MISPDB=$(grep -o -P "(?<='database' => ').*(?=')" $PATH_TO_MISP/app/Config/database.php)
DB_Port=$(grep -o -P "(?<='port' => ).*(?=,)" $PATH_TO_MISP/app/Config/database.php)
MISPDBHost=$(grep -o -P "(?<='host' => ').*(?=')" $PATH_TO_MISP/app/Config/database.php)
echo "Clearing data model cache files"
rm -f $MISPPath/app/tmp/cache/models/myapp_*
rm -f $MISPPath/app/tmp/cache/persistent/myapp_*
rm -f $PATH_TO_MISP/app/tmp/cache/models/myapp_*
rm -f $PATH_TO_MISP/app/tmp/cache/persistent/myapp_*
echo "Wiping MySQL tables"
echo "Removes all users and organizations, except default (id=1)"
@ -72,13 +76,13 @@ echo " - Change DELETE FROM to > 0 in misp-wipe.sql to also remove default ones"
echo " - Defaults are created on first login"
MySQLRUser=${MySQLRUser:-$MySQLUUser}
MySQLRPass=${MySQLRPass:-$MySQLUPass}
mysql -u $MySQLRUser -p$MySQLRPass $MISPDB < $SQL
mysql --host $MISPDBHost -u $MySQLRUser -p$MySQLRPass $MISPDB < $SQL
echo "Inserting default values to MySQL tables"
TMP=/tmp/misp-wipe-$$.sql
cd $MISPPath
cd $PATH_TO_MISP
sed -n '/Default values for initial installation/ { s///; :a; n; p; ba; }' INSTALL/MYSQL.sql | egrep -v '(admin_settings|db_version)' > $TMP
mysql -u $MySQLRUser -p$MySQLRPass $MISPDB < $TMP
mysql --host $MISPDBHost -u $MySQLRUser -p$MySQLRPass $MISPDB < $TMP
rm -f $TMP
echo "Wiping files"
@ -88,7 +92,7 @@ git clean -f -d -x app/tmp
git clean -f -d -x app/files
echo "Updating taxonomies"
baseurl=$(grep -o -P "(?<='baseurl' => ').*(?=')" $MISPPath/app/Config/config.php)
baseurl=$(grep -o -P "(?<='baseurl' => ').*(?=')" $PATH_TO_MISP/app/Config/config.php)
AuthKey=$(echo 'select authkey from users where role_id = 1 order by id limit 1;' | mysql -u $MySQLRUser -p$MySQLRPass $MISPDB 2>/dev/null | tail -1)
curl --header "Authorization: $AuthKey" --header "Accept: application/json" --header "Content-Type: application/json" -o /dev/null -s -X POST ${baseurl}/taxonomies/update