mirror of https://github.com/MISP/MISP
Merge branch '2.4' of github.com:MISP/MISP into 2.4
commit
4b71eced00
|
@ -103,6 +103,21 @@ class AppController extends Controller
|
|||
|
||||
public function beforeFilter()
|
||||
{
|
||||
if (Configure::read('Security.allow_cors')) {
|
||||
// Add CORS headers
|
||||
$this->response->cors($this->request,
|
||||
explode(',', Configure::read('Security.cors_origins')),
|
||||
['*'],
|
||||
['Origin', 'Content-Type', 'Authorization', 'Accept']);
|
||||
|
||||
if ($this->request->is('options')) {
|
||||
// Stop here!
|
||||
// CORS only needs the headers
|
||||
$this->response->send();
|
||||
$this->_stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->params['named']['sql'])) {
|
||||
$this->sql_dump = 1;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ class ACLComponent extends Component
|
|||
'viewEventAttributes' => array('*'),
|
||||
'viewEventGraph' => array('*'),
|
||||
'viewGraph' => array('*'),
|
||||
'viewMitreAttackMatrix' => array('*'),
|
||||
'viewGalaxyMatrix' => array('*'),
|
||||
'xml' => array('*')
|
||||
),
|
||||
'favouriteTags' => array(
|
||||
|
|
|
@ -423,14 +423,23 @@ class RestResponseComponent extends Component
|
|||
$type = 'json';
|
||||
}
|
||||
$cakeResponse = new CakeResponse(array('body'=> $response, 'status' => $code, 'type' => $type));
|
||||
|
||||
if (Configure::read('Security.allow_cors')) {
|
||||
$headers["Access-Control-Allow-Headers"] = "Origin, Content-Type, Authorization, Accept";
|
||||
$headers["Access-Control-Allow-Methods"] = "*";
|
||||
$headers["Access-Control-Allow-Origin"] = explode(',', Configure::read('Security.cors_origins'));
|
||||
}
|
||||
|
||||
if (!empty($headers)) {
|
||||
foreach ($headers as $key => $value) {
|
||||
$cakeResponse->header($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
if ($download) {
|
||||
$cakeResponse->download($download);
|
||||
}
|
||||
|
||||
return $cakeResponse;
|
||||
}
|
||||
|
||||
|
|
|
@ -4663,15 +4663,16 @@ class EventsController extends AppController
|
|||
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
|
||||
}
|
||||
|
||||
public function viewMitreAttackMatrix($scope_id, $scope='event', $disable_picking=false)
|
||||
public function viewGalaxyMatrix($scope_id, $galaxy_id, $scope='event', $disable_picking=false)
|
||||
{
|
||||
$this->loadModel('Galaxy');
|
||||
$mitreAttackGalaxyId = $this->Galaxy->getMitreAttackGalaxyId();
|
||||
$matrixData = $this->Galaxy->getMatrix($galaxy_id);
|
||||
|
||||
$attackTacticData = $this->Galaxy->getMitreAttackMatrix();
|
||||
$attackTactic = $attackTacticData['attackTactic'];
|
||||
$attackTags = $attackTacticData['attackTags'];
|
||||
$killChainOrders = $attackTacticData['killChain'];
|
||||
$instanceUUID = $attackTacticData['instance-uuid'];
|
||||
$tabs = $matrixData['tabs'];
|
||||
$matrixTags = $matrixData['matrixTags'];
|
||||
$killChainOrders = $matrixData['killChain'];
|
||||
$instanceUUID = $matrixData['instance-uuid'];
|
||||
|
||||
if ($scope == 'event') {
|
||||
$eventId = $scope_id;
|
||||
|
@ -4692,17 +4693,20 @@ class EventsController extends AppController
|
|||
throw new Exception("Invalid options.");
|
||||
}
|
||||
|
||||
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores($eventId, $attackTags);
|
||||
$scoresDataEvent = $this->Event->EventTag->getTagScores($eventId, $attackTags);
|
||||
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores($eventId, $matrixTags);
|
||||
$scoresDataEvent = $this->Event->EventTag->getTagScores($eventId, $matrixTags);
|
||||
$maxScore = 0;
|
||||
$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);
|
||||
$sum = (isset($scoresDataAttr['scores'][$key]) ? $scoresDataAttr['scores'][$key] : 0) + (isset($scoresDataEvent['scores'][$key]) ? $scoresDataEvent['scores'][$key] : 0);
|
||||
$scoresData[$key] = $sum;
|
||||
$maxScore = max($maxScore, $sum);
|
||||
}
|
||||
$maxScore = max($scoresDataAttr['maxScore'], $scoresDataEvent['maxScore']);
|
||||
|
||||
$scores = $scoresData;
|
||||
|
||||
if ($this->_isRest()) {
|
||||
$json = array('matrix' => $attackTactic, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
|
||||
$json = array('matrix' => $tabs, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
|
||||
$this->response->type('json');
|
||||
return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json'));
|
||||
} else {
|
||||
|
@ -4716,14 +4720,22 @@ class EventsController extends AppController
|
|||
|
||||
$this->set('eventId', $eventId);
|
||||
$this->set('target_type', $scope);
|
||||
$this->set('killChainOrders', $killChainOrders);
|
||||
$this->set('attackTactic', $attackTactic);
|
||||
$this->set('columnOrders', $killChainOrders);
|
||||
$this->set('tabs', $tabs);
|
||||
$this->set('scores', $scores);
|
||||
$this->set('maxScore', $maxScore);
|
||||
$this->set('colours', $colours);
|
||||
if (!empty($colours)) {
|
||||
$this->set('colours', $colours['mapping']);
|
||||
$this->set('interpolation', $colours['interpolation']);
|
||||
}
|
||||
$this->set('pickingMode', !$disable_picking);
|
||||
$this->set('target_id', $scope_id);
|
||||
$this->render('/Elements/view_mitre_attack_matrix');
|
||||
if ($matrixData['galaxy']['id'] == $mitreAttackGalaxyId) {
|
||||
$this->set('defaultTabName', 'mitre-attack');
|
||||
$this->set('removeTrailling', 2);
|
||||
}
|
||||
|
||||
$this->render('/Elements/view_galaxy_matrix');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,33 +79,13 @@ class GalaxiesController extends AppController
|
|||
|
||||
public function selectGalaxy($target_id, $target_type='event', $namespace='misp')
|
||||
{
|
||||
$expectedDescription = 'ATT&CK Tactic';
|
||||
$mitreAttackGalaxyId = $this->Galaxy->getMitreAttackGalaxyId();
|
||||
$conditions = $namespace == '0' ? array() : array('namespace' => $namespace);
|
||||
if ($namespace == 'mitre-attack' || $namespace == '0') {
|
||||
$conditions[] = array('description !=' => $expectedDescription);
|
||||
$conditions2 = array('namespace' => 'mitre-attack');
|
||||
$conditions2[] = array('description' => $expectedDescription);
|
||||
|
||||
$tacticGalaxies = $this->Galaxy->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions2,
|
||||
));
|
||||
}
|
||||
$galaxies = $this->Galaxy->find('all', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => $conditions,
|
||||
'order' => array('name asc')
|
||||
));
|
||||
if (!empty($tacticGalaxies)) {
|
||||
array_unshift($galaxies, array('Galaxy' => array(
|
||||
'id' => '-1',
|
||||
'uuid' => '-1',
|
||||
'name' => $expectedDescription,
|
||||
'type' => '-1',
|
||||
'icon' => '/img/mitre-attack-icon.ico',
|
||||
'namespace' => 'mitre-attack'
|
||||
)));
|
||||
}
|
||||
|
||||
$items = array();
|
||||
$items[] = array(
|
||||
|
@ -113,7 +93,7 @@ class GalaxiesController extends AppController
|
|||
'value' => "/galaxies/selectCluster/" . h($target_id) . '/' . h($target_type) . '/0'
|
||||
);
|
||||
foreach ($galaxies as $galaxy) {
|
||||
if ($galaxy['Galaxy']['id'] != -1) {
|
||||
if (!isset($galaxy['Galaxy']['kill_chain_order'])) {
|
||||
$items[] = array(
|
||||
'name' => h($galaxy['Galaxy']['name']),
|
||||
'value' => "/galaxies/selectCluster/" . $target_id . '/' . $target_type . '/' . $galaxy['Galaxy']['id'],
|
||||
|
@ -123,13 +103,17 @@ class GalaxiesController extends AppController
|
|||
'infoExtra' => $galaxy['Galaxy']['description'],
|
||||
)
|
||||
);
|
||||
} else { // attackMatrix
|
||||
$items[] = array(
|
||||
} else { // should use matrix instead
|
||||
$param = array(
|
||||
'name' => $galaxy['Galaxy']['name'],
|
||||
'functionName' => "getMitreMatrixPopup('" . $target_type . "', '" . $target_id . "')",
|
||||
'functionName' => "getMatrixPopup('" . $target_type . "', '" . $target_id . "', " . $galaxy['Galaxy']['id'] . ")",
|
||||
'isPill' => true,
|
||||
'img' => "/img/mitre-attack-icon.ico",
|
||||
'isMatrix' => true
|
||||
);
|
||||
if ($galaxy['Galaxy']['id'] == $mitreAttackGalaxyId) {
|
||||
$param['img'] = "/img/mitre-attack-icon.ico";
|
||||
}
|
||||
$items[] = $param;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,8 @@ class GalaxyClustersController extends AppController
|
|||
$cluster['GalaxyCluster']['tag_count'] = count($tag['EventTag']);
|
||||
$cluster['GalaxyCluster']['tag_id'] = $tag['Tag']['id'];
|
||||
}
|
||||
} else {
|
||||
throw new NotFoundException('Cluster not found.');
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
$cluster['GalaxyCluster']['Galaxy'] = $cluster['Galaxy'];
|
||||
|
|
|
@ -1859,14 +1859,17 @@ class UsersController extends AppController
|
|||
{
|
||||
$this->loadModel('Event');
|
||||
$this->loadModel('Galaxy');
|
||||
$attackTacticData = $this->Galaxy->getMitreAttackMatrix();
|
||||
$attackTactic = $attackTacticData['attackTactic'];
|
||||
$attackTags = $attackTacticData['attackTags'];
|
||||
$killChainOrders = $attackTacticData['killChain'];
|
||||
$instanceUUID = $attackTacticData['instance-uuid'];
|
||||
|
||||
$scoresDataAttr = $this->Event->Attribute->AttributeTag->getTagScores(0, $attackTags);
|
||||
$scoresDataEvent = $this->Event->EventTag->getTagScores(0, $attackTags);
|
||||
$galaxy_id = $this->Galaxy->getMitreAttackGalaxyId();
|
||||
$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);
|
||||
|
@ -1875,7 +1878,7 @@ class UsersController extends AppController
|
|||
$scores = $scoresData;
|
||||
|
||||
if ($this->_isRest()) {
|
||||
$json = array('matrix' => $attackTactic, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
|
||||
$json = array('matrix' => $tabs, 'scores' => $scores, 'instance-uuid' => $instanceUUID);
|
||||
return $this->RestResponse->viewData($json, $this->response->type());
|
||||
} else {
|
||||
App::uses('ColourGradientTool', 'Tools');
|
||||
|
@ -1883,12 +1886,17 @@ class UsersController extends AppController
|
|||
$colours = $gradientTool->createGradientFromValues($scores);
|
||||
|
||||
$this->set('target_type', 'attribute');
|
||||
$this->set('killChainOrders', $killChainOrders);
|
||||
$this->set('attackTactic', $attackTactic);
|
||||
$this->set('columnOrders', $killChainOrders);
|
||||
$this->set('tabs', $tabs);
|
||||
$this->set('scores', $scores);
|
||||
$this->set('maxScore', $maxScore);
|
||||
$this->set('colours', $colours);
|
||||
if (!empty($colours)) {
|
||||
$this->set('colours', $colours['mapping']);
|
||||
$this->set('interpolation', $colours['interpolation']);
|
||||
}
|
||||
$this->set('pickingMode', false);
|
||||
$this->set('defaultTabName', "mitre-attack");
|
||||
$this->set('removeTrailling', 2);
|
||||
|
||||
$this->render('statistics_attackmatrix');
|
||||
}
|
||||
|
|
|
@ -1,45 +1,113 @@
|
|||
<?php
|
||||
class ColourGradientTool
|
||||
{
|
||||
public function createGradient($step)
|
||||
{
|
||||
$stepHex = dechex($step);
|
||||
$minHex = 0x0000FF;
|
||||
$maxHex = 0xFF0000;
|
||||
$intervalHex = ($maxHex-$minHex) / $stepHex;
|
||||
$colours = array();
|
||||
for ($i=$minHex; $i<$maxHex; $i+=$intervalHex) {
|
||||
$colours[] = $i;
|
||||
}
|
||||
return $colours;
|
||||
}
|
||||
|
||||
// source: https://graphicdesign.stackexchange.com/a/83867
|
||||
// $values of the form array(item1: val1, item2: val2, ...)
|
||||
public function createGradientFromValues($items)
|
||||
{
|
||||
$starColor = '#0000FF';
|
||||
$endColor = '#FF0000';
|
||||
|
||||
if (count($items) == 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$maxColorHex = 0x0000FF;
|
||||
$minColorHex = 0xE0E0FF;
|
||||
|
||||
$vals = array_values($items);
|
||||
$maxDec = max($vals);
|
||||
$minDec = min($vals);
|
||||
|
||||
if ($maxDec == $minDec) {
|
||||
$intervalHex = 0x0;
|
||||
} else {
|
||||
$intervalHex = ($maxColorHex - $minColorHex)/($maxDec-$minDec);
|
||||
}
|
||||
|
||||
$interpolation = $this->interpolateColors($starColor, $endColor, $maxDec+1, true);
|
||||
$coloursMapping = array();
|
||||
foreach ($items as $name => $val) {
|
||||
$ratio = ($val-$minDec)*($intervalHex);
|
||||
$colour = $maxDec == $minDec ? $maxColorHex : $ratio + $minColorHex;
|
||||
$coloursMapping[$name] = '#' . str_pad(dechex($colour), 6, '0', STR_PAD_LEFT);
|
||||
$color = $interpolation[$val];
|
||||
$coloursMapping[$name] = '#' . str_pad(dechex($color[0]), 2, '0', STR_PAD_LEFT) . str_pad(dechex($color[1]), 2, '0', STR_PAD_LEFT) . str_pad(dechex($color[2]), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
return array('mapping' => $coloursMapping, 'interpolation' => $interpolation);
|
||||
}
|
||||
|
||||
private function hue2rgb($p, $q, $t) {
|
||||
if ($t < 0) $t += 1;
|
||||
if ($t > 1) $t -= 1;
|
||||
if ($t < 1/6) return $p + ($q - $p) * 6 * $t;
|
||||
if ($t < 1/2) return $q;
|
||||
if ($t < 2/3) return $p + ($q - $p) * (2/3 - $t) * 6;
|
||||
return $p;
|
||||
}
|
||||
|
||||
private function hsl2rgb($color) {
|
||||
$l = $color[2];
|
||||
if ($color[1] == 0) {
|
||||
$l = round($l*255);
|
||||
return array($l, $l, $l);
|
||||
} else {
|
||||
$s = $color[1];
|
||||
$q = ($l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s);
|
||||
$p = 2 * $l - $q;
|
||||
$r = $this->hue2rgb($p, $q, $color[0] + 1/3);
|
||||
$g = $this->hue2rgb($p, $q, $color[0]);
|
||||
$b = $this->hue2rgb($p, $q, $color[0] - 1/3);
|
||||
return array(round($r*255), round($g*255), round($b*255));
|
||||
}
|
||||
return $coloursMapping;
|
||||
}
|
||||
|
||||
private function rgb2hsl($color) {
|
||||
$r = $color[0]/255;
|
||||
$g = $color[1]/255;
|
||||
$b = $color[2]/255;
|
||||
$arrRGB = array($r, $g, $b);
|
||||
|
||||
$max = max($arrRGB);
|
||||
$min = min($arrRGB);
|
||||
$h = ($max - $min) / 2;
|
||||
$s = $h;
|
||||
$l = $h;
|
||||
|
||||
if ($max == $min) {
|
||||
$s = 0; // achromatic
|
||||
$h = 0;
|
||||
} else {
|
||||
$d = $max - $min;
|
||||
$s = ($l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min) );
|
||||
if ($max == $r) {
|
||||
$h = ($g - $b) / $d + ($g < $b ? 6 : 0);
|
||||
} elseif ($max == $g) {
|
||||
$h = ($b - $r) / $d + 2;
|
||||
} elseif ($max == $b) {
|
||||
$h = ($r - $g) / $d + 4;
|
||||
}
|
||||
$h = $h / 6;
|
||||
return array($h, $s, $l);
|
||||
}
|
||||
}
|
||||
|
||||
private function interpolateColor($color1, $color2, $factor, $useHSL=false) {
|
||||
if ($useHSL) {
|
||||
$hsl1 = $this->rgb2hsl($color1);
|
||||
$hsl2 = $this->rgb2hsl($color2);
|
||||
for ($i=0; $i<3; $i++) {
|
||||
$hsl1[$i] += $factor*($hsl2[$i] - $hsl1[$i]);
|
||||
}
|
||||
$result = $this->hsl2rgb($hsl1);
|
||||
} else {
|
||||
$result = $color1;
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
$result[$i] = round($result[$i] + $factor * ($color2[$i] - $color1[$i]));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function interpolateColors($hexColor1, $hexColor2, $steps, $useHSL=false) {
|
||||
$stepFactor = 1 / ($steps - 1);
|
||||
$interpolatedColorArray = array();
|
||||
$color1 = sscanf($hexColor1, "#%02x%02x%02x");
|
||||
$color2 = sscanf($hexColor2, "#%02x%02x%02x");
|
||||
|
||||
for($i = 0; $i < $steps; $i++) {
|
||||
$interpolatedColorArray[$i] = $this->interpolateColor($color1, $color2, $stepFactor * $i, $useHSL);
|
||||
}
|
||||
|
||||
return $interpolatedColorArray;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ class AppModel extends Model
|
|||
7 => false, 8 => false, 9 => false, 10 => false, 11 => false, 12 => false,
|
||||
13 => false, 14 => false, 15 => false, 18 => false, 19 => false, 20 => false,
|
||||
21 => false, 22 => false, 23 => false, 24 => false, 25 => false, 26 => false,
|
||||
27 => false, 28 => false
|
||||
27 => false, 28 => false, 29 => false
|
||||
);
|
||||
|
||||
public function afterSave($created, $options = array())
|
||||
|
@ -1089,6 +1089,9 @@ class AppModel extends Model
|
|||
case 28:
|
||||
$sqlArray[] = "ALTER TABLE `servers` ADD `caching_enabled` tinyint(1) NOT NULL DEFAULT 0;";
|
||||
break;
|
||||
case 29:
|
||||
$sqlArray[] = "ALTER TABLE `galaxies` ADD `kill_chain_order` text NOT NULL;";
|
||||
break;
|
||||
case 'fixNonEmptySharingGroupID':
|
||||
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
|
||||
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
|
||||
|
|
|
@ -20,6 +20,14 @@ class Galaxy extends AppModel
|
|||
public function beforeValidate($options = array())
|
||||
{
|
||||
parent::beforeValidate();
|
||||
if (isset($this->data['Galaxy']['kill_chain_order'])) {
|
||||
$json = json_encode($this->data['Galaxy']['kill_chain_order']);
|
||||
if ($json !== null) {
|
||||
$this->data['Galaxy']['kill_chain_order'] = $json;
|
||||
} else {
|
||||
unset($this->data['Galaxy']['kill_chain_order']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -28,6 +36,18 @@ class Galaxy extends AppModel
|
|||
$this->GalaxyCluster->deleteAll(array('GalaxyCluster.galaxy_id' => $this->id));
|
||||
}
|
||||
|
||||
public function afterFind($results, $primary = false)
|
||||
{
|
||||
foreach ($results as $k => $v) {
|
||||
if (isset($v['Galaxy']['kill_chain_order']) && $v['Galaxy']['kill_chain_order'] !== '') {
|
||||
$results[$k]['Galaxy']['kill_chain_order'] = json_decode($v['Galaxy']['kill_chain_order'], true);
|
||||
} else {
|
||||
unset($results[$k]['Galaxy']['kill_chain_order']);
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
private function __load_galaxies($force = false)
|
||||
{
|
||||
$dir = new Folder(APP . 'files' . DS . 'misp-galaxy' . DS . 'galaxies');
|
||||
|
@ -39,7 +59,7 @@ class Galaxy extends AppModel
|
|||
$file->close();
|
||||
}
|
||||
$galaxyTypes = array();
|
||||
foreach ($galaxies as $galaxy) {
|
||||
foreach ($galaxies as $i => $galaxy) {
|
||||
$galaxyTypes[$galaxy['type']] = $galaxy['type'];
|
||||
}
|
||||
$temp = $this->find('all', array(
|
||||
|
@ -353,81 +373,24 @@ class Galaxy extends AppModel
|
|||
}
|
||||
}
|
||||
|
||||
public function getMitreAttackGalaxyId($type="mitre-enterprise-attack-attack-pattern")
|
||||
public function getMitreAttackGalaxyId($type="mitre-attack-pattern", $namespace="mitre-attack")
|
||||
{
|
||||
$galaxy = $this->find('first', array(
|
||||
'recursive' => -1,
|
||||
'fields' => 'id',
|
||||
'conditions' => array('Galaxy.type' => $type),
|
||||
'conditions' => array('Galaxy.type' => $type, 'Galaxy.namespace' => $namespace),
|
||||
));
|
||||
return empty($galaxy) ? 0 : $galaxy['Galaxy']['id'];
|
||||
}
|
||||
|
||||
public function getMitreAttackMatrix()
|
||||
public function getMatrix($galaxy_id)
|
||||
{
|
||||
$killChainOrderEnterprise = array(
|
||||
'initial-access',
|
||||
'execution',
|
||||
'persistence',
|
||||
'privilege-escalation',
|
||||
'defense-evasion',
|
||||
'credential-access',
|
||||
'discovery',
|
||||
'lateral-movement',
|
||||
'collection',
|
||||
'exfiltration',
|
||||
'command-and-control'
|
||||
);
|
||||
$killChainOrderMobile = array(
|
||||
'persistence',
|
||||
'privilege-escalation',
|
||||
'defense-evasion',
|
||||
'credential-access',
|
||||
'discovery',
|
||||
'lateral-movement',
|
||||
'effects', 'collection',
|
||||
'exfiltration',
|
||||
'command-and-control',
|
||||
'general-network-based',
|
||||
'cellular-network-based',
|
||||
'could-based'
|
||||
);
|
||||
$killChainOrderPre = array(
|
||||
'priority-definition-planning',
|
||||
'priority-definition-direction',
|
||||
'target-selection',
|
||||
'technical-information-gathering',
|
||||
'people-information-gathering',
|
||||
'organizational-information-gathering',
|
||||
'technical-weakness-identification',
|
||||
'people-weakness-identification',
|
||||
'organizational-weakness-identification',
|
||||
'adversary-opsec',
|
||||
'establish-&-maintain-infrastructure',
|
||||
'persona-development',
|
||||
'build-capabilities',
|
||||
'test-capabilities',
|
||||
'stage-capabilities',
|
||||
'app-delivery-via-authorized-app-store',
|
||||
'app-delivery-via-other-means',
|
||||
'exploit-via-cellular-network',
|
||||
'exploit-via-internet',
|
||||
);
|
||||
|
||||
$killChainOrders = array(
|
||||
'mitre-enterprise-attack-attack-pattern' => $killChainOrderEnterprise,
|
||||
'mitre-mobile-attack-attack-pattern' => $killChainOrderMobile,
|
||||
'mitre-pre-attack-attack-pattern' => $killChainOrderPre,
|
||||
);
|
||||
|
||||
$expectedDescription = 'ATT&CK Tactic';
|
||||
$expectedNamespace = 'mitre-attack';
|
||||
$conditions = array('Galaxy.description' => $expectedDescription, 'Galaxy.namespace' => $expectedNamespace);
|
||||
$conditions = array('Galaxy.id' => $galaxy_id);
|
||||
$contains = array(
|
||||
'GalaxyCluster' => array('GalaxyElement'),
|
||||
);
|
||||
|
||||
$galaxies = $this->find('all', array(
|
||||
$galaxy = $this->find('first', array(
|
||||
'recursive' => -1,
|
||||
'contain' => $contains,
|
||||
'conditions' => $conditions,
|
||||
|
@ -435,45 +398,60 @@ class Galaxy extends AppModel
|
|||
|
||||
$mispUUID = Configure::read('MISP')['uuid'];
|
||||
|
||||
$attackTactic = array(
|
||||
'killChain' => $killChainOrders,
|
||||
'attackTactic' => array(),
|
||||
'attackTags' => array(),
|
||||
'instance-uuid' => $mispUUID
|
||||
if (!isset($galaxy['Galaxy']['kill_chain_order'])) {
|
||||
throw new Exception(__("Galaxy cannot be represented as a matrix"));
|
||||
|
||||
}
|
||||
$matrixData = array(
|
||||
'killChain' => $galaxy['Galaxy']['kill_chain_order'],
|
||||
'tabs' => array(),
|
||||
'matrixTags' => array(),
|
||||
'instance-uuid' => $mispUUID,
|
||||
'galaxy' => $galaxy['Galaxy']
|
||||
);
|
||||
|
||||
foreach ($galaxies as $galaxy) {
|
||||
$galaxyType = $galaxy['Galaxy']['type'];
|
||||
$clusters = $galaxy['GalaxyCluster'];
|
||||
$attackClusters = array();
|
||||
// add cluster if kill_chain is present
|
||||
foreach ($clusters as $cluster) {
|
||||
if (empty($cluster['GalaxyElement'])) {
|
||||
continue;
|
||||
$clusters = $galaxy['GalaxyCluster'];
|
||||
$cols = array();
|
||||
|
||||
foreach ($clusters as $cluster) {
|
||||
if (empty($cluster['GalaxyElement'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$toBeAdded = false;
|
||||
$clusterType = $cluster['type'];
|
||||
$galaxyElements = $cluster['GalaxyElement'];
|
||||
foreach ($galaxyElements as $element) {
|
||||
// add cluster if kill_chain is present
|
||||
if ($element['key'] == 'kill_chain') {
|
||||
$kc = explode(":", $element['value']);
|
||||
$galaxyType = $kc[0];
|
||||
$kc = $kc[1];
|
||||
$cols[$galaxyType][$kc][] = $cluster;
|
||||
$toBeAdded = true;
|
||||
}
|
||||
$toBeAdded = false;
|
||||
$clusterType = $cluster['type'];
|
||||
$galaxyElements = $cluster['GalaxyElement'];
|
||||
foreach ($galaxyElements as $element) {
|
||||
if ($element['key'] == 'kill_chain') {
|
||||
$kc = explode(":", $element['value'])[2];
|
||||
$attackClusters[$kc][] = $cluster;
|
||||
$toBeAdded = true;
|
||||
}
|
||||
if ($element['key'] == 'external_id') {
|
||||
$cluster['external_id'] = $element['value'];
|
||||
}
|
||||
if ($element['key'] == 'external_id') {
|
||||
$cluster['external_id'] = $element['value'];
|
||||
}
|
||||
if ($toBeAdded) {
|
||||
array_push($attackTactic['attackTags'], $cluster['tag_name']);
|
||||
array_push($matrixData['matrixTags'], $cluster['tag_name']);
|
||||
}
|
||||
}
|
||||
$attackTactic['attackTactic'][$galaxyType] = array(
|
||||
'clusters' => $attackClusters,
|
||||
'galaxy' => $galaxy['Galaxy'],
|
||||
);
|
||||
}
|
||||
$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']);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attackTactic;
|
||||
return $matrixData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1105,6 +1105,24 @@ class Server extends AppModel
|
|||
'test' => 'testBoolFalse',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'allow_cors' => array(
|
||||
'level' => 1,
|
||||
'description' => __('Allow cross-origin requests to this instance, matching origins given in Security.cors_origins. Set to false to totally disable'),
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'cors_origins' => array(
|
||||
'level' => 1,
|
||||
'description' => __('Set the origins from which MISP will allow cross-origin requests. Useful for external integration. Comma seperate if you need more than one.'),
|
||||
'value' => '',
|
||||
'errorMessage' => '',
|
||||
'test' => 'testForEmpty',
|
||||
'type' => 'string',
|
||||
'null' => true
|
||||
)
|
||||
),
|
||||
'SecureAuth' => array(
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
/*
|
||||
* Matrix Generator
|
||||
* Params:
|
||||
Required
|
||||
--------
|
||||
|
||||
- $tabs: Contains the matrix data. Has the format:
|
||||
{
|
||||
tab1: {
|
||||
col1: [
|
||||
{rowData1}, {rowData2}, ...
|
||||
],
|
||||
col2: [
|
||||
{rowData1}, {rowData2}, ...
|
||||
]
|
||||
},
|
||||
tab2: {}
|
||||
}
|
||||
|
||||
Optional
|
||||
--------
|
||||
- $defaultTabName: Set the default active tab. Default value is first tab
|
||||
- $columnOrders: Defined the order of the column in each tabs. Has the format:
|
||||
{
|
||||
tab1: [col1, col2],
|
||||
tab2: [col1, col2]
|
||||
}
|
||||
- $interpolation: The color associated to each value. Has the format: { val1: [r, g, b], val2: [r, g, b] }
|
||||
- $maxScore:
|
||||
- $pickingMode: Interactive picking mode, add a form and the chosen input
|
||||
- $scores: The score associate with either the value or the tag name (if provided)
|
||||
- $removeTrailling: How much part of the name of the cell should be remove: e.g. $removeTrailling=2 => "abc def ghi", will be: "abc"
|
||||
- $colours: The colour associated with the tag name (if provided)
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
?>
|
||||
|
||||
<?php
|
||||
echo $this->Html->script('attack_matrix');
|
||||
echo $this->Html->css('attack_matrix');
|
||||
?>
|
||||
<?php
|
||||
$clusetersNamesMapping = array(); // used to map name with id for the chosen select
|
||||
if (isset($interpolation) && !empty($interpolation)) {
|
||||
foreach ($interpolation as $k => $colArr) {
|
||||
$col = str_pad(dechex($colArr[0]), 2, '0', STR_PAD_LEFT) . str_pad(dechex($colArr[1]), 2, '0', STR_PAD_LEFT) . str_pad(dechex($colArr[2]), 2, '0', STR_PAD_LEFT);
|
||||
$interpolation[$k] = '#' . $col;
|
||||
if ($k == 0) { // force small area on white
|
||||
$interpolation[$k] .= ' 3%';
|
||||
}
|
||||
}
|
||||
$colorScale = implode($interpolation, ', ');
|
||||
} else {
|
||||
$colorScale = 'black';
|
||||
}
|
||||
?>
|
||||
<div class="attack-matrix-options" style="right: initial; background: transparent;">
|
||||
<ul id="attack-matrix-tabscontroller" class="nav nav-tabs" style="margin-bottom: 2px;">
|
||||
<?php
|
||||
if (!isset($defaultTabName)) {
|
||||
reset($tabs);
|
||||
$defaultTabName = key($tabs); // get first key
|
||||
}
|
||||
|
||||
foreach($tabs as $tabName => $column):
|
||||
?>
|
||||
<li class="tactic <?php echo $tabName==$defaultTabName ? "active" : ""; ?>"><span href="#tabMatrix-<?php echo h($tabName); ?>" data-toggle="tab" style="padding-top: 3px; padding-bottom: 3px;"><?php echo h($tabName); ?></span></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="attack-matrix-options matrix-div-submit">
|
||||
<span class="btn btn-inverse btn-matrix-submit" role="button" style="padding: 1px 5px !important;font-size: 12px !important;font-weight: bold;"><?php echo __('Submit'); ?></span>
|
||||
</div>
|
||||
|
||||
<div class="attack-matrix-options">
|
||||
<?php if (isset($interpolation)): ?>
|
||||
<span id="matrix-heatmap-legend-caret">
|
||||
<span id="matrix-heatmap-legend-caret-value">0</span>
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div>
|
||||
<span>0</span>
|
||||
<div id="matrix-heatmap-legend" style="background: linear-gradient(to right, white 0%, <?php echo h($colorScale); ?>);"></div>
|
||||
<span id="matrix-heatmap-maxval"><?php echo h($maxScore); ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<label style="display: inline-block; margin-left: 30px;"><input type="checkbox" id="checkbox_attackMatrix_showAll" checked><span class="fa fa-filter"><?php echo __('Show all');?></span></input></label>
|
||||
</div>
|
||||
|
||||
<?php if (isset($eventId)): ?>
|
||||
<div class="hidden">
|
||||
<?php
|
||||
echo $this->Form->create('Galaxy', array('url' => '/galaxies/attachMultipleClusters/' . (empty($target_id) ? $eventId : $target_id ) . '/' . (empty($target_type) ? 'event' : $target_type), 'style' => 'margin:0px;'));
|
||||
echo $this->Form->input('target_ids', array('type' => 'text'));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</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 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;">
|
||||
<table class="table table-condensed matrix-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php
|
||||
foreach($columnOrders[$tabName] as $co):
|
||||
$name = str_replace("-", " ", $co);
|
||||
?>
|
||||
<th>
|
||||
<?php echo h(ucfirst($name)); ?>
|
||||
<div class="th-inner"><?php echo h(ucfirst($name)); ?></div>
|
||||
</th>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody style="overflow-y: scroll;">
|
||||
<?php
|
||||
$body = '';
|
||||
$added = false;
|
||||
$i = 0;
|
||||
do {
|
||||
$tr = '<tr>';
|
||||
$added = false;
|
||||
foreach($columnOrders[$tabName] as $co) {
|
||||
if (isset($column[$co][$i])) {
|
||||
$added = true;
|
||||
$td = '<td';
|
||||
$cell = $column[$co][$i];
|
||||
if (!is_array($cell)) {
|
||||
$cell = array('value' => $cell);
|
||||
}
|
||||
$value = isset($cell['value']) ? $cell['value'] : 0;
|
||||
if (isset($removeTrailling) && $removeTrailling > 0) {
|
||||
$name = explode(" ", $value);
|
||||
$name = join(" ", array_slice($name, 0, -$removeTrailling)); // remove " - external_id"
|
||||
} else {
|
||||
$name = $value;
|
||||
}
|
||||
$tagName = isset($cell['tag_name']) ? $cell['tag_name'] : $name;
|
||||
$score = empty($scores[$tagName]) ? 0 : $scores[$tagName];
|
||||
$clusterId = isset($cell['id']) ? $cell['id'] : $name;
|
||||
$externalId = isset($cell['external_id']) ? $cell['external_id'] : '';
|
||||
$clusetersNamesMapping[$clusterId] = $name . ($externalId !== '' ? ' (' . $externalId. ')' : '');
|
||||
|
||||
$td .= ' class="heatCell matrix-interaction ' . ($pickingMode ? 'cell-picking"' : '"');
|
||||
$td .= isset($colours[$tagName]) ? ' style="background: ' . h($colours[$tagName]) . '; color: ' . h($this->TextColour->getTextColour($colours[$tagName])) . '"' : '' ;
|
||||
$td .= ' data-score="'.h($score).'"';
|
||||
$td .= ' data-tag_name="'.h($tagName).'"';
|
||||
$td .= ' data-cluster-id="'.h($clusterId).'"';
|
||||
if ($pickingMode) {
|
||||
$td .= ' data-target-type="attribute"';
|
||||
$td .= ' data-target-id="'.h($target_id).'"';
|
||||
}
|
||||
$td .= ' title="'.h($externalId).'"';
|
||||
$td .= '>' . h($name);
|
||||
|
||||
} else { // empty cell
|
||||
$td = '<td style="border: none;">';
|
||||
}
|
||||
$td .= '</td>';
|
||||
$tr .= $td;
|
||||
}
|
||||
$tr .= '</tr>';
|
||||
$body .= $tr;
|
||||
$i++;
|
||||
} while($added);
|
||||
echo $body;
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php if($pickingMode): ?>
|
||||
<div style="padding: 5px;">
|
||||
<select id="attack-matrix-chosen-select" style="width: 100%; margin: 0px;" multiple>
|
||||
<?php
|
||||
foreach ($clusetersNamesMapping as $clusterId => $clusterName) {
|
||||
echo '<option value=' . h($clusterId) .'>' . h($clusterName) . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</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>
|
||||
<?php endif; ?>
|
|
@ -1,134 +0,0 @@
|
|||
<?php
|
||||
$clusetersNamesMapping = array(); // used to map name with id for the chosen select
|
||||
?>
|
||||
<div class="attack-matrix-options" style="right: initial; background: transparent;">
|
||||
<ul id="attack-matrix-tabscontroller" class="nav nav-tabs" style="margin-bottom: 2px;">
|
||||
<?php
|
||||
$enterpriseTag = "mitre-enterprise-attack-attack-pattern";
|
||||
foreach($attackTactic as $tactic):
|
||||
$galaxy = $tactic['galaxy'];
|
||||
?>
|
||||
<li class="tactic <?php echo $galaxy['type']==$enterpriseTag ? "active" : ""; ?>"><span href="#tabMatrix-<?php echo h($galaxy['type']); ?>" data-toggle="tab" style="padding-top: 3px; padding-bottom: 3px;"><?php echo h($galaxy['name']); ?></span></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="attack-matrix-options matrix-div-submit">
|
||||
<span class="btn btn-inverse btn-matrix-submit" role="button" style="padding: 1px 5px !important;font-size: 12px !important;font-weight: bold;"><?php echo __('Submit'); ?></span>
|
||||
</div>
|
||||
|
||||
<div class="attack-matrix-options">
|
||||
<span id="matrix-heatmap-legend-caret">
|
||||
<span id="matrix-heatmap-legend-caret-value">0</span>
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div>
|
||||
<span>0</span>
|
||||
<div id="matrix-heatmap-legend"></div>
|
||||
<span id="matrix-heatmap-maxval"><?php echo h($maxScore); ?></span>
|
||||
</div>
|
||||
<label style="display: inline-block; margin-left: 30px;"><input type="checkbox" id="checkbox_attackMatrix_showAll" checked><span class="fa fa-filter"><?php echo __('Show all');?></span></input></label>
|
||||
</div>
|
||||
|
||||
<div class="hidden">
|
||||
<?php
|
||||
echo $this->Form->create('Galaxy', array('url' => '/galaxies/attachMultipleClusters/' . (empty($target_id) ? $eventId : $target_id ) . '/' . (empty($target_type) ? 'event' : $target_type), 'style' => 'margin:0px;'));
|
||||
echo $this->Form->input('target_ids', array('type' => 'text'));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div id="matrix_container" class="fixed-table-container-inner" style="max-height: 670px;" data-picking-mode="<?php echo $pickingMode ? 'true' : 'false'; ?>">
|
||||
<div class="tab-content">
|
||||
<?php foreach($attackTactic as $galaxy):
|
||||
$galaxyType = $galaxy['galaxy']['type'];
|
||||
?>
|
||||
<div class="tab-pane <?php echo $galaxyType==$enterpriseTag ? "active" : ""; ?>" id="tabMatrix-<?php echo h($galaxyType); ?>">
|
||||
<div class="header-background"></div>
|
||||
<div class="fixed-table-container-inner" style="max-height: 670px;">
|
||||
<table class="table table-condensed matrix-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php
|
||||
foreach($killChainOrders[$galaxyType] as $kc):
|
||||
$name = str_replace("-", " ", $kc);
|
||||
?>
|
||||
<th>
|
||||
<?php echo h(ucfirst($name)); ?>
|
||||
<div class="th-inner"><?php echo h(ucfirst($name)); ?></div>
|
||||
</th>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody style="overflow-y: scroll;">
|
||||
<?php
|
||||
$added = false;
|
||||
$i = 0;
|
||||
do {
|
||||
$added = false;
|
||||
echo '<tr>';
|
||||
$killChainOrder = $killChainOrders[$galaxyType];
|
||||
$attackClusters = $galaxy['clusters'];
|
||||
foreach($killChainOrder as $kc) {
|
||||
if(!isset($attackClusters[$kc])) { // undefined index
|
||||
$td = '<td class="">';
|
||||
} else {
|
||||
$clusters = $attackClusters[$kc];
|
||||
$td = '<td ';
|
||||
if ($i < count($clusters)) {
|
||||
$clusterId = $clusters[$i]['id'];
|
||||
$tagName = $clusters[$i]['tag_name'];
|
||||
$score = empty($scores[$tagName]) ? 0 : $scores[$tagName];
|
||||
$name = join(" ", array_slice(explode(" ", $clusters[$i]['value']), 0, -2)); // remove " - external_id"
|
||||
$clusetersNamesMapping[$clusterId] = $name;
|
||||
$td .= ' class="heatCell matrix-interaction ' . ($pickingMode ? 'cell-picking"' : '"');
|
||||
$td .= isset($colours[$tagName]) ? ' style="background: ' . h($colours[$tagName]) . '; color: ' . h($this->TextColour->getTextColour($colours[$tagName])) . '"' : '' ;
|
||||
$td .= ' data-score="'.h($score).'"';
|
||||
$td .= ' data-tag_name="'.h($tagName).'"';
|
||||
$td .= ' data-cluster-id="'.h($clusterId).'"';
|
||||
if ($pickingMode) {
|
||||
$td .= ' data-target-type="attribute"';
|
||||
$td .= ' data-target-id="'.h($target_id).'"';
|
||||
}
|
||||
$td .= ' title="'.h($clusters[$i]['external_id']).'"';
|
||||
$td .= '>' . h($name);
|
||||
$added = true;
|
||||
} else {
|
||||
$td .= 'class="">';
|
||||
}
|
||||
}
|
||||
$td .= '</td>';
|
||||
echo $td;
|
||||
}
|
||||
echo '</tr>';
|
||||
$i++;
|
||||
} while($added);
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php if($pickingMode): ?>
|
||||
<div style="padding: 5px;">
|
||||
<select id="attack-matrix-chosen-select" style="width: 100%; margin: 0px;" multiple>
|
||||
<?php
|
||||
foreach ($clusetersNamesMapping as $clusterId => $clusterName) {
|
||||
echo '<option value=' . h($clusterId) .'>' . h($clusterName) . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</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>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
echo $this->Html->script('bootstrap-typeahead');
|
||||
echo $this->Html->script('attack_matrix');
|
||||
echo $this->Html->css('attack_matrix');
|
||||
?>
|
|
@ -33,6 +33,7 @@
|
|||
}
|
||||
}
|
||||
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'viewEvent', 'mayModify' => $mayModify, 'mayPublish' => $mayPublish));
|
||||
echo $this->Html->css('attack_matrix');
|
||||
?>
|
||||
<div class="events view">
|
||||
<?php
|
||||
|
@ -495,7 +496,7 @@ function enable_correlation_graph() {
|
|||
}
|
||||
|
||||
function enable_attack_matrix() {
|
||||
$.get("/events/viewMitreAttackMatrix/<?php echo h($event['Event']['id']); ?>/event/1", function(data) {
|
||||
$.get("/events/viewGalaxyMatrix/<?php echo h($event['Event']['id']); ?>/<?php echo h($mitreAttackGalaxyId); ?>/event/1", function(data) {
|
||||
$("#attackmatrix_div").html(data);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,6 +23,14 @@
|
|||
<dd><?php echo h($galaxy['Galaxy']['version']); ?></dd>
|
||||
|
||||
</dl>
|
||||
<?php
|
||||
$kco = '';
|
||||
if (isset($galaxy['Galaxy']['kill_chain_order'])) {
|
||||
$kco = '<strong>' . __('Kill chain order') . '</strong> <span class="useCursorPointer fa fa-expand" onclick="$(\'#killChainOrder\').toggle(\'blind\')"></span>';
|
||||
$kco .= '<div id="killChainOrder" class="hidden" style="border: 1px solid #000; border-radius: 5px; padding: 3px; background: #f4f4f4; margin-left: 20px;">' . json_encode($galaxy['Galaxy']['kill_chain_order']) . '</div>';
|
||||
}
|
||||
echo $kco;
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="clusters_div"></div>
|
||||
|
@ -36,5 +44,9 @@ $(document).ready(function () {
|
|||
$.get("<?php echo $uri;?>", function(data) {
|
||||
$("#clusters_div").html(data);
|
||||
});
|
||||
|
||||
var $kco = $('#killChainOrder');
|
||||
var j = syntaxHighlightJson($kco.text(), 8)
|
||||
$kco.html(j);
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -86,6 +86,10 @@ class GenericPickerHelper extends AppHelper {
|
|||
if (isset($param['template']['infoExtra'])) {
|
||||
$pill_html .= $this->_View->element('genericPickerElements/info_extra', array('infoExtra' => $param['template']['infoExtra'], 'forceIcon' => true));
|
||||
}
|
||||
if (isset($param['isMatrix']) && $param['isMatrix']) {
|
||||
$span = '<span style="position: absolute; font-size: 8px; top: 2px;" class="fa fa-th" title="' . __('Start the galaxy matrix picker') . '"></span>';
|
||||
$pill_html .= $span;
|
||||
}
|
||||
$pill_html .= '</a>';
|
||||
$pill_html .= '</li>';
|
||||
return $pill_html;
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
<div id="attackmatrix_div" style="position: relative; border: solid 1px;" class="statistics_attack_matrix">
|
||||
<?php
|
||||
echo $this->element('view_mitre_attack_matrix');
|
||||
echo $this->element('view_galaxy_matrix');
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b9f13179412b0a6d944ef33493f36c2a49a63706
|
||||
Subproject commit 9ad8a76a38f8f111b856058759714caf559573cc
|
|
@ -1 +1 @@
|
|||
Subproject commit f9bb8bfa9bfe0eb3813df4dc5efa355bece53ce7
|
||||
Subproject commit 08798f12623f5291f6743856c221a8c2c13cc778
|
|
@ -1,11 +1,11 @@
|
|||
.matrix-table td {
|
||||
border-top: none;
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
|
||||
.matrix-table th {
|
||||
padding: 0px 5px;
|
||||
color: transparent;
|
||||
line-height: 12px;
|
||||
line-height: 0px;
|
||||
}
|
||||
|
||||
.matrix-table thead > tr {
|
||||
|
@ -17,6 +17,9 @@
|
|||
.matrix-table tbody {
|
||||
/*height: 670px;*/
|
||||
overflow-y: scroll;
|
||||
/* display: inline-block;
|
||||
position: relative; */
|
||||
top: -23px;
|
||||
}
|
||||
|
||||
table.matrix-table {
|
||||
|
@ -102,7 +105,6 @@ div.th-inner {
|
|||
#matrix-heatmap-legend {
|
||||
width: 300px;
|
||||
height: 10px;
|
||||
background: linear-gradient(to right, white, #0000FF);
|
||||
}
|
||||
|
||||
.attack-matrix-options div {
|
||||
|
|
|
@ -902,6 +902,7 @@ a.pill-pre-picker {
|
|||
background-color: #fcfcfc;
|
||||
font-weight: bold;
|
||||
border: 1px #65737ec8 solid;
|
||||
position: relative;
|
||||
}
|
||||
.nav-pills > .active > a.pill-pre-picker {
|
||||
background-color: #65737e32;
|
||||
|
|
|
@ -265,7 +265,7 @@
|
|||
|
||||
function makeTagging(tagIds) {
|
||||
$('#GalaxyTargetIds').val(JSON.stringify(tagIds));
|
||||
$('#GalaxyViewMitreAttackMatrixForm').submit();
|
||||
$('#GalaxyViewGalaxyMatrixForm').submit();
|
||||
}
|
||||
|
||||
function filterEvent(tagName, tagId) {
|
||||
|
|
|
@ -1476,9 +1476,9 @@ function openPopover(clicked, data, hover, placement) {
|
|||
}
|
||||
}
|
||||
|
||||
function getMitreMatrixPopup(scope_id, scope) {
|
||||
function getMatrixPopup(scope, scope_id, galaxy_id) {
|
||||
cancelPopoverForm();
|
||||
getPopup(scope + '/' + scope_id, 'events', 'viewMitreAttackMatrix', '', '#popover_form_large');
|
||||
getPopup(scope_id + '/' + galaxy_id + '/' + scope, 'events', 'viewGalaxyMatrix', '', '#popover_form_large');
|
||||
}
|
||||
|
||||
function getPopup(id, context, target, admin, popupType) {
|
||||
|
@ -3880,7 +3880,10 @@ function insertJSONRestResponse() {
|
|||
$('#json-response-container').html(parsedJson);
|
||||
}
|
||||
|
||||
function syntaxHighlightJson(json) {
|
||||
function syntaxHighlightJson(json, indent) {
|
||||
if (indent === undefined) {
|
||||
indent = 2;
|
||||
}
|
||||
if (typeof json == 'string') {
|
||||
json = JSON.parse(json);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue