Merge remote-tracking branch 'upstream/2.4' into distributionGraphDonut

pull/3214/head
Sami Mokaddem 2018-05-03 13:52:40 +00:00
commit 6d476814b0
29 changed files with 1224 additions and 909 deletions

View File

@ -23,7 +23,9 @@ addons:
packages:
- python3-dev
- python3-pip
- python3-nose
- libxml2-dev
- libzmq3-dev
- zlib1g-dev
- apache2
- curl
@ -37,15 +39,7 @@ before_install:
- git config --global user.name "TravisCI"
install:
- sudo apt-get install python3-pip python3-nose
- git pull --recurse-submodules && git submodule update
- pip3 install --user pip -U
- pip3 install --user pyzmq
- pip3 install --user coveralls
- pip3 install --user codecov
- pip3 install --user git+https://github.com/CybOXProject/python-cybox.git@v2.1.0.12#egg=Package
- pip3 install --user git+https://github.com/stixproject/python-stix.git@v1.2.0.0#egg=Package
- pip3 install --user git+https://github.com/MISP/PyMISP.git#egg=Package
- pip3 install --user --upgrade -r requirements.txt
- phpenv rehash
- pushd app
- composer install
@ -120,10 +114,6 @@ script:
- ./curl_tests.sh $AUTH
- popd
- pushd PyMISP
- pip3 install --user -U nose
- pip3 install --user coveralls
- pip3 install --user codecov
- pip3 install --user requests-mock
- pip3 install --user .
- nosetests --with-coverage --cover-package=pymisp tests/test_*.py
- python3 tests/test.py

2
PyMISP

@ -1 +1 @@
Subproject commit a35db89102f5c3e8cb0da9da6db5b50af12c32ee
Subproject commit 411016b80b8a5f3a67b96020336b1cf3b2d9a99d

View File

@ -47,7 +47,7 @@ class AppController extends Controller {
public $helpers = array('Utility', 'OrgImg');
private $__queryVersion = '36';
public $pyMispVersion = '2.4.89';
public $pyMispVersion = '2.4.90';
public $phpmin = '5.6.5';
public $phprec = '7.0.16';

View File

@ -122,12 +122,12 @@ class RestResponseComponent extends Component {
'Server' => array(
'add' => array(
'description' => "POST an Server object in JSON format to this API to add a server.",
'mandatory' => array('url', 'name', 'organisation_type', 'authkey', 'json'),
'optional' => array('push', 'pull', 'push_rules', 'pul_rules', 'submitted_cert', 'submitted_client_cert')
'mandatory' => array('url', 'name', 'remote_org_id', 'authkey'),
'optional' => array('push', 'pull', 'push_rules', 'pull_rules', 'submitted_cert', 'submitted_client_cert', 'json')
),
'edit' => array(
'description' => "POST an Server object in JSON format to this API to edit a server.",
'optional' => array('url', 'name', 'organisation_type', 'authkey', 'json', 'push', 'pull', 'push_rules', 'pul_rules', 'submitted_cert', 'submitted_client_cert')
'optional' => array('url', 'name', 'authkey', 'json', 'push', 'pull', 'push_rules', 'pull_rules', 'submitted_cert', 'submitted_client_cert', 'remote_org_id')
)
),
'Sighting' => array(

View File

@ -3566,6 +3566,18 @@ class EventsController extends AppController {
$this->set('resultArray', $resultArray);
$this->set('importComment', '');
$this->set('title', 'Freetext Import Results');
$this->loadModel('Warninglist');
$tldLists = $this->Warninglist->getTldLists();
$missingTldLists = array();
foreach ($tldLists as $tldList) {
$temp = $this->Warninglist->find('first', array(
'recursive' => -1,
'conditions' => array('Warninglist.name' => $tldList),
'fields' => array('Warninglist.id')
));
if (empty($temp)) $missingTldLists[] = $tldList;
}
$this->set('missingTldLists', $missingTldLists);
$this->render('resolved_attributes');
}
}

View File

@ -35,14 +35,14 @@ class GalaxyClustersController extends AppController {
if ( isset($this->params['named']['searchall']) && strlen($this->params['named']['searchall']) > 0) {
$synonym_hits = $this->GalaxyCluster->GalaxyElement->find(
'list', array(
'recursive' => -1,
'conditions' => array(
'LOWER(GalaxyElement.value) LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%',
'GalaxyElement.key' => 'synonyms' ),
'recursive' => -1,
'conditions' => array(
'LOWER(GalaxyElement.value) LIKE' => '%' . strtolower($this->params['named']['searchall']) . '%',
'GalaxyElement.key' => 'synonyms' ),
'fields' => array(
'GalaxyElement.galaxy_cluster_id')
'GalaxyElement.galaxy_cluster_id')
));
$this->paginate['conditions'] =
$this->paginate['conditions'] =
array("AND" => array(
'OR' => array(
"LOWER(GalaxyCluster.value) LIKE" => '%'. strtolower($this->params['named']['searchall']) .'%',
@ -84,6 +84,7 @@ class GalaxyClustersController extends AppController {
$clusters[$k]['sightings'] = $temp;
}
}
$csv = array();
foreach ($clusters as $k => $cluster) {
$startDate = !empty($cluster['sightings']) ? min(array_keys($cluster['sightings'])) : date('Y-m-d');
$startDate = date('Y-m-d', strtotime("-3 days", strtotime($startDate)));
@ -101,6 +102,7 @@ class GalaxyClustersController extends AppController {
}
$this->set('csv', $csv);
$this->set('list', $clusters);
$this->set('galaxy_id', $id);
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
$this->render('ajax/index');

View File

@ -163,7 +163,9 @@ class ServersController extends AppController {
$this->request->data = array('Server' => $this->request->data);
}
}
$json = json_decode($this->request->data['Server']['json'], true);
if (!empty($json)) {
$json = json_decode($this->request->data['Server']['json'], true);
}
$fail = false;
if (empty(Configure::read('MISP.host_org_id'))) $this->request->data['Server']['internal'] = 0;
@ -189,21 +191,55 @@ class ServersController extends AppController {
}
if (!$fail) {
if ($this->_isRest()) {
$defaults = array(
'push' => 0,
'pull' => 0,
'json' => '[]',
'push_rules' => '[]',
'pull_rules' => '[]',
'self_signed' => 0
);
foreach ($defaults as $default => $dvalue) {
if (!isset($this->request->data['Server'][$default])) {
$this->request->data['Server'][$default] = $dvalue;
}
}
}
// force check userid and orgname to be from yourself
$this->request->data['Server']['org_id'] = $this->Auth->user('org_id');
if ($this->request->data['Server']['organisation_type'] < 2) $this->request->data['Server']['remote_org_id'] = $json['id'];
else {
if ($this->_isRest()) {
if (empty($this->request->data['Server']['remote_org_id'])) {
return $this->RestResponse->saveFailResponse('Servers', 'add', false, array('Organisation' => 'Remote Organisation\'s id/uuid not given (remote_org_id)'), $this->response->type());
}
if (Validation::uuid($this->request->data['Server']['remote_org_id'])) {
$orgCondition = array('uuid' => $this->request->data['Server']['remote_org_id']);
} else {
$orgCondition = array('id' => $this->request->data['Server']['remote_org_id']);
}
$existingOrgs = $this->Server->Organisation->find('first', array(
'conditions' => array('uuid' => $json['uuid']),
'conditions' => $orgCondition,
'recursive' => -1,
'fields' => array('id', 'uuid')
));
if (!empty($existingOrgs)) {
$fail = true;
if($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Servers', 'add', false, array('Organisation' => 'Remote Organisation\'s uuid already used'), $this->response->type());
} else {
$this->Session->setFlash(__('That organisation could not be created as the uuid is in use already.'));
if (empty($existingOrgs)) {
return $this->RestResponse->saveFailResponse('Servers', 'add', false, array('Organisation' => 'Invalid Remote Organisation'), $this->response->type());
}
} else {
if ($this->request->data['Server']['organisation_type'] < 2) $this->request->data['Server']['remote_org_id'] = $json['id'];
else {
$existingOrgs = $this->Server->Organisation->find('first', array(
'conditions' => array('uuid' => $json['uuid']),
'recursive' => -1,
'fields' => array('id', 'uuid')
));
if (!empty($existingOrgs)) {
$fail = true;
if($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Servers', 'add', false, array('Organisation' => 'Remote Organisation\'s uuid already used'), $this->response->type());
} else {
$this->Session->setFlash(__('That organisation could not be created as the uuid is in use already.'));
}
}
}
@ -236,10 +272,10 @@ class ServersController extends AppController {
if (!$fail) {
$this->request->data['Server']['org_id'] = $this->Auth->user('org_id');
if ($this->Server->save($this->request->data)) {
if (isset($this->request->data['Server']['submitted_cert']) && $this->request->data['Server']['submitted_cert']['size'] != 0) {
if (isset($this->request->data['Server']['submitted_cert'])) {
$this->__saveCert($this->request->data, $this->Server->id, false);
}
if (isset($this->request->data['Server']['submitted_client_cert']) && $this->request->data['Server']['submitted_client_cert']['size'] != 0) {
if (isset($this->request->data['Server']['submitted_client_cert'])) {
$this->__saveCert($this->request->data, $this->Server->id, true);
}
if($this->_isRest()) {
@ -399,12 +435,12 @@ class ServersController extends AppController {
if (!$fail) {
// Save the data
if ($this->Server->save($this->request->data, true, $fieldList)) {
if (isset($this->request->data['Server']['submitted_cert']) && $this->request->data['Server']['submitted_cert']['size'] != 0 && (!isset($this->request->data['Server']['delete_cert']) || !$this->request->data['Server']['delete_cert'])) {
if (isset($this->request->data['Server']['submitted_cert']) && (!isset($this->request->data['Server']['delete_cert']) || !$this->request->data['Server']['delete_cert'])) {
$this->__saveCert($this->request->data, $this->Server->id, false);
} else {
if (isset($this->request->data['Server']['delete_cert']) && $this->request->data['Server']['delete_cert']) $this->__saveCert($this->request->data, $this->Server->id, false, true);
}
if (isset($this->request->data['Server']['submitted_client_cert']) && $this->request->data['Server']['submitted_client_cert']['size'] != 0 && (!isset($this->request->data['Server']['delete_client_cert']) || !$this->request->data['Server']['delete_client_cert'])) {
if (isset($this->request->data['Server']['submitted_client_cert']) && (!isset($this->request->data['Server']['delete_client_cert']) || !$this->request->data['Server']['delete_client_cert'])) {
$this->__saveCert($this->request->data, $this->Server->id, true);
} else {
if (isset($this->request->data['Server']['delete_client_cert']) && $this->request->data['Server']['delete_client_cert']) $this->__saveCert($this->request->data, $this->Server->id, true, true);
@ -630,19 +666,26 @@ class ServersController extends AppController {
App::uses('File', 'Utility');
App::uses('Folder', 'Utility');
App::uses('FileAccessTool', 'Tools');
if (!$this->Server->checkFilename($server['Server'][$subm]['name'])) {
throw new Exception ('Filename not allowed');
}
$file = new File($server['Server'][$subm]['name']);
$ext = $file->ext();
if (($ext != 'pem') || !$server['Server'][$subm]['size'] > 0) {
$this->Session->setFlash('Incorrect extension or empty file.');
$this->redirect(array('action' => 'index'));
}
// read pem file data
$pemData = (new FileAccessTool())->readFromFile($server['Server'][$subm]['tmp_name'], $server['Server'][$subm]['size']);
if (isset($server['Server'][$subm]['name'])) {
if ($this->request->data['Server']['submitted_client_cert']['size'] != 0) {
if (!$this->Server->checkFilename($server['Server'][$subm]['name'])) {
throw new Exception ('Filename not allowed');
}
$file = new File($server['Server'][$subm]['name']);
$ext = $file->ext();
if (($ext != 'pem') || !$server['Server'][$subm]['size'] > 0) {
$this->Session->setFlash('Incorrect extension or empty file.');
$this->redirect(array('action' => 'index'));
}
// read pem file data
$pemData = (new FileAccessTool())->readFromFile($server['Server'][$subm]['tmp_name'], $server['Server'][$subm]['size']);
} else {
return true;
}
} else {
$pemData = base64_decode($server['Server'][$subm]);
}
$destpath = APP . "files" . DS . "certs" . DS;
$dir = new Folder(APP . "files" . DS . "certs", true);
$pemfile = new File($destpath . $id . $ins . '.' . $ext);
@ -655,6 +698,7 @@ class ServersController extends AppController {
$s['Server'][$attr] = '';
$this->Server->save($s);
}
return true;
}
public function serverSettingsReloadSetting($setting, $id) {

View File

@ -310,9 +310,9 @@ class ComplexTypeTool {
}
if ($domainDetection) {
if (count($temp) > 2) {
return array('types' => array('hostname', 'domain', 'url'), 'to_ids' => true, 'default_type' => 'hostname', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
return array('types' => array('hostname', 'domain', 'url', 'filename'), 'to_ids' => true, 'default_type' => 'hostname', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
} else {
return array('types' => array('domain'), 'to_ids' => true, 'default_type' => 'domain', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
return array('types' => array('domain', 'filename'), 'to_ids' => true, 'default_type' => 'domain', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
}
} else {
// check if it is a URL

View File

@ -420,6 +420,9 @@ class Attribute extends AppModel {
'validComposite' => array(
'rule' => array('validComposite'),
'message' => 'Composite type found but the value not in the composite (value1|value2) format.'
),
'maxTextLength' => array(
'rule' => array('maxTextLength')
)
),
'to_ids' => array(
@ -734,6 +737,13 @@ class Attribute extends AppModel {
return true;
}
public function maxTextLength($fields) {
if (strlen($fields['value']) > 65535) {
return 'The entered string is too long and would get truncated. Please consider adding the data as an attachment instead';
}
return true;
}
public function validCategory($fields) {
$validCategories = array_keys($this->categoryDefinitions);
if (in_array($fields['category'], $validCategories)) return true;

View File

@ -2814,9 +2814,9 @@ class Event extends AppModel {
}
}
}
if (isset($event['Event']['EventTag'])) {
$event['Event']['Tag'] = $event['Event']['EventTag']['Tag'];
unset($event['Event']['EventTag']);
if (isset($data['Event']['EventTag'])) {
$data['Event']['Tag'] = $data['Event']['EventTag']['Tag'];
unset($data['Event']['EventTag']);
}
if (isset($data['Event']['Tag']) && $user['Role']['perm_tagger']) {
foreach ($data['Event']['Tag'] as $tag) {

View File

@ -325,6 +325,7 @@ class Feed extends AppModel {
$hitIds = array();
$this->Event = ClassRegistry::init('Event');
foreach ($objects as $k => $object) {
if ($object['disable_correlation']) continue;
if (in_array($object['type'], $this->Event->Attribute->getCompositeTypes())) {
$value = explode('|', $object['value']);
$hashTable[$k] = md5($value[0]);

View File

@ -165,6 +165,10 @@ class Module extends AppModel {
$settings[$sslSetting] = Configure::read('Plugin.' . $moduleFamily . '_' . $sslSetting);
}
}
// let's set a low timeout for the introspection so that we don't block the loading of pages due to a misconfigured modules
if ($uri == '/modules') {
$settings['timeout'] = 1;
}
$httpSocket = new HttpSocket($settings);
$request = array(
'header' => array(

View File

@ -40,6 +40,10 @@ class Warninglist extends AppModel{
return true;
}
public function getTldLists() {
return $this->__tlds;
}
public function update() {
$directories = glob(APP . 'files' . DS . 'warninglists' . DS . 'lists' . DS . '*', GLOB_ONLYDIR);
$updated = array();

View File

@ -3,107 +3,251 @@
<?php
switch ($menuList) {
case 'event':
?>
<div id="hiddenSideMenuData" class="hidden" data-event-id="<?php echo isset($event['Event']['id']) ? h($event['Event']['id']) : 0; ?>"></div>
<?php
if (
$menuItem === 'addAttribute' ||
$menuItem === 'addObject' ||
$menuItem === 'addAttachment' ||
$menuItem === 'addIOC' ||
$menuItem === 'addThreatConnect' ||
$menuItem === 'populateFromtemplate'
) {
$dataEventId = isset($event['Event']['id']) ? h($event['Event']['id']) : 0;
echo '<div id="hiddenSideMenuData" class="hidden" data-event-id="' . $dataEventId . '"></div>';
if (in_array($menuItem, array('addAttribute', 'addObject', 'addAttachment', 'addIOC', 'addThreatConnect', 'populateFromTemplate'))) {
// we can safely assume that mayModify is true if coming from these actions, as they require it in the controller and the user has already passed that check
$mayModify = true;
if ($isAclPublish) $mayPublish = true;
}
if (($menuItem === 'template_populate_results')):
?>
<li id='litemplate_populate_results'><a href="<?php echo $baseurl;?>/templates/index"><?php echo __('Populate From Template');?></a></li>
<?php
endif;
?>
<?php if ($menuItem === 'freetextResults'): ?>
<li id='lifreetextResults'><a href="#"><?php echo __('Freetext Import Results');?></a></li>
<li class="divider"></li>
<?php endif;?>
<li id='liviewEvent'><a href="<?php echo $baseurl;?>/events/view/<?php echo h($event['Event']['id']);?>"><?php echo __('View Event');?></a></li>
<li id='liviewGraph'><a href="<?php echo $baseurl;?>/events/viewGraph/<?php echo h($event['Event']['id']);?>"><?php echo __('View Correlation Graph');?></a></li>
<li id='lieventLog'><a href="<?php echo $baseurl;?>/logs/event_index/<?php echo h($event['Event']['id']);?>"><?php echo __('View Event History');?></a></li>
<li class="divider"></li>
<?php if ($isSiteAdmin || (isset($mayModify) && $mayModify)): ?>
<li id='lieditEvent'><a href="<?php echo $baseurl;?>/events/edit/<?php echo h($event['Event']['id']);?>"><?php echo __('Edit Event');?></a></li>
<li><?php echo $this->Form->postLink(__('Delete Event'), array('controller' => 'events', 'action' => 'delete', h($event['Event']['id'])), null, __('Are you sure you want to delete # %s?', h($event['Event']['id']))); ?></li>
<li id='liaddAttribute'><a href="<?php echo $baseurl;?>/attributes/add/<?php echo h($event['Event']['id']);?>"><?php echo __('Add Attribute');?></a></li>
<li><a onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'objectTemplates', 'objectChoice');" style="cursor:pointer;"><?php echo __('Add Object');?></a></li>
<li id='liaddAttachment'><a href="<?php echo $baseurl;?>/attributes/add_attachment/<?php echo h($event['Event']['id']);?>"><?php echo __('Add Attachment');?></a></li>
<li id='import'><a onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'events', 'importChoice');" style="cursor:pointer;"><?php echo __('Populate from…');?></a></li>
<?php if ($menuItem === 'populateFromtemplate'): ?>
<li class="active"><a href="<?php echo $baseurl;?>/templates/populateEventFromTemplate/<?php echo $template_id . '/' . h($event['Event']['id']); ?>"><?php echo __('Populate From Template');?></a></li>
<?php endif; ?>
<li id='lienrichEvent'><a href="#" onClick="genericPopup('<?php echo $baseurl?>/events/enrichEvent/<?php echo h($event['Event']['id']); ?>', '#confirmation_box');" style="cursor:pointer;"><?php echo __('Enrich event');?></a></li>
<li id='merge'><a href="<?php echo $baseurl;?>/events/merge/<?php echo h($event['Event']['id']);?>"><?php echo __('Merge attributes from…');?></a></li>
<?php endif; ?>
<?php if (($isSiteAdmin && (!isset($mayModify) || !$mayModify)) || (!isset($mayModify) || !$mayModify)): ?>
<li id='liproposeAttribute'><a href="<?php echo $baseurl;?>/shadow_attributes/add/<?php echo h($event['Event']['id']);?>"><?php echo __('Propose Attribute');?></a></li>
<li id='liproposeAttachment'><a href="<?php echo $baseurl;?>/shadow_attributes/add_attachment/<?php echo h($event['Event']['id']);?>"><?php echo __('Propose Attachment');?></a></li>
<?php endif; ?>
<li class="divider"></li>
<?php
$publishButtons = ' hidden';
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && ($isSiteAdmin || (isset($mayPublish) && $mayPublish))) $publishButtons = "";
?>
<li class="publishButtons not-published<?php echo h($publishButtons); ?>"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'alert')"><?php echo __('Publish Event');?></a></li>
<li class="publishButtons not-published<?php echo h($publishButtons); ?>"><a href="#" onClick="publishPopup('<?php echo h($event['Event']['id']); ?>', 'publish')"><?php echo __('Publish (no email)');?></a></li>
<?php if (Configure::read('MISP.delegation')):?>
<?php if ((Configure::read('MISP.unpublishedprivate') || (isset($event['Event']['distribution']) && $event['Event']['distribution'] == 0)) && (!isset($delegationRequest) || !$delegationRequest) && ($isSiteAdmin || (isset($isAclDelegate) && $isAclDelegate))): ?>
<li id='lidelegateEvent'><a href="#" onClick="delegatePopup('<?php echo h($event['Event']['id']); ?>');"><?php echo __('Delegate Publishing');?></a></li>
<?php endif;?>
<?php if (isset($delegationRequest) && $delegationRequest && ($isSiteAdmin || ($isAclPublish && ($me['org_id'] == $delegationRequest['EventDelegation']['org_id'] || $me['org_id'] == $delegationRequest['EventDelegation']['requester_org_id'])))): ?>
<li class="divider"></li>
<?php if ($isSiteAdmin || ($isAclPublish && ($me['org_id'] == $delegationRequest['EventDelegation']['org_id']))): ?>
<li id='liacceptDelegation'><a href="#" onClick="genericPopup('<?php echo $baseurl?>/event_delegations/acceptDelegation/<?php echo h($delegationRequest['EventDelegation']['id']); ?>', '#confirmation_box');"><?php echo __('Accept Delegation Request');?></a></li>
<?php endif;?>
<li id='lideleteDelegation'><a href="#" onClick="genericPopup('<?php echo $baseurl?>/event_delegations/deleteDelegation/<?php echo h($delegationRequest['EventDelegation']['id']); ?>', '#confirmation_box');"><?php echo __('Discard Delegation Request');?></a></li>
<li class="divider"></li>
<?php endif;?>
<?php endif;?>
<?php if (Configure::read('Plugin.ZeroMQ_enable') && $isSiteAdmin): ?>
<li><?php echo $this->Form->postLink(__('Publish event to ZMQ'), array('action' => 'pushEventToZMQ', $event['Event']['id']));?></li>
<?php endif; ?>
<li id='licontact'><a href="<?php echo $baseurl;?>/events/contact/<?php echo h($event['Event']['id']);?>"><?php echo __('Contact Reporter');?></a></li>
<li><a onClick="getPopup('<?php echo h($event['Event']['id']); ?>', 'events', 'exportChoice');" style="cursor:pointer;"><?php echo __('Download as…');?></a></li>
<li class="divider"></li>
<li><a href="<?php echo $baseurl;?>/events/index"><?php echo __('List Events');?></a></li>
<?php if ($isAclAdd): ?>
<li><a href="<?php echo $baseurl;?>/events/add"><?php echo __('Add Event');?></a></li>
<?php endif;
if (($menuItem === 'template_populate_results')) {
echo $this->element('/side_menu_link', array(
'element_id' => 'template_populate_results',
'url' => '/templates/index',
'text' => 'Populate From Template'
));
}
if ($menuItem === 'freetextResults') {
echo $this->element('/side_menu_link', array(
'element_id' => 'freetextResults',
'url' => '#',
'text' => 'Freetext Import Result'
));
echo $this->element('/side_menu_divider');
}
echo $this->element('/side_menu_link', array(
'element_id' => 'viewEvent',
'url' => '/events/view/' . $event['Event']['id'],
'text' => 'View Event'
));
echo $this->element('/side_menu_link', array(
'element_id' => 'viewGraph',
'url' => '/events/viewGraph/' . $event['Event']['id'],
'text' => 'View Correlation Graph'
));
echo $this->element('/side_menu_link', array(
'element_id' => 'eventLog',
'url' => '/logs/event_index/' . $event['Event']['id'],
'text' => 'View Event History'
));
echo $this->element('/side_menu_divider');
if ($isSiteAdmin || (isset($mayModify) && $mayModify)) {
echo $this->element('/side_menu_link', array(
'element_id' => 'editEvent',
'url' => '/events/edit/' . $event['Event']['id'],
'text' => 'Edit Event'
));
echo '<li>' . $this->Form->postLink(__('Delete Event'), array('controller' => 'events', 'action' => 'delete', h($event['Event']['id'])), null, __('Are you sure you want to delete # %s?', h($event['Event']['id']))) . '</li>';
echo $this->element('/side_menu_link', array(
'element_id' => 'addAttribute',
'url' => '/attributes/add/' . $event['Event']['id'],
'text' => 'Add Attribute'
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array($event['Event']['id'], 'objectTemplates', 'objectChoice')
),
'text' => 'Add Object'
));
echo $this->element('/side_menu_link', array(
'element_id' => 'addAttachment',
'url' => '/attributes/add_attachment/' . $event['Event']['id'],
'text' => 'Add Attachment'
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array($event['Event']['id'], 'events', 'importchoice')
),
'text' => 'Populate from...'
));
if ($menuItem === 'populateFromtemplate') {
echo $this->element('/side_menu_link', array(
'url' => '/templates/populateEventFromTemplate/' . $template_id . '/' . $event['Event']['id'],
'text' => 'Populate From Template'
));
}
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'genericPopup',
'params' => array($baseurl . '/events/enrichEvent/' . $event['Event']['id'], '#confirmation_box')
),
'text' => 'Enrich Event'
));
echo $this->element('/side_menu_link', array(
'element_id' => 'merge',
'url' => '/events/merge/' . $event['Event']['id'],
'text' => 'Merge attributes from...'
));
}
if (($isSiteAdmin && (!isset($mayModify) || !$mayModify)) || (!isset($mayModify) || !$mayModify)) {
echo $this->element('/side_menu_link', array(
'element_id' => 'proposeAttribute',
'url' => '/shadow_attributes/add/' . $event['Event']['id'],
'text' => 'Propose Attribute'
));
echo $this->element('/side_menu_link', array(
'element_id' => 'proposeAttachment',
'url' => '/shadow_attributes/add_attachment/' . $event['Event']['id'],
'text' => 'Propose Attachment'
));
}
echo $this->element('/side_menu_divider');
$publishButtons = ' hidden';
if (isset($event['Event']['published']) && 0 == $event['Event']['published'] && ($isSiteAdmin || (isset($mayPublish) && $mayPublish))) $publishButtons = "";
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'alert')
),
'class' => 'publishButtons not-published ' . $publishButtons,
'text' => 'Publish Event'
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'publishPopup',
'params' => array($event['Event']['id'], 'publish')
),
'class' => 'publishButtons not-published ' . $publishButtons,
'text' => 'Publish (no email)'
));
if (Configure::read('MISP.delegation')) {
if ((Configure::read('MISP.unpublishedprivate') || (isset($event['Event']['distribution']) && $event['Event']['distribution'] == 0)) && (!isset($delegationRequest) || !$delegationRequest) && ($isSiteAdmin || (isset($isAclDelegate) && $isAclDelegate))) {
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'delegatePopup',
'params' => array($event['Event']['id'])
),
'text' => 'Delegate Publishing'
));
}
if (isset($delegationRequest) && $delegationRequest && ($isSiteAdmin || ($isAclPublish && ($me['org_id'] == $delegationRequest['EventDelegation']['org_id'] || $me['org_id'] == $delegationRequest['EventDelegation']['requester_org_id'])))) {
echo $this->element('/side_menu_divider');
if ($isSiteAdmin || ($isAclPublish && ($me['org_id'] == $delegationRequest['EventDelegation']['org_id']))) {
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'genericPopup',
'params' => array($baseurl . '/event_delegations/acceptDelegation/' . $delegationRequest['EventDelegation']['id'], '#confirmation_box')
),
'text' => 'Accept Delegation Request'
));
}
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'genericPopup',
'params' => array($baseurl . '/event_delegations/deleteDelegation/' . $delegationRequest['EventDelegation']['id'], '#confirmation_box')
),
'text' => 'Discard Delegation Request'
));
echo $this->element('/side_menu_divider');
}
}
if (Configure::read('Plugin.ZeroMQ_enable') && $isSiteAdmin) {
echo '<li>' . $this->Form->postLink(__('Publish event to ZMQ'), array('action' => 'pushEventToZMQ', $event['Event']['id'])) . '</li>';
}
echo $this->element('/side_menu_link', array(
'element_id' => 'contact',
'url' => '/events/contact/' . $event['Event']['id'],
'text' => 'Contact Reporter'
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array($event['Event']['id'], 'events', 'exportChoice')
),
'text' => 'Download as...'
));
echo $this->element('/side_menu_divider');
echo $this->element('/side_menu_link', array(
'url' => '/events/index',
'text' => 'List Events'
));
if ($isAclAdd) {
echo $this->element('/side_menu_link', array(
'url' => '/events/add',
'text' => 'Add Event'
));
}
break;
case 'event-collection': ?>
<li id='liindex'><a href="<?php echo $baseurl;?>/events/index"><?php echo __('List Events');?></a></li>
<?php if ($isAclAdd): ?>
<li id='liadd'><a href="<?php echo $baseurl;?>/events/add"><?php echo __('Add Event');?></a></li>
<li id='liaddMISPExport'><a onClick="getPopup('0', 'events', 'importChoice/event-collection');" style="cursor:pointer;"><?php echo __('Import from…');?></a></li>
<?php endif; ?>
<li class="divider"></li>
<li id='lilistAttributes'><a href="<?php echo $baseurl;?>/attributes/index"><?php echo __('List Attributes');?></a></li>
<li id='lisearchAttributes'><a href="<?php echo $baseurl;?>/attributes/search"><?php echo __('Search Attributes');?></a></li>
<?php if ($menuItem == 'searchAttributes2'): ?>
<li class="divider"></li>
<li><a href="<?php echo $baseurl;?>/events/downloadSearchResult.json"><?php echo __('Download results as JSON');?></a></li>
<li><a href="<?php echo $baseurl;?>/events/downloadSearchResult.xml"><?php echo __('Download results as XML');?></a></li>
<li><a href="<?php echo $baseurl;?>/events/csv/download/search"><?php echo __('Download results as CSV');?></a></li>
<?php endif; ?>
<li class="divider"></li>
<li id='liviewProposals'><a href="<?php echo $baseurl;?>/shadow_attributes/index"><?php echo __('View Proposals');?></a></li>
<li id='liviewProposalIndex'><a href="<?php echo $baseurl;?>/events/proposalEventIndex"><?php echo __('Events with proposals');?></a></li>
<li class="divider"></li>
<li id='liexport'><a href="<?php echo $baseurl;?>/events/export"><?php echo __('Export');?></a></li>
<?php if ($isAclAuth): ?>
<li id='liautomation'><a href="<?php echo $baseurl;?>/events/automation"><?php echo __('Automation');?></a></li>
<?php endif;
case 'event-collection':
echo $this->element('/side_menu_link', array(
'element_id' => 'index',
'url' => '/events/index',
'text' => 'List Events'
));
if ($isAclAdd) {
echo $this->element('/side_menu_link', array(
'element_id' => 'add',
'url' => '/events/add',
'text' => 'Add Events'
));
echo $this->element('/side_menu_link', array(
'onClick' => array(
'function' => 'getPopup',
'params' => array('0', 'events', 'importChoice/event-collection')
),
'text' => 'Import from…'
));
}
echo $this->element('/side_menu_divider');
echo $this->element('/side_menu_link', array(
'element_id' => 'index',
'url' => '/attributes/index',
'text' => 'List Attributes'
));
echo $this->element('/side_menu_link', array(
'element_id' => 'search',
'url' => '/attributes/search',
'text' => 'Search Attributes'
));
if ($menuItem == 'searchAttributes2') {
echo $this->element('/side_menu_divider');
echo $this->element('/side_menu_link', array(
'url' => '/events/downloadSearchResult.json',
'text' => 'Download results as JSON'
));
echo $this->element('/side_menu_link', array(
'url' => '/events/downloadSearchResult.xml',
'text' => 'Download results as XML'
));
echo $this->element('/side_menu_link', array(
'url' => '/events/csv/download/search',
'text' => 'Download results as CSV'
));
}
echo $this->element('/side_menu_divider');
echo $this->element('/side_menu_link', array(
'url' => '/shadow_attributes/index',
'text' => 'View Proposals'
));
echo $this->element('/side_menu_link', array(
'url' => '/events/proposalEventIndex',
'text' => 'Events with proposals'
));
echo $this->element('/side_menu_divider');
echo $this->element('/side_menu_link', array(
'url' => '/events/export',
'text' => 'Export'
));
if ($isAclAuth) {
echo $this->element('/side_menu_link', array(
'element_id' => 'automation',
'url' => '/events/automation',
'text' => 'Automation'
));
}
break;
case 'regexp': ?>
@ -119,6 +263,7 @@
<?php
endif;
break;
case 'warninglist':?>
<?php if ($menuItem == 'view'): ?><li class="active"><a href="#"><?php echo __('View Warninglist');?></a></li><?php endif;?>
<li id='liindex'><?php echo $this->Html->link(__('List Warninglists'), array('action' => 'index'));?></li>
@ -127,6 +272,7 @@
<?php
endif;
break;
case 'whitelist':?>
<li id='liindex'><?php echo $this->Html->link(__('List Whitelist'), array('admin' => $isSiteAdmin, 'action' => 'index'));?></li>
<?php if ($isSiteAdmin): ?>

View File

@ -0,0 +1 @@
<li class="divider"></li>

View File

@ -0,0 +1,33 @@
<?php
$a = '';
if (!empty($element_id)) {
$element_id = 'id="li' . $element_id . '"';
} else {
if (!empty($url)) {
$urlparts = explode('/', $url);
$element_id = 'id="li' . h(end($urlparts)) . '"';
} else {
$element_id = '';
}
}
if (empty($url)) {
$a = 'href="#"';
} else {
$a = 'href="' . $baseurl . h($url) . '"';
}
if (!empty($class)) {
$class = 'class="' . h($class) . '"';
} else {
$class = '';
}
if (!empty($onClick)) {
$params = array();
foreach ($onClick['params'] as $param) {
$params[] = h($param);
}
$params = implode('\', \'', $params);
$a .= sprintf(' onClick="%s(\'%s\')"', $onClick['function'], $params);
}
echo sprintf('<li %s %s><a %s>%s</a></li>', $element_id, $class, $a, h($text));
?>

View File

@ -2,6 +2,14 @@
<h2><?php echo h($title); ?></h2>
<?php $scope = !empty($proposals) ? 'proposals' : 'attributes'; ?>
<p><?php echo __('Below you can see the %s that are to be created. Make sure that the categories and the types are correct, often several options will be offered based on an inconclusive automatic resolution.', $scope);?></p>
<?php
if (!empty($missingTldLists)) {
$missingTldLists = implode(', ', $missingTldLists);
$missingTldLists = __('Warning: You are missing warninglist(s) that are used to recognise TLDs. Make sure your MISP has the warninglist submodule enabled and updated or else this tool might end up missing valid domains/hostnames/urls. The missing lists are: %s', $missingTldLists);
echo sprintf('<p class="bold red">%s</p>', $missingTldLists);
}
?>
<p></p>
<?php
$instanceDefault = 5;
if (!empty(Configure::read('MISP.default_attribute_distribution'))) {

View File

@ -21,7 +21,7 @@
'class' => 'form-control span6'
));
echo $this->Form->input('input_source', array(
'label' => __('Source Format'),
'label' => __('Input Source'),
'div' => 'input clear',
'options' => array('network' => 'Network', 'local' => 'Local'),
'class' => 'form-control span6'

View File

@ -17,11 +17,6 @@
<?php
$tab = "Center";
$filtered = false;
if (count($list) > 0){
$galaxy_id = $list[0]['GalaxyCluster']['galaxy_id'];
}else{
$galaxy_id = "";
}
if(isset($passedArgsArray)){
if (count($passedArgsArray) > 0) {
$tab = "Left";

@ -1 +1 @@
Subproject commit 3b5db95174a13e20db15eecb7837a4447a08e0dd
Subproject commit 3382e18393781c2802b4fecde9662c87a78e47de

View File

@ -1,25 +0,0 @@
from stix.extensions.identity.ciq_identity_3_0 import (CIQIdentity3_0Instance, STIXCIQIdentity3_0, OrganisationInfo, PartyName, Address, ElectronicAddressIdentifier, FreeTextAddress)
from stix.common import Identity
def resolveIdentityAttribute(incident, attribute, namespace):
ciq_identity = CIQIdentity3_0Instance()
identity_spec = STIXCIQIdentity3_0()
if attribute["type"] == 'target-user':
identity_spec.party_name = PartyName(person_names = [attribute["value"]])
elif attribute["type"] == 'target-external':
# we don't know if target-external is a person or an organisation, so as described at http://docs.oasis-open.org/ciq/v3.0/prd03/specs/ciq-specs-v3-prd3.html#_Toc207716018, use NameLine
identity_spec.party_name = PartyName(name_lines = ["External target: " + attribute["value"]])
elif attribute["type"] == 'target-org':
identity_spec.party_name = PartyName(organisation_names = [attribute["value"]])
elif attribute["type"] == 'target-location':
identity_spec.add_address(Address(FreeTextAddress(address_lines = [attribute["value"]])))
elif attribute["type"] == 'target-email':
identity_spec.add_electronic_address_identifier(ElectronicAddressIdentifier(value = attribute["value"]))
ciq_identity.specification = identity_spec
ciq_identity.id_ = namespace + ":Identity-" + attribute["uuid"]
# is this a good idea?
ciq_identity.name = attribute["type"] + ": " + attribute["value"] + " (MISP Attribute #" + attribute["id"] + ")"
incident.add_victim(ciq_identity)
return incident

View File

@ -1,370 +0,0 @@
from cybox.core import Object, Observable, ObservableComposition
from cybox.objects.file_object import File
from cybox.objects.address_object import Address
from cybox.objects.port_object import Port
from cybox.objects.hostname_object import Hostname
from cybox.objects.uri_object import URI
from cybox.objects.pipe_object import Pipe
from cybox.objects.mutex_object import Mutex
from cybox.objects.artifact_object import Artifact
from cybox.objects.memory_object import Memory
from cybox.objects.email_message_object import EmailMessage, EmailHeader, Attachments
from cybox.objects.domain_name_object import DomainName
from cybox.objects.win_registry_key_object import *
from cybox.common import Hash, ByteRun, ByteRuns
from cybox.objects.http_session_object import *
from cybox.objects.as_object import AutonomousSystem
from stix.extensions.test_mechanism.snort_test_mechanism import *
import ntpath, socket, sys
from stix.indicator import Indicator
this_module = sys.modules[__name__]
hash_type_attributes = {"single":["md5", "sha1", "sha224", "sha256", "sha384", "sha512", "sha512/224", "sha512/256", "ssdeep", "imphash", "authentihash", "pehash", "tlsh", "x509-fingerprint-sha1"], "composite": ["filename|md5", "filename|sha1", "filename|sha224", "filename|sha256", "filename|sha384", "filename|sha512", "filename|sha512/224", "filename|sha512/256", "filename|authentihash", "filename|ssdeep", "filename|tlsh", "filename|imphash", "filename|pehash", "malware-sample"]}
simple_type_to_method = {}
simple_type_to_method.update(dict.fromkeys(hash_type_attributes["single"] + hash_type_attributes["composite"] + ["filename"] + ["attachment"], "resolveFileObservable"))
simple_type_to_method.update(dict.fromkeys(["ip-src", "ip-dst", "ip-src|port", "ip-dst|port"], "generateIPObservable"))
simple_type_to_method.update(dict.fromkeys(["port"], "generatePortObservable"))
simple_type_to_method.update(dict.fromkeys(["domain|ip"], "generateDomainIPObservable"))
simple_type_to_method.update(dict.fromkeys(["regkey", "regkey|value"], "generateRegkeyObservable"))
simple_type_to_method.update(dict.fromkeys(["hostname", "domain", "url", "AS", "mutex", "named pipe", "link"], "generateSimpleObservable"))
simple_type_to_method.update(dict.fromkeys(["email-src", "email-dst", "email-subject"], "resolveEmailObservable"))
simple_type_to_method.update(dict.fromkeys(["http-method", "user-agent"], "resolveHTTPObservable"))
simple_type_to_method.update(dict.fromkeys(["pattern-in-file", "pattern-in-traffic", "pattern-in-memory"], "resolvePatternObservable"))
# mapping for the attributes that can go through the simpleobservable script
misp_cybox_name = {"domain" : "DomainName", "hostname" : "Hostname", "url" : "URI", "AS" : "AutonomousSystem", "mutex" : "Mutex", "named pipe" : "Pipe", "link" : "URI"}
cybox_name_attribute = {"DomainName" : "value", "Hostname" : "hostname_value", "URI" : "value", "AutonomousSystem" : "number", "Pipe" : "name", "Mutex" : "name"}
misp_indicator_type = {"domain" : "Domain Watchlist", "hostname" : "Domain Watchlist", "url" : "URL Watchlist", "AS" : "", "mutex" : "Host Characteristics", "named pipe" : "Host Characteristics", "link" : ""}
cybox_validation = {"AutonomousSystem": "isInt"}
# mapping Windows Registry Hives and their abbreviations
# see https://cybox.mitre.org/language/version2.1/xsddocs/objects/Win_Registry_Key_Object_xsd.html#RegistryHiveEnum
# the dict keys must be UPPER CASE and end with \\
misp_reghive = {
"HKEY_CLASSES_ROOT\\" : "HKEY_CLASSES_ROOT",
"HKCR\\" : "HKEY_CLASSES_ROOT",
"HKEY_CURRENT_CONFIG\\" : "HKEY_CURRENT_CONFIG",
"HKCC\\" : "HKEY_CURRENT_CONFIG",
"HKEY_CURRENT_USER\\" : "HKEY_CURRENT_USER",
"HKCU\\" : "HKEY_CURRENT_USER",
"HKEY_LOCAL_MACHINE\\" : "HKEY_LOCAL_MACHINE",
"HKLM\\" : "HKEY_LOCAL_MACHINE",
"HKEY_USERS\\" : "HKEY_USERS",
"HKU\\" : "HKEY_USERS",
"HKEY_CURRENT_USER_LOCAL_SETTINGS\\" : "HKEY_CURRENT_USER_LOCAL_SETTINGS",
"HKCULS\\" : "HKEY_CURRENT_USER_LOCAL_SETTINGS",
"HKEY_PERFORMANCE_DATA\\" : "HKEY_PERFORMANCE_DATA",
"HKPD\\" : "HKEY_PERFORMANCE_DATA",
"HKEY_PERFORMANCE_NLSTEXT\\" : "HKEY_PERFORMANCE_NLSTEXT",
"HKPN\\" : "HKEY_PERFORMANCE_NLSTEXT",
"HKEY_PERFORMANCE_TEXT\\" : "HKEY_PERFORMANCE_TEXT",
"HKPT\\" : "HKEY_PERFORMANCE_TEXT",
}
def generateObservable(indicator, attribute):
if (attribute["type"] in ("snort", "yara")):
generateTM(indicator, attribute)
else:
observable = None;
if (attribute["type"] in simple_type_to_method.keys()):
action = getattr(this_module, simple_type_to_method[attribute["type"]], None)
if (action != None):
property = action(indicator, attribute)
if property is False:
return False
if isinstance(property, Observable):
return indicator.add_observable(property)
property.condition = "Equals"
object = Object(property)
object.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":" + property.__class__.__name__ + "-" + attribute["uuid"]
observable = Observable(object)
observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-" + attribute["uuid"]
indicator.add_observable(observable)
def resolveFileObservable(indicator, attribute):
hashValue = ""
filenameValue = ""
fuzzy = False
if (attribute["type"] in hash_type_attributes["composite"]):
values = attribute["value"].split('|')
filenameValue = values[0]
hashValue = values[1]
indicator.add_indicator_type("File Hash Watchlist")
composite = attribute["type"].split('|')
if (len(composite) > 1 and composite[1] == "ssdeep"):
fuzzy = True
else:
if (attribute["type"] in ("filename", "attachment")):
filenameValue = attribute["value"]
else:
hashValue = attribute["value"]
indicator.add_indicator_type("File Hash Watchlist")
if (attribute["type"] == "ssdeep"):
fuzzy = True
observable = generateFileObservable(filenameValue, hashValue, fuzzy)
return observable
def generateFileObservable(filenameValue, hashValue, fuzzy):
file_object = File()
if (filenameValue != ""):
if (("/" in filenameValue) or ("\\" in filenameValue)):
file_object.file_path = ntpath.dirname(filenameValue)
file_object.file_path.condition = "Equals"
file_object.file_name = ntpath.basename(filenameValue)
file_object.file_name.condition = "Equals"
else:
file_object.file_name = filenameValue
file_object.file_name.condition = "Equals"
if (hashValue != ""):
file_object.add_hash(Hash(hash_value=hashValue, exact=True))
if (fuzzy):
file_object._fields["Hashes"]._inner[0].simple_hash_value = None
file_object._fields["Hashes"]._inner[0].fuzzy_hash_value = hashValue
file_object._fields["Hashes"]._inner[0].fuzzy_hash_value.condition = "Equals"
file_object._fields["Hashes"]._inner[0].type_ = Hash.TYPE_SSDEEP
file_object._fields["Hashes"]._inner[0].type_.condition = "Equals"
return file_object
def resolveIPType(attribute_value, attribute_type):
address_object = Address()
cidr = False
if ("|" in attribute_value):
attribute_value = attribute_value.split('|')[0]
if ("/" in attribute_value):
ip = attribute_value.split('/')[0]
cidr = True
else:
ip = attribute_value
try:
socket.inet_aton(ip)
ipv4 = True
except socket.error:
ipv4 = False
if (cidr == True):
address_object.category = "cidr"
condition = "Contains"
elif (ipv4 == True):
address_object.category = "ipv4-addr"
condition = "Equals"
else:
address_object.category = "ipv6-addr"
condition = "Equals"
if attribute_type.startswith("ip-src"):
address_object.is_source = True
address_object.is_destination = False
if attribute_type.startswith("ip-dst"):
address_object.is_source = False
address_object.is_destination = True
address_object.address_value = attribute_value
address_object.condition = condition
return address_object
def generateDomainIPObservable(indicator, attribute):
indicator.add_indicator_type("Domain Watchlist")
domain = attribute["value"].split('|')[0]
ip = attribute["value"].split('|')[1]
address_object = resolveIPType(ip, attribute["type"])
address_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":AddressObject-" + attribute["uuid"]
address_observable = Observable(address_object)
address_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":Address-" + attribute["uuid"]
domain_object = DomainName()
domain_object.value = domain
domain_object.value.condition = "Equals"
domain_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":DomainNameObject-" + attribute["uuid"]
domain_observable = Observable(domain_object)
domain_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":DomainName-" + attribute["uuid"]
compositeObject = ObservableComposition(observables = [address_observable, domain_observable])
compositeObject.operator = "AND"
observable = Observable(id_ = cybox.utils.idgen.__generator.namespace.prefix + ":ObservableComposition-" + attribute["uuid"])
observable.observable_composition = compositeObject
return observable
def generateIPObservable(indicator, attribute):
indicator.add_indicator_type("IP Watchlist")
address_object = resolveIPType(attribute["value"], attribute["type"])
address_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":AddressObject-" + attribute["uuid"]
if ("|" in attribute["value"]):
port = attribute["value"].split('|')[1]
address_observable = Observable(address_object)
address_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":Address-" + attribute["uuid"]
port_object = Port()
port_object.port_value = attribute["value"].split('|')[1]
port_object.port_value.condition = "Equals"
port_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":PortObject-" + attribute["uuid"]
port_observable = Observable(port_object)
port_observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":Port-" + attribute["uuid"]
compositeObject = ObservableComposition(observables = [address_observable, port_observable])
compositeObject.operator = "AND"
observable = Observable(id_ = cybox.utils.idgen.__generator.namespace.prefix + ":ObservableComposition-" + attribute["uuid"])
observable.observable_composition = compositeObject
return observable
else:
return address_object
def generatePortObservable(indicator, attribute):
port_object = Port()
port_object.port_value = attribute["value"]
port_object.port_value.condition = "Equals"
port_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":PortObject-" + attribute["uuid"]
return port_object
def generateRegkeyObservable(indicator, attribute):
indicator.add_indicator_type("Host Characteristics")
regkey = ""
regvalue = ""
if (attribute["type"] == "regkey|value"):
regkey = attribute["value"].split('|')[0]
regvalue = attribute["value"].split('|')[1]
else:
regkey = attribute["value"]
reghive, regkey = resolveRegHive(regkey)
reg_object = WinRegistryKey()
reg_object.key = regkey
reg_object.key.condition = "Equals"
if (reghive != None):
reg_object.hive = reghive
reg_object.hive.condition = "Equals"
if (regvalue != ""):
reg_value_object = RegistryValue()
reg_value_object.data = regvalue
reg_value_object.data.condition = "Equals"
reg_object.values = RegistryValues(reg_value_object)
return reg_object
def generateSimpleObservable(indicator, attribute):
cyboxName = misp_cybox_name[attribute["type"]]
if cyboxName in cybox_validation:
validator = getattr(this_module, cybox_validation[cyboxName], None)
if not (validator(attribute["value"])):
return False
constructor = getattr(this_module, cyboxName, None)
indicatorType = misp_indicator_type[attribute["type"]]
if (indicatorType != ""):
indicator.add_indicator_type(indicatorType)
new_object = constructor()
setattr(new_object, cybox_name_attribute[cyboxName], attribute["value"])
setattr(getattr(new_object, cybox_name_attribute[cyboxName]), "condition", "Equals")
return new_object
def generateTM(indicator, attribute):
if (attribute["type"] == "snort"):
tm = SnortTestMechanism()
attribute["value"] = attribute["value"].encode('utf-8')
tm.rules = [attribute["value"]]
else:
# remove the following line and uncomment the code below once yara test mechanisms get added to python-stix
return indicator
#tm = SnortTestMechanism()
#tm.rules = [attribute["value"]]
indicator.test_mechanisms = [tm]
def resolveEmailObservable(indicator, attribute):
indicator.add_indicator_type("Malicious E-mail")
new_object = EmailMessage()
email_header = EmailHeader()
if (attribute["type"] == "email-src"):
email_header.from_ = attribute["value"]
email_header.from_.condition = "Equals"
elif(attribute["type"] == "email-dst"):
email_header.to = attribute["value"]
email_header.to.condition = "Equals"
else:
email_header.subject = attribute["value"]
email_header.subject.condition = "Equals"
new_object.header = email_header
return new_object
def resolveHTTPObservable(indicator, attribute):
request_response = HTTPRequestResponse()
client_request = HTTPClientRequest()
if (attribute["type"] == "user-agent"):
header = HTTPRequestHeader()
header_fields = HTTPRequestHeaderFields()
header_fields.user_agent = attribute["value"]
header.parsed_header = header_fields
client_request.http_request_header = header
else:
line = HTTPRequestLine()
line.http_method = attribute["value"]
line.http_method.condition = "Equals"
client_request.http_request_line = line
request_response.http_client_request = client_request
new_object = HTTPSession()
request_response.to_xml()
new_object.http_request_response = [request_response]
return new_object
# use this when implementing pattern in memory and pattern in traffic
def resolvePatternObservable(indicator, attribute):
new_object = None
if attribute["type"] == "pattern-in-file":
byte_run = ByteRun()
byte_run.byte_run_data = attribute["value"]
new_object = File()
new_object.byte_runs = ByteRuns(byte_run)
# custom properties are not implemented in the API yet
# elif attribute["type"] == "pattern-in-memory":
# elif attribute["type"] == "pattern-in-traffic":
return new_object
# create an artifact object for the malware-sample type.
def createArtifactObject(indicator, attribute):
artifact = Artifact(data = attribute["data"])
artifact.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":ArtifactObject-" + attribute["uuid"]
observable = Observable(artifact)
observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-artifact-" + attribute["uuid"]
indicator.add_observable(observable)
# return either a composition if data is set in attribute, or just an observable with a filename if it's not set
def returnAttachmentComposition(attribute):
file_object = File()
file_object.file_name = attribute["value"]
file_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":FileObject-" + attribute["uuid"]
observable = Observable()
if "data" in attribute:
artifact = Artifact(data = attribute["data"])
artifact.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":ArtifactObject-" + attribute["uuid"]
observable_artifact = Observable(artifact)
observable_artifact.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-artifact-" + attribute["uuid"]
observable_file = Observable(file_object)
observable_file.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-file-" + attribute["uuid"]
composition = ObservableComposition(observables = [observable_artifact, observable_file])
observable.observable_composition = composition
else:
observable = Observable(file_object)
observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-" + attribute["uuid"]
if attribute["comment"] != "":
observable.description = attribute["comment"]
return observable
# email-attachment are mapped to an email message observable that contains the attachment as a file object
def generateEmailAttachmentObject(indicator, attribute):
file_object = File()
file_object.file_name = attribute["value"]
file_object.file_name.condition = "Equals"
email = EmailMessage()
email.attachments = Attachments()
email.add_related(file_object, "Contains", inline=True)
file_object.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":FileObject-" + attribute["uuid"]
email.attachments.append(file_object.parent.id_)
email.parent.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":EmailMessageObject-" + attribute["uuid"]
observable = Observable(email)
observable.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":observable-" + attribute["uuid"]
indicator.observable = observable
# split registry string into hive and key
def resolveRegHive(regStr):
regStr = regStr.lstrip('\\')
regStrU = regStr.upper()
for hive in misp_reghive.iterkeys():
if regStrU.startswith(hive):
return misp_reghive[hive], regStr[len(hive):]
return None, regStr
def isInt(var):
if var.isdigit():
return True
return False

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
import sys, json, uuid, os, time, datetime, re
from misp2cybox import *
from dateutil.tz import tzutc
from stix.indicator import Indicator
from stix.indicator.valid_time import ValidTime
@ -126,6 +125,7 @@ def main(args):
stix_header.title="Export from {} MISP".format(orgname)
stix_header.package_intents="Threat Report"
stix_package.stix_header = stix_header
stix_package.version = "1.1.1"
if args[3] == 'json':
stix_string = stix_package.to_json()[:-1]

View File

@ -43,13 +43,16 @@ class StixParser():
self.misp_event = MISPEvent()
self.misp_event['Galaxy'] = []
self.references = defaultdict(list)
self.dns_objects = defaultdict(dict)
self.dns_ips = []
# Load data from STIX document, and other usefull data
def load(self, args, pathname):
try:
filename = '{}/tmp/{}'.format(pathname, args[1])
event = self.load_event(filename)
if "CIRCL:Package" in event.id_ and "CIRCL MISP" in event.stix_header.title:
title = event.stix_header.title
if "Export from " in title and "MISP" in title:
fromMISP = True
else:
fromMISP = False
@ -83,6 +86,7 @@ class StixParser():
self.attribute_types_mapping = {
'AddressObjectType': self.handle_address,
"ArtifactObjectType": self.handle_attachment,
"DNSRecordObjectType": self.handle_dns,
'DomainNameObjectType': self.handle_domain_or_url,
'EmailMessageObjectType': self.handle_email_attribute,
'FileObjectType': self.handle_file,
@ -110,7 +114,10 @@ class StixParser():
else:
# external STIX format file
self.buildExternalDict()
self.build_references()
if self.dns_objects:
self.resolve_dns_objects()
if self.references:
self.build_references()
# Build a MISP event, parsing STIX data following the structure used in our own exporter
def buildMispDict(self):
@ -132,9 +139,30 @@ class StixParser():
if self.event.courses_of_action:
self.parse_coa(self.event.courses_of_action)
def resolve_dns_objects(self):
for domain in self.dns_objects['domain']:
domain_object = self.dns_objects['domain'][domain]
ip_reference = domain_object['related']
domain_attribute = domain_object['data']
if ip_reference in self.dns_objects['ip']:
misp_object = MISPObject('passive-dns')
domain_attribute['object_relation'] = "rrname"
misp_object.add_attribute(**domain_attribute)
ip = self.dns_objects['ip'][ip_reference]['value']
ip_attribute = {"type": "text", "value": ip, "object_relation": "rdata"}
misp_object.add_attribute(**ip_attribute)
rrtype = "AAAA" if ":" in ip else "A"
rrtype_attribute = {"type": "text", "value": rrtype, "object_relation": "rrtype"}
misp_object.add_attribute(**rrtype_attribute)
self.misp_event.add_object(**misp_object)
else:
self.misp_event.add_attribute(**domain_attribute)
for ip in self.dns_objects['ip']:
if ip not in self.dns_ips:
self.misp_event.add_attribute(**self.dns_objects['ip'][ip])
# Make references between objects
def build_references(self):
print(self.references)
for misp_object in self.misp_event.objects:
object_uuid = misp_object.uuid
if object_uuid in self.references:
@ -255,6 +283,24 @@ class StixParser():
def handle_attachment(properties, title):
return eventTypes[properties._XSI_TYPE]['type'], title, properties.raw_artifact.value
# Return type & attributes of a dns object
@staticmethod
def handle_dns(properties):
relation = []
if properties.domain_name:
relation.append(["domain", str(properties.domain_name.value), ""])
if properties.ip_address:
relation.append(["ip-dst", str(properties.ip_address.value), ""])
if relation:
if len(relation) == '2':
domain = relation[0][1]
ip = relattion[1][1]
attributes = [["text", domain, "rrname"], ["text", ip, "rdata"]]
rrtype = "AAAA" if ":" in ip else "A"
attributes.append(["text", rrtype, "rrtype"])
return "passive-dns", self.return_attributes(attributes), ""
return relation[0]
# Return type & value of a domain or url attribute
@staticmethod
def handle_domain_or_url(properties):
@ -327,8 +373,25 @@ class StixParser():
if len(attributes) == 2:
if b_hash and b_file:
return self.handle_filename_object(attributes, is_object)
path, filename = self.handle_filename_path_case(attributes)
if path and filename:
attribute_value = "{}\\{}".format(path, filename)
if '\\' in filename and path == filename:
attribute_value = filename
return "filename", attribute_value, ""
return "file", self.return_attributes(attributes), ""
@staticmethod
def handle_filename_path_case(attributes):
path, filename = [""] * 2
if attributes[0][2] == 'filename' and attributes[1][2] == 'path':
path = attributes[1][1]
filename = attributes[0][1]
elif attributes[0][2] == 'path' and attributes[1][2] == 'filename':
path = attributes[0][1]
filename = attributes[1][1]
return path, filename
# Return the appropriate type & value when we have 1 filename & 1 hash value
@staticmethod
def handle_filename_object(attributes, is_object):
@ -593,8 +656,18 @@ class StixParser():
if attr_type is str or attr_type is int:
# if the returned value is a simple value, we build an attribute
attribute = {'to_ids': False, 'uuid': object_uuid}
# if observable_object.related_objects:
# attribute
if observable_object.related_objects:
related_objects = observable_object.related_objects
if attribute_type == "url" and len(related_objects) == 1 and related_objects[0].relationship.value == "Resolved_To":
related_ip = self.fetch_uuid(related_objects[0].idref)
self.dns_objects['domain'][object_uuid] = {"related": related_ip,
"data": {"type": "text", "value": attribute_value}}
if related_ip not in self.dns_ips:
self.dns_ips.append(related_ip)
continue
if attribute_type in ('ip-src', 'ip-dst'):
self.dns_objects['ip'][object_uuid] = {"type": attribute_type, "value": attribute_value}
continue
self.handle_attribute_case(attribute_type, attribute_value, compl_data, attribute)
else:
# otherwise, it is a dictionary of attributes, so we build an object
@ -602,7 +675,7 @@ class StixParser():
self.handle_object_case(attribute_type, attribute_value, compl_data, object_uuid=object_uuid)
if observable_object.related_objects:
for related_object in observable_object.related_objects:
relationship = related_object.relationship.value.inner().replace('_', '-')
relationship = related_object.relationship.value.lower().replace('_', '-')
self.references[object_uuid].append({"idref": self.fetch_uuid(related_object.idref),
"relationship": relationship})

@ -1 +1 @@
Subproject commit 3f93daa0664629e75329e821800a564495ada026
Subproject commit 47e838bea30bf270415634c956695144a3003395

View File

@ -2,6 +2,7 @@ class ContextualMenu {
constructor(options) {
this.options = options;
this.trigger_container = options.trigger_container;
this.container = options.container;
this.bootstrap_popover = options.bootstrap_popover;
this.right_click = options.right_click;
this.has_been_shown_once = false;
@ -103,7 +104,7 @@ class ContextualMenu {
var div = document.createElement('div');
div.classList.add("contextual-menu");
div.classList.add("contextual-menu-styling");
document.body.appendChild(div);
this.container.appendChild(div);
// register on click for the trigger_container
var that = this;
if (this.right_click) {
@ -130,7 +131,7 @@ class ContextualMenu {
__create_menu_div_bootstrap_popover() {
var div = document.createElement('div');
div.classList.add("contextual-menu");
document.body.appendChild(div);
this.container.appendChild(div);
var that = this;
this.trigger_container.tabIndex = 0; // required for the popover focus feature
var additional_styling = this.options.style === undefined ? "" : this.options.style;

View File

@ -148,7 +148,8 @@ class EventGraph {
var menu_scope = new ContextualMenu({
trigger_container: document.getElementById("network-scope"),
bootstrap_popover: true,
style: "z-index: 1"
style: "z-index: 1",
container: document.getElementById("eventgraph_div")
});
menu_scope.add_select({
id: "select_graph_scope",
@ -188,7 +189,8 @@ class EventGraph {
var menu_physic = new ContextualMenu({
trigger_container: document.getElementById("network-physic"),
bootstrap_popover: true,
style: "z-index: 1"
style: "z-index: 1",
container: document.getElementById("eventgraph_div")
});
menu_physic.add_select({
id: "select_physic_solver",
@ -227,7 +229,8 @@ class EventGraph {
var menu_display = new ContextualMenu({
trigger_container: document.getElementById("network-display"),
bootstrap_popover: true,
style: "z-index: 1"
style: "z-index: 1",
container: document.getElementById("eventgraph_div")
});
menu_display.add_select({
id: "select_display_layout",
@ -311,7 +314,8 @@ class EventGraph {
var menu_filter = new ContextualMenu({
trigger_container: document.getElementById("network-filter"),
bootstrap_popover: true,
style: "z-index: 1"
style: "z-index: 1",
container: document.getElementById("eventgraph_div")
});
menu_filter.add_action_table({
id: "table_attr_presence",
@ -403,7 +407,8 @@ class EventGraph {
var menu_canvas = new ContextualMenu({
trigger_container: document.getElementById("eventgraph_network"),
right_click: true,
style: "z-index: 1"
style: "z-index: 1",
container: document.getElementById("eventgraph_div")
});
menu_canvas.add_button({
label: "View/Edit",
@ -1812,7 +1817,7 @@ var loadingText_creating = 'Constructing network';
var loadingText_redrawing = 'Redrawing network';
var shortcut_text = "<b>V</b> Center camera"
+ "\n<b>X</b> Expaned node"
+ "\n<b>X</b> Expand node"
+ "\n<b>C</b> Collapse node"
+ "\n<b>SHIFT+E</b> Edit node"
+ "\n<b>SHIFT+F</b> Search for value"

8
requirements.txt Normal file
View File

@ -0,0 +1,8 @@
pyzmq
coveralls
codecov
stix == 1.2.0.0
git+https://github.com/MISP/PyMISP.git#egg=Package
requests-mock
pip
nose