Merge branch '2.4' into 1501

pull/1544/head
iglocska 2016-09-18 11:07:10 +02:00
commit a599ec24f7
39 changed files with 469 additions and 151 deletions

1
.gitignore vendored
View File

@ -61,3 +61,4 @@
/app/tmp/cached_exports/csv_all/*
/app/tmp/cached_exports/csv_sig/*
*.swp
*.iml

View File

@ -327,6 +327,31 @@ class EventShell extends AppShell
$this->Job->saveField('date_modified', date("y-m-d H:i:s"));
}
public function cachebro()
{
$broHeader = "#fields indicator\tindicator_type\tmeta.source\tmeta.url\tmeta.do_notice\tmeta.if_in\n";
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
$id = $this->args[1];
$this->Job->id = $id;
$format = $this->args[2];
$this->Job->saveField('progress', 1);
$types = array('ip', 'email', 'domain', 'filename', 'filehash', 'certhash', 'software', 'url'); //Bro types
$typeCount = count($types);
$dir = new Folder(APP . DS . '/tmp/cached_exports/' . $format, true, 0750);
if ($user['Role']['perm_site_admin']) {
$zipname = DS . 'misp.bro.ADMIN.intel.zip';
} else {
$zipname = DS . 'misp.bro.' . $user['Organisation']['name'] . '.intel.zip';
}
$tmpZipname = $this->Attribute->brozip($user, false, false, false, false, false, false, $id);
rename($tmpZipname[0] . $tmpZipname[1], $dir->pwd() . $zipname);
$folder = new Folder($tmpZipname[0]);
$folder->delete();
$this->Job->saveField('progress', 100);
$this->Job->saveField('message', 'Job done.');
}
public function alertemail() {
$userId = $this->args[0];
$processId = $this->args[1];

View File

@ -1089,7 +1089,7 @@ class AttributesController extends AppController {
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
// reset the paginate_conditions
$this->Session->write('paginate_conditions',array());
if ($this->request->is('post') && ($this->request->here == $fullAddress)) {
if ($this->request->is('post')) {
$keyword = $this->request->data['Attribute']['keyword'];
$keyword2 = $this->request->data['Attribute']['keyword2'];
$tags = $this->request->data['Attribute']['tags'];
@ -1850,6 +1850,61 @@ class AttributesController extends AppController {
$this->render('/Attributes/rpz');
}
public function bro($key='download', $type='all', $tags=false, $eventId=false, $allowNonIDS=false, $from=false, $to=false, $last=false) {
if ($this->request->is('post')) {
if ($this->request->input('json_decode', true)) {
$data = $this->request->input('json_decode', true);
} else {
$data = $this->request->data;
}
if (!empty($data) && !isset($data['request'])) {
$data = array('request' => $data);
}
$paramArray = array('type', 'tags', 'eventId', 'allowNonIDS', 'from', 'to', 'last');
foreach ($paramArray as $p) {
if (isset($data['request'][$p])) ${$p} = $data['request'][$p];
}
}
$simpleFalse = array('type', 'tags', 'eventId', 'allowNonIDS', 'from', 'to', 'last');
foreach ($simpleFalse as $sF) {
if (!is_array(${$sF}) && (${$sF} === 'null' || ${$sF} == '0' || ${$sF} === false || strtolower(${$sF}) === 'false')) ${$sF} = false;
}
if ($type !== 'null' || $type !== '0' || $type !== 'false') {
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 ($key != 'download') {
// check if the key is valid -> search for users based on key
$user = $this->checkAuthUser($key);
if (!$user) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
} else {
if (!$this->Auth->user('id')) {
throw new UnauthorizedException('You have to be logged in to do that.');
}
}
$filename = 'misp.' . $type . '.intel';
if ($eventId) {
$filename = 'misp.' . $type . '.event_' . $eventId . '.intel';
}
if ($type != 'all') {
$responseFile = implode(PHP_EOL, $this->Attribute->bro($this->Auth->user(), $type, $tags, $eventId, $allowNonIDS, $from, $to, $last)) . PHP_EOL;
$this->response->body($responseFile);
$this->response->type('txt');
} else {
$tmpZipname = $this->Attribute->brozip($this->Auth->user(), $tags, $eventId, $allowNonIDS, $from, $to, $last);
$this->response->body(file_get_contents($tmpZipname[0] . $tmpZipname[1]));
$this->response->type('zip');
$folder = new Folder($tmpZipname[0]);
$folder->delete();
$filename .= '.zip';
}
$this->response->download($filename);
return $this->response;
}
}
public function reportValidationIssuesAttributes($eventId = false) {
// TODO improve performance of this function by eliminating the additional SQL query per attribute
// search for validation problems in the attributes

View File

@ -61,7 +61,6 @@ class IOCExportComponent extends Component {
);
private function __frameComposite($attribute) {
$types = explode('|', $attribute['type']);
$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);
@ -70,7 +69,6 @@ class IOCExportComponent extends Component {
}
private function __frameIndicator($mapping, $uuid, $value, $extraIndent = false) {
$indent = " ";
$padding = 6;
if ($extraIndent) {
$padding = 8;

View File

@ -4,10 +4,6 @@ App::uses('AppController', 'Controller');
class EventDelegationsController extends AppController {
public $components = array('Session', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.

View File

@ -1483,6 +1483,17 @@ class EventsController extends AppController {
if (!$this->userRole['perm_auth']) {
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
App::uses('BroExport', 'Export');
$export = new BroExport();
$temp = $export->mispTypes;
$broTypes = array('all' => 'All types listed below.');
foreach ($temp as $broType => $mispTypes) {
foreach ($mispTypes as $mT) {
$broTypes[$broType][] = $mT[0];
}
$broTypes[$broType] = implode(', ', $broTypes[$broType]);
}
$this->set('broTypes', $broTypes);
// generate the list of Attribute types
$this->loadModel('Attribute');
$this->set('sigTypes', array_keys($this->Attribute->typeDefinitions));
@ -1719,7 +1730,6 @@ class EventsController extends AppController {
if ($last) $last = $this->Event->resolveTimeDelta($last);
// backwards compatibility, swap key and format
if ($format != 'snort' && $format != 'suricata') {
$key = $format;
$format = 'suricata'; // default format
}
$this->response->type('txt'); // set the content type
@ -3150,6 +3160,12 @@ class EventsController extends AppController {
'requiresPublished' => true,
'checkbox' => false,
),
'bro' => array(
'url' => '/attributes/bro/download/all/false/' . $id,
'text' => 'Download Bro rules',
'requiresPublished' => true,
'checkbox' => false
),
'text' => array(
'url' => '/attributes/text/download/all/false/' . $id,
'text' => 'Export all attribute values as a text file',

View File

@ -4,10 +4,6 @@ App::uses('AppController', 'Controller');
class FavouriteTagsController extends AppController {
public $components = array('Session', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.

View File

@ -12,10 +12,6 @@ class JobsController extends AppController {
),
);
public function beforeFilter() {
parent::beforeFilter();
}
public function index($queue = false) {
if (!$this->_isSiteAdmin()) throw new MethodNotAllowedException();
if (!Configure::read('MISP.background_jobs')) throw new NotFoundException('Background jobs are not enabled on this instance.');

View File

@ -4,10 +4,6 @@ App::uses('AppController', 'Controller');
class NewsController extends AppController {
public $components = array('Session', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
}
public $paginate = array(
'limit' => 5,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
@ -17,7 +13,6 @@ class NewsController extends AppController {
);
public function index() {
$this->News->bindModel(array('belongsTo' => array('User' => array('className' => 'User'))));
$this->paginate['contain'] = array('User' => array('fields' => array('User.email')));
$newsItems = $this->paginate();
$this->loadModel('User');

View File

@ -20,10 +20,6 @@ class PostsController extends AppController {
'limit' => 60,
);
public function beforeFilter() {
parent::beforeFilter();
}
// Find the thread_id and post_id in advance. If a user clicks post comment on the event view, send the event's related thread's ID
// Usage:
// /posts/add : Creates new thread with the added post as the first post. Title set by user

View File

@ -13,10 +13,6 @@ class RegexpController extends AppController {
)
);
public function beforeFilter() {
parent::beforeFilter();
}
public function admin_add() {
$this->loadModel('Attribute');
$types = array_keys($this->Attribute->typeDefinitions);

View File

@ -26,10 +26,6 @@ class RolesController extends AppController {
)
);
public function beforeFilter() {
parent::beforeFilter();
}
public function view($id = null) {
$this->Role->id = $id;
if (!$this->Role->exists()) {

View File

@ -23,10 +23,6 @@ class TagsController extends AppController {
public $helpers = array('TextColour');
public function beforeFilter() { // TODO REMOVE
parent::beforeFilter();
}
public function index($favouritesOnly = false) {
$this->loadModel('Event');
$this->loadModel('Taxonomy');
@ -258,12 +254,6 @@ class TagsController extends AppController {
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
));
$this->set('tags', $tags);
$tags = $this->Tag->find('all', array('recursive' => -1, 'order' => array('Tag.name ASC')));
$tagNames = array('None');
foreach ($tags as $k => $v) {
$tagNames[$v['Tag']['id']] = $v['Tag']['name'];
}
$this->set('allTags', $tagNames);
$event = $this->Tag->EventTag->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'),

View File

@ -12,10 +12,6 @@ class TasksController extends AppController {
)
);
public function beforeFilter() {
parent::beforeFilter();
}
public function index() {
if (!$this->_isSiteAdmin()) throw new MethodNotAllowedException();
if (!Configure::read('MISP.background_jobs')) throw new NotFoundException('Background jobs are not enabled on this instance.');

View File

@ -4,10 +4,6 @@ App::uses('AppController', 'Controller');
class TaxonomiesController extends AppController {
public $components = array('Session', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.

View File

@ -16,10 +16,6 @@ class ThreadsController extends AppController {
'limit' => 60,
);
public function beforeFilter() {
parent::beforeFilter();
}
public function viewEvent($id) {
$this->loadModel('Event');
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id));

View File

@ -4,10 +4,6 @@ App::uses('AppController', 'Controller');
class WarninglistsController extends AppController {
public $components = array('Session', 'RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.

View File

@ -16,10 +16,6 @@ class WhitelistsController extends AppController {
)
);
public function beforeFilter() { // TODO REMOVE
parent::beforeFilter();
}
public function admin_add() {
if (!$this->userRole['perm_regexp_access']) $this->redirect(array('controller' => 'regexp', 'action' => 'index', 'admin' => false));
$this->AdminCrud->adminAdd();

View File

@ -0,0 +1,170 @@
<?php
class BroExport {
public $rules = array();
public $header = "#fields indicator\tindicator_type\tmeta.source\tmeta.url\tmeta.do_notice\tmeta.if_in";
// mapping from misp attribute type to the bro intel type
// alternative mechanisms are:
// - alternate: array containing a detection regex and a replacement bro type
// - composite: for composite misp attributes (domain|ip), use the provided bro type if the second value is queried
// - replace: run a replacement regex on the value before generating the bro rule
private $mapping = array(
'ip-dst' => array('brotype' => 'ADDR', 'alternate' => array('#/#', 'SUBNET')),
'ip-src' => array('brotype' => 'ADDR', 'alternate' => array('#/#', 'SUBNET')),
'email-src' => array('brotype' => 'EMAIL'),
'email-dst' => array('brotype' => 'EMAIL'),
'email-attachment' => array('brotype' => 'FILE_NAME'),
'filename' => array('brotype' => 'FILE_NAME'),
'hostname' => array('brotype' => 'DOMAIN'),
'domain' => array('brotype' => 'DOMAIN'),
'domain|ip' => array('brotype' => 'DOMAIN', 'composite' => 'ADDR'),
'url' => array('brotype' => 'URL', 'replace' => array('#^https?://#', '')),
'user-agent' => array('brotype' => 'SOFTWARE'),
'md5' => array('brotype' => 'FILE_HASH'),
'malware-sample' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
'filename|md5' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
'sha1' => array('brotype' => 'FILE_HASH'),
'filename|sha1' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
'sha256' => array('brotype' => 'FILE_HASH'),
'filename|sha256' => array('brotype' => 'FILE_NAME', 'composite' => 'FILE_HASH'),
'x509-fingerprint-sha1' => array('brotype' => 'CERT_HASH'),
);
// export group to misp type mapping
// the mapped type is in an array format, first value being the misp type, second being the value field used
public $mispTypes = array(
'ip' => array(
array('ip-src', 1),
array('ip-dst', 1),
array('domain|ip', 2)
),
'url' => array(
array('url', 1)
),
'domain' => array(
array('hostname', 1),
array('domain', 1),
array('domain|ip', 1)
),
'email' => array(
array('email-src', 1),
array('email-dst', 1)
),
'filename' => array(
array('filename', 1),
array('email-attachment', 1),
array('attachment', 1),
array('filename|md5', 1),
array('filename|sha1', 1),
array('filename|sha256', 1),
array('malware-sample', 1)
),
'filehash' => array(
array('md5', 1),
array('sha1', 1),
array('sha256', 1),
array('filename|md5', 2),
array('filename|sha1', 2),
array('filename|sha256', 2),
array('malware-sample', 2)
),
'certhash' => array(
array('x509-fingerprint-sha1', 1)
),
'software' => array(
array('user-agent', 1)
)
);
private $whitelist = null;
public function export($items, $orgs, $valueField, $intel, $whitelist, $instanceString) {
//For bro format organisation
$orgsName = array();
// generate the rules
foreach ($items as $item) {
if (!isset($orgs[$item['Event']['orgc_id']])) {
continue;
} else {
$orgName = $instanceString . ' (' . $item['Event']['uuid'] . ')' . ' - ' . $orgs[$item['Event']['orgc_id']];
}
$ruleFormatReference = Configure::read('MISP.baseurl') . '/events/view/' . $item['Event']['id'];
$ruleFormat = "%s\t%s\t" . $orgName . "\t" . $ruleFormatReference . "\t%s\t%s";
$rule = $this->__generateRule($item['Attribute'], $ruleFormat, $valueField, $whitelist);
if (!empty($rule)) {
if (!in_array($rule, $intel)) {
$intel[] = $rule;
}
}
}
return $intel;
}
private function __generateRule($attribute, $ruleFormat, $valueField, $whitelist) {
if (isset($this->mapping[$attribute['type']])) {
$brotype = $this->mapping[$attribute['type']]['brotype'];
$overruled = $this->checkWhitelist($attribute['value'], $whitelist);
if (isset($this->mapping[$attribute['type']]['alternate'])) {
if (preg_match($this->mapping[$attribute['type']]['alternate'][0], $attribute['value'])) {
$brotype = $this->mapping[$attribute['type']]['alternate'][1];
}
}
if ($valueField == 2 && isset($this->mapping[$attribute['type']]['composite'])) {
$brotype = $this->mapping[$attribute['type']]['composite'];
}
$attribute['value'] = $this->replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
if (isset($this->mapping[$attribute['type']]['replace'])) {
$attribute['value'] = preg_replace(
$this->mapping[$attribute['type']]['replace'][0],
$this->mapping[$attribute['type']]['replace'][1],
$attribute['value']
);
}
return sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' :
$attribute['value'], // value - for composite values only the relevant element is taken
'Intel:' . $brotype, // type
'T', // meta.do_notice
'-' // meta.if_in
);
}
return false;
}
/**
* Replaces characters that are not allowed in a signature.
* example: " is converted to |22|
* @param unknown_type $value
*/
public static function replaceIllegalChars($value) {
$replace_pairs = array(
'|' => '|7c|', // Needs to stay on top !
'"' => '|22|',
';' => '|3b|',
':' => '|3a|',
'\\' => '|5c|',
'0x' => '|30 78|'
);
return strtr($value, $replace_pairs);
}
public function checkWhitelist($value, $whitelist) {
foreach ($whitelist as $wlitem) {
if (preg_match($wlitem, $value)) {
return true;
}
}
return false;
}
public function getMispTypes($type) {
$mispTypes = array();
if (isset($this->mispTypes[$type])) {
$mispTypes = $this->mispTypes[$type];
}
return $mispTypes;
}
}

View File

@ -522,7 +522,6 @@ class Attribute extends AppModel {
$value = $fields['value'];
$eventId = $this->data['Attribute']['event_id'];
$type = $this->data['Attribute']['type'];
$toIds = $this->data['Attribute']['to_ids'];
$category = $this->data['Attribute']['category'];
// check if the attribute already exists in the same event
@ -1411,6 +1410,103 @@ class Attribute extends AppModel {
return $values;
}
function bro($user, $type, $tags = false, $eventId = false, $from = false, $to = false, $last = false) {
//restricting to non-private or same org if the user is not a site-admin.
$conditions['AND'] = array('Attribute.to_ids =' => 1, 'Event.published =' => 1);
if ($from) $conditions['AND']['Event.date >='] = $from;
if ($to) $conditions['AND']['Event.date <='] = $to;
if ($last) $conditions['AND']['Event.publish_timestamp >='] = $last;
if ($eventId !== false) {
$conditions['AND'][] = array('Event.id' => $eventId);
}
else if ($tags !== false) {
// If we sent any tags along, load the associated tag names for each attribute
$tag = ClassRegistry::init('Tag');
$args = $this->dissectArgs($tags);
$tagArray = $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;
}
App::uses('BroExport', 'Export');
$export = new BroExport();
$this->Whitelist = ClassRegistry::init('Whitelist');
$this->whitelist = $this->Whitelist->getBlockedValues();
$instanceString = 'MISP';
if (Configure::read('MISP.host_org_id') && Configure::read('MISP.host_org_id') > 0) {
$this->Event->Orgc->id = Configure::read('MISP.host_org_id');
if ($this->Event->Orgc->exists()) {
$instanceString = $this->Event->Orgc->field('name') . ' MISP';
}
}
$mispTypes = $export->getMispTypes($type);
$intel = array($export->header);
foreach($mispTypes as $mispType) {
$conditions['AND']['Attribute.type'] = $mispType[0];
$intel = $this->__bro($intel, $user, $conditions, $mispType[1], $export, $this->whitelist, $instanceString);
}
return $intel;
}
private function __bro($intel, $user, $conditions, $valueField, $export, $whitelist, $instanceString) {
$attributes = $this->fetchAttributes($user, array(
'conditions' => $conditions, // array of conditions
'order' => 'Attribute.value' . $valueField . ' ASC',
'recursive' => -1, // int
'fields' => array('Attribute.id', 'Attribute.event_id', 'Attribute.type', 'Attribute.value' . $valueField . " as value"),
'contain' => array('Event' => array('fields' => array('Event.id', 'Event.threat_level_id', 'Event.orgc_id', 'Event.uuid'))),
'group' => array('Attribute.type', 'Attribute.value' . $valueField), // fields to GROUP BY
)
);
$orgs = $this->Event->Orgc->find('list', array(
'fields' => array('Orgc.id', 'Orgc.name')
));
return $export->export($attributes, $orgs, $valueField, $intel, $whitelist, $instanceString);
}
public function brozip($user, $tags, $eventId, $allowNonIDS, $from, $to, $last, $jobId = false) {
App::uses('BroExport', 'Export');
$export = new BroExport();
$types = array_keys($export->mispTypes);
$typeCount = count($types);
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
$this->Job->id = $jobId;
if (!$this->Job->exists()) {
$jobId = false;
}
}
$dir = new Folder(APP . 'tmp/files/' . $this->Event->generateRandomFileName(), true, 0750);
$tmpZipname = DS . "bro_export_tmp.zip";
$zip = new File($dir->pwd() . $tmpZipname);
foreach ($types as $k => $type) {
$final = $this->bro($user, $type, $tags, $eventId, $allowNonIDS, $from, $to, $last);
$filename = $type . '.intel';
$file = new File($dir->pwd() . DS . $filename);
$file->write(implode(PHP_EOL, $final));
$file->close();
$execRetval = '';
$execOutput = array();
exec('zip -gj ' . $zip->path . ' ' . $dir->pwd() . '/' . $filename, $execOutput, $execRetval);
if ($execRetval != 0) { // not EXIT_SUCCESS
throw new Exception('An error has occured while attempting to zip the intel files.');
}
$file->delete(); // delete the original non-zipped-file
if ($jobId) {
$this->Job->saveField('progress', $k / $typeCount * 100);
}
}
$zip->close();
return array($dir->pwd(), $tmpZipname);
}
public function generateCorrelation($jobId = false, $startPercentage = 0) {
$this->Correlation = ClassRegistry::init('Correlation');
$this->Correlation->deleteAll(array('id !=' => 0), false);
@ -1696,12 +1792,12 @@ class Attribute extends AppModel {
'recursive' => -1,
'contain' => array(
'Event' => array(
'fields' => array('id', 'info', 'org_id'),
'fields' => array('id', 'info', 'org_id', 'orgc_id'),
),
),
);
if (isset($options['contain'])) $params['contain'] = array_merge_recursive($params['contain'], $options['contain']);
else $option['contain']['Event']['fields'] = array('id', 'info', 'org_id');
else $option['contain']['Event']['fields'] = array('id', 'info', 'org_id', 'orgc_id');
if (isset($options['fields'])) $params['fields'] = $options['fields'];
if (isset($options['conditions'])) $params['conditions']['AND'][] = $options['conditions'];
if (isset($options['order'])) $params['order'] = $options['order'];

View File

@ -97,6 +97,13 @@ class Event extends AppModel {
'canHaveAttachments' => false,
'description' => 'Click this to download all network related attributes that you have access to under the Snort rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a whitelist containing host, domain name and IP numbers to exclude from the NIDS export.',
),
'bro' => array(
'extension' => '.intel.zip',
'type' => 'Bro',
'requiresPublished' => 1,
'canHaveAttachments' => false,
'description' => 'Click this to download all network related attributes that you have access to under the Bro rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a whitelist containing host, domain name and IP numbers to exclude from the NIDS export.',
),
'stix' => array(
'extension' => '.xml',
'type' => 'STIX',

View File

@ -19,18 +19,14 @@ class EventDelegation extends AppModel {
);
public $belongsTo = array(
'Event' => array(
'className' => 'Event',
),
'Event',
'Org' => array(
'className' => 'Organisation',
),
'RequesterOrg' => array(
'className' => 'Organisation'
),
'SharingGroup' => array(
'className' => 'SharingGroup'
)
'SharingGroup'
);
public function attachTagToEvent($event_id, $tag_id) {

View File

@ -19,12 +19,8 @@ class EventTag extends AppModel {
);
public $belongsTo = array(
'Event' => array(
'className' => 'Event',
),
'Tag' => array(
'className' => 'Tag',
),
'Event',
'Tag'
);
// take an array of tag names to be included and an array with tagnames to be excluded and find all event IDs that fit the criteria

View File

@ -50,6 +50,11 @@ class Job extends AppModel {
$type = 'nids';
$extra2 = isset($user['nids_sid']) ? $user['nids_sid'] : 0;
}
if ($type === 'bro') {
$extra = $type;
$type = 'bro';
$extra2 = isset($user['nids_sid']) ? $user['nids_sid'] : 0;
}
if ($type === 'rpz') $extra = $type;
$this->save($data);
$id = $this->id;

View File

@ -18,9 +18,5 @@ class News extends AppModel {
)
);
public $belongsTo = array(
'User' => array(
'className' => 'User',
)
);
public $belongsTo = 'User';
}

View File

@ -2448,6 +2448,7 @@ class Server extends AppModel {
APP . 'tmp' . DS . 'xml' => 0,
APP . 'tmp' . DS . 'files' => 0,
APP . 'tmp' . DS . 'logs' => 0,
APP . 'tmp' . DS . 'bro' => 0,
);
foreach ($writeableDirs as $path => &$error) {
$dir = new Folder($path);

View File

@ -19,12 +19,8 @@ class ServerTag extends AppModel {
);
public $belongsTo = array(
'Server' => array(
'className' => 'Server',
),
'Tag' => array(
'className' => 'Tag',
),
'Server',
'Tag'
);
public function attachTagToServer($server_id, $tag_id) {

View File

@ -19,12 +19,8 @@ class Sighting extends AppModel {
);
public $belongsTo = array(
'Attribute' => array(
'className' => 'Attribute',
),
'Event' => array(
'className' => 'Event',
),
'Attribute',
'Event',
'Organisation' => array(
'className' => 'Organisation',
'foreignKey' => 'org_id'

View File

@ -0,0 +1,5 @@
<?php
foreach ($attributes as $attribute) {
echo $attribute;
echo PHP_EOL;
}

View File

@ -2,7 +2,7 @@
<?php echo $this->Form->create('Attribute');?>
<fieldset>
<legend>Search Attribute</legend>
You can search for attributes based on contained expression within the value, event ID, submiting organisation, category and type. <br />For the value, event ID and organisation, you can enter several search terms by entering each term as a new line. To exclude things from a result, use the NOT operator (!) infront of the term.<br/><br />
You can search for attributes based on contained expression within the value, event ID, submitting organisation, category and type. <br />For the value, event ID and organisation, you can enter several search terms by entering each term as a new line. To exclude things from a result, use the NOT operator (!) in front of the term.<br/><br />
<?php
echo $this->Form->input('keyword', array('type' => 'textarea', 'label' => 'Containing the following expressions', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('keyword2', array('type' => 'textarea', 'label' => 'Being attributes of the following event IDs or event UUIDs', 'div' => 'clear', 'class' => 'input-xxlarge'));
@ -43,12 +43,12 @@ echo $this->Form->end();
</div>
<script type="text/javascript">
//
//Generate Category / Type filtering array
// Generate Category / Type filtering array
//
var category_type_mapping = new Array();
<?php
// all types for Categorie ALL
// all types for Category ALL
echo "category_type_mapping['ALL'] = {";
$first = true;
foreach ($typeDefinitions as $type => $def) {
@ -58,7 +58,7 @@ foreach ($typeDefinitions as $type => $def) {
}
echo "}; \n";
//all types for empty Categorie
// all types for empty Category
echo "category_type_mapping[''] = {";
$first = true;
foreach ($typeDefinitions as $type => $def) {
@ -68,7 +68,7 @@ foreach ($typeDefinitions as $type => $def) {
}
echo "}; \n";
// Types per Categorie
// Types per Category
foreach ($categoryDefinitions as $category => $def) {
echo "category_type_mapping['" . addslashes($category) . "'] = {";
$first = true;
@ -82,7 +82,7 @@ foreach ($categoryDefinitions as $category => $def) {
?>
//
//Generate Type / Category filtering array
// Generate Type / Category filtering array
//
var type_category_mapping = new Array();
@ -182,7 +182,7 @@ $(document).ready(function() {
});
// workaround for browsers like IE and Chrome that do now have an onmouseover on the 'options' of a select.
// disadvangate is that user needs to click on the item to see the tooltip.
// disadvantage is that user needs to click on the item to see the tooltip.
// no solutions exist, except to generate the select completely using html.
$("#AttributeType, #AttributeCategory").on('change', function(e) {
var $e = $(e.target);

View File

@ -1,2 +0,0 @@
<?php
echo $this->element('eventattributerow', array('object' => $object));

View File

@ -3,7 +3,7 @@
<table>
<tr>
<td style="padding-right:0px;">
<span class="<?php echo ($editable == 'yes' ? 'tagFirstHalf' : 'tagComplete'); ?>" style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></a>
<span class="<?php echo ($editable == 'yes' ? 'tagFirstHalf' : 'tagComplete'); ?>" style="background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></span>
</td>
<?php if ($editable == 'yes'): ?>
<td style="padding-left:0px;padding-right:5px;">

View File

@ -204,7 +204,61 @@ Use semicolons instead (the search will automatically search for colons instead)
echo $baseurl.'/attributes/text/download/all/tag1&amp;&amp;tag2&amp;&amp;!tag3';
?>
</pre>
<h3>Bro IDS export</h3>
<p>An export of all attributes of a specific bro type to a formatted plain text file. By default only published and IDS flagged attributes are exported.</p>
<p>You can configure your tools to automatically download a file one of the Bro types.</p>
<pre>
<?php
foreach (array_keys($broTypes) as $broType) {
echo $baseurl.'/attributes/bro/download/'.$broType . "\n";
}
?>
</pre>
<p>To restrict the results by tags, use the usual syntax. Please be aware the colons (:) cannot be used in the tag search. Use semicolons instead (the search will automatically search for colons instead). To get ip values from events tagged tag1 but not tag2 use:</p>
<pre>
<?php
echo $baseurl.'/attributes/bro/download/ip/tag1&&!tag2';
?>
</pre>
<p>It is possible to restrict the bro exports on based on a set of filters. POST a JSON object or an XML at the Bro API to filter the results.</p>
<pre>
<?php
echo $baseurl.'/attributes/bro/download';
?>
</pre>
<p>JSON:</p>
<pre>Headers
Authorization: [your API key]
Accept: application/json
Content-type: application/json
</pre>
<code>{"request": {"type":"ip", "eventid":["!51","!62"],"withAttachment":false,"tags":["APT1","!OSINT"],"from":false,"to":"2015-02-15"}}</code><br /><br />
<p>XML:</p>
<pre>Headers
Authorization: [your API key]
Accept: application/json
Content-type: application/json
</pre>
<code>&lt;request&gt;&lt;type&gt;ip&lt;/type&gt;&lt;eventid&gt;!51&lt;/eventid&gt;&lt;eventid&gt;!62&lt;/eventid&gt;&lt;withAttachment&gt;false&lt;/withAttachment&gt;&lt;tags&gt;APT1&lt;/tags&gt;&lt;tags&gt;!OSINT&lt;/tags&gt;&lt;from&gt;false&lt;/from&gt;&lt;to&gt;2015-02-15&lt;/to&gt;&lt;/request&gt;</code><br /><br />
<p>Alternatively, it is also possible to pass the filters via the parameters in the URL, though it is highly advised to use POST requests with JSON objects instead. The format is as described below:</p>
<pre>
<?php
echo $baseurl.'/attributes/bro/download/[type]/[tags]/[event_id]/[allowNonIDS]/[from]/[to]/[last]';
?>
</pre>
<b>type</b>: The Bro type, any valid Bro type is accepted. The mapping between Bro and MISP types is as follows:<br />
<pre>
<?php
foreach ($broTypes as $key => $value) {
echo '<b>' . h($key) . '</b>: ' . h($value) . PHP_EOL;
}
?>
</pre>
<p>
<b>tags</b>: To include a tag in the results just write its names into this parameter. To exclude a tag prepend it with a '!'.
You can also chain several tag commands together with the '&amp;&amp;' operator. Please be aware the colons (:) cannot be used in the tag search.
Use semicolons instead (the search will automatically search for colons instead).<br />
<b>event_id</b>: Restrict the results to the given event IDs. <br />
<b>allowNonIDS</b>: Allow attributes to be exported that are not marked as "to_ids".<br />
<b>from</b>: Events with the date set to a date after the one specified in the from field (format: 2015-02-15). This filter will use the date of the event.<br />

View File

@ -38,7 +38,18 @@
domain name and IP numbers to exclude from the NIDS export.
</div>
</div>
<div class="row bottom-buffer">
<div class="row bottom-buffer">
<div class="span3">
<?php echo $this->Html->link('Download Bro signatures', array('controller' => 'attributes', 'action' => 'bro', 'download'), array('class' => 'btn btn-block full-width')); ?>
</div>
<div class="span9">Click these to download all network related attributes that you
have access to under the Bro rule format. Only <em>published</em>
events and attributes marked as <em>IDS Signature</em> are exported.
Administration is able to maintain a whitelist containing host,
domain name and IP numbers to exclude from the NIDS export.
</div>
</div>
<div class="row bottom-buffer">
<div class="span3">
<?php echo $this->Html->link('Download RPZ Zone File', array('controller' => 'attributes', 'action' => 'rpz', 'download'), array('class' => 'btn btn-block full-width')); ?>
</div>

View File

@ -1,8 +0,0 @@
<div class="succes index">
<h2>Succes</h2><?php
if (0 == count($succes)):?>
<p>No Successes.</p><?php
else:?>
<p>Succes, all done.</p><?php
endif;?>
</div>

View File

@ -30,7 +30,6 @@
echo $this->Html->script('jquery'); // Include jQuery library
?>
<!--?php echo $scripts_for_layout; ?-->
</head>
<body>
<div id="popover_form" class="ajax_popover_form"></div>

View File

@ -10,7 +10,6 @@
</title>
<?php
echo $this->Html->meta('icon');
// echo $this->Html->css('cake.generic');
echo $this->Html->css('roboto');
echo $this->Html->css('bootstrap'); // see http://twitter.github.io/bootstrap/base-css.html
echo $this->Html->css('bootstrap-datepicker');
@ -19,9 +18,6 @@
echo $this->Html->css('main');
echo $this->Html->css('print', 'stylesheet', array('media' => 'print'));
// FIXME chri: re-add print stylesheet
//echo $this->Html->css(array('print'), 'stylesheet', array('media' => 'print'));
echo $this->fetch('meta');
echo $this->fetch('css');
echo $this->fetch('script');
@ -29,7 +25,6 @@
echo $this->Html->script('jquery'); // Include jQuery library
?>
<!--?php echo $scripts_for_layout; ?-->
</head>
<body>
<div id="gray_out" class="gray_out"></div>

View File

@ -1,8 +0,0 @@
<div class="succes index">
<h2>Succes</h2><?php
if (0 == count($succes)):?>
<p>No Successes.</p><?php
else:?>
<p>Succes, all done.</p><?php
endif;?>
</div>

View File

@ -400,29 +400,6 @@ function submitForm(type, id, field, context) {
return false;
};
function submitTagForm(id) {
$.ajax({
data: $('#EventTag').closest("form").serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
loadEventTags(id);
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadEventTags(id);
},
complete:function() {
$(".loading").hide();
},
type:"post",
url:"/events/addTag/" + id
});
return false;
}
function quickSubmitTagForm(event_id, tag_id) {
$('#EventTag').val(tag_id);
$.ajax({