mirror of https://github.com/MISP/MISP
Merge branch '2.4' into feature/tag_filter_rework
commit
05a89f5e87
|
@ -513,14 +513,13 @@ class AppController extends Controller {
|
|||
));
|
||||
foreach ($attributes as $k => $attribute) {
|
||||
if ($k > 0) {
|
||||
$attribute['Attribute']['uuid'] = CakeText::uuid();
|
||||
$this->Attribute->save($attribute);
|
||||
$this->Attribute->delete($attribute['Attribute']['id']);
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Server->updateDatabase('makeAttributeUUIDsUnique');
|
||||
$this->Session->setFlash('Done. Assigned new UUIDs to ' . $counter . ' attribute(s).');
|
||||
$this->Session->setFlash('Done. Deleted ' . $counter . ' duplicate attribute(s).');
|
||||
$this->redirect(array('controller' => 'pages', 'action' => 'display', 'administration'));
|
||||
}
|
||||
|
||||
|
|
|
@ -2252,11 +2252,17 @@ class EventsController extends AppController {
|
|||
'value', 'comment', 'to_ids', 'timestamp');
|
||||
$requested_obj_attributes = array('uuid', 'name', 'meta-category');
|
||||
if (isset($this->params['url']['attributes'])) {
|
||||
$requested_attributes = explode(',', $this->params['url']['attributes']);
|
||||
if (!isset($this->params['url']['obj_attributes'])) $requested_obj_attributes = array();
|
||||
$requested_attributes = explode(',', $this->params['url']['attributes']);
|
||||
}
|
||||
if (isset($this->params['url']['obj_attributes'])) {
|
||||
$requested_obj_attributes = explode(',', $this->params['url']['obj_attributes']);
|
||||
$requested_obj_attributes = explode(',', $this->params['url']['obj_attributes']);
|
||||
}
|
||||
if (isset($data['request']['attributes'])) {
|
||||
if (!isset($data['request']['obj_attributes'])) $requested_obj_attributes = array();
|
||||
$requested_attributes = $data['request']['attributes'];
|
||||
}
|
||||
if (isset($data['request']['obj_attributes'])) $requested_obj_attributes = $data['request']['obj_attributes'];
|
||||
if (isset($events)) {
|
||||
foreach ($events as $eventid) {
|
||||
$attributes = $this->Event->csv($user, $eventid, $ignore, $list, false, $category, $type, $includeContext, $enforceWarninglist);
|
||||
|
@ -3317,6 +3323,7 @@ class EventsController extends AppController {
|
|||
unset($distributions[4]);
|
||||
}
|
||||
|
||||
$this->set('proposals', $event['Event']['orgc_id'] != $this->Auth->user('org_id') && !$this->_isSiteAdmin());
|
||||
$this->set('distributions', $distributions);
|
||||
$this->set('sgs', $sgs);
|
||||
$this->set('event', $event);
|
||||
|
@ -3459,22 +3466,30 @@ class EventsController extends AppController {
|
|||
}
|
||||
}
|
||||
}
|
||||
$emailResult = '';
|
||||
$messageScope = $objectType == 'ShadowAttribute' ? 'proposals' : 'attributes';
|
||||
if ($saved > 0) {
|
||||
$event = $this->Event->find('first', array(
|
||||
'conditions' => array('Event.id' => $id),
|
||||
'recursive' => -1
|
||||
));
|
||||
if ($event['Event']['published'] == 1) {
|
||||
$event['Event']['published'] = 0;
|
||||
if ($objectType != 'ShadowAttribute') {
|
||||
$event = $this->Event->find('first', array(
|
||||
'conditions' => array('Event.id' => $id),
|
||||
'recursive' => -1
|
||||
));
|
||||
if ($event['Event']['published'] == 1) {
|
||||
$event['Event']['published'] = 0;
|
||||
}
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Event->save($event);
|
||||
} else {
|
||||
if (!$this->Event->ShadowAttribute->sendProposalAlertEmail($id)) {
|
||||
$emailResult = " but sending out the alert e-mails has failed for at least one recipient";
|
||||
}
|
||||
}
|
||||
$date = new DateTime();
|
||||
$event['Event']['timestamp'] = $date->getTimestamp();
|
||||
$this->Event->save($event);
|
||||
}
|
||||
if ($failed > 0) {
|
||||
$this->Session->setFlash($saved . ' attributes created. ' . $failed . ' attributes could not be saved. This may be due to attributes with similar values already existing.');
|
||||
$this->Session->setFlash($saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. This may be due to attributes with similar values already existing.');
|
||||
} else {
|
||||
$this->Session->setFlash($saved . ' attributes created.');
|
||||
$this->Session->setFlash($saved . ' ' . $messageScope . ' created' . $emailResult . '.');
|
||||
}
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'view', $id));
|
||||
} else {
|
||||
|
|
|
@ -676,6 +676,13 @@ class ServersController extends AppController {
|
|||
$this->set('priorities', $priorities);
|
||||
$this->set('k', $id);
|
||||
$this->layout = false;
|
||||
|
||||
$subGroup = 'general';
|
||||
if ($pathToSetting[0] === 'Plugin') {
|
||||
$subGroup = explode('_', $pathToSetting[1])[0];
|
||||
}
|
||||
$this->set('subGroup', $subGroup);
|
||||
|
||||
$this->render('/Elements/healthElements/settings_row');
|
||||
}
|
||||
|
||||
|
@ -939,6 +946,9 @@ class ServersController extends AppController {
|
|||
}
|
||||
|
||||
public function serverSettingsEdit($setting, $id = false, $forceSave = false) {
|
||||
// invalidate config.php from php opcode cache
|
||||
opcache_reset();
|
||||
|
||||
if (!$this->_isSiteAdmin()) throw new MethodNotAllowedException();
|
||||
if (!isset($setting) || !isset($id)) throw new MethodNotAllowedException();
|
||||
$this->set('id', $id);
|
||||
|
|
|
@ -55,7 +55,13 @@ class UsersController extends AppController {
|
|||
$user['User']['pgp_status'] = isset($pgpDetails[2]) ? $pgpDetails[2] : 'OK';
|
||||
$user['User']['fingerprint'] = !empty($pgpDetails[4]) ? $pgpDetails[4] : 'N/A';
|
||||
}
|
||||
$this->set('user', $user);
|
||||
if ($this->_isRest()) {
|
||||
unset($user['User']['server_id']);
|
||||
$user['User']['password'] = '*****';
|
||||
return $this->RestResponse->viewData(array('User' => $user['User']), $this->response->type());
|
||||
} else {
|
||||
$this->set('user', $user);
|
||||
}
|
||||
}
|
||||
|
||||
public function request_API(){
|
||||
|
@ -709,7 +715,7 @@ class UsersController extends AppController {
|
|||
$c = 0;
|
||||
foreach ($fields as $field) {
|
||||
if (isset($fieldsOldValues[$c]) && $fieldsOldValues[$c] != $fieldsNewValues[$c]) {
|
||||
if ($field != 'confirm_password') {
|
||||
if ($field != 'confirm_password' && $field != 'enable_password') {
|
||||
$fieldsResultStr = $fieldsResultStr . ', ' . $field . ' (' . $fieldsOldValues[$c] . ') => (' . $fieldsNewValues[$c] . ')';
|
||||
}
|
||||
}
|
||||
|
@ -862,9 +868,9 @@ class UsersController extends AppController {
|
|||
$this->User->save($user['User'], true, array('id', 'last_login', 'current_login'));
|
||||
if (empty($this->Auth->authenticate['Form']['passwordHasher']) && !empty($passwordToSave)) $this->User->saveField('password', $passwordToSave);
|
||||
$this->User->Behaviors->enable('SysLogLogable.SysLogLogable');
|
||||
// TODO removed the auto redirect for now, due to security concerns - will look more into this
|
||||
// $this->redirect($this->Auth->redirectUrl());
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index'));
|
||||
// no state changes are ever done via GET requests, so it is safe to return to the original page:
|
||||
$this->redirect($this->Auth->redirectUrl());
|
||||
// $this->redirect(array('controller' => 'events', 'action' => 'index'));
|
||||
} else {
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
|
|
|
@ -11,7 +11,8 @@ class ComplexTypeTool {
|
|||
'/\(dot\)/' => '.',
|
||||
'/\\\\\./' => '.',
|
||||
'/\.+/' => '.',
|
||||
'/\[hxxp:\/\/\]/' => 'http://'
|
||||
'/\[hxxp:\/\/\]/' => 'http://',
|
||||
'/\\\/' => ''
|
||||
);
|
||||
|
||||
private $__tlds = array();
|
||||
|
@ -89,6 +90,10 @@ class ComplexTypeTool {
|
|||
return array_values($array);
|
||||
}
|
||||
|
||||
private function __parse_row($row, $delimiter) {
|
||||
$columns = str_getcsv($row, $delimiter);
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a CSV file with the given settings
|
||||
|
@ -100,7 +105,13 @@ class ComplexTypeTool {
|
|||
*/
|
||||
public function checkCSV($input, $settings = array()) {
|
||||
$delimiter = !empty($settings['delimiter']) ? $settings['delimiter'] : ",";
|
||||
$lines = explode("\n", $input);
|
||||
$rows = str_getcsv($input, "\n");
|
||||
$data = array();
|
||||
foreach ($rows as $k => $row) {
|
||||
if (empty($row[0]) || $row[0] === '#') continue;
|
||||
$data[$k] = str_getcsv($row, $delimiter);
|
||||
}
|
||||
unset($rows);
|
||||
unset($input);
|
||||
$values = !empty($settings['value']) ? $settings['value'] : array();
|
||||
if (!is_array($values)) {
|
||||
|
@ -110,15 +121,8 @@ class ComplexTypeTool {
|
|||
$values[$key] = intval($value);
|
||||
}
|
||||
$iocArray = array();
|
||||
foreach ($lines as $linePos => $line) {
|
||||
$line = trim($line);
|
||||
if (empty($line) || $line[0] === "#") continue;
|
||||
if ($delimiter === '\t') {
|
||||
$elements = preg_split('/\t/', $line);
|
||||
} else {
|
||||
$elements = explode($delimiter, $line);
|
||||
}
|
||||
foreach ($elements as $elementPos => $element) {
|
||||
foreach ($data as $rowPos => $row) {
|
||||
foreach ($row as $elementPos => $element) {
|
||||
if ((!empty($values) && in_array(($elementPos + 1), $values)) || empty($values)) {
|
||||
$element = trim($element, " \t\n\r\0\x0B\"\'");
|
||||
if (isset($settings['excluderegex']) && !empty($settings['excluderegex'])) {
|
||||
|
@ -209,7 +213,7 @@ class ComplexTypeTool {
|
|||
}
|
||||
$inputRefanged = rtrim($inputRefanged, ".");
|
||||
if (strpos($input, '@') !== false) {
|
||||
if (filter_var($input, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input);
|
||||
if (filter_var($input, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst', 'target-email', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $input);
|
||||
}
|
||||
// note down and remove the port if it's a url / domain name / hostname / ip
|
||||
// input2 from here on is the variable containing the original input with the port removed. It is only used by url / domain name / hostname / ip
|
||||
|
|
|
@ -129,6 +129,11 @@ class PubSubTool {
|
|||
return $this->__pushToRedis(':data:misp_json_' . $type, json_encode($data, JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
public function publish($data, $type, $action = false) {
|
||||
if (!empty($action)) $data['action'] = $action;
|
||||
return $this->__pushToRedis(':data:misp_json_' . $type, json_encode($data, JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
public function killService($settings = false) {
|
||||
$redis = new Redis();
|
||||
if ($this->checkIfRunning()) {
|
||||
|
|
|
@ -8,7 +8,12 @@ class SyncTool {
|
|||
if (!empty($server)) {
|
||||
if ($server['Server']['cert_file']) $params['ssl_cafile'] = APP . "files" . DS . "certs" . DS . $server['Server']['id'] . '.pem';
|
||||
if ($server['Server']['client_cert_file']) $params['ssl_local_cert'] = APP . "files" . DS . "certs" . DS . $server['Server']['id'] . '_client.pem';
|
||||
if ($server['Server']['self_signed']) $params['ssl_allow_self_signed'] = $server['Server']['self_signed'];
|
||||
if ($server['Server']['self_signed']) {
|
||||
$params['ssl_allow_self_signed'] = true;
|
||||
$params['ssl_verify_peer_name'] = false;
|
||||
if (!isset($server['Server']['cert_file']))
|
||||
$params['ssl_verify_peer'] = false;
|
||||
}
|
||||
}
|
||||
$HttpSocket = new HttpSocket($params);
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ class Attribute extends AppModel {
|
|||
|
||||
// skip Correlation for the following types
|
||||
public $nonCorrelatingTypes = array(
|
||||
'vulnerability',
|
||||
'comment',
|
||||
'http-method',
|
||||
'aba-rtn',
|
||||
|
@ -205,6 +204,8 @@ class Attribute extends AppModel {
|
|||
'ip-dst|port' => array('desc' => 'IP destination and port number seperated by a |', 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'ip-src|port' => array('desc' => 'IP source and port number seperated by a |', 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'hostname|port' => array('desc' => 'Hostname and port number seperated by a |', 'default_category' => 'Network activity', 'to_ids' => 1),
|
||||
'mac-address' => array('desc' => 'Mac address', 'default_category' => 'Network activity', 'to_ids' => 0),
|
||||
'mac-eui-64' => array('desc' => 'Mac EUI-64 address', 'default_category' => 'Network activity', 'to_ids' => 0),
|
||||
// verify IDS flag defaults for these
|
||||
'email-dst-display-name' => array('desc' => 'Email destination display name', 'default_category' => 'Payload delivery', 'to_ids' => 0),
|
||||
'email-src-display-name' => array('desc' => 'Email source display name', 'default_category' => 'Payload delivery', 'to_ids' => 0),
|
||||
|
@ -269,7 +270,7 @@ class Attribute extends AppModel {
|
|||
'Payload delivery' => array(
|
||||
'desc' => 'Information about how the malware is delivered',
|
||||
'formdesc' => 'Information about the way the malware payload is initially delivered, for example information about the email or web-site, vulnerability used, originating IP etc. Malware sample itself should be attached here.',
|
||||
'types' => array('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy','authentihash', 'pehash', 'tlsh', 'filename', '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|impfuzzy', 'filename|pehash', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'hostname', 'domain', 'email-src', 'email-dst', 'email-subject', 'email-attachment', 'email-body', 'url', 'user-agent', 'AS', 'pattern-in-file', 'pattern-in-traffic', 'yara', 'sigma', 'attachment', 'malware-sample', 'link', 'malware-type', 'comment', 'text', 'hex', 'vulnerability', 'x509-fingerprint-sha1', 'other', 'hostname|port', 'email-dst-display-name', 'email-src-display-name', 'email-header', 'email-reply-to', 'email-x-mailer', 'email-mime-boundary', 'email-thread-index', 'email-message-id', 'mobile-application-id', 'whois-registrant-email')
|
||||
'types' => array('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy','authentihash', 'pehash', 'tlsh', 'filename', '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|impfuzzy', 'filename|pehash', 'mac-address', 'mac-eui-64', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'hostname', 'domain', 'email-src', 'email-dst', 'email-subject', 'email-attachment', 'email-body', 'url', 'user-agent', 'AS', 'pattern-in-file', 'pattern-in-traffic', 'yara', 'sigma', 'attachment', 'malware-sample', 'link', 'malware-type', 'comment', 'text', 'hex', 'vulnerability', 'x509-fingerprint-sha1', 'other', 'hostname|port', 'email-dst-display-name', 'email-src-display-name', 'email-header', 'email-reply-to', 'email-x-mailer', 'email-mime-boundary', 'email-thread-index', 'email-message-id', 'mobile-application-id', 'whois-registrant-email')
|
||||
),
|
||||
'Artifacts dropped' => array(
|
||||
'desc' => 'Any artifact (files, registry keys etc.) dropped by the malware or other modifications to the system',
|
||||
|
@ -287,7 +288,7 @@ class Attribute extends AppModel {
|
|||
),
|
||||
'Network activity' => array(
|
||||
'desc' => 'Information about network traffic generated by the malware',
|
||||
'types' => array('ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'port', 'hostname', 'domain', 'domain|ip', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-file', 'pattern-in-traffic', 'attachment', 'comment', 'text', 'x509-fingerprint-sha1', 'other', 'hex', 'cookie')
|
||||
'types' => array('ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'port', 'hostname', 'domain', 'domain|ip', 'mac-address', 'mac-eui-64', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-file', 'pattern-in-traffic', 'attachment', 'comment', 'text', 'x509-fingerprint-sha1', 'other', 'hex', 'cookie')
|
||||
),
|
||||
'Payload type' => array(
|
||||
'desc' => 'Information about the final payload(s)',
|
||||
|
@ -296,12 +297,12 @@ class Attribute extends AppModel {
|
|||
),
|
||||
'Attribution' => array(
|
||||
'desc' => 'Identification of the group, organisation, or country behind the attack',
|
||||
'types' => array('threat-actor', 'campaign-name', 'campaign-id', 'whois-registrant-phone', 'whois-registrant-email', 'whois-registrant-name', 'whois-registrar', 'whois-creation-date','comment', 'text', 'x509-fingerprint-sha1', 'other')
|
||||
'types' => array('threat-actor', 'campaign-name', 'campaign-id', 'whois-registrant-phone', 'whois-registrant-email', 'whois-registrant-name', 'whois-registrar', 'whois-creation-date','comment', 'text', 'x509-fingerprint-sha1', 'other', 'dns-soa-email')
|
||||
),
|
||||
'External analysis' => array(
|
||||
'desc' => 'Any other result from additional analysis of the malware like tools output',
|
||||
'formdesc' => 'Any other result from additional analysis of the malware like tools output Examples: pdf-parser output, automated sandbox analysis, reverse engineering report.',
|
||||
'types' => array('md5', 'sha1', 'sha256','filename', 'filename|md5', 'filename|sha1', 'filename|sha256', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'hostname', 'domain', 'domain|ip', 'url', 'user-agent', 'regkey', 'regkey|value', 'AS', 'snort', 'pattern-in-file', 'pattern-in-traffic', 'pattern-in-memory', 'vulnerability', 'attachment', 'malware-sample', 'link', 'comment', 'text', 'x509-fingerprint-sha1', 'github-repository', 'other', 'cortex')
|
||||
'types' => array('md5', 'sha1', 'sha256','filename', 'filename|md5', 'filename|sha1', 'filename|sha256', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'mac-address', 'mac-eui-64', 'hostname', 'domain', 'domain|ip', 'url', 'user-agent', 'regkey', 'regkey|value', 'AS', 'snort', 'pattern-in-file', 'pattern-in-traffic', 'pattern-in-memory', 'vulnerability', 'attachment', 'malware-sample', 'link', 'comment', 'text', 'x509-fingerprint-sha1', 'github-repository', 'other', 'cortex')
|
||||
),
|
||||
'Financial fraud' => array(
|
||||
'desc' => 'Financial Fraud indicators',
|
||||
|
@ -347,6 +348,8 @@ class Attribute extends AppModel {
|
|||
'filename' => 'Payload delivery',
|
||||
'ip-src' => 'Network activity',
|
||||
'ip-dst' => 'Network activity',
|
||||
'mac-address' => 'Network activity',
|
||||
'mac-eui-64' => 'Network activity',
|
||||
'hostname' => 'Network activity',
|
||||
'domain' => 'Network activity',
|
||||
'url' => 'Network activity',
|
||||
|
@ -357,7 +360,8 @@ class Attribute extends AppModel {
|
|||
'hex' => 'Other',
|
||||
'attachment' => 'External analysis',
|
||||
'malware-sample' => 'Payload delivery',
|
||||
'cortex' => 'External analysis'
|
||||
'cortex' => 'External analysis',
|
||||
'dns-soa-email' => 'Attribution'
|
||||
);
|
||||
|
||||
// typeGroupings are a mapping to high level groups for attributes
|
||||
|
@ -366,7 +370,7 @@ class Attribute extends AppModel {
|
|||
// This helps generate quick filtering for the event view, but we may reuse this and enhance it in the future for other uses (such as the API?)
|
||||
public $typeGroupings = array(
|
||||
'file' => array('attachment', 'pattern-in-file', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy','authentihash', 'pehash', 'tlsh', 'filename', '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', 'x509-fingerprint-sha1'),
|
||||
'network' => array('ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port', 'hostname', 'hostname|port', 'domain', 'domain|ip', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-traffic', 'x509-fingerprint-sha1'),
|
||||
'network' => array('ip-src', 'ip-dst', 'ip-src|port', 'ip-dst|port', 'mac-address', 'mac-eui-64', 'hostname', 'hostname|port', 'domain', 'domain|ip', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-traffic', 'x509-fingerprint-sha1'),
|
||||
'financial' => array('btc', 'iban', 'bic', 'bank-account-nr', 'aba-rtn', 'bin', 'cc-number', 'prtn', 'phone-number')
|
||||
);
|
||||
|
||||
|
@ -900,6 +904,16 @@ class Attribute extends AppModel {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 'mac-address':
|
||||
if (preg_match('/^([a-fA-F0-9]{2}[:|\-| |\.]?){6}$/', $value) == 1) {
|
||||
$returnValue = true;
|
||||
}
|
||||
break;
|
||||
case 'mac-eui-64':
|
||||
if (preg_match('/^([a-fA-F0-9]{2}[:|\-| |\.]?){8}$/', $value) == 1) {
|
||||
$returnValue = true;
|
||||
}
|
||||
break;
|
||||
case 'hostname':
|
||||
case 'domain':
|
||||
if (preg_match("#^[A-Z0-9.\-_]+\.[A-Z0-9\-]{2,}$#i", $value)) {
|
||||
|
@ -935,7 +949,7 @@ class Attribute extends AppModel {
|
|||
case 'dns-soa-email':
|
||||
case 'jabber-id':
|
||||
// we don't use the native function to prevent issues with partial email addresses
|
||||
if (preg_match("#^[A-Z0-9._&%$+-=~]*@[A-Z0-9.\-_]+\.[A-Z0-9\-]{2,}$#i", $value)) {
|
||||
if (preg_match("#^.*\@.*\..*$#i", $value)) {
|
||||
$returnValue = true;
|
||||
} else {
|
||||
$returnValue = 'Email address has an invalid format. Please double check the value or select type "other".';
|
||||
|
@ -1206,6 +1220,11 @@ class Attribute extends AppModel {
|
|||
}
|
||||
return $parts[0] . '|' . $parts[1];
|
||||
break;
|
||||
case 'mac-address':
|
||||
case 'mac-eui-64':
|
||||
$value = str_replace(array('.', ':', '-', ' '), '', $value);
|
||||
$value = wordwrap($value, 2, ':', true);
|
||||
break;
|
||||
case 'hostname|port':
|
||||
$value = strtolower($value);
|
||||
str_replace(':', '|', $value);
|
||||
|
@ -2990,7 +3009,8 @@ class Attribute extends AppModel {
|
|||
return true;
|
||||
}
|
||||
} else {
|
||||
$attribute['timestamp'] = $date;
|
||||
$date = new DateTime();
|
||||
$attribute['timestamp'] = $date->getTimestamp();;
|
||||
}
|
||||
} else {
|
||||
$this->create();
|
||||
|
@ -2999,7 +3019,7 @@ class Attribute extends AppModel {
|
|||
$this->create();
|
||||
}
|
||||
$attribute['event_id'] = $eventId;
|
||||
if ($attribute['distribution'] == 4) {
|
||||
if (isset($attribute['distribution']) && $attribute['distribution'] == 4) {
|
||||
$attribute['sharing_group_id'] = $this->SharingGroup->captureSG($attribute['SharingGroup'], $user);
|
||||
}
|
||||
$fieldList = array(
|
||||
|
|
|
@ -425,10 +425,10 @@ class Event extends AppModel {
|
|||
$this->Correlation = ClassRegistry::init('Correlation');
|
||||
$db = $this->getDataSource();
|
||||
if (isset($this->data['Event']['date'])) {
|
||||
$this->Correlation->updateAll(array('Correlation.date' => $db->value($this->data['Event']['date'])), array('Correlation.event_id' => $db->value($this->data['Event']['id'])));
|
||||
$this->Correlation->updateAll(array('Correlation.date' => $db->value($this->data['Event']['date'])), array('Correlation.event_id' => intval($this->data['Event']['id'])));
|
||||
}
|
||||
if (isset($this->data['Event']['info'])) {
|
||||
$this->Correlation->updateAll(array('Correlation.info' => $db->value($this->data['Event']['info'])), array('Correlation.event_id' => $db->value($this->data['Event']['id'])));
|
||||
$this->Correlation->updateAll(array('Correlation.info' => $db->value($this->data['Event']['info'])), array('Correlation.event_id' => intval($this->data['Event']['id'])));
|
||||
}
|
||||
}
|
||||
if (empty($this->data['Event']['unpublishAction']) && empty($this->data['Event']['skip_zmq']) && Configure::read('Plugin.ZeroMQ_enable') && Configure::read('Plugin.ZeroMQ_event_notifications_enable')) {
|
||||
|
|
|
@ -3,7 +3,16 @@
|
|||
App::uses('AppModel', 'Model');
|
||||
|
||||
class Log extends AppModel {
|
||||
|
||||
public $warningActions = array(
|
||||
'warning',
|
||||
'change_pw',
|
||||
'login_fail',
|
||||
'version_warning',
|
||||
'auth_fail'
|
||||
);
|
||||
public $errorActions = array(
|
||||
'error'
|
||||
);
|
||||
public $validate = array(
|
||||
'action' => array(
|
||||
'rule' => array('inList', array(
|
||||
|
@ -94,6 +103,7 @@ class Log extends AppModel {
|
|||
$this->data['Log'][$tf] = substr($this->data['Log'][$tf], 0, 65532) . '...';
|
||||
}
|
||||
}
|
||||
$this->logData($this->data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -223,4 +233,31 @@ class Log extends AppModel {
|
|||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
function logData($data) {
|
||||
if (Configure::read('Plugin.ZeroMQ_enable') && Configure::read('Plugin.ZeroMQ_user_notifications_enable')) {
|
||||
$pubSubTool = $this->getPubSubTool();
|
||||
$pubSubTool->publish($data, 'audit', 'log');
|
||||
}
|
||||
if (Configure::read('Security.syslog')) {
|
||||
// write to syslogd as well
|
||||
$syslog = new SysLog();
|
||||
$action = 'info';
|
||||
if (isset($data['Log']['action'])) {
|
||||
if (in_array($data['Log']['action'], $this->errorActions)) {
|
||||
$action = 'err';
|
||||
}
|
||||
if (in_array($data['Log']['action'], $this->warningActions)) {
|
||||
$action = 'warning';
|
||||
}
|
||||
}
|
||||
|
||||
$entry = $data['Log']['action'];
|
||||
if (!empty($data['Log']['description'])) {
|
||||
$entry .= sprintf(' -- %s', $data['Log']['description']);
|
||||
}
|
||||
$syslog->write($action, $entry);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ class Organisation extends AppModel{
|
|||
parent::beforeValidate();
|
||||
if (empty($this->data['Organisation']['uuid'])) {
|
||||
$this->data['Organisation']['uuid'] = CakeText::uuid();
|
||||
} else {
|
||||
$this->data['Organisation']['uuid'] = trim($this->data['Organisation']['uuid']);
|
||||
}
|
||||
$date = date('Y-m-d H:i:s');
|
||||
if (!empty($this->data['Organisation']['restricted_to_domain'])) {
|
||||
|
|
|
@ -952,6 +952,15 @@ class Server extends AppModel {
|
|||
'type' => 'string',
|
||||
'editable' => false,
|
||||
),
|
||||
'syslog' => array(
|
||||
'level' => 0,
|
||||
'description' => 'Enable this setting to pass all audit log entries directly to syslog. Keep in mind, this is verbose and will include user, organisation, event data.',
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'password_policy_length' => array(
|
||||
'level' => 2,
|
||||
'description' => 'Password length requirement. If it is not set or it is set to 0, then the default value is assumed (12).',
|
||||
|
@ -1244,6 +1253,14 @@ class Server extends AppModel {
|
|||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
),
|
||||
'ZeroMQ_audit_notifications_enable' => array(
|
||||
'level' => 2,
|
||||
'description' => 'Enables or disables the publishing of log entries to the ZMQ pubsub feed. Keep in mind, this can get pretty verbose depending on your logging settings.',
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
),
|
||||
'Sightings_enable' => array(
|
||||
'level' => 1,
|
||||
'description' => 'Enables or disables the sighting functionality. When enabled, users can use the UI or the appropriate APIs to submit sightings data about indicators.',
|
||||
|
@ -2204,6 +2221,9 @@ class Server extends AppModel {
|
|||
}
|
||||
|
||||
public function serverSettingReadSingle($settingObject, $settingName, $leafKey) {
|
||||
// invalidate config.php from php opcode cache
|
||||
opcache_reset();
|
||||
|
||||
$setting = Configure::read($settingName);
|
||||
$result = $this->__evaluateLeaf($settingObject, $leafKey, $setting);
|
||||
$result['setting'] = $settingName;
|
||||
|
@ -2800,7 +2820,7 @@ class Server extends AppModel {
|
|||
try {
|
||||
$response = $HttpSocket->get($uri, '', $request);
|
||||
} catch (Exception $e) {
|
||||
if ($response->code != '200') {
|
||||
if (!isset($response) || $response->code != '200') {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
|
@ -2810,11 +2830,11 @@ class Server extends AppModel {
|
|||
'email' => $user['email'],
|
||||
'action' => 'error',
|
||||
'user_id' => $user['id'],
|
||||
'title' => 'Error: Connection to the server has failed.',
|
||||
'title' => 'Error: Connection to the server has failed.' . isset($response->code) ? ' Returned response code: ' . $response->code : '',
|
||||
));
|
||||
}
|
||||
}
|
||||
if ($response->code != '200') {
|
||||
if (!isset($response) || $response->code != '200') {
|
||||
return 1;
|
||||
}
|
||||
$remoteVersion = json_decode($response->body, true);
|
||||
|
|
|
@ -176,7 +176,7 @@ class SharingGroup extends AppModel {
|
|||
} else if ($scope == 'uuid') {
|
||||
$sgs = $this->find('list', array(
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'uuid'),
|
||||
'fields' => array('SharingGroup.id', 'SharingGroup.uuid'),
|
||||
'conditions' => $conditions,
|
||||
));
|
||||
return $sgs;
|
||||
|
|
|
@ -249,20 +249,10 @@ class SysLogLogableBehavior extends LogableBehavior {
|
|||
}
|
||||
}
|
||||
$this->Log->create($logData);
|
||||
$this->Log->save(null, array(
|
||||
'validate' => false));
|
||||
|
||||
// write to syslogd as well
|
||||
$syslog = new SysLog();
|
||||
if (isset($logData['Log']['change'])) {
|
||||
$syslog->write('notice', $logData['Log']['description'].' -- '.$logData['Log']['change']);
|
||||
} else {
|
||||
$syslog->write('notice', $logData['Log']['description']);
|
||||
}
|
||||
$this->Log->save(null, array('validate' => false));
|
||||
}
|
||||
|
||||
function setup(Model $Model, $config = array()) {
|
||||
|
||||
if (!is_array($config)) {
|
||||
$config = array();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
if ($setting['type'] == 'boolean') $setting['value'] = ($setting['value'] === true ? 'true' : 'false');
|
||||
if (isset($setting['options'])) $setting['value'] = $setting['options'][$setting['value']];
|
||||
?>
|
||||
<tr id ="<?php echo h($k); ?>_row">
|
||||
<tr id ="<?php echo h("${subGroup}_$k"); ?>_row" class="subGroup_<?php echo h($subGroup);?>">
|
||||
<?php
|
||||
if (!empty($setting['redacted'])) {
|
||||
$setting['value'] = '*****';
|
||||
|
@ -17,10 +17,10 @@
|
|||
<td class="short" style="<?php echo $bgColour; ?>"><?php echo h($priorities[$setting['level']]);?></td>
|
||||
<td class="short" style="<?php echo $bgColour; ?>"><?php echo h($setting['setting']);?></td>
|
||||
<?php if ((isset($setting['editable']) && !$setting['editable']) || $setting['level'] == 3): ?>
|
||||
<td id="setting_<?php echo $k; ?>_passive" class="inline-field-solid" style="<?php echo $bgColour; ?>width:500px;"><?php echo nl2br(h($setting['value']));?></td>
|
||||
<td id="setting_<?php echo h("${subGroup}_$k"); ?>_passive" class="inline-field-solid" style="<?php echo $bgColour; ?>width:500px;"><?php echo nl2br(h($setting['value']));?></td>
|
||||
<?php else: ?>
|
||||
<td id="setting_<?php echo $k; ?>_solid" class="inline-field-solid" ondblclick="serverSettingsActivateField('<?php echo $setting['setting'];?>', '<?php echo $k;?>')" style="<?php echo $bgColour; ?>width:500px;"><?php echo h($setting['value']);?></td>
|
||||
<td id="setting_<?php echo $k; ?>_placeholder" class="short hidden inline-field-placeholder" style="<?php echo $bgColour; ?>width:500px;"></td>
|
||||
<td id="setting_<?php echo h("${subGroup}_$k"); ?>_solid" class="inline-field-solid" ondblclick="serverSettingsActivateField('<?php echo $setting['setting'];?>', '<?php echo $k;?>')" style="<?php echo $bgColour; ?>width:500px;"><?php echo h($setting['value']);?></td>
|
||||
<td id="setting_<?php echo h("${subGroup}_$k"); ?>_placeholder" class="short hidden inline-field-placeholder" style="<?php echo $bgColour; ?>width:500px;"></td>
|
||||
<?php endif; ?>
|
||||
<td style="<?php echo $bgColour; ?>"><?php echo h($setting['description']);?></td>
|
||||
<td class="short" style="<?php echo $bgColour; ?>"><?php if (isset($setting['error']) && $setting['level'] != 3) echo h($setting['errorMessage']); ?></td>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<div class="index">
|
||||
<h2><?php echo h($title);?></h2>
|
||||
<p>Below you can see the attributes 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. </p>
|
||||
<?php $scope = !empty($proposals) ? 'proposals' : 'attributes'; ?>
|
||||
<p>Below you can see the <?php echo $scope; ?> 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. </p>
|
||||
<?php
|
||||
$instanceDefault = 5;
|
||||
if (!empty(Configure::read('MISP.default_attribute_distribution'))) {
|
||||
|
@ -194,7 +195,7 @@
|
|||
?>
|
||||
</table>
|
||||
<span>
|
||||
<button class="btn btn-primary" style="float:left;" onClick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', '<?php echo count($resultArray); ?>', '<?php echo h($type); ?>');">Submit</button>
|
||||
<button class="btn btn-primary" style="float:left;" onClick="freetextImportResultsSubmit('<?php echo h($event['Event']['id']); ?>', '<?php echo count($resultArray); ?>', '<?php echo h($type); ?>');">Submit <?php echo $scope; ?></button>
|
||||
<span style="float:right">
|
||||
<?php
|
||||
if (!empty($optionsRearranged)):
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
echo $this->fetch('script');
|
||||
|
||||
echo $this->Html->script('jquery'); // Include jQuery library
|
||||
echo $this->Html->script('misp-touch'); // touch interface support
|
||||
?>
|
||||
|
||||
</head>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b046eb4ba77ac6f01f99e7c0b62a1d7e85a66e39
|
||||
Subproject commit b83616d520dbfaca6f312a3ff54a53aedc8dc5d5
|
|
@ -74,9 +74,9 @@ def main(args):
|
|||
command = r.lpop(namespace + ":command")
|
||||
if command is not None:
|
||||
handleCommand(command)
|
||||
topics = ["misp_json", "misp_json_event", "misp_json_attribute", "misp_json_sighting",
|
||||
topics = ["misp_json", "misp_json_event", "misp_json_attribute", "misp_json_sighting",
|
||||
"misp_json_organisation", "misp_json_user", "misp_json_conversation",
|
||||
"misp_json_object", "misp_json_object_reference"]
|
||||
"misp_json_object", "misp_json_object_reference", "misp_json_audit"]
|
||||
message_received = False
|
||||
for topic in topics:
|
||||
data = r.lpop(namespace + ":data:" + topic)
|
||||
|
@ -84,7 +84,7 @@ def main(args):
|
|||
pubMessage(topic, data, socket)
|
||||
message_received = True
|
||||
if (message_received == False):
|
||||
time.sleep(1)
|
||||
time.sleep(0.2)
|
||||
if ((int(time.time()) - start_time) % 10 == 0):
|
||||
status_entry = int(((int(time.time()) - start_time)/10) % 5)
|
||||
status_message = {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys, json, os, datetime, re
|
||||
import sys, json, os, datetime, re, base64
|
||||
import pymisp
|
||||
from stix2 import *
|
||||
from misp2stix2_dictionaries import *
|
||||
|
@ -28,12 +28,10 @@ non_indicator_attributes = ['text', 'comment', 'other', 'link', 'target-user', '
|
|||
'target-machine', 'target-org', 'target-location', 'target-external',
|
||||
'vulnerability', 'attachment']
|
||||
|
||||
noChangesTypes = ['', '']
|
||||
|
||||
def saveFile(args, pathname, package):
|
||||
def saveFile(args, package):
|
||||
filename = args[1] + '.out'
|
||||
with open(filename, 'w') as f:
|
||||
f.write(str(package))
|
||||
f.write(json.dumps(package, cls=base.STIXJSONEncoder))
|
||||
|
||||
# converts timestamp to the format used by STIX
|
||||
def getDateFromTimestamp(timestamp):
|
||||
|
@ -57,7 +55,7 @@ def readAttributes(event, identity, object_refs, external_refs):
|
|||
if attr_type in non_indicator_attributes:
|
||||
if attr_type == "link":
|
||||
handleLink(attribute, external_refs)
|
||||
elif attr_type in ('text', 'comment', 'other'):
|
||||
elif attr_type in ('text', 'comment', 'other') or attr_type not in mispTypesMapping:
|
||||
addCustomObject(object_refs, attributes, attribute, identity)
|
||||
else:
|
||||
handleNonIndicatorAttribute(object_refs, attributes, attribute, identity)
|
||||
|
@ -72,7 +70,13 @@ def readAttributes(event, identity, object_refs, external_refs):
|
|||
addObservedData(object_refs, attributes, attribute, identity)
|
||||
else:
|
||||
addCustomObject(object_refs, attributes, attribute, identity)
|
||||
if event.Galaxy:
|
||||
galaxy = False
|
||||
try:
|
||||
if event.Galaxy:
|
||||
galaxy = True
|
||||
except:
|
||||
pass
|
||||
if galaxy:
|
||||
galaxies = event.Galaxy
|
||||
for galaxy in galaxies:
|
||||
galaxyType = galaxy['type']
|
||||
|
@ -88,7 +92,13 @@ def readAttributes(event, identity, object_refs, external_refs):
|
|||
addThreatActor(object_refs, attributes, galaxy, identity)
|
||||
elif galaxyType in ['rat', 'exploit-kit'] or 'tool' in galaxyType:
|
||||
addTool(object_refs, attributes, galaxy, identity)
|
||||
if event.Object:
|
||||
objct = False
|
||||
try:
|
||||
if event.Object:
|
||||
objct = True
|
||||
except:
|
||||
pass
|
||||
if objct:
|
||||
for obj in event.Object:
|
||||
to_ids = False
|
||||
for obj_attr in obj.Attribute:
|
||||
|
@ -366,18 +376,23 @@ def defineObservableObject(attr_type, attr_val):
|
|||
if '|' in attr_type:
|
||||
_, attr_type2 = attr_type.split('|')
|
||||
attr_val1, attr_val2 = attr_val.split('|')
|
||||
object1 = observed_object['1']
|
||||
if '|ip' in attr_type:
|
||||
object1 = observed_object['1']
|
||||
addr_type = defineAddressType(attr_val2)
|
||||
object0['value'] = attr_val1
|
||||
object1['type'] = addr_type
|
||||
object1['value'] = attr_val2
|
||||
elif 'ip-' in attr_type:
|
||||
object1 = observed_object['1']
|
||||
addr_type = defineAddressType(attr_val2)
|
||||
prot_type = addr_type.split('-')[0]
|
||||
object1['protocols'].append(prot_type)
|
||||
object0['type'] = addr_type
|
||||
object0['value'] = attr_val1
|
||||
object1['dst_port'] = attr_val2
|
||||
object1['protocols'].append(defineProtocols[attr_val2] if attr_val2 in defineProtocols else 'tcp')
|
||||
elif 'hostname' in attr_type:
|
||||
object1 = observed_object['1']
|
||||
object0['value'] = attr_val1
|
||||
object1['dst_port'] = attr_val2
|
||||
elif 'regkey' in attr_type:
|
||||
|
@ -394,11 +409,16 @@ def defineObservableObject(attr_type, attr_val):
|
|||
if 'x509' in attr_type:
|
||||
object0['hashes']['sha1'] = attr_val
|
||||
return observed_object
|
||||
elif attr_type == 'attachment':
|
||||
payload = attr_val.encode()
|
||||
object0['payload_bin'] = base64.b64encode(payload)
|
||||
elif 'ip-' in attr_type:
|
||||
addr_type = defineAddressType(attr_val)
|
||||
object0['type'] = addr_type
|
||||
elif attr_type == 'port':
|
||||
object0['protocols'].append(defineProtocols[attr_val] if attr_val in defineProtocols else 'tcp')
|
||||
for obj_attr in object0:
|
||||
if obj_attr in ('name', 'value', 'body', 'subject', 'dst_port', 'key'):
|
||||
if obj_attr in ('name', 'value', 'body', 'subject', 'dst_port', 'key', 'display_name'):
|
||||
object0[obj_attr] = attr_val
|
||||
if 'hashes' in obj_attr:
|
||||
object0[obj_attr] = {attr_type: attr_val}
|
||||
|
@ -503,13 +523,18 @@ def defineObservableObjectIpPort(obj_name, obj_attr):
|
|||
attr_type = attr.type
|
||||
if attr_type == 'ip-dst':
|
||||
attr_val = attr.value
|
||||
obj['0']['type'] = defineAddressType(attr_val)
|
||||
addr_type = defineAddressType(attr_val)
|
||||
obj['0']['type'] = addr_type
|
||||
obj['0']['value'] = attr_val
|
||||
prot_type = addr_type.split('-')[0]
|
||||
obj['1']['protocols'].append(prot_type)
|
||||
elif attr_type in ('text', 'datetime'):
|
||||
obj_relation = attr.object_relation
|
||||
if obj_name not in objectTypes[attr_type]:
|
||||
continue
|
||||
obj['1'][objectTypes[attr_type][obj_name][obj_relation]] = attr.value
|
||||
elif 'port' in attr_type:
|
||||
obj['1']['protocols'].append(defineProtocols[attr_val] if attr_val in defineProtocols else 'tcp')
|
||||
else:
|
||||
obj['1'][objectTypes[attr_type][attr.object_relation]] = attr.value
|
||||
return obj
|
||||
|
@ -582,6 +607,13 @@ def getRegistryKeyInfo(obj_attr):
|
|||
return reg_attr
|
||||
|
||||
def definePattern(attr_type, attr_val):
|
||||
if "'" in attr_val:
|
||||
sQuoteTmp = attr_val.replace('\'', '##APOSTROPHE##')
|
||||
attr_val = sQuoteTmp
|
||||
if '"' in attr_val:
|
||||
dQuoteTmp = attr_val.replace('"', '##QUOTE##')
|
||||
#tmp = attr_val.replace('\'', '’')
|
||||
attr_val = dQuoteTmp
|
||||
if '|' in attr_type:
|
||||
attr_type1, attr_type2 = attr_type.split('|')
|
||||
attr_val1, attr_val2 = attr_val.split('|')
|
||||
|
@ -673,27 +705,26 @@ def eventReport(event, identity, object_refs, external_refs):
|
|||
labels.append(tag['name'])
|
||||
|
||||
args_report = {'type': "report", 'id': "report--{}".format(event.uuid), 'created_by_ref': identity,
|
||||
'name': name, 'published': timestamp}
|
||||
'name': name, 'published': timestamp, 'object_refs': object_refs}
|
||||
|
||||
if labels:
|
||||
args_report['labels'] = labels
|
||||
else:
|
||||
args_report['labels'] = ['threat-report']
|
||||
if object_refs:
|
||||
args_report['object_refs'] = object_refs
|
||||
if external_refs:
|
||||
args_report['external_references'] = external_refs
|
||||
report = Report(**args_report)
|
||||
return report
|
||||
|
||||
def generateEventPackage(event, SDOs):
|
||||
#return SDOs
|
||||
bundle_id = event.uuid
|
||||
bundle_args = {'type': "bundle", 'spec_version': "2.0", 'id': "bundle--{}".format(bundle_id), 'objects': SDOs}
|
||||
bundle = Bundle(**bundle_args)
|
||||
return bundle
|
||||
|
||||
def main(args):
|
||||
pathname = os.path.dirname(sys.argv[0])
|
||||
pathname = os.path.dirname(args[0])
|
||||
if len(sys.argv) > 3:
|
||||
namespace[0] = sys.argv[3]
|
||||
if len(sys.argv) > 4:
|
||||
|
@ -712,7 +743,7 @@ def main(args):
|
|||
for attribute in attributes:
|
||||
SDOs.append(attribute)
|
||||
stix_package = generateEventPackage(misp, SDOs)
|
||||
saveFile(args, pathname, stix_package)
|
||||
saveFile(args, stix_package)
|
||||
print(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -90,20 +90,24 @@ mispTypesMapping = {
|
|||
'pattern': 'file:name = \'{0}\' AND file:hashes.\'tlsh\' = \'{1}\''},
|
||||
'x509-fingerprint-sha1': {'observable': {'0': {'type': 'x509-certificate', 'hashes': {'sha1': ''}}},
|
||||
'pattern': 'x509-certificate:hashes = \'{0}\''},
|
||||
'port': {'observable': {'0': {'type': 'network-traffic', 'dst_port': ''}},
|
||||
'port': {'observable': {'0': {'type': 'network-traffic', 'dst_port': '', 'protpocols': []}},
|
||||
'pattern': 'network-traffic:dst_port = \'{0}\''},
|
||||
'ip-dst|port': {'observable': {'0': {'type': '', 'value': ''}, '1': {'type': 'network-traffic', 'dst_ref': '0', 'dst_port': ''}},
|
||||
'ip-dst|port': {'observable': {'0': {'type': '', 'value': ''}, '1': {'type': 'network-traffic', 'dst_ref': '0', 'dst_port': '', 'protocols': []}},
|
||||
'pattern': 'network-traffic:dst_port = \'{1}\' AND network-traffic:dst_ref.type = \'{2}\' AND network-traffic:dst_ref.value = \'{0}\''},
|
||||
'ip-src|port': {'observable': {'0': {'type': '', 'value': ''}, '1': {'type': 'network-traffic', 'src_ref': '0', 'dst_port': ''}},
|
||||
'ip-src|port': {'observable': {'0': {'type': '', 'value': ''}, '1': {'type': 'network-traffic', 'src_ref': '0', 'dst_port': '', 'protocols': []}},
|
||||
'pattern': 'network-traffic:src_port = \'{1}\' AND network-traffic:src_ref.type = \'{2}\' AND network-traffic:src_ref.value = \'{0}\''},
|
||||
'hostname|port': {'observable': {'0': {'type': 'domain-name', 'value': ''}, '1': {'type': 'traffic-network', 'dst_ref': '0', 'dst_port': ''}},
|
||||
'hostname|port': {'observable': {'0': {'type': 'domain-name', 'value': ''}, '1': {'type': 'network-traffic', 'dst_ref': '0', 'dst_port': '', 'protocols': []}},
|
||||
'pattern': 'domain-name:value = \'{0}\' AND network-traffic:dst_port = \'{1}\''},
|
||||
'email-dst-display-name': {'observable': {'0': {'type': 'email-addr', 'display_name': ''}},
|
||||
'pattern': 'email-addr:display_name = \'{0}\''},
|
||||
'email-src-display-name': {'observable': {'0': {'type': 'email-addr', 'display_name': ''}},
|
||||
'pattern': 'email-addr:display_name = \'{0}\''},
|
||||
'email-reply-to': {'observable': {'0': {'type': 'email-addr', 'value': ''}},
|
||||
'pattern': 'email-addr:value = \'{0}\''}
|
||||
'pattern': 'email-addr:value = \'{0}\''},
|
||||
'attachment': {'observable': {'0': {'type': 'artifact', 'payload_bin': ''}},
|
||||
'pattern': 'artifact:payload_bin = \'{0}\''},
|
||||
'mac-address': {'observable': {'0': {'type': 'mac-addr', 'value': ''}},
|
||||
'pattern': 'mac-addr:value = \'{0}\''}
|
||||
}
|
||||
|
||||
objectsMapping = {'domain-ip': {'pattern': 'domain-name:{0} = \'{1}\' AND '},
|
||||
|
@ -158,3 +162,5 @@ objectTypes = {'text': {'x509': {'subject': 'subject', 'issuer': 'issuer', 'pubk
|
|||
'domain-ip': 'resolves_to_refs[*].value'},
|
||||
'reg-datatype': 'datatype', 'reg-data': 'data', 'reg-name': 'name', 'reg-key': 'key'
|
||||
}
|
||||
|
||||
defineProtocols = {'80': 'http', '443': 'https'}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2017 CIRCL Computer Incident Response Center Luxembourg (smile gie)
|
||||
# Copyright (C) 2017 Christian Studer
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys, json, os, time
|
||||
import pymisp
|
||||
|
||||
eventTypes = {"ipv4-addr": {"src": "ip-src", "dst": "ip-dst", "value": "address_value"},
|
||||
"ipv6-addr": {"src": "ip-src", "dst": "ip-dst", "value": "address_value"},
|
||||
"URIObjectType": {"type": "url", "value": "value"},
|
||||
"FileObjectType": {"type": "filename", "value": "file_name"},
|
||||
"to": {"type": "email-dst", "value": "address_value"},
|
||||
"from": {"type": "email-src", "value": "value"},
|
||||
"subject": {"type": "email-subject", "value": "value"},
|
||||
"user_agent": "user-agent"}
|
||||
|
||||
def loadEvent(args, pathname):
|
||||
try:
|
||||
filename = '{}/tmp/{}'.format(pathname, args[1])
|
||||
tempFile = open(filename, 'r')
|
||||
if filename.endswith('.json'):
|
||||
event = json.loads(tempFile.read())
|
||||
return event
|
||||
except:
|
||||
print(json.dumps({'success': 0, 'message': 'The temporary STIX export file could not be read'}))
|
||||
sys.exit(1)
|
||||
|
||||
def getTimestampfromDate(date):
|
||||
dt = date.split("+")[0]
|
||||
return int(time.mktime(time.strptime(dt, "%Y-%m-%dT%H:%M:%S")))
|
||||
|
||||
def buildMispDict(stixEvent):
|
||||
mispDict = {}
|
||||
stixTimestamp = stixEvent.get("timestamp")
|
||||
date = stixTimestamp.split("T")[0]
|
||||
mispDict["date"] = date
|
||||
timestamp = getTimestampfromDate(stixTimestamp)
|
||||
mispDict["timestamp"] = timestamp
|
||||
mispDict["info"] = stixEvent["stix_header"].get("title")
|
||||
event = stixEvent["incidents"][0]
|
||||
orgSource = event["information_source"]["identity"]["name"]
|
||||
orgReporter = event["reporter"]["identity"]["name"]
|
||||
indicators = event["related_indicators"]["indicators"]
|
||||
mispDict["Attribute"] = []
|
||||
for indic in indicators:
|
||||
attribute = {}
|
||||
indicator = indic.get("indicator")
|
||||
timestamp = indicator.get("timestamp").split("+")[0]
|
||||
attribute["timestamp"] = getTimestampfromDate(timestamp)
|
||||
observable = indicator.get("observable")
|
||||
properties = observable["object"]["properties"]
|
||||
try:
|
||||
cat = properties.get("category")
|
||||
if "ip" in cat:
|
||||
if properties.get("is_source"):
|
||||
attr_type = "src"
|
||||
else:
|
||||
attr_type = "dst"
|
||||
typeVal = eventTypes[cat][attr_type]
|
||||
value = eventTypes[cat]["value"]
|
||||
valueVal = properties[value]["value"]
|
||||
except:
|
||||
cat = properties.get("xsi:type")
|
||||
if cat == 'EmailMessageObjectType':
|
||||
header = properties["header"]
|
||||
emailType = list(header)[0]
|
||||
typeVal = eventTypes[emailType]["type"]
|
||||
value = eventTypes[emailType]["value"]
|
||||
headerVal = header[emailType]
|
||||
if emailType == "to":
|
||||
headerVal = headerVal[0]
|
||||
elif emailType == "from":
|
||||
headerVal = headerVal["address_value"]
|
||||
valueVal = headerVal.get(value)
|
||||
elif cat == "FileObjectType" and "hashes" in properties:
|
||||
hashes = properties["hashes"][0]
|
||||
typeVal = hashes["type"].get("value").lower()
|
||||
valueVal = hashes["simple_hash_value"].get("value")
|
||||
elif cat == "HTTPSessionObjectType":
|
||||
http = properties["http_request_response"][0]
|
||||
httpAttr = http["http_client_request"]["http_request_header"]["parsed_header"]
|
||||
attrVal = list(httpAttr)[0]
|
||||
valueVal = httpAttr.get(attrVal)
|
||||
typeVal = eventTypes[attrVal]
|
||||
else:
|
||||
value = eventTypes[cat]["value"]
|
||||
typeVal = eventTypes[cat]["type"]
|
||||
valueVal = properties[value]["value"]
|
||||
attribute["type"] = typeVal
|
||||
attribute["value"] = valueVal
|
||||
attribute["category"] = indic.get("relationship")
|
||||
#print(attribute)
|
||||
mispDict["Attribute"].append(attribute)
|
||||
return mispDict
|
||||
|
||||
def saveFile(args, pathname, misp):
|
||||
filename = "{}/tmp/{}.in".format(pathname, args[1])
|
||||
eventDict = misp.to_dict(with_timestamp=True)
|
||||
print(eventDict)
|
||||
with open(filename, 'w') as f:
|
||||
f.write(json.dumps(eventDict))
|
||||
|
||||
def main(args):
|
||||
pathname = os.path.dirname(args[0])
|
||||
stixEvent = loadEvent(args, pathname)
|
||||
stixEvent = stixEvent["package"]
|
||||
mispDict = buildMispDict(stixEvent)
|
||||
#print(mispDict)
|
||||
misp = pymisp.MISPEvent(None, False)
|
||||
misp.from_dict(**mispDict)
|
||||
saveFile(args, pathname, misp)
|
||||
print(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* support for touch devices without the need
|
||||
*/
|
||||
|
||||
$(document).ready(function() {
|
||||
var touchStartTime = 0;
|
||||
var touchTarget = null;
|
||||
|
||||
document.body.addEventListener('touchstart', function(ev) {
|
||||
if (touchStartTime == 0) {
|
||||
touchStartTime = (new Date()).getTime();
|
||||
touchTarget = ev.target;
|
||||
}
|
||||
}, false);
|
||||
document.body.addEventListener('touchcancel', function(ev) {
|
||||
// iphone only
|
||||
touchStartTime = 0;
|
||||
touchTarget = null;
|
||||
}, false);
|
||||
document.body.addEventListener('touchend', function(ev) {
|
||||
var touchEndTime = (new Date()).getTime();
|
||||
var canTrigger = (touchStartTime > 0 && (touchEndTime - touchStartTime) > 500 && touchTarget == ev.target);
|
||||
|
||||
// reset the variables BEFORE calling the event handler
|
||||
// so that our code works even if the handler dies
|
||||
touchStartTime = 0;
|
||||
touchTarget = null;
|
||||
|
||||
if (canTrigger) {
|
||||
var newEvent = new MouseEvent('dblclick', ev);
|
||||
try {
|
||||
ev.target.dispatchEvent(newEvent);
|
||||
} catch (e) {
|
||||
// don't care, this was complimentary event anyway
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
});
|
Loading…
Reference in New Issue