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 attribute
pull/274/head
iglocska 2014-03-13 16:03:16 +01:00
parent f4a884bef7
commit 789839649d
3 changed files with 161 additions and 45 deletions

View File

@ -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');

View File

@ -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'));
?>

View File

@ -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