new: [Correlations] added dedicated controller/model/views

pull/7374/head
iglocska 2021-04-22 09:46:10 +02:00
parent 0a1c3f3458
commit 9e1b9f9b6e
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
3 changed files with 273 additions and 0 deletions

View File

@ -0,0 +1,59 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property AuthKey $AuthKey
*/
class CorrelationsController extends AppController
{
public function top_correlations()
{
$options = [
'filters' => ['value', 'quickFilter'],
'quickFilters' => ['value']
];
$this->Correlation->virtualFields['count'] = 'COUNT(*)';
$params = $this->IndexFilter->harvestParameters(empty($options['filters']) ? [] : $options['filters']);
$query = [
'fields' => ['value', 'count'],
'group' => ['value'],
'order' => 'count desc',
'recursive' => -1
];
if (!empty($this->params['named']['limit'])) {
$query['limit'] = $this->params['named']['limit'];
}
if (!empty($this->params['named']['page'])) {
$query['page'] = $this->params['named']['page'];
}
$query = $this->CRUD->setFilters($params, $query);
$query = $this->CRUD->setQuickFilters($params, $query, empty($options['quickFilters']) ? [] : $options['quickFilters']);
if ($this->IndexFilter->isRest()) {
$data = $this->Correlation->find('all', $query);
return $this->RestResponse->viewData($data, 'json');
} else {
if (empty($query['limit'])) {
$query['limit'] = 20;
}
if (empty($query['page'])) {
$query['page'] = 1;
}
$this->paginate = $query;
$data = $this->Correlation->find('all', $query);
$this->set('data', $data);
$this->set('title_for_layout', __('Top correlations index'));
$this->set('menuData', [
'menuList' => 'correlationExclusions',
'menuItem' => 'top_correlations'
]);
}
if ($this->IndexFilter->isRest()) {
return $this->restResponsePayload;
}
$this->set('title_for_layout', __('Correlation Exclusions index'));
$this->set('menuData', [
'menuList' => 'correlationExclusions',
'menuItem' => 'index'
]);
}
}

155
app/Model/Correlation.php Normal file
View File

@ -0,0 +1,155 @@
<?php
App::uses('AppModel', 'Model');
App::uses('RandomTool', 'Tools');
class Correlation extends AppModel
{
public function correlateValueRouter($value)
{
if (Configure::read('MISP.background_jobs')) {
$job = ClassRegistry::init('Job');
$job->create();
$data = array(
'worker' => 'default',
'job_type' => 'correlateValue',
'job_input' => $value,
'status' => 0,
'retries' => 0,
'org_id' => 0,
'org' => 0,
'message' => 'Recorrelating',
);
$job->save($data);
$jobId = $job->id;
$process_id = CakeResque::enqueue(
'email',
'EventShell',
['correlateValue', $value, $jobId],
true
);
$job->saveField('process_id', $process_id);
return true;
} else {
return $this->correlateValue($value, $jobId);
}
}
public function addAdvancedCorrelations($correlatingAttribute)
{
$a = $correlatingAttribute['Attribute'];
if (Configure::read('MISP.enable_advanced_correlations')) {
if (in_array($a['type'], array('ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port'))) {
return $this->Attribute->cidrCorrelation($a);
} else if ($a['type'] === 'ssdeep' && function_exists('ssdeep_fuzzy_compare')) {
$this->FuzzyCorrelateSsdeep = ClassRegistry::init('FuzzyCorrelateSsdeep');
$fuzzyIds = $this->FuzzyCorrelateSsdeep->query_ssdeep_chunks($a['value1'], $a['id']);
if (!empty($fuzzyIds)) {
$ssdeepIds = $this->find('list', array(
'recursive' => -1,
'conditions' => array(
'Attribute.type' => 'ssdeep',
'Attribute.id' => $fuzzyIds
),
'fields' => array('Attribute.id', 'Attribute.value1')
));
$threshold = Configure::read('MISP.ssdeep_correlation_threshold') ?: 40;
$attributeIds = array();
foreach ($ssdeepIds as $attributeId => $v) {
$ssdeep_value = ssdeep_fuzzy_compare($a['value1'], $v);
if ($ssdeep_value >= $threshold) {
$attributeIds[] = $attributeId;
}
}
return ['Attribute.id' => $attributeIds];
}
}
}
}
public function correlateValue($value, $jobId)
{
$valueConditions = [
'Attribute.value1' => $exclusion['CorrelationExclusion']['value'],
'AND' => [
'Attribute.value2' => $exclusion['CorrelationExclusion']['value'],
'NOT' => ['Attribute.type' => $this->Attribute->primaryOnlyCorrelatingTypes]
]
];
$conditions = [
'OR' => $valueConditions,
'NOT' => [
'Attribute.type' => $this->Attribute->nonCorrelatingTypes,
],
'Attribute.disable_correlation' => 0,
'Event.disable_correlation' => 0,
'Attribute.deleted' => 0
];
$this->Attribute = ClassRegistry::init('Attribute');
$correlatingAttributes[$k] = $this->Attribute->find('all', [
'conditions' => $conditions,
'recursive' => -1,
'fields' => [
'Attribute.event_id',
'Attribute.id',
'Attribute.distribution',
'Attribute.sharing_group_id',
'Attribute.value1',
'Attribute.value2',
],
'contain' => [
'Event' => [
'fields' => ['Event.id', 'Event.date', 'Event.info', 'Event.org_id', 'Event.distribution', 'Event.sharing_group_id', 'Event.disable_correlation']
]
],
'order' => [],
]);
$count = count($correlatingAttributes);
$correlations = [];
foreach ($correlatingAttributes as $k => $correlatingAttribute) {
if (
in_array($correlatingAttribute2['Attribute']['type'], $this->Attribute->nonCorrelatingTypes) ||
!empty($correlatingAttribute['Event']['disable_correlation'])
) {
continue;
}
foreach ($correlatingAttribute as $k2 => $correlatingAttribute2) {
if (
$correlatingAttribute['Attribute']['event_id'] === $correlatingAttribute2['Attribute']['event_id'] ||
!empty($correlatingAttribute2['Event']['disable_correlation']) ||
in_array($correlatingAttribute2['Attribute']['type'], $this->Attribute->nonCorrelatingTypes)
) {
continue;
}
$correlations[] = array(
'value' => $value,
'1_event_id' => $correlatingAttribute['Event']['id'],
'1_attribute_id' => $correlatingAttribute['Attribute']['id'],
'event_id' => $correlatingAttribute2['Attribute']['event_id'],
'attribute_id' => $correlatingAttribute2['Attribute']['id'],
'org_id' => $correlatingAttribute2['Event']['org_id'],
'distribution' => $correlatingAttribute2['Event']['distribution'],
'a_distribution' => $correlatingAttribute2['Attribute']['distribution'],
'sharing_group_id' => $correlatingAttribute2['Event']['sharing_group_id'],
'a_sharing_group_id' => $correlatingAttribute2['Attribute']['sharing_group_id'],
'date' => $correlatingAttribute2['Event']['date'],
'info' => $correlatingAttribute2['Event']['info']
);
}
$correlations = $this->addAdvancedCorrelations($correlatingAttribute);
}
if (Configure::read('MISP.deadlock_avoidance')) {
return $this->saveMany($correlations, array(
'atomic' => false,
'callbacks' => false,
'deep' => false,
'validate' => false,
'fieldList' => $fields,
));
} else {
$db = $this->getDataSource();
return $db->insertMulti('correlations', $fields, $correlations);
}
}
}

View File

@ -0,0 +1,59 @@
<?php
echo sprintf('<div%s>', empty($ajax) ? ' class="index"' : '');
echo $this->element('genericElements/IndexTable/index_table', [
'data' => [
'stupid_pagination' => 1,
'data' => $data,
'top_bar' => [
'pull' => 'right',
'children' => [
[
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'searchKey' => 'quickFilter',
]
]
],
'fields' => [
[
'name' => 'Value',
'sort' => 'Correlation.value',
'data_path' => 'Correlation.value',
'class' => 'short'
],
[
'name' => 'Correlation count',
'sort' => 'Correlation.count',
'data_path' => 'Correlation.count'
]
],
'title' => empty($ajax) ? $title_for_layout : false,
'description' => empty($ajax) ? __('The values with the most correlation entries.') : false,
'pull' => 'right',
'actions' => [
[
'onclick' => sprintf(
'openGenericModal(\'%s/correlation_exclusions/add/redirect:top_correlations/value:[onclick_params_data_path]\');',
$baseurl
),
'onclick_params_data_path' => 'Correlation.value',
'icon' => 'trash',
'title' => __('Add exclusion entry for value'),
]
]
]
]);
echo '</div>';
if (empty($ajax)) {
echo $this->element('/genericElements/SideMenu/side_menu', $menuData);
}
?>
<script type="text/javascript">
var passedArgsArray = <?php echo $passedArgs; ?>;
$(function() {
$('#quickFilterButton').click(function() {
runIndexQuickFilter();
});
});
</script>