mirror of https://github.com/MISP/MISP
Alternate search results
- Users can now elect to receive their attribute search results in the new alternative view - instead of receiving a list of attributes matching the search options, users are presented with a list of events that contain matching attributes - number of matches and a percentage of those matches being marked as indicators for IDSes are shown - the events are ordered by the percentage of IDS worthy attributepull/274/head
parent
f4a884bef7
commit
789839649d
|
@ -961,54 +961,59 @@ class AttributesController extends AppController {
|
|||
$conditions['AND'][] = $temp;
|
||||
}
|
||||
}
|
||||
$this->Attribute->recursive = 0;
|
||||
$this->paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 attributes?
|
||||
'conditions' => $conditions,
|
||||
'contain' => array('Event.orgc', 'Event.id', 'Event.org')
|
||||
);
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
// merge in private conditions
|
||||
$this->paginate = Set::merge($this->paginate, array(
|
||||
'conditions' =>
|
||||
array("OR" => array(
|
||||
array('Event.org =' => $this->Auth->user('org')),
|
||||
array("AND" => array('Event.org !=' => $this->Auth->user('org')), array('Event.distribution !=' => 0), array('Attribute.distribution !=' => 0)))),
|
||||
)
|
||||
if ($this->request->data['Attribute']['alternate']) {
|
||||
$events = $this->searchAlternate($conditions);
|
||||
$this->set('events', $events);
|
||||
$this->render('alternate_search_result');
|
||||
} else {
|
||||
$this->Attribute->recursive = 0;
|
||||
$this->paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 attributes?
|
||||
'conditions' => $conditions,
|
||||
'contain' => array('Event.orgc', 'Event.id', 'Event.org')
|
||||
);
|
||||
}
|
||||
|
||||
$idList = array();
|
||||
$attributeIdList = array();
|
||||
$attributes = $this->paginate();
|
||||
// if we searched for IOCs only, apply the whitelist to the search result!
|
||||
|
||||
if ($ioc) {
|
||||
$this->loadModel('Whitelist');
|
||||
$attributes = $this->Whitelist->removeWhitelistedFromArray($attributes, true);
|
||||
}
|
||||
|
||||
foreach ($attributes as &$attribute) {
|
||||
$attributeIdList[] = $attribute['Attribute']['id'];
|
||||
if (!in_array($attribute['Attribute']['event_id'], $idList)) {
|
||||
$idList[] = $attribute['Attribute']['event_id'];
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
// merge in private conditions
|
||||
$this->paginate = Set::merge($this->paginate, array(
|
||||
'conditions' =>
|
||||
array("OR" => array(
|
||||
array('Event.org =' => $this->Auth->user('org')),
|
||||
array("AND" => array('Event.org !=' => $this->Auth->user('org')), array('Event.distribution !=' => 0), array('Attribute.distribution !=' => 0)))),
|
||||
)
|
||||
);
|
||||
}
|
||||
$idList = array();
|
||||
$attributeIdList = array();
|
||||
$attributes = $this->paginate();
|
||||
// if we searched for IOCs only, apply the whitelist to the search result!
|
||||
|
||||
if ($ioc) {
|
||||
$this->loadModel('Whitelist');
|
||||
$attributes = $this->Whitelist->removeWhitelistedFromArray($attributes, true);
|
||||
}
|
||||
|
||||
foreach ($attributes as &$attribute) {
|
||||
$attributeIdList[] = $attribute['Attribute']['id'];
|
||||
if (!in_array($attribute['Attribute']['event_id'], $idList)) {
|
||||
$idList[] = $attribute['Attribute']['event_id'];
|
||||
}
|
||||
}
|
||||
$this->set('attributes', $attributes);
|
||||
|
||||
// and store into session
|
||||
$this->Session->write('paginate_conditions', $this->paginate);
|
||||
$this->Session->write('paginate_conditions_keyword', $keyword);
|
||||
$this->Session->write('paginate_conditions_keyword2', $keyword2);
|
||||
$this->Session->write('paginate_conditions_org', $org);
|
||||
$this->Session->write('paginate_conditions_type', $type);
|
||||
$this->Session->write('paginate_conditions_category', $category);
|
||||
$this->Session->write('search_find_idlist', $idList);
|
||||
$this->Session->write('search_find_attributeidlist', $attributeIdList);
|
||||
|
||||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
}
|
||||
$this->set('attributes', $attributes);
|
||||
|
||||
// and store into session
|
||||
$this->Session->write('paginate_conditions', $this->paginate);
|
||||
$this->Session->write('paginate_conditions_keyword', $keyword);
|
||||
$this->Session->write('paginate_conditions_keyword2', $keyword2);
|
||||
$this->Session->write('paginate_conditions_org', $org);
|
||||
$this->Session->write('paginate_conditions_type', $type);
|
||||
$this->Session->write('paginate_conditions_category', $category);
|
||||
$this->Session->write('search_find_idlist', $idList);
|
||||
$this->Session->write('search_find_attributeidlist', $attributeIdList);
|
||||
|
||||
// set the same view as the index page
|
||||
$this->render('index');
|
||||
} else {
|
||||
// no search keyword is given, show the search form
|
||||
|
||||
|
@ -1051,6 +1056,58 @@ class AttributesController extends AppController {
|
|||
$this->render('index');
|
||||
}
|
||||
}
|
||||
|
||||
// If the checkbox for the alternate search is ticked, then this method is called to return the data to be represented
|
||||
// This alternate view will show a list of events with matching search results and the percentage of those matched attributes being marked as to_ids
|
||||
// events are sorted based on relevance (as in the percentage of matches being flagged as indicators for IDS)
|
||||
public function searchAlternate($data) {
|
||||
$data['AND'][] = array(
|
||||
"OR" => array(
|
||||
array('Event.org =' => $this->Auth->user('org')),
|
||||
array("AND" => array('Event.org !=' => $this->Auth->user('org')), array('Event.distribution !=' => 0), array('Attribute.distribution !=' => 0))));
|
||||
$attributes = $this->Attribute->find('all', array(
|
||||
'conditions' => $data,
|
||||
'fields' => array(
|
||||
'Attribute.id', 'Attribute.event_id', 'Attribute.type', 'Attribute.category', 'Attribute.to_ids', 'Attribute.value', 'Attribute.distribution',
|
||||
'Event.id', 'Event.org', 'Event.orgc', 'Event.info', 'Event.distribution', 'Event.attribute_count'
|
||||
)));
|
||||
$events = array();
|
||||
foreach ($attributes as $attribute) {
|
||||
if (isset($events[$attribute['Event']['id']])) {
|
||||
if ($attribute['Attribute']['to_ids']) {
|
||||
$events[$attribute['Event']['id']]['to_ids']++;
|
||||
} else {
|
||||
$events[$attribute['Event']['id']]['no_ids']++;
|
||||
}
|
||||
} else {
|
||||
$events[$attribute['Event']['id']]['Event'] = $attribute['Event'];
|
||||
$events[$attribute['Event']['id']]['to_ids'] = 0;
|
||||
$events[$attribute['Event']['id']]['no_ids'] = 0;
|
||||
if ($attribute['Attribute']['to_ids']) {
|
||||
$events[$attribute['Event']['id']]['to_ids']++;
|
||||
} else {
|
||||
$events[$attribute['Event']['id']]['no_ids']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($events as &$event) {
|
||||
$event['relevance'] = 100 * $event['to_ids'] / ($event['no_ids'] + $event['to_ids']);
|
||||
}
|
||||
$events = $this->__subval_sort($events, 'relevance');
|
||||
return $events;
|
||||
}
|
||||
|
||||
// Sort the array of arrays based on a value of a sub-array
|
||||
private function __subval_sort($a,$subkey) {
|
||||
foreach($a as $k=>$v) {
|
||||
$b[$k] = strtolower($v[$subkey]);
|
||||
}
|
||||
arsort($b);
|
||||
foreach($b as $key=>$val) {
|
||||
$c[] = $a[$key];
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
|
||||
public function downloadAttributes() {
|
||||
$idList = $this->Session->read('search_find_idlist');
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<div class="event index">
|
||||
<h2>Alternate Search Results</h2>
|
||||
<p> This is a list of events that match the given search criteria sorted according to the percentage of matched attributes that are marked as IDS signatures (blue = IDS matches, red = non IDS matches).</p>
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<tr>
|
||||
<th>Event id</th>
|
||||
<th>Org</th>
|
||||
<th>Event info</th>
|
||||
<th>Event graph</th>
|
||||
<th>Matches</th>
|
||||
<th>Attribute Count</th>
|
||||
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
foreach ($events as $event) {
|
||||
?>
|
||||
<tr>
|
||||
<td class="short"><a href="/events/view/<?php echo (h($event['Event']['id'])); ?>"><?php echo (h($event['Event']['id'])); ?></a></td>
|
||||
<td class="short">
|
||||
<?php
|
||||
$imgRelativePath = 'orgs' . DS . h($event['Event']['orgc']) . '.png';
|
||||
$imgAbsolutePath = APP . WEBROOT_DIR . DS . 'img' . DS . $imgRelativePath;
|
||||
if (file_exists($imgAbsolutePath)) echo $this->Html->image('orgs/' . h($event['Event']['orgc']) . '.png', array('alt' => h($event['Event']['orgc']), 'title' => h($event['Event']['orgc']), 'style' => 'width:24px; height:24px'));
|
||||
else echo $this->Html->tag('span', h($event['Event']['orgc']), array('class' => 'welcome', 'style' => 'float:left;'));
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php
|
||||
if (strlen(h($event['Event']['info'])) > 60) {
|
||||
echo (substr(h($event['Event']['info']), 0, 60)) . '...';
|
||||
} else echo h($event['Event']['info']);
|
||||
?>
|
||||
</td>
|
||||
<?php
|
||||
$to_ids = 100 * h($event['to_ids']) / (h($event['to_ids']) + h($event['no_ids']));
|
||||
?>
|
||||
<td>
|
||||
<div class="progress" style="width:300px;">
|
||||
<div class="bar bar-info" style="width:<?php echo $to_ids . '%'; ?>"></div>
|
||||
<div class="bar bar-danger" style="width:<?php echo 100-$to_ids . '%'; ?>"></div>
|
||||
<span style="position:absolute;width:300px;color:white;display: block;text-align:center;"><?php echo intval($to_ids) . '%'; ?></span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="short"><?php echo h($event['to_ids']) + h($event['no_ids']) ?></td>
|
||||
<td class="short"><?php echo (h($event['Event']['attribute_count'])) ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->element('side_menu', array('menuList' => 'event-collection', 'menuItem' => 'searchAttributes'));
|
||||
?>
|
|
@ -28,6 +28,10 @@
|
|||
'type' => 'checkbox',
|
||||
'label' => 'Only find valid IOCs',
|
||||
));
|
||||
echo $this->Form->input('alternate', array(
|
||||
'type' => 'checkbox',
|
||||
'label' => 'Alternate Search Result (Events)',
|
||||
));
|
||||
?>
|
||||
</fieldset>
|
||||
<?php
|
||||
|
|
Loading…
Reference in New Issue