diff --git a/app/Lib/Export/NibblerExport.php b/app/Lib/Export/NibblerExport.php new file mode 100644 index 000000000..08ec1225d --- /dev/null +++ b/app/Lib/Export/NibblerExport.php @@ -0,0 +1,110 @@ + 1 + ); + + private $__mapping = array( + 'ip-dst' => 'IP', + 'ip-src' => 'IP', + 'domain' => 'Domain', + 'domain|ip' => ['Domain', 'IP'], + 'hostname' => 'Hostname', + 'md5' => 'MD5', + 'sha1' => 'SHA1', + 'sha256' => 'SHA256', + 'filename|md5' => array('Filename', 'MD5'), + 'malware-sample' => array('Filename', 'MD5'), + 'filename|sha1' => array('Filename', 'SHA1'), + 'filename|sha256' => array('Filename', 'SHA256') + ); + + private function __escapeSpecialChars($value) + { + $value = preg_replace("/\r|\n/", "##LINEBREAK##", $value ); + $value = preg_replace("/,/", "##COMMA##", $value ); + $value = preg_replace("/\|/", "##PIPE##", $value ); + return $value; + } + + private function __convertAttribute($attribute, $event) + { + if (empty($this->__mapping[$attribute['type']])) { + return ''; + } + $result = array(); + $attributes = array(); + if (is_array($this->__mapping[$attribute['type']])) { + $attribute['value'] = explode('|', $attribute['value']); + foreach (array(0,1) as $part) { + $result[] = sprintf( + '%s|%s|%s|%s|%s', + $this->__escapeSpecialChars($attribute['value'][$part]), + $this->__mapping[$attribute['type']][$part], + '/events/view/' . $event['uuid'], + $this->__escapeSpecialChars($event['info']), + $this->__decideOnAction($attribute['AttributeTag']) + ); + } + } else { + $result[] = sprintf( + '%s|%s|%s|%s|%s', + $this->__escapeSpecialChars($attribute['value']), + $this->__mapping[$attribute['type']], + '/events/view/' . $event['uuid'], + $this->__escapeSpecialChars($event['info']), + $this->__decideOnAction($attribute['AttributeTag']) + ); + } + return implode($this->separator(), $result); + } + + private function __decideOnAction($attributeTags) + { + foreach($attributeTags as $attributeTag) { + if ( + $attributeTag['Tag']['name'] === 'nibbler:block' + ) { + return 'BLOCK'; + } + } + return 'ALERT'; + } + + public function handler($data, $options = array()) + { + if ($options['scope'] === 'Attribute') { + $data['Attribute']['AttributeTag'] = $data['AttributeTag']; + return $this->__convertAttribute($data['Attribute'], $data['Event']); + } + if ($options['scope'] === 'Event') { + $result = array(); + foreach ($data['Attribute'] as $attribute) { + $temp = $this->__convertAttribute($attribute, $data['Event']); + if ($temp) $result[] = $temp; + } + return implode($this->separator(), $result); + } + return ''; + } + + public function header($options = array()) + { + return sprintf( + "# Nibbler rules generated by MISP at %s\n", + date('Y-m-d H:i:s') + ); + } + + public function footer() + { + return "\n"; + } + + public function separator() + { + return "\n"; + } +} diff --git a/app/Model/Attribute.php b/app/Model/Attribute.php index dc1096c2d..1d978ceb5 100644 --- a/app/Model/Attribute.php +++ b/app/Model/Attribute.php @@ -408,7 +408,8 @@ class Attribute extends AppModel 'csv' => array('csv', 'CsvExport', 'csv'), 'cache' => array('txt', 'CacheExport', 'cache'), 'attack-sightings' => array('json', 'AttackSightingsExport', 'json'), - 'netfilter' => array('txt', 'NetfilterExport', 'sh') + 'netfilter' => array('txt', 'NetfilterExport', 'sh'), + 'nibbler' => array('nibbler', 'NibblerExport', 'nibbler') ); // FIXME we need a better way to list the defaultCategories knowing that new attribute types will continue to appear in the future. We should generate this dynamically or use a function using the default_category of the $typeDefinitions @@ -4395,8 +4396,9 @@ class Attribute extends AppModel $temp = ''; foreach ($results as $attribute) { $elementCounter++; - $temp .= $exportTool->handler($attribute, $exportToolParams); - if ($temp !== '') { + $handlerResult = $exportTool->handler($attribute, $exportToolParams); + $temp .= $handlerResult; + if ($handlerResult !== '') { if ($i != count($results) -1) { $temp .= $exportTool->separator($exportToolParams); } diff --git a/app/Model/Event.php b/app/Model/Event.php index cc07a2553..db2f33b66 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -169,7 +169,7 @@ class Event extends AppModel 'requiresPublished' => 1, 'params' => array('returnFormat' => 'yara-json'), 'description' => 'Click this to download Yara rules generated from all relevant attributes. Rules are returned in a JSON format with information about origin (generated or parsed) and validity.' - ), + ) ); public $validFormats = array( @@ -190,7 +190,8 @@ class Event extends AppModel 'cache' => array('txt', 'CacheExport', 'cache'), 'attack' => array('html', 'AttackExport', 'html'), 'attack-sightings' => array('json', 'AttackSightingsExport', 'json'), - 'netfilter' => array('txt', 'NetfilterExport', 'sh') + 'netfilter' => array('txt', 'NetfilterExport', 'sh'), + 'nibbler' => array('nibbler', 'NibblerExport', 'nibbler') ); public $csv_event_context_fields_to_fetch = array(