mirror of https://github.com/MISP/MISP
Merge remote-tracking branch 'upstream/2.4' into distributionGraphDonut
commit
6d476814b0
16
.travis.yml
16
.travis.yml
|
@ -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
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit a35db89102f5c3e8cb0da9da6db5b50af12c32ee
|
||||
Subproject commit 411016b80b8a5f3a67b96020336b1cf3b2d9a99d
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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): ?>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<li class="divider"></li>
|
|
@ -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));
|
||||
?>
|
|
@ -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'))) {
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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]
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue