mirror of https://github.com/MISP/MISP
new: [events:restSearch] Added `context` export format
The `context` export format includes: - List of used taxonomies - List of used galaxy cluster - List of custom tags - Mitre Att&ck matrixpull/8208/head
parent
69b0937ea2
commit
155bf23776
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
class ContextExport
|
||||
{
|
||||
private $__attack_export_tool = null;
|
||||
|
||||
public $additional_params = [
|
||||
'flatten' => 1,
|
||||
'includeEventTags' => 1,
|
||||
'includeGalaxy' => 1,
|
||||
'noSightings' => true,
|
||||
'noEventReports' => true,
|
||||
'noShadowAttributes' => true,
|
||||
'sgReferenceOnly' => true,
|
||||
'includeEventCorrelations' => false,
|
||||
];
|
||||
private $__eventTags = [];
|
||||
private $__eventGalaxies = [];
|
||||
|
||||
private $__aggregatedTags = [];
|
||||
private $__aggregatedClusters = [];
|
||||
|
||||
private $__taxonomyFetched = [];
|
||||
private $__galaxyFetched = [];
|
||||
|
||||
public $non_restrictive_export = true;
|
||||
public $renderView = 'context_view';
|
||||
|
||||
public function handler($data, $options = array())
|
||||
{
|
||||
$this->__aggregate($data, Hash::extract($data, 'EventTag.{n}.Tag'));
|
||||
if (!empty($data['Attribute'])) {
|
||||
foreach ($data['Attribute'] as $attribute) {
|
||||
$this->__aggregate($attribute, Hash::extract($attribute, 'AttributeTag.{n}.Tag'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->__attack_export_tool->handler($data, $options);
|
||||
return '';
|
||||
}
|
||||
|
||||
public function header($options = array())
|
||||
{
|
||||
$this->__TaxonomyModel = ClassRegistry::init('Taxonomy');
|
||||
$this->__GalaxyModel = ClassRegistry::init('Galaxy');
|
||||
App::uses('AttackExport', 'Export');
|
||||
$this->__attack_export_tool = new AttackExport();
|
||||
$this->__attack_export_tool->handler($options);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
$attackFinal = $this->__attack_export_tool->footer();
|
||||
$this->__aggregateTagsPerTaxonomy();
|
||||
$this->__aggregateClustersPerGalaxy();
|
||||
$attackData = json_decode($attackFinal, true);
|
||||
return json_encode([
|
||||
'attackData' => $attackData,
|
||||
'tags' => $this->__aggregatedTags,
|
||||
'clusters' => $this->__aggregatedClusters,
|
||||
]);
|
||||
}
|
||||
|
||||
public function separator()
|
||||
{
|
||||
$this->__attack_export_tool->separator();
|
||||
return '';
|
||||
}
|
||||
|
||||
private function __aggregate($entity, $tags)
|
||||
{
|
||||
if (!empty($entity['Galaxy'])) {
|
||||
foreach ($entity['Galaxy'] as $galaxy) {
|
||||
foreach ($galaxy['GalaxyCluster'] as $galaxyCluster) {
|
||||
$this->__eventGalaxies[$galaxyCluster['tag_name']] = $galaxyCluster;
|
||||
$this->fetchGalaxyForTag($galaxyCluster['tag_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($tags)) {
|
||||
foreach ($tags as $tag) {
|
||||
if (strpos($tag['name'], 'misp-galaxy:') === 0) {
|
||||
continue;
|
||||
}
|
||||
$this->__eventTags[$tag['name']] = $tag;
|
||||
$this->fetchTaxonomyForTag($tag['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function fetchTaxonomyForTag($tagname)
|
||||
{
|
||||
$splits = $this->__TaxonomyModel->splitTagToComponents($tagname);
|
||||
if (!isset($this->__taxonomyFetched[$splits['namespace']])) {
|
||||
$fetchedTaxonomy = $this->__TaxonomyModel->getTaxonomyForTag($tagname, false, true);
|
||||
if (!empty($fetchedTaxonomy)) {
|
||||
$this->__taxonomyFetched[$splits['namespace']]['Taxonomy'] = $fetchedTaxonomy['Taxonomy'];
|
||||
$this->__taxonomyFetched[$splits['namespace']]['TaxonomyPredicate'] = [];
|
||||
foreach ($fetchedTaxonomy['TaxonomyPredicate'] as $predicate) {
|
||||
$this->__taxonomyFetched[$splits['namespace']]['TaxonomyPredicate'][$predicate['value']] = $predicate;
|
||||
if (!empty($predicate['TaxonomyEntry'])) {
|
||||
$this->__taxonomyFetched[$splits['namespace']]['TaxonomyPredicate'][$predicate['value']]['TaxonomyEntry'] = [];
|
||||
foreach ($predicate['TaxonomyEntry'] as $entry) {
|
||||
$this->__taxonomyFetched[$splits['namespace']]['TaxonomyPredicate'][$predicate['value']]['TaxonomyEntry'][$entry['value']] = $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function fetchGalaxyForTag($tagname)
|
||||
{
|
||||
$splits = $this->__TaxonomyModel->splitTagToComponents($tagname);
|
||||
$galaxy = $this->__GalaxyModel->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Galaxy.type' => $splits['predicate'])
|
||||
));
|
||||
$this->__galaxyFetched[$splits['predicate']] = $galaxy;
|
||||
}
|
||||
|
||||
private function __aggregateTagsPerTaxonomy()
|
||||
{
|
||||
ksort($this->__eventTags);
|
||||
foreach ($this->__eventTags as $tagname => $tagData) {
|
||||
$splits = $this->__TaxonomyModel->splitTagToComponents($tagname);
|
||||
$taxonomy = [];
|
||||
if (!empty($this->__taxonomyFetched[$splits['namespace']])) {
|
||||
$taxonomy = $this->__taxonomyFetched[$splits['namespace']];
|
||||
}
|
||||
if (!empty($taxonomy['TaxonomyPredicate'][$splits['predicate']])) {
|
||||
$predicate = $taxonomy['TaxonomyPredicate'][$splits['predicate']];
|
||||
$entry = null;
|
||||
if (!empty($splits['value'])) {
|
||||
$entry = $predicate['TaxonomyEntry'][$splits['value']];
|
||||
}
|
||||
unset($predicate['TaxonomyEntry']);
|
||||
$this->__aggregatedTags[$splits['namespace']][] = [
|
||||
'Taxonomy' => $taxonomy['Taxonomy'],
|
||||
'TaxonomyPredicate' => $predicate,
|
||||
'TaxonomyEntry' => $entry,
|
||||
'Tag' => $tagData,
|
||||
];
|
||||
} else {
|
||||
$this->__aggregatedTags['Custom Tags'][]['Tag'] = $tagData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function __aggregateClustersPerGalaxy()
|
||||
{
|
||||
ksort($this->__eventGalaxies);
|
||||
foreach ($this->__eventGalaxies as $tagname => $cluster) {
|
||||
$splits = $this->__TaxonomyModel->splitTagToComponents($tagname);
|
||||
$galaxy = $this->__galaxyFetched[$splits['predicate']];
|
||||
$this->__aggregatedClusters[$splits['predicate']][] = [
|
||||
'Galaxy' => $galaxy['Galaxy'],
|
||||
'GalaxyCluster' => $cluster,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -73,6 +73,7 @@ class Event extends AppModel
|
|||
'attack' => array('html', 'AttackExport', 'html'),
|
||||
'attack-sightings' => array('json', 'AttackSightingsExport', 'json'),
|
||||
'cache' => array('txt', 'CacheExport', 'cache'),
|
||||
'context' => array('html', 'ContextExport', 'html'),
|
||||
'count' => array('txt', 'CountExport', 'txt'),
|
||||
'csv' => array('csv', 'CsvExport', 'csv'),
|
||||
'hashes' => array('txt', 'HashesExport', 'txt'),
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<div>
|
||||
<h1><?= __('Aggregated context data') ?></h1>
|
||||
<h2><?= __('Tags and Taxonomies') ?></h2>
|
||||
<div>
|
||||
<?php
|
||||
$htmlTags = '';
|
||||
foreach ($tags as $namespace => $entries) {
|
||||
$htmlTags .= sprintf('<div><h4>%s</h4></div>', h($namespace));
|
||||
if (!empty($entries[0]['Taxonomy']['description'])) {
|
||||
$htmlTags .= sprintf('<div><i>%s</i></div>', h($entries[0]['Taxonomy']['description']));
|
||||
}
|
||||
$htmlTags .= '<ul>';
|
||||
foreach ($entries as $entry) {
|
||||
$taxonomyInfo = '<ul>';
|
||||
if (!empty($entry['TaxonomyPredicate'])) {
|
||||
$taxonomyInfo .= sprintf(
|
||||
'<li><strong>%s</strong>: %s</li>',
|
||||
h($entry['TaxonomyPredicate']['value']),
|
||||
h($entry['TaxonomyPredicate']['expanded'])
|
||||
);
|
||||
}
|
||||
if (!empty($entry['TaxonomyEntry'])) {
|
||||
$taxonomyInfo .= sprintf(
|
||||
'<li><strong>%s</strong>: %s</li>',
|
||||
h($entry['TaxonomyEntry']['value']),
|
||||
h($entry['TaxonomyEntry']['expanded'])
|
||||
);
|
||||
}
|
||||
$taxonomyInfo .= '</ul>';
|
||||
$htmlTags .= sprintf(
|
||||
'<li>%s</li>%s',
|
||||
$this->element('tag', ['tag' => $entry]),
|
||||
$taxonomyInfo
|
||||
);
|
||||
}
|
||||
$htmlTags .= '</ul>';
|
||||
}
|
||||
echo $htmlTags;
|
||||
?>
|
||||
</div>
|
||||
|
||||
<h2><?= __('Galaxy Clusters') ?></h2>
|
||||
<div>
|
||||
<?php
|
||||
$htmlClusters = '';
|
||||
foreach ($clusters as $tagname => $entries) {
|
||||
$htmlClusters .= sprintf(
|
||||
'<div><h4>%s %s</h4></div>',
|
||||
sprintf('<i class="%s"></i>', $this->FontAwesome->getClass($entries[0]['Galaxy']['icon'])),
|
||||
h($entries[0]['Galaxy']['name'])
|
||||
);
|
||||
if (!empty($entries[0]['Galaxy']['description'])) {
|
||||
$htmlClusters .= sprintf('<div><i>%s</i></div>', h($entries[0]['Galaxy']['description']));
|
||||
}
|
||||
$htmlClusters .= '<ul>';
|
||||
foreach ($entries as $cluster) {
|
||||
$htmlClusters .= sprintf(
|
||||
'<li><strong><a href="%s" target="_blank">%s</a></strong></li> %s',
|
||||
$baseurl . '/galaxy_clusters/view/' . h($cluster['GalaxyCluster']['id']),
|
||||
h($cluster['GalaxyCluster']['value']),
|
||||
strlen(h($cluster['GalaxyCluster']['description'])) > 300 ?
|
||||
(substr(h($cluster['GalaxyCluster']['description']), 0, 300) . '...') : h($cluster['GalaxyCluster']['description']),
|
||||
);
|
||||
}
|
||||
$htmlClusters .= '</ul>';
|
||||
}
|
||||
echo $htmlClusters;
|
||||
?>
|
||||
</div>
|
||||
|
||||
<h2><?= __('Mitre ATT&CK Matrix') ?></h2>
|
||||
<div id="attackmatrix_div" style="position: relative; border: solid 1px;" class="statistics_attack_matrix">
|
||||
<?php
|
||||
echo $this->element('view_galaxy_matrix', $attackData);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue