From 6d822ee45ecf46eb39ec6a6d45d3622cb9920e69 Mon Sep 17 00:00:00 2001 From: Iglocska Date: Fri, 16 Sep 2016 16:49:54 +0200 Subject: [PATCH] fix: Refactor of the bro export to always create a zip archive with separate files if "all" types are queried --- app/Console/Command/EventShell.php | 29 ++----------------- app/Controller/AttributesController.php | 21 +++++++++----- app/Lib/Export/BroExport.php | 14 ++++----- app/Model/Attribute.php | 38 ++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 44 deletions(-) diff --git a/app/Console/Command/EventShell.php b/app/Console/Command/EventShell.php index f253023c4..553375d93 100644 --- a/app/Console/Command/EventShell.php +++ b/app/Console/Command/EventShell.php @@ -339,38 +339,13 @@ class EventShell extends AppShell $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'; } - $random_component = $this->Event->generateRandomFileName(); - $tmpZipname = DS . "bro_export_tmp_" . $random_component . ".zip"; - $zip = new File($dir->pwd() . $tmpZipname); - foreach ($types as $k => $type) { - $final = $this->Attribute->bro($user, $type); - $filename = $type . '.intel'; - - $file = new File($dir->pwd() . DS . $filename); - $file->write($broHeader); - foreach ($final as $attribute) { - $file->append($attribute . "\n"); - } - $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 - $this->Job->saveField('progress', $k / $typeCount * 100); - } - $zip->close(); - rename($dir->pwd() . $tmpZipname, $dir->pwd() . $zipname); + $tmpZipname = $this->Attribute->brozip($user, false, false, false, false, false, false, $id); + rename($tmpZipname[0] . $tmpZipname[1], $dir->pwd() . $zipname); $this->Job->saveField('progress', 100); $this->Job->saveField('message', 'Job done.'); } diff --git a/app/Controller/AttributesController.php b/app/Controller/AttributesController.php index 6b02ac5e6..f0425b220 100644 --- a/app/Controller/AttributesController.php +++ b/app/Controller/AttributesController.php @@ -1870,17 +1870,24 @@ class AttributesController extends AppController { throw new UnauthorizedException('You have to be logged in to do that.'); } } - $this->response->type('txt'); // set the content type $filename = 'misp.' . $type . '.intel'; if ($eventId) { $filename = 'misp.' . $type . '.event_' . $eventId . '.intel'; } - $this->header('Content-Disposition: download; filename="' . $filename . '"'); - $this->layout = 'text/default'; - $attributes = array("#fields indicator\tindicator_type\tmeta.source\tmeta.url\tmeta.do_notice\tmeta.if_in"); - $attributes = array_merge($attributes, $this->Attribute->bro($this->Auth->user(), $type, $tags, $eventId, $allowNonIDS, $from, $to, $last)); - $this->set('attributes', $attributes); - $this->render('/Attributes/bro'); + 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; } } diff --git a/app/Lib/Export/BroExport.php b/app/Lib/Export/BroExport.php index 7263ee878..472cceffd 100644 --- a/app/Lib/Export/BroExport.php +++ b/app/Lib/Export/BroExport.php @@ -4,6 +4,8 @@ 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 @@ -33,7 +35,7 @@ class BroExport { // 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 - private $__mispTypes = array( + public $mispTypes = array( 'ip' => array( array('ip-src', 1), array('ip-dst', 1), @@ -160,14 +162,8 @@ class BroExport { public function getMispTypes($type) { $mispTypes = array(); - if ($type !== 'all') { - if (isset($this->__mispTypes[$type])) { - $mispTypes = $this->__mispTypes[$type]; - } - } else { - foreach ($this->__mispTypes as $mispType) { - $mispTypes = array_merge($mispTypes, $mispType); - } + if (isset($this->mispTypes[$type])) { + $mispTypes = $this->mispTypes[$type]; } return $mispTypes; } diff --git a/app/Model/Attribute.php b/app/Model/Attribute.php index d36d09af7..cdffcfd25 100644 --- a/app/Model/Attribute.php +++ b/app/Model/Attribute.php @@ -1449,7 +1449,7 @@ class Attribute extends AppModel { } } $mispTypes = $export->getMispTypes($type); - $intel = array(); + $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); @@ -1472,6 +1472,42 @@ class Attribute extends AppModel { )); 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');