new: Rework of the restsearch APIs

- allows for alternate download types (supported for now: openioc)
- major refactor of the openioc export
- refactor of the CIDR tool
pull/2200/head
iglocska 2017-03-31 19:27:34 +02:00
parent 1ef6081b0d
commit 3b6807ef72
20 changed files with 542 additions and 382 deletions

View File

@ -55,7 +55,7 @@ class EventShell extends AppShell
if (!empty($eventIds)) {
foreach ($eventIds as $k => $eventId) {
$temp = $this->Event->fetchEvent($user, array('eventid' => $eventId['Event']['id'], 'includeAttachments' => Configure::read('MISP.cached_attachments')));
$file->append($converter->event2XML($temp[0], $user['Role']['perm_site_admin']) . PHP_EOL);
$file->append($converter->convert($temp[0], $user['Role']['perm_site_admin']) . PHP_EOL);
$this->Job->saveField('progress', ($k+1) / $eventCount *100);
}
}
@ -88,7 +88,7 @@ class EventShell extends AppShell
$file->write('{"response":[');
foreach ($eventIds as $k => $eventId) {
$result = $this->Event->fetchEvent($user, array('eventid' => $eventId['Event']['id'], 'includeAttachments' => Configure::read('MISP.cached_attachments')));
$file->append($converter->event2JSON($result[0]));
$file->append($converter->convert($result[0]));
if ($k < count($eventIds) -1 ) $file->append(',');
$this->Job->saveField('progress', ($k+1) / $eventCount *100);
}

View File

@ -1641,6 +1641,8 @@ class AttributesController extends AppController {
$this->set('fails', $this->Attribute->checkComposites());
}
// Use the rest interface to search for attributes. Usage:
// MISP-base-url/attributes/restSearch/[api-key]/[value]/[type]/[category]/[orgc]
// value, type, category, orgc are optional
@ -1653,14 +1655,14 @@ class AttributesController extends AppController {
foreach ($simpleFalse as $sF) {
if (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false') ${$sF} = false;
}
if ($key != null && $key != 'download') {
if ($key != null && strlen($key) == 40) {
$user = $this->checkAuthUser($key);
if (!$user) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
} else {
$key = strtolower($key);
if (!$this->Auth->user()) throw new UnauthorizedException('You are not authorized. Please send the Authorization header with your auth key along with an Accept header for application/xml.');
$user = $this->checkAuthUser($this->Auth->user('authkey'));
}
if (!$user) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
// request handler for POSTed queries. If the request is a post, the parameters (apart from the key) will be ignored and replaced by the terms defined in the posted json or xml object.
// The correct format for both is a "request" root element, as shown by the examples below:
@ -1669,8 +1671,14 @@ class AttributesController extends AppController {
// the response type is used to determine the parsing method (xml/json)
if ($this->request->is('post')) {
if ($this->response->type() === 'application/json') {
if ($key == 'xml') {
throw new MethodNotAllowedException('Content type and parameter mismatch. Expecting JSON.');
}
$data = $this->request->input('json_decode', true);
} else if ($this->response->type() === 'application/xml' && !empty($this->request->data)) {
if ($key == 'json') {
throw new MethodNotAllowedException('Content type and parameter mismatch. Expecting XML.');
}
$data = $this->request->data;
} else {
throw new BadRequestException('Either specify the search terms in the url, or POST a json array / xml (with the root element being "request" and specify the correct accept and content type headers.');
@ -1692,116 +1700,26 @@ class AttributesController extends AppController {
if ($from) $from = $this->Attribute->Event->dateFieldCheck($from);
if ($to) $to = $this->Attribute->Event->dateFieldCheck($to);
if ($last) $last = $this->Attribute->Event->resolveTimeDelta($last);
if (!isset($this->request->params['ext']) || $this->request->params['ext'] !== 'json') {
$this->response->type('xml'); // set the content type
$this->layout = 'xml/default';
$this->header('Content-Disposition: download; filename="misp.search.attribute.results.xml"');
} else {
$this->response->type('json'); // set the content type
$this->layout = 'json/default';
$this->header('Content-Disposition: download; filename="misp.search.attribute.results.json"');
}
$conditions['AND'] = array();
$subcondition = array();
$this->loadModel('Attribute');
// add the values as specified in the 2nd parameter to the conditions
$parameters = array('value', 'type', 'category', 'org', 'eventid', 'uuid');
foreach ($parameters as $k => $param) {
if (isset(${$parameters[$k]}) && ${$parameters[$k]}!==false) {
if (is_array(${$parameters[$k]})) $elements = ${$parameters[$k]};
else $elements = explode('&&', ${$parameters[$k]});
foreach ($elements as $v) {
if (empty($v)) continue;
if (substr($v, 0, 1) == '!') {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameters[$k] === 'value' && $this->Cidr->checkCIDR(substr($v, 1), 4)) {
$cidrresults = $this->Cidr->CIDR(substr($v, 1));
foreach ($cidrresults as $result) {
$subcondition['AND'][] = array('Attribute.value NOT LIKE' => $result);
}
} else if ($parameters[$k] === 'org') {
// from here
$found_orgs = $this->Attribute->Event->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower(substr($v, 1)) . '%'),
));
foreach ($found_orgs as $o) $subcondition['AND'][] = array('Event.orgc_id !=' => $o['Org']['id']);
} else if ($parameters[$k] === 'eventid') {
$subcondition['AND'][] = array('Attribute.event_id !=' => substr($v, 1));
} else if ($parameters[$k] === 'uuid') {
$subcondition['AND'][] = array('Event.uuid !=' => substr($v, 1));
$subcondition['AND'][] = array('Attribute.uuid !=' => substr($v, 1));
} else {
$subcondition['AND'][] = array('Attribute.' . $parameters[$k] . ' NOT LIKE' => '%'.substr($v, 1).'%');
}
} else {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameters[$k] === 'value' && $this->Cidr->checkCIDR($v, 4)) {
$cidrresults = $this->Cidr->CIDR($v);
foreach ($cidrresults as $result) {
$subcondition['OR'][] = array('Attribute.value LIKE' => $result);
}
} else if ($parameters[$k] === 'org') {
// from here
$found_orgs = $this->Attribute->Event->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower($v) . '%'),
));
foreach ($found_orgs as $o) $subcondition['OR'][] = array('Event.orgc_id' => $o['Org']['id']);
} else if ($parameters[$k] === 'eventid') {
if (!empty($v)) $subcondition['OR'][] = array('Attribute.event_id' => $v);
} else if ($parameters[$k] === 'uuid') {
$subcondition['OR'][] = array('Attribute.uuid' => $v);
$subcondition['OR'][] = array('Event.uuid' => $v);
} else {
if (!empty($v)) $subcondition['OR'][] = array('Attribute.' . $parameters[$k] . ' LIKE' => '%'.$v.'%');
}
}
}
array_push ($conditions['AND'], $subcondition);
$subcondition = array();
if (isset(${$parameters[$k]}) && ${$parameters[$k]} !== false) {
$conditions = $this->Attribute->setSimpleConditions($parameters[$k], ${$parameters[$k]}, $conditions);
}
}
// If we sent any tags along, load the associated tag names for each attribute
if ($tags) {
$args = $this->Attribute->dissectArgs($tags);
$this->loadModel('Tag');
$tagArray = $this->Tag->fetchEventTagIds($args[0], $args[1]);
$temp = array();
foreach ($tagArray[0] as $accepted) {
$temp['OR'][] = array('Event.id' => $accepted);
}
$conditions['AND'][] = $temp;
$temp = array();
foreach ($tagArray[1] as $rejected) {
$temp['AND'][] = array('Event.id !=' => $rejected);
}
$conditions['AND'][] = $temp;
}
if ($tags) $conditions = $this->Attribute->setTagConditions($tags, $conditions);
if ($from) $conditions['AND'][] = array('Event.date >=' => $from);
if ($to) $conditions['AND'][] = array('Event.date <=' => $to);
if ($publish_timestamp) {
if (is_array($publish_timestamp)) {
$conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp[0]);
$conditions['AND'][] = array('Event.publish_timestamp <=' => $publish_timestamp[1]);
} else {
$conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp);
}
}
if ($publish_timestamp) $conditions = $this->Attribute->setPublishTimestampConditions($publish_timestamp, $conditions);
if ($last) $conditions['AND'][] = array('Event.publish_timestamp >=' => $last);
if ($published) $conditions['AND'][] = array('Event.published' => $published);
if ($timestamp) $conditions['AND'][] = array('Attribute.timestamp >=' => $timestamp);
if ($to_ids) {
if ($to_ids === 'exclude') {
$conditions['AND'][] = array('Attribute.to_ids' => 0);
} else {
$conditions['AND'][] = array('Attribute.to_ids' => 1);
}
}
if ($to_ids) $conditions = $this->Attribute->setToIDSConditions($to_ids, $conditions);
// change the fields here for the attribute export!!!! Don't forget to check for the permissions, since you are not going through fetchevent. Maybe create fetchattribute?
$params = array(
'conditions' => $conditions,
@ -1818,7 +1736,25 @@ class AttributesController extends AppController {
$results = $this->Attribute->fetchAttributes($this->Auth->user(), $params);
$this->loadModel('Whitelist');
$results = $this->Whitelist->removeWhitelistedFromArray($results, true);
$this->set('results', $results);
if ($key == 'openioc') {
App::uses('IOCExportTool', 'Tools');
$this->IOCExport = new IOCExportTool();
$results = $this->IOCExport->buildAll($this->Auth->user(), $results, 'attribute');
} else {
$results = array('response' => array('Attribute' => $results));
foreach ($results['response']['Attribute'] as $k => $v) {
$results['response']['Attribute'][$k] = $results['response']['Attribute'][$k]['Attribute'];
unset(
$results['response']['Attribute'][$k]['value1'],
$results['response']['Attribute'][$k]['value2']
);
}
}
$responseType = $this->response->type();
if ($key == 'openioc') {
$responseType = 'openioc';
}
return $this->RestResponse->viewData($results, $responseType);
}
// returns an XML with attributes that belong to an event. The type of attributes to be returned can be restricted by type using the 3rd parameter.

View File

@ -1,112 +1,6 @@
<?php
class IOCExportComponent extends Component {
private $final = array();
public function buildAll($user, $event) {
$this->__buildTop($event);
foreach ($event['Attribute'] as $attribute) {
$this->__buildAttribute($attribute);
}
$this->__buildBottom();
return $this->final;
}
// Builds the top with the event information
private function __buildTop($event) {
// We will start adding all the components that will be in the xml file here
$this->final[] = '<?xml version="1.0" encoding="utf-8"?>';
$this->final[] = '<ioc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="' . $event['Event']['uuid'] . '" last-modified="' . $event['Event']['date'] . 'T00:00:00" xmlns="http://schemas.mandiant.com/2010/ioc">';
$this->final[] = ' <short_description>Event #' . h($event['Event']['id']) . '</short_description>';
$this->final[] = ' <description>' . h($event['Event']['info']) . '</description>';
$this->final[] = ' <keywords />';
$this->final[] = ' <authored_by>' . h($event['Orgc']['name']) . '</authored_by>';
$this->final[] = ' <authored_date>' . h($event['Event']['date']) . 'T00:00:00</authored_date>';
$this->final[] = ' <links />';
$this->final[] = ' <definition>';
// for now, since we don't have any logical links between attributes, we'll OR all of them
$this->final[] = ' <Indicator operator="OR" id="' . h($event['Event']['uuid']) . '">';
}
public $mapping = array(
'composite' => array(
'regkey|value' => array(array('Network', 'RegistryItem/KeyPath', 'string'), array('Network', 'RegistryItem/Value', 'string')),
'filename|md5' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Md5sum', 'md5')),
'filename|sha1' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Sha1sum', 'sha1')),
'filename|sha256' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Sha256sum', 'sha256')),
'malware-sample' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Md5sum', 'md5')),
'domain|ip' => array(array('Network', 'Network/DNS', 'string'), array('PortItem', 'PortItem/remoteIP', 'IP')),
),
'simple' => array(
'md5' => array('FileItem', 'FileItem/Md5sum', 'md5'),
'sha1' => array('FileItem', 'FileItem/Sha1sum', 'sha1'),
'sha256' => array('FileItem', 'FileItem/Sha256sum', 'sha256'),
'filename' => array('FileItem', 'FileItem/FileName', 'string'),
'ip-src' => array('PortItem', 'PortItem/remoteIP', 'IP'),
'ip-dst' => array('RouteEntryItem', 'RouteEntryItem/Destination', 'IP'),
'hostname' => array('RouteEntryItem', 'RouteEntryItem/Destination', 'string'),
'email-src' => array('Email', 'Email/From', 'string'),
'email-dst' => array('Email', 'Email/To', 'string'),
'email-subject' => array('Email', 'Email/Subject', 'string'),
'email-attachment' => array('Email', 'Email/Attachment/Name', 'string'),
'domain' => array('Network', 'Network/DNS', 'string'),
'url' => array('UrlHistoryItem', 'UrlHistoryItem/URL', 'string'),
'user-agent' => array('Network', 'Network/UserAgent', 'string'),
'regkey' => array('Network', 'RegistryItem/KeyPath', 'string'),
'snort' => array('Snort', 'Snort/Snort', 'string'),
'attachment' => array('FileItem', 'FileItem/FileName', 'string'),
'link' => array('URL', 'UrlHistoryItem/URL', 'md5')
)
);
private function __frameComposite($attribute) {
$values = explode('|', $attribute['value']);
$this->final[] = ' <Indicator operator="AND" id="' . h($attribute['uuid']) . '">';
$this->__frameIndicator($this->mapping['composite'][$attribute['type']][0], $attribute['uuid'], $values[0], true);
$this->__frameIndicator($this->mapping['composite'][$attribute['type']][1], $attribute['uuid'], $values[1], true);
$this->final[] = ' </Indicator>';
}
private function __frameIndicator($mapping, $uuid, $value, $extraIndent = false) {
$padding = 6;
if ($extraIndent) {
$padding = 8;
}
$this->final[] = str_repeat(' ', $padding) . '<IndicatorItem id="' . h($uuid) . '" condition="is">';
$this->final[] = str_repeat(' ', ($padding + 2)) . '<Context document="' . $mapping[0] . '" search="' . $mapping[1] . '" type="mir" />';
$this->final[] = str_repeat(' ', ($padding + 2)) . '<Content type="' . $mapping[2] . '">' . h($value) . '</Content>';
$this->final[] = str_repeat(' ', $padding) . '</IndicatorItem>';
}
// This method will turn each eligible attribute into an indicator
private function __buildAttribute($attribute) {
// Hop over attributes that don't have the to ids flag turned on and check whether the attribute is sent for IOC export based on category/type
if (!$this->__checkValidTypeForIOC($attribute) || $attribute['to_ids'] == 0) return;
if ($attribute['type'] == 'malware-sample') $attribute['type'] = 'filename|md5';
if (strpos($attribute['type'], '|')) {
if ($this->mapping['composite'][$attribute['type']]) {
$this->__frameComposite($attribute);
}
} else {
if (isset($this->mapping['simple'][$attribute['type']])) {
$this->__frameIndicator($this->mapping['simple'][$attribute['type']], $attribute['uuid'], $attribute['value'], false);
}
}
}
// Just closing some tags at the bottom of the .ioc file
private function __buildBottom() {
$this->final[] = ' </Indicator>';
$this->final[] = ' </definition>';
$this->final[] = '</ioc>';
}
// Simple check for valid categories and types for IOC generation
private function __checkValidTypeForIOC($attribute) {
// categories that should be included
$Category = array('Payload delivery', 'Artifacts dropped', 'Payload installation', 'Persistence mechanism', 'Network activity');
if (!in_array($attribute['category'], $Category)) return false;
return true;
}
// removed in favour of th IOCExportTool
// File used as a placeholder to avoid model caching issues
}

View File

@ -65,12 +65,14 @@ class RestResponseComponent extends Component {
return $this->__sendResponse($response, 200, $format);
}
private function __sendResponse($response, $code, $format = false) {
private function __sendResponse($response, $code, $format = false, $raw = false) {
if (strtolower($format) === 'application/xml') {
$response = Xml::build($response);
if (!$raw) $response = Xml::build($response);
$type = 'xml';
} else if(strtolower($format) == 'openioc') {
$type = 'xml';
} else {
$response = json_encode($response, JSON_PRETTY_PRINT);
if (!$raw) $response = json_encode($response, JSON_PRETTY_PRINT);
$type = 'json';
}
return new CakeResponse(array('body'=> $response,'status' => $code, 'type' => $type));
@ -89,11 +91,11 @@ class RestResponseComponent extends Component {
return array('action' => $action, 'admin' => $admin);
}
public function viewData($data, $format = false, $errors = false) {
public function viewData($data, $format = false, $errors = false, $raw = false) {
if (!empty($errors)) {
$data['errors'] = $errors;
}
return $this->__sendResponse($data, 200, $format);
return $this->__sendResponse($data, 200, $format, $raw);
}
public function describe($controller, $action, $id = false, $format = false) {

View File

@ -8,7 +8,6 @@ class EventsController extends AppController {
'Security',
'Email',
'RequestHandler',
'IOCExport',
'IOCImport',
'Cidr'
);
@ -1848,7 +1847,7 @@ class EventsController extends AppController {
}
}
$result = $this->Whitelist->removeWhitelistedFromArray($result, false);
$final .= $converter->event2XML($result[0]) . PHP_EOL;
$final .= $converter->convert($result[0]) . PHP_EOL;
}
if ($validEvents == 0) throw new NotFoundException('No events found that match the passed parameters.');
$final .= '</response>' . PHP_EOL;
@ -2461,14 +2460,13 @@ class EventsController extends AppController {
// && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two.
// ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't.
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $searchall = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $metadata = false, $uuid = false, $publish_timestamp = false, $timestamp = false, $published = false, $enforceWarninglist = false) {
if ($key != 'download') {
if ($key != null && strlen($key) == 40) {
if (!$this->checkAuthUser($key)) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
} else {
if (!$this->Auth->user()) {
throw new UnauthorizedException('You are not authorized. Please send the Authorization header with your auth key along with an Accept header for application/xml.');
}
$key = strtolower($key);
if (!$this->Auth->user()) throw new UnauthorizedException('You are not authorized. Please send the Authorization header with your auth key along with an Accept header for application/xml.');
}
if (!is_array($value)) $value = str_replace('|', '/', $value);
// request handler for POSTed queries. If the request is a post, the parameters (apart from the key) will be ignored and replaced by the terms defined in the posted json or xml object.
@ -2517,104 +2515,15 @@ class EventsController extends AppController {
$parameters = array('value', 'type', 'category', 'org', 'eventid', 'uuid');
foreach ($parameters as $k => $param) {
if (isset(${$parameters[$k]})) {
if (is_array(${$parameters[$k]})) {
$elements = ${$parameters[$k]};
} else {
$elements = explode('&&', ${$parameters[$k]});
}
foreach ($elements as $v) {
if ($v == '') continue;
if (substr($v, 0, 1) == '!') {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameters[$k] === 'value' && $this->Cidr->checkCIDR(substr($v, 1), 4)) {
$cidrresults = $this->Cidr->CIDR(substr($v, 1));
foreach ($cidrresults as $result) {
$subcondition['AND'][] = array('Attribute.value NOT LIKE' => $result);
}
} else {
if ($parameters[$k] === 'org') {
$found_orgs = $this->Event->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower(substr($v, 1)) . '%'),
));
foreach ($found_orgs as $o) {
$subcondition['AND'][] = array('Event.orgc_id !=' => $o['Org']['id']);
}
} else if ($parameters[$k] === 'eventid') {
$subcondition['AND'][] = array('Attribute.event_id !=' => substr($v, 1));
} else if ($parameters[$k] === 'uuid') {
$subcondition['AND'][] = array('Event.uuid !=' => substr($v, 1));
$subcondition['AND'][] = array('Attribute.uuid !=' => substr($v, 1));
} else {
$subcondition['AND'][] = array('Attribute.' . $parameters[$k] . ' NOT LIKE' => '%'.substr($v, 1).'%');
}
}
} else {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameters[$k] === 'value' && $this->Cidr->checkCIDR($v, 4)) {
$cidrresults = $this->Cidr->CIDR($v);
foreach ($cidrresults as $result) {
if (!empty($result)) $subcondition['OR'][] = array('Attribute.value LIKE' => $result);
}
} else {
if ($parameters[$k] === 'org') {
$found_orgs = $this->Event->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower($v) . '%'),
));
foreach ($found_orgs as $o) {
$subcondition['OR'][] = array('Event.orgc_id' => $o['Org']['id']);
}
} else if ($parameters[$k] === 'eventid') {
$subcondition['OR'][] = array('Attribute.event_id' => $v);
} else if ($parameters[$k] === 'uuid') {
$subcondition['OR'][] = array('Attribute.uuid' => $v);
$subcondition['OR'][] = array('Event.uuid' => $v);
}else {
if (!empty($v)) $subcondition['OR'][] = array('Attribute.' . $parameters[$k] . ' LIKE' => '%'.$v.'%');
}
}
}
}
if (!empty($subcondition)) array_push ($conditions['AND'], $subcondition);
$subcondition = array();
$conditions = $this->Event->setSimpleConditions($parameters[$k], ${$parameters[$k]}, $conditions);
}
}
// If we sent any tags along, load the associated tag names for each attribute
if ($tags) {
$args = $this->Event->Attribute->dissectArgs($tags);
$this->loadModel('Tag');
$tagArray = $this->Tag->fetchEventTagIds($args[0], $args[1]);
$temp = array();
foreach ($tagArray[0] as $accepted) {
$temp['OR'][] = array('Event.id' => $accepted);
}
$conditions['AND'][] = $temp;
$temp = array();
foreach ($tagArray[1] as $rejected) {
$temp['AND'][] = array('Event.id !=' => $rejected);
}
$conditions['AND'][] = $temp;
}
if ($tags) $conditions = $this->Event->Attribute->setTagConditions($tags, $conditions);
if ($from) $conditions['AND'][] = array('Event.date >=' => $from);
if ($to) $conditions['AND'][] = array('Event.date <=' => $to);
if ($publish_timestamp) {
if (is_array($publish_timestamp)) {
$conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp[0]);
$conditions['AND'][] = array('Event.publish_timestamp <=' => $publish_timestamp[1]);
} else {
$conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp);
}
}
if ($timestamp) {
if (is_array($timestamp)) {
$conditions['AND'][] = array('Event.timestamp >=' => $timestamp[0]);
$conditions['AND'][] = array('Event.timestamp <=' => $timestamp[1]);
} else {
$conditions['AND'][] = array('Event.timestamp >=' => $timestamp);
}
}
if ($publish_timestamp) $conditions = $this->Event->Attribute->setPublishTimestampConditions($publish_timestamp, $conditions);
if ($timestamp) $conditions = $this->Event->Attribute->setTimestampConditions($timestamp, $conditions);
if ($last) $conditions['AND'][] = array('Event.publish_timestamp >=' => $last);
if ($published) $conditions['AND'][] = array('Event.published' => $published);
$params = array(
@ -2631,56 +2540,48 @@ class EventsController extends AppController {
}
}
$this->loadModel('Whitelist');
if ((!isset($this->request->params['ext']) || $this->request->params['ext'] !== 'json') && $this->response->type() !== 'application/json') {
App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
$final = "";
$final .= '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
foreach ($eventIds as $currentEventId) {
$result = $this->Event->fetchEvent($this->Auth->user(), array(
'eventid' => $currentEventId,
'includeAttachments' => $withAttachments,
'metadata' => $metadata,
'enforceWarninglist' => $enforceWarninglist
));
if (!empty($result)) {
$result = $this->Whitelist->removeWhitelistedFromArray($result, false);
$final .= $converter->event2XML($result[0]) . PHP_EOL;
}
}
$final .= '</response>' . PHP_EOL;
if (isset($eventid) && $eventid) {
$final_filename="misp.event." . $eventid . "." . $result[0]['Event']['uuid'] . ".xml";
} else {
$final_filename="misp.search.events.results.xml";
}
$this->response->body($final);
$this->response->type('xml');
$this->response->download($final_filename);
$responseType = 'xml';
$converters = array(
'xml' => 'XMLConverterTool',
'json' => 'JSONConverterTool',
'openioc' => 'IOCExportTool'
);
if (in_array($key, array('json', 'xml', 'openioc'))) {
$responseType = $key;
} else if (((isset($this->request->params['ext']) && $this->request->params['ext'] == 'xml')) || $this->response->type() == 'application/xml') {
$responseType = 'xml';
} else {
App::uses('JSONConverterTool', 'Tools');
$converter = new JSONConverterTool();
$final = '{"response":[';
foreach ($eventIds as $k => $currentEventId) {
$result = $this->Event->fetchEvent($this->Auth->user(), array(
'eventid' => $currentEventId,
'includeAttachments' => $withAttachments,
'metadata' => $metadata,
'enforceWarninglist' => $enforceWarninglist
));
$final .= $converter->event2JSON($result[0]);
if ($k < count($eventIds) -1 ) $final .= ',';
}
$final .= ']}';
if (isset($eventid) && $eventid) {
$final_filename="misp.event." . $eventid . "." . $result[0]['Event']['uuid'] . ".json";
} else {
$final_filename="misp.search.events.results.json";
}
$this->response->body($final);
$this->response->type('json');
$this->response->download($final_filename);
$responseType = 'json';
}
App::uses($converters[$responseType], 'Tools');
$converter = new $converters[$responseType]();
$final = $converter->generateTop($this->Auth->user());
foreach ($eventIds as $currentEventId) {
$result = $this->Event->fetchEvent($this->Auth->user(), array(
'eventid' => $currentEventId,
'includeAttachments' => $withAttachments,
'metadata' => $metadata,
'enforceWarninglist' => $enforceWarninglist
));
if (!empty($result)) {
$result = $this->Whitelist->removeWhitelistedFromArray($result, false);
$final .= $converter->convert($result[0]);
}
}
$final .= $converter->generateBottom($responseType, $final);
$extension = $responseType;
if ($key == 'openioc') {
$extension = '.ioc';
}
if (isset($eventid) && $eventid) {
$final_filename="misp.event." . $eventid . "." . $result[0]['Event']['uuid'] . '.' . $extension;
} else {
$final_filename="misp.search.events.results." . $extension;
}
$this->response->type($responseType);
$this->autoRender = false;
$this->response->body($final);
$this->response->download($final_filename);
return $this->response;
}
@ -2690,8 +2591,6 @@ class EventsController extends AppController {
$this->response->type('text'); // set the content type
if ($eventid == null) {
throw new Exception('Not yet implemented');
} else {
$this->header('Content-Disposition: download; filename="misp.openIOC' . $eventid . '.ioc"');
}
$this->layout = 'text/default';
@ -2718,8 +2617,14 @@ class EventsController extends AppController {
$event = $temp[0];
// send the event and the vars needed to check authorisation to the Component
App::uses('IOCExportTool', 'Tools');
$this->IOCExport = new IOCExportTool();
$final = $this->IOCExport->buildAll($this->Auth->user(), $event);
$this->set('final', $final);
$this->response->type('xml');
$this->autoRender = false;
$this->response->body($final);
$this->response->download('misp.openIOC' . $eventid . '.ioc');
return $this->response;
}
public function create_dummy_event() {

View File

@ -1,4 +1,4 @@
<?php
<?php
App::uses('AppController', 'Controller');
class UsersController extends AppController {

View File

@ -0,0 +1,56 @@
<?php
class CIDRTool {
function CIDR($cidr) {
list($address, $prefix) = explode('/', $cidr, 2);
$address = decbin(ip2long($address));
$address = substr("00000000000000000000000000000000",0,32 - strlen($address)) . $address;
$min = '';
$max = '';
for ($i = 0; $i < $prefix; $i++) {
$min .= $address[$i];
}
$max = $min;
$min = str_pad($min, 32, '0', STR_PAD_RIGHT);
$max = str_pad($max, 32, '1', STR_PAD_RIGHT);
$minArray = array();
$maxArray = array();
$searchTermLeft = '';
$searchTermMin = 0;
$searchTermMax = 0;
$results = array();
for ($i = 0; $i < 4; $i++) {
$minArray[] = bindec(substr($min, ($i*8), 8));
$maxArray[] = bindec(substr($max, ($i*8), 8));
if ($minArray[$i] === $maxArray[$i]) $searchTermLeft .= $minArray[$i] . '.';
else {
$searchTermMin = $minArray[$i];
$searchTermMax = $maxArray[$i];
break;
}
}
$length = $i;
for ($i = 0; $i < ($searchTermMax - $searchTermMin + 1); $i++) {
$results[$i] = $searchTermLeft . ($searchTermMin + $i);
if ($length < 3) $results[$i] .= '.%';
}
return $results;
}
function checkCIDR($cidr, $ipVersion) {
if (strpos($cidr, '/') === FALSE || substr_count($cidr, '/') !== 1) {
return false;
}
list($net, $maskbits) = explode('/', $cidr);
if (!is_numeric($maskbits) || $maskbits < 0) {
return false;
}
if ($ipVersion == 4) {
return ($maskbits <= 32) && filter_var($net, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
} else if ($ipVersion == 6) {
return ($maskbits <= 128) && filter_var($net, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
} else {
throw new InvalidArgumentException('checkCIDR does only support IPv4 & IPv6');
}
}
}

View File

@ -0,0 +1,158 @@
<?php
class IOCExportTool {
public function buildAll($user, $data, $scope = 'event') {
$final = '';
if (!isset($data['Attribute'])) {
$data = array('Attribute' => $data);
}
if ($scope == 'event') {
$final = $this->generateSingleTop($data);
} else {
$final = $this->generateTop($user, $data);
}
foreach ($data['Attribute'] as $attribute) {
$final .= $this->generateAttribute($attribute);
}
$final .= $this->generateBottom();
return $final;
}
public function convert($data) {
$final = '';
foreach ($data['Attribute'] as $attribute) {
$final .= $this->generateAttribute($attribute);
}
return $final;
}
public function getResult() {
return $this->__final;
}
// generates the top with the event information
public function generateSingleTop($event) {
// We will start adding all the components that will be in the xml file here
$temp = '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL;
$temp .= '<ioc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="' . $event['Event']['uuid'] . '" last-modified="' . $event['Event']['date'] . 'T00:00:00" xmlns="http://schemas.mandiant.com/2010/ioc">' . PHP_EOL;
$temp .= ' <short_description>Event #' . h($event['Event']['id']) . '</short_description>' . PHP_EOL;
$temp .= ' <description>' . h($event['Event']['info']) . ' (' . h($event['Event']['uuid']) . ')</description>' . PHP_EOL;
$temp .= ' <keywords />' . PHP_EOL;
$temp .= ' <authored_by>' . h($event['Orgc']['name']) . '</authored_by>' . PHP_EOL;
$temp .= ' <authored_date>' . h($event['Event']['date']) . 'T00:00:00</authored_date>' . PHP_EOL;
$temp .= ' <links />' . PHP_EOL;
$temp .= ' <definition>' . PHP_EOL;
$temp .= ' <Indicator operator="OR" id="' . CakeText::uuid() . '">' . PHP_EOL;
return $temp;
}
public function generateTop($user) {
$temp = '';
// We will start adding all the components that will be in the xml file here
$date = date("Y-m-d\Th:i:s");
$temp .= '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL;
$temp .= '<ioc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="' . CakeText::uuid() . '" last-modified="' . $date . '" xmlns="http://schemas.mandiant.com/2010/ioc">' . PHP_EOL;
$temp .= ' <short_description>Filtered indicator list</short_description>' . PHP_EOL;
$temp .= ' <description>Filtered indicator list</description>' . PHP_EOL;
$temp .= ' <keywords />' . PHP_EOL;
$temp .= ' <authored_by>' . h($user['Organisation']['name']) . '</authored_by>' . PHP_EOL;
$temp .= ' <authored_date>' . $date . '</authored_date>' . PHP_EOL;
$temp .= ' <links />' . PHP_EOL;
$temp .= ' <definition>' . PHP_EOL;
$temp .= ' <Indicator operator="OR" id="' . CakeText::uuid() . '">' . PHP_EOL;
return $temp;
}
public $mapping = array(
'composite' => array(
'regkey|value' => array(array('Network', 'RegistryItem/KeyPath', 'string'), array('Network', 'RegistryItem/Value', 'string')),
'filename|md5' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Md5sum', 'md5')),
'filename|sha1' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Sha1sum', 'sha1')),
'filename|sha256' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Sha256sum', 'sha256')),
'malware-sample' => array(array('FileItem', 'FileItem/FileName', 'string'), array('FileItem', 'FileItem/Md5sum', 'md5')),
'domain|ip' => array(array('Network', 'Network/DNS', 'string'), array('PortItem', 'PortItem/remoteIP', 'IP')),
),
'simple' => array(
'md5' => array('FileItem', 'FileItem/Md5sum', 'md5'),
'sha1' => array('FileItem', 'FileItem/Sha1sum', 'sha1'),
'sha256' => array('FileItem', 'FileItem/Sha256sum', 'sha256'),
'filename' => array('FileItem', 'FileItem/FileName', 'string'),
'ip-src' => array('PortItem', 'PortItem/remoteIP', 'IP'),
'ip-dst' => array('RouteEntryItem', 'RouteEntryItem/Destination', 'IP'),
'hostname' => array('RouteEntryItem', 'RouteEntryItem/Destination', 'string'),
'email-src' => array('Email', 'Email/From', 'string'),
'email-dst' => array('Email', 'Email/To', 'string'),
'email-subject' => array('Email', 'Email/Subject', 'string'),
'email-attachment' => array('Email', 'Email/Attachment/Name', 'string'),
'domain' => array('Network', 'Network/DNS', 'string'),
'url' => array('UrlHistoryItem', 'UrlHistoryItem/URL', 'string'),
'user-agent' => array('Network', 'Network/UserAgent', 'string'),
'regkey' => array('Network', 'RegistryItem/KeyPath', 'string'),
'snort' => array('Snort', 'Snort/Snort', 'string'),
'attachment' => array('FileItem', 'FileItem/FileName', 'string'),
'link' => array('URL', 'UrlHistoryItem/URL', 'md5')
)
);
public function frameComposite($attribute) {
$temp = '';
$values = explode('|', $attribute['value']);
$temp .= ' <Indicator operator="AND" id="' . h($attribute['uuid']) . '">' . PHP_EOL;
$temp .= $this->frameIndicator($this->mapping['composite'][$attribute['type']][0], $attribute['uuid'], $values[0], true);
$temp .= $this->frameIndicator($this->mapping['composite'][$attribute['type']][1], $attribute['uuid'], $values[1], true);
$temp .= ' </Indicator>' . PHP_EOL;
return $temp;
}
public function frameIndicator($mapping, $uuid, $value, $extraIndent = false) {
$temp = '';
$padding = 6;
if ($extraIndent) {
$padding = 8;
}
$temp .= str_repeat(' ', $padding) . '<IndicatorItem id="' . h($uuid) . '" condition="is">' . PHP_EOL;
$temp .= str_repeat(' ', ($padding + 2)) . '<Context document="' . $mapping[0] . '" search="' . $mapping[1] . '" type="mir" />' . PHP_EOL;
$temp .= str_repeat(' ', ($padding + 2)) . '<Content type="' . $mapping[2] . '">' . h($value) . '</Content>' . PHP_EOL;
$temp .= str_repeat(' ', $padding) . '</IndicatorItem>' . PHP_EOL;
return $temp;
}
// This method will turn each eligible attribute into an indicator
public function generateAttribute($attribute) {
$temp = '';
if (isset($attribute['Attribute'])) {
$attribute = $attribute['Attribute'];
}
// Hop over attributes that don't have the to ids flag turned on and check whether the attribute is sent for IOC export based on category/type
if (!$this->checkValidTypeForIOC($attribute) || $attribute['to_ids'] == 0) return false;
if ($attribute['type'] == 'malware-sample') $attribute['type'] = 'filename|md5';
if (strpos($attribute['type'], '|')) {
if ($this->mapping['composite'][$attribute['type']]) {
$temp .= $this->frameComposite($attribute);
}
} else {
if (isset($this->mapping['simple'][$attribute['type']])) {
$temp .= $this->frameIndicator($this->mapping['simple'][$attribute['type']], $attribute['uuid'], $attribute['value'], false);
}
}
return $temp;
}
// Just closing some tags at the bottom of the .ioc file
public function generateBottom() {
$temp = '';
$temp .= ' </Indicator>' . PHP_EOL;
$temp .= ' </definition>' . PHP_EOL;
$temp .= '</ioc>' . PHP_EOL;
return $temp;
}
// Simple check for valid categories and types for IOC generation
public function checkValidTypeForIOC($attribute) {
// categories that should be included
$Category = array('Payload delivery', 'Artifacts dropped', 'Payload installation', 'Persistence mechanism', 'Network activity');
if (!in_array($attribute['category'], $Category)) return false;
return true;
}
}

View File

@ -1,6 +1,15 @@
<?php
class JSONConverterTool {
public function event2JSON($event, $isSiteAdmin=false) {
public function generateTop() {
return '{"response":[';
}
public function generateBottom() {
return ']}' . PHP_EOL;
}
public function convert($event, $isSiteAdmin=false) {
$toRearrange = array('Org', 'Orgc', 'SharingGroup', 'Attribute', 'ShadowAttribute', 'RelatedAttribute', 'RelatedEvent', 'Galaxy');
foreach ($toRearrange as $object) {
if (isset($event[$object])) {
@ -15,7 +24,7 @@ class JSONConverterTool {
$event['Event']['Tag'][$k] = $tag['Tag'];
}
}
//
// cleanup the array from things we do not want to expose
//
@ -84,7 +93,7 @@ class JSONConverterTool {
public function eventCollection2Format($events, $isSiteAdmin=false) {
$results = array();
foreach ($events as $event) $results[] = $this->event2JSON($event, $isSiteAdmin);
foreach ($events as $event) $results[] = $this->convert($event, $isSiteAdmin);
return implode(',' . PHP_EOL, $results);
}

View File

@ -63,7 +63,7 @@ class PubSubTool {
$settings = $this->__setupPubServer();
App::uses('JSONConverterTool', 'Tools');
$jsonTool = new JSONConverterTool();
$json = $jsonTool->event2JSON($event);
$json = $jsonTool->convert($event);
$redis = new Redis();
$redis->connect($settings['redis_host'], $settings['redis_port']);
$redis->select($settings['redis_database']);

View File

@ -4,6 +4,14 @@ class XMLConverterTool {
private $__toEscape = array("&", "<", ">", "\"", "'");
private $__escapeWith = array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;');
public function generateTop() {
return '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
}
public function generateBottom() {
return '</response>' . PHP_EOL;
}
public function recursiveEcho($array) {
$text = "";
if (is_array($array)) foreach ($array as $k => $v) {
@ -27,7 +35,7 @@ class XMLConverterTool {
return $text;
}
public function event2xmlArray($event, $isSiteAdmin=false) {
public function convertArray($event, $isSiteAdmin=false) {
$event['Event']['Org'][0] = $event['Org'];
$event['Event']['Orgc'][0] = $event['Orgc'];
if (isset($event['SharingGroup']['SharingGroupOrg'])) {
@ -157,8 +165,8 @@ class XMLConverterTool {
return $result;
}
public function event2XML($event, $isSiteAdmin=false) {
$xmlArray = $this->event2xmlArray($event, $isSiteAdmin);
public function convert($event, $isSiteAdmin=false) {
$xmlArray = $this->convertArray($event, $isSiteAdmin);
$result = array('Event' => array(0 => $xmlArray['Event']));
if (isset($xmlArray['errors']) && !empty($xmlArray['errors'])) $result['errors'] = array($xmlArray['errors']);
return $this->recursiveEcho($result);
@ -171,7 +179,7 @@ class XMLConverterTool {
public function eventCollection2Format($events, $isSiteAdmin=false) {
$result = "";
foreach ($events as $event) $result .= $this->event2XML($event) . PHP_EOL;
foreach ($events as $event) $result .= $this->convert($event) . PHP_EOL;
return $result;
}

View File

@ -74,6 +74,24 @@ class Attribute extends AppModel {
'nationality'
);
public $searchResponseTypes = array(
'xml' => array(
'type' => 'xml',
'layout' => 'xml/default',
'header' => 'Content-Disposition: download; filename="misp.search.attribute.results.xml"'
),
'json' => array(
'type' => 'json',
'layout' => 'json/default',
'header' => 'Content-Disposition: download; filename="misp.search.attribute.results.json"'
),
'openioc' => array(
'type' => 'xml',
'layout' => 'xml/default',
'header' => 'Content-Disposition: download; filename="misp.search.attribute.results.openioc.xml"'
),
);
public $typeDefinitions = array(
'md5' => array('desc' => 'A checksum in md5 format', 'formdesc' => "You are encouraged to use filename|md5 instead. A checksum in md5 format, only use this if you don't know the correct filename", 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha1' => array('desc' => 'A checksum in sha1 format', 'formdesc' => "You are encouraged to use filename|sha1 instead. A checksum in sha1 format, only use this if you don't know the correct filename", 'default_category' => 'Payload delivery', 'to_ids' => 1),
@ -2320,4 +2338,111 @@ class Attribute extends AppModel {
}
return true;
}
public function convertToOpenIOC($user, $attributes) {
return $this->IOCExport->buildAll($this->Auth->user(), $event);
}
public function setTagConditions($tags, $conditions) {
$args = $this->dissectArgs($tags);
$tagArray = $this->AttributeTag->Tag->fetchEventTagIds($args[0], $args[1]);
$temp = array();
foreach ($tagArray[0] as $accepted) {
$temp['OR'][] = array('Event.id' => $accepted);
}
$conditions['AND'][] = $temp;
$temp = array();
foreach ($tagArray[1] as $rejected) {
$temp['AND'][] = array('Event.id !=' => $rejected);
}
$conditions['AND'][] = $temp;
return $conditions;
}
public function setPublishTimestampConditions($publish_timestamp, $conditions) {
if (is_array($publish_timestamp)) {
$conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp[0]);
$conditions['AND'][] = array('Event.publish_timestamp <=' => $publish_timestamp[1]);
} else {
$conditions['AND'][] = array('Event.publish_timestamp >=' => $publish_timestamp);
}
return $conditions;
}
public function setTimestampConditions($timestamp, $conditions, $scope = 'Event') {
if (is_array($timestamp)) {
$conditions['AND'][] = array($scope . '.timestamp >=' => $timestamp[0]);
$conditions['AND'][] = array($scope . '.timestamp <=' => $timestamp[1]);
} else {
$conditions['AND'][] = array($scope . '.timestamp >=' => $timestamp);
}
return $conditions;
}
public function setToIDSConditions($to_ids, $conditions) {
if ($to_ids === 'exclude') {
$conditions['AND'][] = array('Attribute.to_ids' => 0);
} else {
$conditions['AND'][] = array('Attribute.to_ids' => 1);
}
return $conditions;
}
public function setSimpleConditions($parameterKey, $parameterValue, $conditions) {
$subcondition = array();
App::uses('CIDRTool', 'Tools');
$cidr = new CIDRTool();
if (is_array($parameterValue)) $elements = $parameterValue;
else $elements = explode('&&', $parameterValue);
foreach ($elements as $v) {
if (empty($v)) continue;
if (substr($v, 0, 1) == '!') {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameterKey === 'value' && $cidr->checkCIDR(substr($v, 1), 4)) {
$cidrresults = $cidr->CIDR(substr($v, 1));
foreach ($cidrresults as $result) {
$subcondition['AND'][] = array('Attribute.value NOT LIKE' => $result);
}
} else if ($parameterKey === 'org') {
// from here
$found_orgs = $this->Event->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower(substr($v, 1)) . '%'),
));
foreach ($found_orgs as $o) $subcondition['AND'][] = array('Event.orgc_id !=' => $o['Org']['id']);
} else if ($parameterKey === 'eventid') {
$subcondition['AND'][] = array('Attribute.event_id !=' => substr($v, 1));
} else if ($parameterKey === 'uuid') {
$subcondition['AND'][] = array('Event.uuid !=' => substr($v, 1));
$subcondition['AND'][] = array('Attribute.uuid !=' => substr($v, 1));
} else {
$subcondition['AND'][] = array('Attribute.' . $parameterKey . ' NOT LIKE' => '%'.substr($v, 1).'%');
}
} else {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameterKey === 'value' && $cidr->checkCIDR($v, 4)) {
$cidrresults = $cidr->CIDR($v);
foreach ($cidrresults as $result) {
$subcondition['OR'][] = array('Attribute.value LIKE' => $result);
}
} else if ($parameterKey === 'org') {
// from here
$found_orgs = $this->Event->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower($v) . '%'),
));
foreach ($found_orgs as $o) $subcondition['OR'][] = array('Event.orgc_id' => $o['Org']['id']);
} else if ($parameterKey === 'eventid') {
if (!empty($v)) $subcondition['OR'][] = array('Attribute.event_id' => $v);
} else if ($parameterKey === 'uuid') {
$subcondition['OR'][] = array('Attribute.uuid' => $v);
$subcondition['OR'][] = array('Event.uuid' => $v);
} else {
if (!empty($v)) $subcondition['OR'][] = array('Attribute.' . $parameterKey . ' LIKE' => '%'.$v.'%');
}
}
}
array_push ($conditions['AND'], $subcondition);
return $conditions;
}
}

View File

@ -3267,4 +3267,71 @@ class Event extends AppModel {
}
return array('data' => array(), 'csv' => array());
}
public function setSimpleConditions($parameterKey, $parameterValue, $conditions) {
if (is_array($parameterValue)) {
$elements = $parameterValue;
} else {
$elements = explode('&&', $parameterValue);
}
App::uses('CIDRTool', 'Tools');
$cidr = new CIDRTool();
$subcondition = array();
foreach ($elements as $v) {
if ($v == '') continue;
if (substr($v, 0, 1) == '!') {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameterKey === 'value' && $cidr->checkCIDR(substr($v, 1), 4)) {
$cidrresults = $cidr->CIDR(substr($v, 1));
foreach ($cidrresults as $result) {
$subcondition['AND'][] = array('Attribute.value NOT LIKE' => $result);
}
} else {
if ($parameterKey === 'org') {
$found_orgs = $this->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower(substr($v, 1)) . '%'),
));
foreach ($found_orgs as $o) {
$subcondition['AND'][] = array('Event.orgc_id !=' => $o['Org']['id']);
}
} else if ($parameterKey === 'eventid') {
$subcondition['AND'][] = array('Attribute.event_id !=' => substr($v, 1));
} else if ($parameterKey === 'uuid') {
$subcondition['AND'][] = array('Event.uuid !=' => substr($v, 1));
$subcondition['AND'][] = array('Attribute.uuid !=' => substr($v, 1));
} else {
$subcondition['AND'][] = array('Attribute.' . $parameterKey . ' NOT LIKE' => '%'.substr($v, 1).'%');
}
}
} else {
// check for an IPv4 address and subnet in CIDR notation (e.g. 127.0.0.1/8)
if ($parameterKey === 'value' && $cidr->checkCIDR($v, 4)) {
$cidrresults = $cidr->CIDR($v);
foreach ($cidrresults as $result) {
if (!empty($result)) $subcondition['OR'][] = array('Attribute.value LIKE' => $result);
}
} else {
if ($parameterKey === 'org') {
$found_orgs = $this->Org->find('all', array(
'recursive' => -1,
'conditions' => array('LOWER(name) LIKE' => '%' . strtolower($v) . '%'),
));
foreach ($found_orgs as $o) {
$subcondition['OR'][] = array('Event.orgc_id' => $o['Org']['id']);
}
} else if ($parameterKey === 'eventid') {
$subcondition['OR'][] = array('Attribute.event_id' => $v);
} else if ($parameterKey === 'uuid') {
$subcondition['OR'][] = array('Attribute.uuid' => $v);
$subcondition['OR'][] = array('Event.uuid' => $v);
}else {
if (!empty($v)) $subcondition['OR'][] = array('Attribute.' . $parameterKey . ' LIKE' => '%'.$v.'%');
}
}
}
}
if (!empty($subcondition)) array_push ($conditions['AND'], $subcondition);
return $conditions;
}
}

View File

@ -1,4 +1,4 @@
<?php
App::uses('JSONConverterTool', 'Tools');
$converter = new JSONConverterTool();
echo $converter->event2JSON($event);
echo $converter->convert($event);

View File

@ -3,7 +3,7 @@ App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
foreach ($results as $event) {
echo $converter->event2XML($event) . PHP_EOL;
echo $converter->convert($event) . PHP_EOL;
}
echo '<xml_version>' . $mispVersion . '</xml_version>';
echo '</response>' . PHP_EOL;

View File

@ -3,7 +3,7 @@ App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
foreach ($results as $event) {
echo $converter->event2XML($event) . PHP_EOL;
echo $converter->convert($event) . PHP_EOL;
}
echo '<xml_version>' . $mispVersion . '</xml_version>';
echo '</response>' . PHP_EOL;

View File

@ -2,6 +2,6 @@
App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
echo $converter->event2XML($event) . PHP_EOL;
echo $converter->convert($event) . PHP_EOL;
echo '<xml_version>' . $mispVersion . '</xml_version>';
echo '</response>' . PHP_EOL;

View File

@ -3,7 +3,7 @@ App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
foreach ($results as $event) {
echo $converter->event2XML($event) . PHP_EOL;
echo $converter->convert($event) . PHP_EOL;
}
echo '<xml_version>' . $mispVersion . '</xml_version>';
echo '</response>' . PHP_EOL;

View File

@ -2,6 +2,6 @@
App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
echo $converter->event2XML($event) . PHP_EOL;
echo $converter->convert($event) . PHP_EOL;
echo '<xml_version>' . $mispVersion . '</xml_version>';
echo '</response>' . PHP_EOL;

View File

@ -3,7 +3,7 @@ App::uses('XMLConverterTool', 'Tools');
$converter = new XMLConverterTool();
echo '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
foreach ($results as $event) {
echo $converter->event2XML($event) . PHP_EOL;
echo $converter->convert($event) . PHP_EOL;
}
echo '<xml_version>' . $mispVersion . '</xml_version>';
echo '</response>' . PHP_EOL;