Merge branch '2.4' of github.com:MISP/MISP into fix-update-tags-on-attribute-edit

pull/6144/head
mokaddem 2020-07-27 08:19:11 +02:00
commit e41ffb5c9e
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
27 changed files with 892 additions and 429 deletions

2
PyMISP

@ -1 +1 @@
Subproject commit f176fb0884770ff303de2c4db6606fbe4fcc4199
Subproject commit 2fb61d4b32db8ac42c85cc3881f4441c2a7511e6

View File

@ -1219,20 +1219,6 @@ class EventsController extends AppController
$event = $this->Sightingdb->attachToEvent($event, $this->Auth->user());
}
$this->params->params['paging'] = array($this->modelClass => $params);
// workaround to get the event dates in to the attribute relations
$relatedDates = array();
if (isset($event['RelatedEvent'])) {
foreach ($event['RelatedEvent'] as $relation) {
$relatedDates[$relation['Event']['id']] = $relation['Event']['date'];
}
if (isset($event['RelatedAttribute'])) {
foreach ($event['RelatedAttribute'] as $key => $relatedAttribute) {
foreach ($relatedAttribute as $key2 => $relation) {
$event['RelatedAttribute'][$key][$key2]['date'] = $relatedDates[$relation['id']];
}
}
}
}
$this->set('event', $event);
$dataForView = array(
'Attribute' => array('attrDescriptions' => 'fieldDescriptions', 'distributionDescriptions' => 'distributionDescriptions', 'distributionLevels' => 'distributionLevels', 'shortDist' => 'shortDist'),
@ -1374,21 +1360,12 @@ class EventsController extends AppController
'Event' => array('eventDescriptions' => 'fieldDescriptions', 'analysisDescriptions' => 'analysisDescriptions', 'analysisLevels' => 'analysisLevels')
);
// workaround to get the event dates in to the attribute relations and number of correlation per related event
$relatedDates = array();
// workaround to get number of correlation per related event
$relatedEventCorrelationCount = array();
if (!empty($event['RelatedEvent'])) {
foreach ($event['RelatedEvent'] as $relation) {
$relatedDates[$relation['Event']['id']] = $relation['Event']['date'];
}
if (!empty($event['RelatedAttribute'])) {
foreach ($event['RelatedAttribute'] as $key => $relatedAttribute) {
foreach ($relatedAttribute as $key2 => $relation) {
if (!empty($relatedDates[$relation['id']])) {
$event['RelatedAttribute'][$key][$key2]['date'] = $relatedDates[$relation['id']];
}
$relatedEventCorrelationCount[$relation['id']][$relation['value']] = 1;
}
if (!empty($event['RelatedAttribute'])) {
foreach ($event['RelatedAttribute'] as $relatedAttribute) {
foreach ($relatedAttribute as $relation) {
$relatedEventCorrelationCount[$relation['id']][$relation['value']] = true;
}
}
}

View File

@ -290,11 +290,6 @@ class ShadowAttributesController extends AppController
} else {
$this->set('ajax', false);
}
if (empty($eventId)) {
if (empty($event)) {
throw new NotFoundException(__('Invalid Event'));
}
}
$event = $this->ShadowAttribute->Event->fetchEvent($this->Auth->user(), array('eventid' => $eventId));
if (empty($event)) {
throw new NotFoundException(__('Invalid Event'));
@ -457,14 +452,15 @@ class ShadowAttributesController extends AppController
$categories = array_keys($this->ShadowAttribute->Event->Attribute->categoryDefinitions);
$categories = $this->_arrayToValuesIndexArray($categories);
$this->set('categories', $categories);
foreach ($this->ShadowAttribute->Event->Attribute->categoryDefinitions as $key => $value) {
$info['category'][$key] = array('key' => $key, 'desc' => isset($value['formdesc'])? $value['formdesc'] : $value['desc']);
$fieldDesc = ['category' => [], 'type' => []];
foreach ($this->ShadowAttribute->categoryDefinitions as $key => $value) {
$fieldDesc['category'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
foreach ($this->ShadowAttribute->Event->Attribute->typeDefinitions as $key => $value) {
$info['type'][$key] = array('key' => $key, 'desc' => isset($value['formdesc'])? $value['formdesc'] : $value['desc']);
foreach ($this->ShadowAttribute->typeDefinitions as $key => $value) {
$fieldDesc['type'][$key] = isset($value['formdesc']) ? $value['formdesc'] : $value['desc'];
}
$this->set('info', $info);
$this->set('typeDefinitions', $this->ShadowAttribute->typeDefinitions);
$this->set('fieldDesc', $fieldDesc);
$this->set('categoryDefinitions', $this->ShadowAttribute->categoryDefinitions);
}

View File

@ -0,0 +1,22 @@
<?php
require_once 'OrgsContributorsGeneric.php';
class OrgsContributorLastMonthWidget extends OrgsContributorsGeneric
{
public $title = 'Active Contributors in the last 30 days';
public $description = 'Display the logos of all organisations having shared at least one event in the past month.';
protected function filter($user, $org, $start_timestamp) {
$conditions = $this->Event->createEventConditions($user);
$conditions['AND'][] = array('OR' => array('Event.orgc_id' => $org['Organisation']['id'], 'Event.org_id' => $org['Organisation']['id']));
$conditions['AND'][] = array('Event.timestamp >=' => $start_timestamp);
$results = array_values($this->Event->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'limit' => 1,
'fields' => array('Event.id')
)));
return count($results) > 0;
}
}
?>

View File

@ -0,0 +1,48 @@
<?php
class OrgsContributorsGeneric
{
public $render = 'OrgsPictures';
public $width = 4;
public $height = 4;
public $cacheLifetime = 3600;
public $autoRefreshDelay = false;
public $params = array (
'blacklist_orgs' => 'A list of organisation names to filter out',
'timeframe' => 'Number of days considered for the query (30 by default)'
);
public $placeholder =
'{
"blacklist_orgs": ["Orgs to filter"],
"timeframe": "30"
}';
//This is the default filter - to be overriden in children classes
protected function filter($user, $org, $options) {
return true;
}
public function handler($user, $options = array())
{
$this->Org = ClassRegistry::init('Organisation');
$this->Event = ClassRegistry::init('Event');
if (!empty($options['timeframe'])) {
$days = (int) $options['timeframe'];
} else {
$days = 30;
}
$start_timestamp = $this->Event->resolveTimeDelta($days.'d');
$orgs = $this->Org->find('all', array( 'conditions' => array('Organisation.local' => 1)));
$result = array();
foreach($orgs as $org) {
if(!empty($options['blacklist_orgs']) && in_array($org['Organisation']['name'], $options['blacklist_orgs'])) {
continue;
}
if ($this->filter($user, $org, $start_timestamp)) {
$result[] = $org;
}
}
return $result;
}
}
?>

View File

@ -0,0 +1,35 @@
<?php
require_once 'OrgsContributorsGeneric.php';
class OrgsUsingMitreWidget extends OrgsContributorsGeneric
{
public $title = 'Orgs using MITRE ATT&CK';
public $description = 'Display the logos of all organisations having shared at least one event using the MITRE ATT&CK tags in the last 100 days';
protected function filter($user, $org, $start_timestamp) {
$options['joins'] = array(
array('table' => 'event_tags',
'alias' => 'EventTag',
'type' => 'INNER',
'conditions' => array(
'EventTag.event_id = Event.id',
)
),
array('table' => 'tags',
'alias' => 'Tag',
'type' => 'INNER',
'conditions' => array(
'Tag.id = EventTag.tag_id'
)
)
);
$options['fields'] = 'Event.id';
$options['limit'] = 1;
$conditions = $this->Event->createEventConditions($user);
$conditions['AND'][] = array('Event.orgc_id' => $org['Organisation']['id'], 'Event.published' => 1, 'Event.timestamp >=' => $start_timestamp, 'Tag.name LIKE' => 'misp-galaxy:mitre%');
$options['conditions'] = array('AND' => $conditions);
$events = $this->Event->find('all', $options);
return count($events) > 0;
}
}
?>

View File

@ -0,0 +1,28 @@
<?php
require_once 'OrgsContributorsGeneric.php';
class OrgsUsingObjectsWidget extends OrgsContributorsGeneric
{
public $title = 'Orgs using MISP objects';
public $description = 'Display the logos of all organisations having shared at least one event containing an object in the last 100 days';
protected function filter($user, $org, $start_timestamp) {
$options['joins'] = array(
array('table' => 'objects',
'alias' => 'Objects',
'type' => 'INNER',
'conditions' => array(
'Objects.event_id = Event.id',
)
)
);
$options['fields'] = 'Event.id';
$options['limit'] = 1;
$conditions = $this->Event->createEventConditions($user);
$conditions['AND'][] = array('Event.orgc_id' => $org['Organisation']['id'], 'Event.timestamp >' => $start_timestamp);
$options['conditions'] = $conditions;
$eventsIds = $this->Event->find('all', $options);
return count($eventsIds) > 0;
}
}
?>

View File

@ -0,0 +1,153 @@
<?php
/**
* Sharing Graph widget which computes a sharing score for each local organizations
* The score is computed for each month.
*
* Warning: the scoring function is very experimental. Tweak it as you wish.
*/
class SharingGraphWidget
{
public $title = 'Sharing Trends';
public $render = 'MultiLineChart';
public $width = 8;
public $height = 6;
public $description = 'A graph to show sharing trends per organisation';
public $cacheLifetime = 10;
public $autoRefreshDelay = false;
public $params = array (
'blacklist_orgs' => 'A list of organisation names to filter out',
'months' => 'Number of past months to consider for the graph'
);
public $placeholder =
'{
"blacklist_orgs": ["Orgs to filter"],
"months": "6"
}';
private function attribute_scoring($attribute) {
// each attribute gets 1 point
return 1;
}
private function object_scoring($object) {
$score = 0;
$this->Object->bindModel(array('hasMany' => array('ObjectReference' => array('foreignKey' => 'object_id'))));
$o = $this->Object->find('first', array('conditions' => array('id' => $object['id'])));
// We score for each object reference from this object
foreach ($o['ObjectReference'] as $reference ) {
//TODO more points for different types of references ?
$score += 2;
}
return $score+50; // bonus for having an object
}
private function event_scoring($event) {
$score = 0;
$attr_count = 0;
// Simple attribute scoring
foreach($event['Attribute'] as $attribute) {
$attr_count++;
$score += $this->attribute_scoring($attribute);
// cap at 100 attributes max per event to avoid privileging large dump
if ($attr_count > 100)
break;
}
//Object scoring
foreach($event['Object'] as $object) {
$score += $this->object_scoring($object);
}
// Todo check use of taxonomies, tagging for extra points
return $score;
}
/*
* Target_month must be from 1 to 12
* Target year must be 4 digits
*/
private function org_scoring($user, $org, $target_month, $target_year) {
$total_score = 0;
$start_date = $target_year.'-'.$target_month.'-01';
if($target_month == 12) {
$end_date = ($target_year+1).'-01-01';
} else {
$end_date = $target_year.'-'.($target_month+1).'-01';
}
$conditions = array('Event.orgc_id' => $org['Organisation']['id'], 'Event.date >=' => $start_date, 'Event.date <' => $end_date);
//This is required to enforce the ACL (not pull directly from the DB)
$eventIds = $this->Event->fetchSimpleEventIds($user, array('conditions' => $conditions));
if(!empty($eventIds)) {
$params = array('Event.id' => $eventIds);
$events = $this->Event->find('all', array('conditions' => array('AND' => $params)));
foreach($events as $event) {
$total_score+= $this->event_scoring($event);
}
}
return $total_score;
}
private function filter_ghost_orgs(&$data, $orgs){
foreach ($data['data'] as &$item) {
foreach(array_keys($orgs) as $org_name) {
unset($item[$org_name]);
}
}
}
public function handler($user, $options = array())
{
$this->Log = ClassRegistry::init('Log');
$this->Org = ClassRegistry::init('Organisation');
$this->Event = ClassRegistry::init('Event');
$this->Attribute = ClassRegistry::init('Attribute');
$this->Object = ClassRegistry::init('Object');
$this->ObjectReference = ClassRegistry::init('ObjectReference');
$orgs = $this->Org->find('all', array( 'conditions' => array('Organisation.local' => 1)));
$current_month = date('n');
$current_year = date('Y');
$limit = 6; // months
if(!empty($options['months'])) {
$limit = (int) ($options['months']);
}
$offset = 0;
$ghost_orgs = array(); // track orgs without any contribution
// We start by putting all orgs_id in there:
foreach($orgs as $org) {
// We check for blacklisted orgs
if(!empty($options['blacklist_orgs']) && in_array($org['Organisation']['name'], $options['blacklist_orgs'])) {
unset($orgs[$offset]);
} else {
$ghost_orgs[$org['Organisation']['name']] = true;
}
$offset++;
}
$data = array();
$data['data'] = array();
for ($i=0; $i < $limit; $i++) {
$target_month = $current_month - $i;
$target_year = $current_year;
if ($target_month < 1) {
$target_month += 12;
$target_year -= 1;
}
$item = array();
$item ['date'] = $target_year.'-'.$target_month.'-01';
foreach($orgs as $org) {
$score = $this->org_scoring($user, $org, $target_month, $target_year);
$item[$org['Organisation']['name']] = (int) round(log($score, 1.1)); // taking the logarithmic view
// if a positive score is detected at least once it's enough to be
// considered for the graph
if($score > 0) {
unset($ghost_orgs[$org['Organisation']['name']]);
}
}
$data['data'][] = $item;
}
$this->filter_ghost_orgs($data, $ghost_orgs);
return $data;
}
}

View File

@ -1,4 +1,5 @@
<?php
require_once __DIR__ . '/TmpFileTool.php';
class ComplexTypeTool
{
@ -140,31 +141,28 @@ class ComplexTypeTool
return array_values($array);
}
/*
* parse a CSV file with the given settings
/**
* Parse a CSV file with the given settings
* All lines starting with # are stripped
* The settings can contain the following:
* delimiter: Expects a delimiter string (default is a simple comma).
* For example, to split the following line: "value1##comma##value2" simply pass $settings['delimiter'] = "##comma##";
* values: Expects an array (or a comma separated string) with numeric values denoting the columns containing indicators. If this is not set then every value will be checked. (column numbers start at 1)
* @param string $input
* @param array $settings
* @return array
* @throws Exception
*/
public function checkCSV($input, $settings = array())
{
$delimiter = !empty($settings['delimiter']) ? $settings['delimiter'] : ",";
$rows = str_getcsv($input, "\n");
unset($input);
$data = array();
foreach ($rows as $k => $row) {
if (empty($row[0]) || $row[0] === '#') {
continue;
}
if ($delimiter == '\t') {
$data[$k] = explode("\t", $row);
} else {
$data[$k] = str_getcsv($row, $delimiter);
}
if (empty($input)) {
return [];
}
$delimiter = !empty($settings['delimiter']) ? $settings['delimiter'] : ",";
if ($delimiter === '\t') {
$delimiter = "\t";
}
unset($rows);
$values = !empty($settings['value']) ? $settings['value'] : array();
if (!is_array($values)) {
$values = explode(',', $values);
@ -172,23 +170,34 @@ class ComplexTypeTool
foreach ($values as $key => $value) {
$values[$key] = intval($value);
}
$iocArray = array();
foreach ($data as $rowPos => $row) {
// Write to tmp file to save memory
$tmpFile = new TmpFileTool();
$tmpFile->write($input);
unset($input);
$iocArray = [];
foreach ($tmpFile->csv($delimiter) as $row) {
if (!empty($row[0][0]) && $row[0][0] === '#') { // Comment
continue;
}
foreach ($row as $elementPos => $element) {
if ((!empty($values) && in_array(($elementPos + 1), $values)) || empty($values)) {
if (empty($values) || in_array(($elementPos + 1), $values)) {
$element = trim($element, " \t\n\r\0\x0B\"\'");
if (isset($settings['excluderegex']) && !empty($settings['excluderegex'])) {
if (preg_match($settings['excluderegex'], $element)) {
continue;
}
if (empty($element)) {
continue;
}
if (!empty($settings['excluderegex']) && preg_match($settings['excluderegex'], $element)) {
continue;
}
$resolvedResult = $this->__resolveType($element);
if (!empty($resolvedResult)) {
if ($resolvedResult) {
$iocArray[] = $resolvedResult;
}
}
}
}
return $iocArray;
}
@ -244,9 +253,8 @@ class ComplexTypeTool
private function __resolveType($raw_input)
{
$input = array(
'raw' => trim($raw_input)
);
$input = array('raw' => trim($raw_input));
$input = $this->__refangInput($input);
$input = $this->__extractPort($input);

View File

@ -37,6 +37,31 @@ class TmpFileTool
}
}
/**
* Get one line from file parsed as CSV.
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
* @return Generator
* @throws Exception
*/
public function csv($delimiter = ',', $enclosure = '"', $escape = "\\")
{
$this->rewind();
$line = 0;
while (!feof($this->tmpfile)) {
$result = fgetcsv($this->tmpfile, 0, $delimiter, $enclosure, $escape);
if ($result === false) {
throw new Exception("Could not read line $line from temporary CSV file.");
}
$line++;
yield $result;
}
fclose($this->tmpfile);
$this->tmpfile = null;
}
/**
* @return Generator
* @throws Exception

View File

@ -2890,4 +2890,31 @@ class AppModel extends Model
{
return Configure::read('MISP.tmpdir') ?: sys_get_temp_dir();
}
/**
* Decodes JSON string and throws exception if string is not valid JSON or if is not array.
*
* @param string $json
* @return array
* @throws JsonException
* @throws UnexpectedValueException
*/
protected function jsonDecode($json)
{
if (defined('JSON_THROW_ON_ERROR')) {
// JSON_THROW_ON_ERROR is supported since PHP 7.3
$decoded = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} else {
$decoded = json_decode($json, true);
if ($decoded === null) {
throw new UnexpectedValueException('Could not parse JSON: ' . json_last_error_msg(), json_last_error());
}
}
if (!is_array($decoded)) {
throw new UnexpectedValueException('JSON must be array type, get ' . gettype($decoded));
}
return $decoded;
}
}

View File

@ -977,34 +977,47 @@ class Event extends AppModel
'order' => false,
'limit' => $max_correlations
));
if (empty($correlations)) {
return array();
}
$eventIds = [];
foreach ($correlations as $correlation) {
$eventIds[] = $correlation[$settings[$context]['correlationModel']]['event_id'];
}
$conditions = $this->createEventConditions($user);
$conditions['AND']['Event.id'] = $eventIds;
$events = $this->find('all', array(
'recursive' => -1,
'conditions' => $conditions,
'fields' => array('Event.id', 'Event.orgc_id', 'Event.info', 'Event.date'),
));
$eventInfos = array();
foreach ($events as $event) {
$eventInfos[$event['Event']['id']] = $event['Event'];
}
$relatedAttributes = array();
$orgc_ids = array();
foreach ($correlations as $k => $correlation) {
if (empty($orgc_ids[$correlation[$settings[$context]['correlationModel']]['event_id']])) {
$temp = $this->find('first', array(
'recursive' => -1,
'conditions' => array('Event.id' => $correlation[$settings[$context]['correlationModel']]['event_id']),
'fields' => array('Event.orgc_id')
));
if (!empty($temp)) {
$orgc_ids[$correlation[$settings[$context]['correlationModel']]['event_id']] = $temp['Event']['orgc_id'];
}
foreach ($correlations as $correlation) {
$correlation = $correlation[$settings[$context]['correlationModel']];
// User don't have access to correlated attribute event, skip.
if (!isset($eventInfos[$correlation['event_id']])) {
continue;
}
$eventInfo = $eventInfos[$correlation['event_id']];
$current = array(
'id' => $correlation[$settings[$context]['correlationModel']]['event_id'],
'attribute_id' => $correlation[$settings[$context]['correlationModel']]['attribute_id'],
'info' => $correlation[$settings[$context]['correlationModel']]['info'],
'value' => $correlation[$settings[$context]['correlationModel']]['value'],
'id' => $correlation['event_id'],
'attribute_id' => $correlation['attribute_id'],
'value' => $correlation['value'],
'org_id' => $eventInfo['orgc_id'],
'info' => $eventInfo['info'],
'date' => $eventInfo['date'],
);
if (!empty($orgc_ids[$correlation[$settings[$context]['correlationModel']]['event_id']])) {
$current['org_id'] = $orgc_ids[$correlation[$settings[$context]['correlationModel']]['event_id']];
} else {
$current['org_id'] = 'unknown';
}
if (empty($relatedAttributes[$correlation[$settings[$context]['correlationModel']][$settings[$context]['parentIdField']]]) || !in_array($current, $relatedAttributes[$correlation[$settings[$context]['correlationModel']][$settings[$context]['parentIdField']]])) {
$relatedAttributes[$correlation[$settings[$context]['correlationModel']][$settings[$context]['parentIdField']]][] = $current;
}
unset($correlations[$k]);
$parentId = $correlation[$settings[$context]['parentIdField']];
$relatedAttributes[$parentId][] = $current;
}
return $relatedAttributes;
}
@ -1116,13 +1129,10 @@ class Event extends AppModel
return $result;
}
}
$uploadFailed = false;
try {
$json = json_decode($newTextBody, true);
$this->jsonDecode($newTextBody);
} catch (Exception $e) {
$uploadFailed = true;
}
if (!is_array($json) || $uploadFailed) {
$this->logException("Invalid JSON returned when pushing to remote server {$server['Server']['id']}", $e);
return $this->__logUploadResult($server, $event, $newTextBody);
}
return 'Success';
@ -1172,18 +1182,8 @@ class Event extends AppModel
{
switch ($response->code) {
case '200': // 200 (OK) + entity-action-result
if ($response->isOk()) {
$newTextBody = $response->body();
return true;
} else {
try {
$jsonArray = json_decode($response->body, true);
} catch (Exception $e) {
return true;
}
return $jsonArray['name'];
}
// no break
$newTextBody = $response->body();
return true;
case '302': // Found
$newLocation = $response->headers['Location'];
$newTextBody = $response->body();
@ -6036,7 +6036,7 @@ class Event extends AppModel
'action' => 'warning',
'user_id' => 0,
'title' => 'Uploading Event (' . $event['Event']['id'] . ') to Server (' . $server['Server']['id'] . ')',
'change' => 'Returned message: ', $newTextBody,
'change' => 'Returned message: ' . $newTextBody,
));
return false;
}

View File

@ -2709,12 +2709,12 @@ class Server extends AppModel
if (empty($filter_rules)) {
return $final;
}
$filter_rules = json_decode($filter_rules, true);
$filter_rules = $this->jsonDecode($filter_rules);
$url_params = array();
foreach ($filter_rules as $field => $rules) {
$temp = array();
if ($field === 'url_params') {
$url_params = json_decode($rules, true);
$url_params = $this->jsonDecode($rules);
} else {
foreach ($rules as $operator => $elements) {
foreach ($elements as $k => $element) {
@ -4249,7 +4249,7 @@ class Server extends AppModel
}
if ($response->code == '405') {
try {
$responseText = json_decode($response->body, true)['message'];
$responseText = $this->jsonDecode($response->body)['message'];
} catch (Exception $e) {
return array('status' => 3);
}
@ -4452,7 +4452,12 @@ class Server extends AppModel
public function isJson($string)
{
return (json_last_error() == JSON_ERROR_NONE);
try {
$this->jsonDecode($string);
return true;
} catch (Exception $e) {
return false;
}
}
public function captureServer($server, $user)
@ -4995,9 +5000,19 @@ class Server extends AppModel
$expected = array('stix' => '>1.2.0.9', 'cybox' => '>2.1.0.21', 'mixbox' => '1.0.3', 'maec' => '>4.1.0.14', 'stix2' => '>2.0', 'pymisp' => '>2.4.120');
// check if the STIX and Cybox libraries are working using the test script stixtest.py
$scriptResult = shell_exec($this->getPythonVersion() . ' ' . APP . 'files' . DS . 'scripts' . DS . 'stixtest.py');
$scriptResult = json_decode($scriptResult, true);
if ($scriptResult == null) {
return array('operational' => 0, 'stix' => array('expected' => $expected['stix']), 'cybox' => array('expected' => $expected['cybox']), 'mixbox' => array('expected' => $expected['mixbox']), 'maec' => array('expected' => $expected['maec']), 'stix2' => array('expected' => $expected['stix2']), 'pymisp' => array('expected' => $expected['pymisp']));
try {
$scriptResult = $this->jsonDecode($scriptResult);
} catch (Exception $e) {
$this->logException('Invalid JSON returned from stixtest', $e);
return array(
'operational' => 0,
'stix' => array('expected' => $expected['stix']),
'cybox' => array('expected' => $expected['cybox']),
'mixbox' => array('expected' => $expected['mixbox']),
'maec' => array('expected' => $expected['maec']),
'stix2' => array('expected' => $expected['stix2']),
'pymisp' => array('expected' => $expected['pymisp'])
);
}
$scriptResult['operational'] = $scriptResult['success'];
if ($scriptResult['operational'] == 0) {
@ -5944,11 +5959,14 @@ class Server extends AppModel
}
if ($response->isOk()) {
try {
$response = json_decode($response->body, true);
$response = $this->jsonDecode($response->body);
} catch (Exception $e) {
$message = 'Invalid response received from the remote instance.';
$this->logException($message, $e);
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$message = 'Invalid response received from the remote instance.';
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Server',

View File

@ -5,25 +5,84 @@ use PHPUnit\Framework\TestCase;
class ComplexTypeToolTest extends TestCase
{
public function testCheckCSV(): void
{
$complexTypeTool = new ComplexTypeTool();
$csv = <<<CSV
# Downloaded from 1.1.1.1
127.0.0.1
"127.0.0.2"
CSV;
$results = $complexTypeTool->checkCSV($csv);
$this->assertCount(2, $results);
}
public function testCheckCSVTabulator(): void
{
$complexTypeTool = new ComplexTypeTool();
$csv = <<<CSV
###########################################################################################
# Downloaded from 1.1.1.1
###########################################################################################
127.0.0.1\t127.0.0.3
"127.0.0.2"
58.214.25.190
58.214.239.53
CSV;
$results = $complexTypeTool->checkCSV($csv, ['delimiter' => '\t']);
$this->assertCount(5, $results);
}
public function testCheckCSVValues(): void
{
$complexTypeTool = new ComplexTypeTool();
$csv = <<<CSV
127.0.0.1\t127.0.0.2
127.0.0.3\t127.0.0.4
CSV;
$results = $complexTypeTool->checkCSV($csv, ['value' => '1', 'delimiter' => '\t']);
$this->assertCount(2, $results);
foreach (['127.0.0.1', '127.0.0.3'] as $k => $test) {
$this->assertEquals($test, $results[$k]['value']);
$this->assertEquals('ip-dst', $results[$k]['default_type']);
}
}
public function testCheckCSVEmpty(): void
{
$complexTypeTool = new ComplexTypeTool();
$results = $complexTypeTool->checkCSV('');
$this->assertCount(0, $results);
}
public function testCheckCSVEmptyLines(): void
{
$complexTypeTool = new ComplexTypeTool();
$results = $complexTypeTool->checkCSV(",,,\t\n,,,,,");
$this->assertCount(0, $results);
}
public function testCheckCSVTestFile(): void
{
$complexTypeTool = new ComplexTypeTool();
$results = $complexTypeTool->checkCSV(file_get_contents(__DIR__ . '/../../tests/event.csv'));
$this->assertCount(37, $results);
}
public function testCheckFreeTextHeader(): void
{
$complexTypeTool = new ComplexTypeTool();
$results = $complexTypeTool->checkFreeText(<<<EOT
$text = <<<EOT
# LAST 1000 # UTC UPDATE 2020-07-13 08:15:00
127.0.0.1,(127.0.0.2), <127.0.0.3>; "127.0.0.4" '127.0.0.5'
EOT
);
127.0.0.1,(127.0.0.2), <127.0.0.3>; "127.0.0.4" "'127.0.0.5'"
EOT;
$results = $complexTypeTool->checkFreeText($text);
$this->assertCount(5, $results);
$this->assertEquals('127.0.0.1', $results[0]['value']);
$this->assertEquals('ip-dst', $results[0]['default_type']);
$this->assertEquals('127.0.0.2', $results[1]['value']);
$this->assertEquals('ip-dst', $results[1]['default_type']);
$this->assertEquals('127.0.0.3', $results[2]['value']);
$this->assertEquals('ip-dst', $results[2]['default_type']);
$this->assertEquals('127.0.0.4', $results[3]['value']);
$this->assertEquals('ip-dst', $results[3]['default_type']);
$this->assertEquals('127.0.0.5', $results[4]['value']);
$this->assertEquals('ip-dst', $results[4]['default_type']);
foreach (['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4', '127.0.0.5'] as $k => $test) {
$this->assertEquals($test, $results[$k]['value']);
$this->assertEquals('ip-dst', $results[$k]['default_type']);
}
}
public function testCheckFreeTextIpv4(): void
@ -267,6 +326,15 @@ EOT
$this->assertEquals('url', $results[0]['default_type']);
}
public function testCheckFreeTextUrlWithPort(): void
{
$complexTypeTool = new ComplexTypeTool();
$results = $complexTypeTool->checkFreeText('https://github.com:443/MISP/MISP');
$this->assertCount(1, $results);
$this->assertEquals('https://github.com:443/MISP/MISP', $results[0]['value']);
$this->assertEquals('url', $results[0]['default_type']);
}
public function testCheckFreeTextUrlWithoutProtocol(): void
{
$complexTypeTool = new ComplexTypeTool();

View File

@ -54,7 +54,7 @@
array(
'field' => 'to_ids',
'type' => 'checkbox',
'label' => __("for Intrusion Detection System"),
'label' => __("For Intrusion Detection System"),
//'stayInLine' => 1
),
array(
@ -75,7 +75,6 @@
'type' => 'text',
'hidden' => true
),
'<div id="extended_event_preview" style="width:446px;"></div>'
),
'submit' => array(
'action' => $action,

View File

@ -0,0 +1,31 @@
<div>
<table class="table table-striped table-hover table-condensed">
<?php
/*
* Display a simple array.
* The size of the keys array is considered for the width.
* Expected input:
* { keys: <array of string>, rows: <array of arrays>}
*
* Example:
* {keys: ['id', 'name', 'score'], rows: [['1', 'test', '10'], ['2', 'john', '5']]}
*
*/
$count = count($data['keys']);
echo '<tr>';
foreach ($data['keys'] as $key) {
echo '<th>'.h($key).'</th>';
}
echo '</tr>';
foreach ($data['rows'] as $row) {
echo '<tr>';
for ($i=0; $i<$count; $i++) {
if (isset($row[$i])) {
echo '<td>'.h($row[$i]).'</td>';
}
}
echo '</tr>';
}
?>
</table>
</div>

View File

@ -0,0 +1,44 @@
<div>
<p>
<?php
/*
* Display orgs logos
* The input is a list of item.
* Each item is expected to contain an org object with the name and id populated
*
* Example:
* [{'Organisation' => array('name' => 'orgA', 'id' => 1)}, {'Organisation' => ...}]
*
*/
foreach ($data as $org) {
echo '<a href="/organisations/view/'.h($org['Organisation']['id']).'" title="'.h($org['Organisation']['name']).'" target="_blank">';
$img_data = $this->OrgImg->getOrgImg(array('name' => $org['Organisation']['name'], 'id' => $org['Organisation']['id'], 'size' => 48), true, true);
if (strncmp($img_data, "<span", 5) === 0) { // the org has not uploaded a logo
// We simulate a Logo where we take the first letter of the name
$letter = substr($org['Organisation']['name'],0,1);
echo '<div class="logo-box">'.$letter.'</div>';
} else {
echo $img_data;
}
echo '</a>';
}
?>
</p>
</div>
<style widget-scoped>
.logo-box {
display: inline-block;
width: 44px;
height: 29px;
border: 2px solid white;
background-color: rgb(240,240,240);
color: rgb(0,136,204);
font-size: 30px;
text-align: center;
vertical-align: middle;
padding-top: 15px;
text-transform: uppercase;
font-weight: bold;
}
</style>

View File

@ -9,8 +9,7 @@
$mayModify = ($isSiteAdmin || ($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Orgc']['id'] == $me['org_id']) || ($isAclModifyOrg && $event['Orgc']['id'] == $me['org_id']));
$mayPublish = ($isAclPublish && $event['Orgc']['id'] == $me['org_id']);
$mayChangeCorrelation = !Configure::read('MISP.completely_disable_correlation') && ($isSiteAdmin || ($mayModify && Configure::read('MISP.allow_disabling_correlation')));
$possibleAction = 'Proposal';
if ($mayModify) $possibleAction = 'Attribute';
$possibleAction = $mayModify ? 'attribute' : 'shadow_attribute';
$all = false;
if (isset($this->params->params['paging']['Event']['page'])) {
if ($this->params->params['paging']['Event']['page'] == 0) $all = true;

View File

@ -49,7 +49,7 @@
'children' => array(
array(
'id' => 'create-button',
'title' => $possibleAction === 'Attribute' ? __('Add attribute') : __('Add proposal'),
'title' => $possibleAction === 'attribute' ? __('Add attribute') : __('Add proposal'),
'fa-icon' => 'plus',
//'onClick' => 'clickCreateButton',
'onClick' => 'openGenericModal',

View File

@ -1,3 +1,7 @@
<?php
$this->set('menuItem', $menuItem);
$divider = $this->element('/genericElements/SideMenu/side_menu_divider');
?>
<div class="actions sideMenu">
<ul class="nav nav-list">
<?php
@ -10,7 +14,6 @@
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'dashboardAdd',
'url' => '#',
'text' => __('Add Widget'),
'onClick' => array(
'function' => 'openGenericModalPost',
@ -19,7 +22,6 @@
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'dashboardImport',
'url' => '#',
'text' => __('Import Config JSON'),
'onClick' => array(
'function' => 'openGenericModal',
@ -28,7 +30,6 @@
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'dashboardExport',
'url' => '#',
'text' => __('Export Config JSON'),
'onClick' => array(
'function' => 'openGenericModal',
@ -37,7 +38,6 @@
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'dashboardSave',
'url' => '#',
'text' => __('Save Dashboard Config'),
'onClick' => array(
'function' => 'openGenericModal',
@ -51,9 +51,9 @@
));
break;
case 'event':
$dataEventId = isset($event['Event']['id']) ? h($event['Event']['id']) : 0;
echo '<div id="hiddenSideMenuData" class="hidden" data-event-id="' . $dataEventId . '"></div>';
if (in_array($menuItem, array('addAttribute', 'addObject', 'addAttachment', 'addIOC', 'addThreatConnect', 'populateFromTemplate', 'merge'))) {
$eventId = intval($event['Event']['id']);
echo '<div id="hiddenSideMenuData" class="hidden" data-event-id="' . $eventId . '"></div>';
if (in_array($menuItem, array('editEvent', 'addAttribute', 'addObject', 'addAttachment', 'addIOC', 'addThreatConnect', 'populateFromTemplate', 'merge'))) {
// we can safely assume that mayModify is true if coming from these actions, as they require it in the controller and the user has already passed that check
$mayModify = true;
if ($isAclPublish) $mayPublish = true;
@ -68,49 +68,47 @@
if ($menuItem === 'enrichmentResults') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'enrichmentResults',
'url' => '#',
'text' => __('Enrichment Module Result')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
if ($menuItem === 'freetextResults') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'freetextResults',
'url' => '#',
'text' => __('Freetext Import Result')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'viewEvent',
'url' => '/events/view/' . $event['Event']['id'],
'url' => '/events/view/' . $eventId,
'text' => __('View Event')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'viewGraph',
'url' => '/events/viewGraph/' . $event['Event']['id'],
'url' => '/events/viewGraph/' . $eventId,
'text' => __('View Correlation Graph')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'eventLog',
'url' => '/logs/event_index/' . $event['Event']['id'],
'url' => '/logs/event_index/' . $eventId,
'text' => __('View Event History')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
if ($isSiteAdmin || (isset($mayModify) && $mayModify)) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'editEvent',
'url' => '/events/edit/' . $event['Event']['id'],
'url' => '/events/edit/' . $eventId,
'text' => __('Edit Event')
));
echo $this->element('/genericElements/SideMenu/side_menu_post_link', array(
'url' => '/events/delete/' . h($event['Event']['id']),
'url' => '/events/delete/' . $eventId,
'text' => __('Delete Event'),
'message' => __('Are you sure you want to delete # %s?', h($event['Event']['id']))
'message' => __('Are you sure you want to delete event #%s?', $eventId)
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'addAttribute',
'url' => '/attributes/add/' . $event['Event']['id'],
'url' => '/attributes/add/' . $eventId,
'text' => __('Add Attribute')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
@ -118,75 +116,75 @@
'text' => __('Add Object'),
'onClick' => array(
'function' => 'popoverPopup',
'params' => array('this', h($event['Event']['id']), 'objectTemplates', 'objectMetaChoice')
'params' => array('this', $eventId, 'objectTemplates', 'objectMetaChoice')
),
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'addAttachment',
'url' => '/attributes/add_attachment/' . $event['Event']['id'],
'url' => '/attributes/add_attachment/' . $eventId,
'text' => __('Add Attachment')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array($event['Event']['id'], 'events', 'importChoice')
'params' => array($eventId, 'events', 'importChoice')
),
'text' => __('Populate from...')
));
if ($menuItem === 'populateFromtemplate') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/templates/populateEventFromTemplate/' . $template_id . '/' . $event['Event']['id'],
'url' => '/templates/populateEventFromTemplate/' . $template_id . '/' . $eventId,
'text' => __('Populate From Template')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'genericPopup',
'params' => array($baseurl . '/events/enrichEvent/' . $event['Event']['id'], '#confirmation_box')
'params' => array($baseurl . '/events/enrichEvent/' . $eventId, '#confirmation_box')
),
'text' => __('Enrich Event')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'merge',
'url' => '/events/merge/' . $event['Event']['id'],
'url' => '/events/merge/' . $eventId,
'text' => __('Merge attributes from...')
));
}
if (($isSiteAdmin && (!isset($mayModify) || !$mayModify)) || (!isset($mayModify) || !$mayModify)) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'proposeAttribute',
'url' => '/shadow_attributes/add/' . $event['Event']['id'],
'url' => '/shadow_attributes/add/' . $eventId,
'text' => __('Propose Attribute')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'proposeAttachment',
'url' => '/shadow_attributes/add_attachment/' . $event['Event']['id'],
'url' => '/shadow_attributes/add_attachment/' . $eventId,
'text' => __('Propose Attachment')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
$publishButtons = ' hidden';
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && ($isSiteAdmin || (isset($mayPublish) && $mayPublish))) $publishButtons = "";
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'alert')
'params' => array($eventId, 'alert')
),
'class' => 'publishButtons not-published ' . $publishButtons,
'class' => 'publishButtons not-published' . $publishButtons,
'text' => __('Publish Event')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'publish')
'params' => array($eventId, 'publish')
),
'class' => 'publishButtons not-published ' . $publishButtons,
'class' => 'publishButtons not-published' . $publishButtons,
'text' => __('Publish (no email)')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'unpublish')
'params' => array($eventId, 'unpublish')
),
'class' => (isset($event['Event']['published']) && (1 == $event['Event']['published'] && $mayModify)) ? '' : 'hidden',
'text' => __('Unpublish')
@ -195,7 +193,7 @@
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'sighting')
'params' => array($eventId, 'sighting')
),
'class' => 'publishButtons',
'text' => __('Publish Sightings')
@ -206,13 +204,13 @@
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'delegatePopup',
'params' => array($event['Event']['id'])
'params' => array($eventId)
),
'text' => __('Delegate Publishing')
));
}
if (isset($delegationRequest) && $delegationRequest && ($isSiteAdmin || ($isAclPublish && ($me['org_id'] == $delegationRequest['EventDelegation']['org_id'] || $me['org_id'] == $delegationRequest['EventDelegation']['requester_org_id'])))) {
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
if ($isSiteAdmin || ($isAclPublish && ($me['org_id'] == $delegationRequest['EventDelegation']['org_id']))) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
@ -229,22 +227,23 @@
),
'text' => __('Discard Delegation Request')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
}
if (Configure::read('Plugin.ZeroMQ_enable') && $isAclZmq) {
if ($isAclZmq && Configure::read('Plugin.ZeroMQ_enable')) {
echo $this->element('/genericElements/SideMenu/side_menu_post_link', array(
'url' => '/events/pushEventToZMQ/' . h($event['Event']['id']),
'url' => '/events/pushEventToZMQ/' . $eventId,
'text' => __('Publish event to ZMQ'),
'message' => __('Are you sure you wish to republish the current event to the ZMQ channel?')
));
}
if (Configure::read('Plugin.Kafka_enable') &&
if ($isAclKafka &&
Configure::read('Plugin.Kafka_enable') &&
Configure::read('Plugin.Kafka_event_notifications_enable') &&
Configure::read('Plugin.Kafka_event_notifications_topic') &&
$isAclKafka) {
Configure::read('Plugin.Kafka_event_notifications_topic')
) {
echo $this->element('/genericElements/SideMenu/side_menu_post_link', array(
'url' => '/events/pushEventToKafka/' . h($event['Event']['id']),
'url' => '/events/pushEventToKafka/' . $eventId,
'text' => __('Publish event to Kafka'),
'message' => __('Are you sure you wish to republish the current event to the Kafka topic?')
));
@ -252,18 +251,18 @@
if (!empty($event['Orgc']['local'])) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'contact',
'url' => '/events/contact/' . $event['Event']['id'],
'url' => '/events/contact/' . $eventId,
'text' => __('Contact Reporter')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array($event['Event']['id'], 'events', 'exportChoice')
'params' => array($eventId, 'events', 'exportChoice')
),
'text' => __('Download as...')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/events/index',
'text' => __('List Events')
@ -330,7 +329,7 @@
'text' => __('REST client')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'listAttributes',
'url' => '/attributes/index',
@ -342,7 +341,7 @@
'text' => __('Search Attributes')
));
if ($menuItem == 'searchAttributes2') {
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
@ -351,7 +350,7 @@
'text' => __('Download as...')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'viewProposals',
'url' => '/shadow_attributes/index/all:0',
@ -367,7 +366,7 @@
'url' => '/event_delegations/index/context:pending',
'text' => __('View delegation requests')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/events/export',
'text' => __('Export')
@ -401,7 +400,7 @@
));
}
if ($menuItem === 'edit') {
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/admin/regexp/edit/' . h($id),
'text' => __('Edit Regexp')
@ -468,7 +467,7 @@
));
}
if ($menuItem == 'edit') {
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/admin/whitelists/edit' . h($id),
'text' => __('Edit Whitelist')
@ -491,7 +490,7 @@
'url' => '/users/change_pw',
'text' => __('Change Password')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
} else if((Configure::read('Plugin.CustomAuth_custom_password_reset'))) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'custom_pw_reset',
@ -561,7 +560,7 @@
'text' => __('Add Sharing Group')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'userGuide',
'url' => '/pages/display/doc/general',
@ -630,7 +629,7 @@
));
}
if ($menuItem === 'edit' && $isSiteAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'edit',
'url' => '/servers/edit/' . h($id),
@ -707,7 +706,7 @@
'text' => __('Delete User'),
'message' => __('Are you sure you want to delete # %s? It is highly recommended to never delete users but to disable them instead.', h($id))
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
if ($isSiteAdmin && $menuItem === 'editRole') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
@ -721,7 +720,7 @@
'text' => __('Delete Role'),
'message' => __('Are you sure you want to delete # %s?', h($id))
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
if ($isSiteAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
@ -757,7 +756,7 @@
'text' => __('Contact Users')
));
}
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
if ($isSiteAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'addOrg',
@ -794,7 +793,7 @@
'url' => '/organisations/index',
'text' => __('List Organisations')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'addRole',
'url' => '/admin/roles/add',
@ -807,7 +806,7 @@
'text' => __('List Roles')
));
if ($isSiteAdmin) {
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/servers/serverSettings',
'text' => __('Server Settings & Maintenance')
@ -820,14 +819,14 @@
'url' => '/servers/updateProgress',
'text' => __('Update Progress')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
if (Configure::read('MISP.background_jobs')) {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'jobs',
'url' => '/jobs/index',
'text' => __('Jobs')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'tasks',
'url' => '/tasks',
@ -889,7 +888,7 @@
'url' => '/posts/add/thread/' . h($thread_id),
'text' => __('Add Post')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
}
if ($menuItem === 'edit') {
@ -903,7 +902,7 @@
'url' => '/threads/view/' . h($id),
'text' => __('Edit Post')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/threads/index',
@ -934,7 +933,6 @@
if ($menuItem === 'edit') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'edit',
'url' => '#',
'text' => __('Edit Tag')
));
}
@ -1026,7 +1024,7 @@
'url' => '/decayingModel/import',
'text' => __('Import Decaying Model')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/decayingModel/add',
'text' => __('Add Decaying Model')
@ -1035,7 +1033,7 @@
'url' => '/decayingModel/decayingTool',
'text' => __('Decaying Models Tool')
));
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $divider;
}
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/decayingModel/index',
@ -1138,7 +1136,6 @@
if ($menuItem === 'edit') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'edit',
'url' => '#',
'text' => __('Edit News Item')
));
}
@ -1232,8 +1229,3 @@
?>
</ul>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#li<?php echo h($menuItem); ?>').addClass("active");
});
</script>

View File

@ -1,46 +1,42 @@
<?php
$a = '';
if (!empty($element_id)) {
$element_id = 'id="li' . $element_id . '"';
} else {
if (!empty($url)) {
$urlparts = explode('/', $url);
$element_id = 'id="li' . h(end($urlparts)) . '"';
$active = $this->get('menuItem');
if (empty($element_id) && !empty($url)) {
$urlparts = explode('/', $url);
$element_id = end($urlparts);
}
if ($active === $element_id) {
$class .= ' active';
}
if (!empty($element_id)) {
$li = ' id="li' . h($element_id) . '"';
} else {
$li = '';
}
if (!empty($class)) {
$li .= ' class="' . h(trim($class)) . '"';
}
if (empty($url)) {
$a = 'href="#"';
} else if (strpos($url, '://') !== false) {
$a = 'href="' . h($url) . '"';
} else {
$a = 'href="' . $this->get('baseurl') . h($url) . '"';
}
if (!empty($onClick)) {
$params = '';
foreach ($onClick['params'] as $param) {
if (!empty($params)) {
$params .= ', ';
}
if ($param === 'this') {
$params .= $param;
} else {
$element_id = '';
$params .= "'" . h($param) . "'";
}
}
if (empty($url)) {
$a = 'href="#"';
} else if (strpos($url, '://') !== null) {
$a = 'href="' . h($url) . '"';
} else {
$a = 'href="' . $baseurl . h($url) . '"';
}
if (!empty($class)) {
$class = 'class="' . h($class) . '"';
} else {
$class = '';
}
if (!empty($onClick)) {
$params = '';
foreach ($onClick['params'] as $param) {
if (!empty($params)) {
$params .= ', ';
}
if ($param === 'this') {
$params .= $param;
} else {
$params .= "'" . h($param) . "'";
}
}
$a .= sprintf(' onClick="%s(%s)"', $onClick['function'], $params);
}
if (!empty($download)) {
$download = 'download="' . h($download) . '"';
} else {
$download = '';
}
echo sprintf('<li %s %s><a %s %s>%s</a></li>', $element_id, $class, $a, $download, h($text));
?>
$a .= sprintf(' onclick="%s(%s)"', $onClick['function'], $params);
}
if (!empty($download)) {
$a .= ' download="' . h($download) . '"';
}
echo "<li$li><a $a>" . h($text) . '</a></li>';

View File

@ -1,32 +1,21 @@
<?php
$a = '';
if (!empty($element_id)) {
$element_id = 'id="li' . $element_id . '"';
if (!empty($element_id)) {
$li = ' id="li' . $element_id . '"';
} else {
if (!empty($url)) {
$urlparts = explode('/', $url);
$li = ' id="li' . h(end($urlparts)) . '"';
} else {
if (!empty($url)) {
$urlparts = explode('/', $url);
$element_id = 'id="li' . h(end($urlparts)) . '"';
} else {
$element_id = '';
}
$li = '';
}
if (empty($url)) {
$a = '';
} else if (strpos($url, '://') !== null) {
$a = h($url);
} else {
$a = $baseurl . h($url);
}
if (!empty($class)) {
$class = 'class="' . h($class) . '"';
} else {
$class = '';
}
$post_link = $this->Form->postLink(
__('%s', $text),
$url,
null,
empty($message) ? null : $message
);
echo sprintf('<li %s %s>%s</li>', $element_id, $class, $post_link);
?>
}
if (!empty($class)) {
$li .= ' class="' . h($class) . '"';
}
$post_link = $this->Form->postLink(
$text,
$url,
null,
empty($message) ? null : $message
);
echo "<li$li>$post_link</li>";

View File

@ -1,141 +1,128 @@
<div class="shadow_attributes <?php if (!isset($ajax) || !$ajax) echo 'form';?>">
<?php echo $this->Form->create('ShadowAttribute', array('url' => '/shadow_attributes/add/' . $event_id));?>
<fieldset>
<legend><?php echo __('Add Proposal'); ?></legend>
<div id="formWarning" class="message ajaxMessage"></div>
<div class="add_attribute_fields">
<?php
echo $this->Form->hidden('event_id');
echo $this->Form->input('category', array(
<?php
echo $this->element('genericElements/Form/genericForm', array(
'form' => $this->Form,
'data' => array(
'title' => __('Add Proposal'),
'model' => 'ShadowAttribute',
'fields' => array(
array(
'field' => 'event_id',
'class' => 'org-id-picker-hidden-field',
'type' => 'text',
'hidden' => true
),
array(
'field' => 'category',
'class' => 'input',
'empty' => __('(choose one)'),
'div' => 'input',
'label' => __('Category ') . $this->element('formInfo', array('type' => 'category')),
));
echo $this->Form->input('type', array(
'empty' => __('(first choose category)'),
'label' => __('Type ') . $this->element('formInfo', array('type' => 'type')),
));
?>
<div class="input clear"></div>
<?php
echo $this->Form->input('value', array(
'type' => 'textarea',
'error' => array('escape' => false),
'class' => 'input-xxlarge clear'
));
echo $this->Form->input('comment', array(
'type' => 'text',
'label' => __('Contextual Comment'),
'error' => array('escape' => false),
'div' => 'input clear',
'class' => 'input-xxlarge'
));
?>
<div class="input clear"></div>
<?php
echo $this->Form->input('to_ids', array(
'checked' => true,
'label' => __('for Intrusion Detection System'),
));
echo $this->Form->input('batch_import', array(
'type' => 'checkbox',
));
echo $this->Form->input('first_seen', array(
'options' => $categories,
'stayInLine' => 1
),
array(
'field' => 'type',
'class' => 'input',
'empty' => __('(choose category first)'),
'options' => $types
),
array(
'field'=> 'value',
'type' => 'textarea',
'class' => 'input span6',
'div' => 'input clear'
),
array(
'field' => 'comment',
'type' => 'text',
'div' => 'input hidden',
'required' => false,
));
echo $this->Form->input('last_seen', array(
'class' => 'input span6',
'div' => 'input clear',
'label' => __("Contextual Comment")
),
array(
'field' => 'to_ids',
'type' => 'checkbox',
'label' => __("For Intrusion Detection System"),
//'stayInLine' => 1
),
array(
'field' => 'batch_import',
'type' => 'checkbox'
),
array(
'field' => 'first_seen',
'type' => 'text',
'div' => 'input hidden',
'required' => false,
));
?>
<div id="bothSeenSliderContainer"></div>
</div>
</fieldset>
<p style="color:red;font-weight:bold;display:none;<?php if ($ajax) echo 'text-align:center;'; ?>" id="warning-message"><?php echo __('Warning: You are about to share data that is of a classified nature (Attribution / targeting data). Make sure that you are authorised to share this.');?></p>
<?php if (isset($ajax) && $ajax): ?>
<div class="overlay_spacing">
<table>
<tr>
<td style="vertical-align:top">
<span tite="<?php echo __('Propose');?>" role="button" tabindex="0" aria-label="<?php echo __('Propose');?>" id="submitButton" class="btn btn-primary" onClick="submitPopoverForm('<?php echo $event_id;?>', 'propose')"><?php echo __('Propose');?></span>
</td>
<td style="width:540px;">
<p style="color:red;font-weight:bold;display:none;<?php if (isset($ajax) && $ajax) echo "text-align:center;"?>" id="warning-message"><?php echo __('Warning: You are about to share data that is of a sensitive nature (Attribution / targeting data). Make sure that you are authorised to share this.');?></p>
</td>
<td style="vertical-align:top;">
<span class="btn btn-inverse" id="cancel_attribute_add"><?php echo __('Cancel');?></span>
</td>
</tr>
</table>
</div>
<?php
else:
echo $this->Form->button(__('Propose'), array('class' => 'btn btn-primary'));
endif;
echo $this->Form->end();
?>
</div>
<?php
$event['Event']['id'] = $this->request->data['ShadowAttribute']['event_id'];
if (!$ajax) {
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'proposeAttribute', 'event' => $event));
}
echo $this->element('form_seen_input');
?>
<script type="text/javascript">
<?php
$formInfoTypes = array('category' => 'Category', 'type' => 'Type');
echo 'var formInfoFields = ' . json_encode($formInfoTypes) . PHP_EOL;
foreach ($formInfoTypes as $formInfoType => $humanisedName) {
echo 'var ' . $formInfoType . 'FormInfoValues = {' . PHP_EOL;
foreach ($info[$formInfoType] as $key => $formInfoData) {
echo '"' . $key . '": "<span class=\"blue bold\">' . h($formInfoData['key']) . '</span>: ' . h($formInfoData['desc']) . '<br />",' . PHP_EOL;
}
echo '}' . PHP_EOL;
}
?>
//
//Generate Category / Type filtering array
//
var category_type_mapping = new Array();
<?php
foreach ($categoryDefinitions as $category => $def) {
echo "category_type_mapping['" . addslashes($category) . "'] = {";
$first = true;
foreach ($def['types'] as $type) {
if ($first) $first = false;
else echo ', ';
echo "'" . addslashes($type) . "' : '" . addslashes($type) . "'";
}
echo "}; \n";
}
'hidden' => true
),
array(
'field' => 'last_seen',
'type' => 'text',
'hidden' => true
),
),
'submit' => array(
'action' => 'add',
'text' => __('Propose'),
'ajaxSubmit' => sprintf(
'submitPopoverForm(%s, %s, 0, 1)',
"'" . h($event_id) . "'",
"'add'"
)
),
'metaFields' => array(
'<div id="bothSeenSliderContainer" style="height: 170px;"></div>'
)
)
));
if (!$ajax) {
$event = ['Event' => ['id' => $event_id ]];
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'proposeAttribute', 'event' => $event));
}
?>
<script type="text/javascript">
var category_type_mapping = <?= json_encode(array_map(function($value) {
return array_combine($value['types'], $value['types']);
}, $categoryDefinitions)); ?>;
$(document).ready(function() {
initPopoverContent('ShadowAttribute');
$("#ShadowAttributeCategory").on('change', function(e) {
formCategoryChanged('ShadowAttribute');
if ($(this).val() === 'Attribution' || $(this).val() === 'Targeting data') {
$("#warning-message").show();
} else {
$("#warning-message").hide();
}
});
$("#ShadowAttributeCategory, #ShadowAttributeType").change(function() {
initPopoverContent('ShadowAttribute');
});
<?php if ($ajax): ?>
$('#cancel_attribute_add').click(function() {
cancelPopoverForm();
$('#ShadowAttributeCategory').change(function() {
formCategoryChanged('ShadowAttribute');
$('#ShadowAttributeType').chosen('destroy').chosen();
});
<?php endif; ?>
});
</script>
$(function() {
$('#ShadowAttributeType').closest('form').submit(function( event ) {
if ($('#ShadowAttributeType').val() === 'datetime') {
// add timezone of the browser if not set
var allowLocalTZ = true;
var $valueInput = $('#ShadowAttributeValue')
var dateValue = moment($valueInput.val())
if (dateValue.isValid()) {
if (dateValue.creationData().format !== "YYYY-MM-DDTHH:mm:ssZ" && dateValue.creationData().format !== "YYYY-MM-DDTHH:mm:ss.SSSSZ") {
// Missing timezone data
var confirm_message = '<?php echo __('Timezone missing, auto-detected as: ') ?>' + dateValue.format('Z')
confirm_message += '<?php echo '\r\n' . __('The following value will be submitted instead: '); ?>' + dateValue.toISOString(allowLocalTZ)
if (confirm(confirm_message)) {
$valueInput.val(dateValue.toISOString(allowLocalTZ));
} else {
return false;
}
}
} else {
var textStatus = '<?php echo __('Value is not a valid datetime. Expected format YYYY-MM-DDTHH:mm:ssZ') ?>'
showMessage('fail', textStatus);
return false;
}
}
});
<?php if (!$ajax): ?>
$('#ShadowAttributeType').chosen();
$('#ShadowAttributeCategory').chosen();
<?php else: ?>
$('#genericModal').on('shown', function() {
$('#ShadowAttributeType').chosen();
$('#ShadowAttributeCategory').chosen();
})
<?php endif; ?>
});
</script>
<?php echo $this->element('form_seen_input'); ?>
<?php echo $this->Js->writeBuffer(); // Write cached scripts

View File

@ -38,7 +38,7 @@
<div class="input clear"></div>
<?php
echo $this->Form->input('to_ids', array(
'label' => __('IDS Signature?'),
'label' => __('For Intrusion Detection System'),
));
echo $this->Form->input('first_seen', array(
'type' => 'text',

View File

@ -29,7 +29,7 @@ from cybox.objects.network_connection_object import NetworkConnection
from cybox.objects.network_socket_object import NetworkSocket
from cybox.objects.pipe_object import Pipe
from cybox.objects.port_object import Port
from cybox.objects.process_object import Process
from cybox.objects.process_object import ChildPIDList, ImageInfo, PortList, Process
from cybox.objects.socket_address_object import SocketAddress
from cybox.objects.system_object import System, NetworkInterface, NetworkInterfaceList
from cybox.objects.unix_user_account_object import UnixUserAccount
@ -918,12 +918,27 @@ class StixBuilder(object):
if feature in attributes_dict:
setattr(process_object, feature.replace('-', '_'), attributes_dict[feature][0])
if 'child-pid' in attributes_dict:
# child-pid = attributes['child-pid']
for child in attributes['child-pid']:
process_object.child_pid_list.append(child)
# if 'port' in attributes_dict:
# for port in attributes['port']:
# process_object.port_list.append(self.create_port_object(port['value']))
for child in attributes_dict['child-pid']:
try:
process_object.child_pid_list.append(child)
except AttributeError:
process_object.child_pid_list = ChildPIDList()
process_object.child_pid_list.append(child)
if 'port' in attributes_dict:
for port in attributes_dict['port']:
port_object = self.create_port_object(port)
try:
process_object.port_list.append(port_object)
except AttributeError:
process_object.port_list = PortList()
process_object.port_list.append(port_object)
for key, feature in zip(('image', 'command-line'), ('file_name', 'command_line')):
if key in attributes_dict:
try:
setattr(process_object.image_info, feature, attributes_dict[key])
except AttributeError:
process_object.image_info = ImageInfo()
setattr(process_object.image_info, feature, attributes_dict[key][0])
uuid = misp_object['uuid']
process_object.parent.id_ = "{}:ProcessObject-{}".format(self.namespace_prefix, uuid)
observable = Observable(process_object)

View File

@ -406,9 +406,14 @@ class StixParser():
if properties.child_pid_list:
for child in properties.child_pid_list:
attributes.append(["text", child.value, "child-pid"])
# if properties.port_list:
# for port in properties.port_list:
# attributes.append(["src-port", port.port_value.value, "port"])
if properties.port_list:
for port in properties.port_list:
attributes.append(["port", port.port_value.value, "port"])
if properties.image_info:
if properties.image_info.file_name:
attributes.append(["filename", properties.image_info.file_name.value, "image"])
if properties.image_info.command_line:
attributes.append(["text", properties.image_info.command_line.value, "command-line"])
if properties.network_connection_list:
references = []
for connection in properties.network_connection_list:

View File

@ -3908,13 +3908,14 @@ function getFormInfoContent(property, field) {
function formCategoryChanged(id) {
// fill in the types
var options = $('#' + id +'Type').prop('options');
$('option', $('#' + id +'Type')).remove();
$.each(category_type_mapping[$('#' + id +'Category').val()], function(val, text) {
var $type = $('#' + id + 'Type');
var options = $type.prop('options');
$('option', $type).remove();
$.each(category_type_mapping[$('#' + id + 'Category').val()], function(val, text) {
options[options.length] = new Option(text, val);
});
// enable the form element
$('#AttributeType').prop('disabled', false);
$type.prop('disabled', false);
}
function malwareCheckboxSetter(context) {