mirror of https://github.com/MISP/MISP
new: [user:periodic_report] Added security recommendations section showing course of actions related to attack techniques
parent
e0fce46994
commit
44c5fceb63
|
@ -1635,6 +1635,9 @@ class Event extends AppModel
|
|||
if (!isset($options['fetchFullClusters'])) {
|
||||
$options['fetchFullClusters'] = true;
|
||||
}
|
||||
if (!isset($options['fetchFullClusterRelationship'])) {
|
||||
$options['fetchFullClusterRelationship'] = false;
|
||||
}
|
||||
foreach ($possibleOptions as $opt) {
|
||||
if (!isset($options[$opt])) {
|
||||
$options[$opt] = false;
|
||||
|
@ -1983,7 +1986,7 @@ class Event extends AppModel
|
|||
$event['warnings'] = $eventWarnings;
|
||||
}
|
||||
$this->__attachTags($event, $justExportableTags);
|
||||
$this->__attachGalaxies($event, $user, $options['excludeGalaxy'], $options['fetchFullClusters']);
|
||||
$this->__attachGalaxies($event, $user, $options['excludeGalaxy'], $options['fetchFullClusters'], $options['fetchFullClusterRelationship']);
|
||||
$event = $this->Orgc->attachOrgs($event, $fieldsOrg);
|
||||
if (!$sharingGroupReferenceOnly && $event['Event']['sharing_group_id']) {
|
||||
if (isset($sharingGroupData[$event['Event']['sharing_group_id']])) {
|
||||
|
@ -2147,7 +2150,7 @@ class Event extends AppModel
|
|||
* @param bool $excludeGalaxy
|
||||
* @param bool $fetchFullCluster
|
||||
*/
|
||||
private function __attachGalaxies(array &$event, array $user, $excludeGalaxy, $fetchFullCluster)
|
||||
private function __attachGalaxies(array &$event, array $user, $excludeGalaxy, $fetchFullCluster, $fetchFullRelationship=false)
|
||||
{
|
||||
$galaxyTags = [];
|
||||
$event['Galaxy'] = [];
|
||||
|
@ -2176,7 +2179,7 @@ class Event extends AppModel
|
|||
}
|
||||
|
||||
$this->GalaxyCluster = ClassRegistry::init('GalaxyCluster');
|
||||
$clusters = $this->GalaxyCluster->getClustersByTags($galaxyTags, $user, true, $fetchFullCluster);
|
||||
$clusters = $this->GalaxyCluster->getClustersByTags($galaxyTags, $user, true, $fetchFullCluster, $fetchFullRelationship);
|
||||
|
||||
if (empty($clusters)) {
|
||||
return;
|
||||
|
@ -7614,4 +7617,52 @@ class Event extends AppModel
|
|||
'all_timestamps' => array_keys($clusteredTags['eventNumberPerRollingWindow']),
|
||||
];
|
||||
}
|
||||
|
||||
public function extractRelatedCourseOfActions(array $events): array
|
||||
{
|
||||
$mitre_attack_galaxy_type = 'mitre-attack-pattern';
|
||||
$mitre_coa_galaxy_type = 'mitre-course-of-action';
|
||||
$allowedRelationTypes = ['mitigates'];
|
||||
$coa = [];
|
||||
foreach ($events as $event) {
|
||||
foreach ($event['Galaxy'] as $galaxy) {
|
||||
foreach ($galaxy['GalaxyCluster'] as $cluster) {
|
||||
foreach ($cluster['GalaxyClusterRelation'] as $relation) {
|
||||
if (in_array($relation['referenced_galaxy_cluster_type'], $allowedRelationTypes) && $relation['TargetCluster']['type'] == $mitre_coa_galaxy_type) {
|
||||
if (!isset($coa[$relation['TargetCluster']['tag_name']])) {
|
||||
$coa[$relation['TargetCluster']['tag_name']] = $relation['TargetCluster'];
|
||||
$coa[$relation['TargetCluster']['tag_name']]['occurrence'] = 0;
|
||||
$coa[$relation['TargetCluster']['tag_name']]['techniques'] = [];
|
||||
}
|
||||
$coa[$relation['TargetCluster']['tag_name']]['occurrence'] += 1;
|
||||
if ($cluster['type'] == $mitre_attack_galaxy_type) {
|
||||
$coa[$relation['TargetCluster']['tag_name']]['techniques'][$cluster['tag_name']] = $cluster;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($cluster['TargetingClusterRelation'])) {
|
||||
foreach ($cluster['TargetingClusterRelation'] as $relation) {
|
||||
if (in_array($relation['referenced_galaxy_cluster_type'], $allowedRelationTypes) && $relation['GalaxyCluster']['type'] == $mitre_coa_galaxy_type) {
|
||||
if (!isset($coa[$relation['GalaxyCluster']['tag_name']])) {
|
||||
$coa[$relation['GalaxyCluster']['tag_name']] = $relation['GalaxyCluster'];
|
||||
$coa[$relation['GalaxyCluster']['tag_name']]['techniques'] = [];
|
||||
$coa[$relation['GalaxyCluster']['tag_name']]['occurrence'] = 0;
|
||||
}
|
||||
$coa[$relation['GalaxyCluster']['tag_name']]['occurrence'] += 1;
|
||||
if ($cluster['type'] == $mitre_attack_galaxy_type
|
||||
) {
|
||||
$coa[$relation['GalaxyCluster']['tag_name']]['techniques'][$cluster['tag_name']] = $cluster;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uasort($coa, function ($a, $b) {
|
||||
return $a['occurrence'] > $b['occurrence'] ? -1 : 1;
|
||||
});
|
||||
|
||||
return $coa;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -973,7 +973,7 @@ class GalaxyCluster extends AppModel
|
|||
* @param bool $fetchFullCluster
|
||||
* @return array
|
||||
*/
|
||||
public function getClustersByTags(array $tagNames, array $user, $postProcess = true, $fetchFullCluster = true)
|
||||
public function getClustersByTags(array $tagNames, array $user, $postProcess = true, $fetchFullCluster = true, $fetchFullRelationship = false)
|
||||
{
|
||||
$options = [
|
||||
'conditions' => ['GalaxyCluster.tag_name' => $tagNames],
|
||||
|
@ -982,7 +982,7 @@ class GalaxyCluster extends AppModel
|
|||
$options['contain'] = ['Galaxy', 'GalaxyElement'];
|
||||
}
|
||||
|
||||
$clusters = $this->fetchGalaxyClusters($user, $options, $fetchFullCluster);
|
||||
$clusters = $this->fetchGalaxyClusters($user, $options, $fetchFullCluster, $fetchFullRelationship);
|
||||
|
||||
if (!empty($clusters) && $postProcess) {
|
||||
$tagIds = array_change_key_case(array_flip($tagNames));
|
||||
|
@ -1028,7 +1028,7 @@ class GalaxyCluster extends AppModel
|
|||
* @param bool $full
|
||||
* @return array
|
||||
*/
|
||||
public function fetchGalaxyClusters(array $user, array $options, $full=false)
|
||||
public function fetchGalaxyClusters(array $user, array $options, $full=false, $includeFullClusterRelationship=false)
|
||||
{
|
||||
$params = array(
|
||||
'conditions' => $this->buildConditions($user),
|
||||
|
@ -1048,6 +1048,9 @@ class GalaxyCluster extends AppModel
|
|||
'SharingGroup'
|
||||
);
|
||||
}
|
||||
if (!empty($includeFullClusterRelationship)) {
|
||||
$params['contain']['GalaxyClusterRelation'][] = 'TargetCluster';
|
||||
}
|
||||
if (!empty($options['contain'])) {
|
||||
$params['contain'] = $options['contain'];
|
||||
}
|
||||
|
@ -1126,6 +1129,9 @@ class GalaxyCluster extends AppModel
|
|||
if (!empty($targetingClusterRelation['SharingGroup']['id'])) {
|
||||
$targetingClusterRelation['TargetingClusterRelation']['SharingGroup'] = $targetingClusterRelation['SharingGroup'];
|
||||
}
|
||||
if ($includeFullClusterRelationship) {
|
||||
$targetingClusterRelation['TargetingClusterRelation']['GalaxyCluster'] = $targetingClusterRelation['SourceCluster'];
|
||||
}
|
||||
$targetingClusterRelations[$k] = $targetingClusterRelation['TargetingClusterRelation'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1808,7 +1808,8 @@ class User extends AppModel
|
|||
$filters['includeEventCorrelations'] = !empty($periodicSettings['include_correlations']);
|
||||
$filters['includeGranularCorrelations'] = !empty($periodicSettings['include_correlations']);
|
||||
$filters['noSightings'] = true;
|
||||
$filters['fetchFullClusters'] = false;
|
||||
$filters['fetchFullClusters'] = true;
|
||||
$filters['fetchFullClusterRelationship'] = true;
|
||||
$filters['includeScoresOnEvent'] = true;
|
||||
$events = $this->Event->fetchEvent($user, $filters);
|
||||
|
||||
|
@ -1833,6 +1834,10 @@ class User extends AppModel
|
|||
'tagFilterPrefixes' => $tagFilterPrefixes,
|
||||
];
|
||||
$trending_summary = $this->__renderTrendingSummary($trendData);
|
||||
$securityRecommendationsData = [
|
||||
'course_of_action' => $this->Event->extractRelatedCourseOfActions($events),
|
||||
];
|
||||
$security_recommendations = $this->__renderSecurityRecommenrations($securityRecommendationsData);
|
||||
|
||||
$emailTemplate = $this->prepareEmailTemplate($period);
|
||||
$emailTemplate->set('baseurl', $this->Event->__getAnnounceBaseurl());
|
||||
|
@ -1843,6 +1848,7 @@ class User extends AppModel
|
|||
$emailTemplate->set('period', $period);
|
||||
$emailTemplate->set('aggregated_context', $aggregated_context);
|
||||
$emailTemplate->set('trending_summary', $trending_summary);
|
||||
$emailTemplate->set('security_recommendations', $security_recommendations);
|
||||
$emailTemplate->set('analysisLevels', $this->Event->analysisLevels);
|
||||
$emailTemplate->set('distributionLevels', $this->Event->distributionLevels);
|
||||
if ($rendered) {
|
||||
|
@ -1862,6 +1868,11 @@ class User extends AppModel
|
|||
return $this->__renderGeneric('Elements' . DS . 'Events', 'trendingSummary', $trendData);
|
||||
}
|
||||
|
||||
private function __renderSecurityRecommenrations(array $data): string
|
||||
{
|
||||
return $this->__renderGeneric('Elements' . DS . 'Events', 'securityRecommendations', $data);
|
||||
}
|
||||
|
||||
private function __renderGeneric(string $viewPath, string $viewFile, array $viewVars): string
|
||||
{
|
||||
$view = new View();
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
$colorMapping = [
|
||||
0 => '#cc0033',
|
||||
1 => '#f89406',
|
||||
];
|
||||
?>
|
||||
|
||||
<h2><?= __('Preventive Measures & Mitigations') ?></h2>
|
||||
<?php foreach (array_values($course_of_action) as $i => $coa) : ?>
|
||||
<div style="margin-bottom: 0.5em;">
|
||||
<div>
|
||||
<span class="tag" style="background-color: <?= $colorMapping[$i] ?? '#999' ?>; color: #fff; border-radius: 9px; padding: 2px 8px;">
|
||||
<?= h($coa['occurrence']) ?>
|
||||
</span>
|
||||
<strong><a href="<?= $baseurl . '/galaxy_clusters/view/' . h($coa['id']) ?>" target="_blank"><?= h($coa['value']) ?></a>: </strong>
|
||||
<?= h($this->Markdown->toText($coa['description'])) ?>
|
||||
</div>
|
||||
<ul>
|
||||
<?php foreach ($coa['techniques'] as $technique) : ?>
|
||||
<li>
|
||||
<code><?= h($technique['value']) ?></code>:
|
||||
<small><?= h($technique['description']) ?></small>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
|
@ -552,6 +552,19 @@ $top_mitre_attack_techniques = array_slice($mitre_attack_techniques, 0, 10);
|
|||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($this->fetch('security-recommendations')) : ?>
|
||||
<?= $this->fetch('security-recommendations'); ?>
|
||||
<?php else: ?>
|
||||
<div class="panel">
|
||||
<div class="panel-header">
|
||||
<?= __('Security Recommendations') ?>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<?= $security_recommendations; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?= $this->fetch('content'); ?>
|
||||
|
||||
<style>
|
||||
|
|
Loading…
Reference in New Issue