Merge branch 'quick-fix-metacategory-graph' into ref_graph

pull/3154/head
Sami Mokaddem 2018-04-06 07:50:27 +00:00
commit 921224ed40
75 changed files with 1348 additions and 829 deletions

View File

@ -14,7 +14,7 @@ and how important these are to the users.
## Reporting security vulnerabilities
Reporting security vulnerabilities is of great importance for us, as MISP is used in multiple critical infrastructures. In the case of a security vulnerability report, we ask the reporter to directly report to [CIRCL](https://www.circl.lu/contact/), encrypting the report with the PGP key: CA57 2205 C002 4E06 BA70 BE89 EAAD CFFC 22BD 4CD5. We usually fix reported and confirmed security vulnerabilities in less than 48 hours, followed by a software release containing the fixes within the following days. If you report security vulnerabilities, don't forget to tell us if and how you want to be acknowledged and if you already requested CVE(s). If not, we will request the CVE directly.
Reporting security vulnerabilities is of great importance for us, as MISP is used in multiple critical infrastructures. In the case of a security vulnerability report, we ask the reporter to directly report to [CIRCL](https://www.circl.lu/contact/), encrypting the report with the GnuPG key: CA57 2205 C002 4E06 BA70 BE89 EAAD CFFC 22BD 4CD5. We usually fix reported and confirmed security vulnerabilities in less than 48 hours, followed by a software release containing the fixes within the following days. If you report security vulnerabilities, don't forget to tell us if and how you want to be acknowledged and if you already requested CVE(s). If not, we will request the CVE directly.
As one of the critical user-bases of MISP consists of the CSIRT community, it is our duty to clearly state which bug could be potentially abused and could have a security impact on a deployed MISP instance. CVE assignment is performed even for minor bugs having some possible security impact. This allows users using MISP instances in their environment to understand which bugs could have an impact on their security. We firmly believe that, even though unfortunately it is often not regarded as common practice in our industry, being as transparent as possible about vulnerabilities, no matter how minor, is of absolute crucial importance. At MISP-project, we care about the security of our users and prefer to have a high number of published CVEs than to a few swept under the rug.
@ -26,7 +26,7 @@ If you want to contribute to the [MISP core](https://github.com/MISP/MISP) proje
- Branch off from 2.4 (2.4 branch is the main branch of development in MISP) `git checkout 2.4`
- Then create a branch for your own contribution (bug fixes, enhancement, new features) by typing `git checkout -b fix-glossy-user-interface`
- Work on your fix or feature (only work on that, avoid committing any debug functionalities, testing or unused code)
- Commit your fix or feature (and sign it with PGP - if you have a PGP key) with a meaningful commit message as recommended in [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- Commit your fix or feature (and sign it with GnuPG - if you have a GnuPG key) with a meaningful commit message as recommended in [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- MISP uses [gitchangelog](https://github.com/vaab/gitchangelog/blob/master/src/gitchangelog/gitchangelog.rc.reference) to generate changelog, so it's recommended to use `new:` for new features, `fix:` when it's a bug-fix or `chg` when it's re-factoring or clean-up..
- Push and then open a pull-request via the GitHub interface.

View File

@ -83,7 +83,7 @@ systemctl enable rh-redis32-redis.service
scl enable rh-mariadb102 rh-php71 rh-redis32 bash
2.08/ Secure the MariaDB installation, run the following command and follow the prompts
mysqld_secure_installation
mysql_secure_installation
2.10/ Update the PHP extension repository and install required package
pear channel-update pear.php.net
@ -156,9 +156,9 @@ php composer.phar install
4.03/ Install and configure php redis connector through pecl
pecl install redis
echo "extension=redis.so" > /etc/opt/rh/rh-php56/php-fpm.d/redis.ini
ln -s ../php-fpm.d/redis.ini /etc/opt/rh/rh-php56/php.d/99-redis.ini
systemctl restart rh-php56-php-fpm.service
echo "extension=redis.so" > /etc/opt/rh/rh-php71/php-fpm.d/redis.ini
ln -s ../php-fpm.d/redis.ini /etc/opt/rh/rh-php71/php.d/99-redis.ini
systemctl restart rh-php71-php-fpm.service
4.04/ Set a timezone in php.ini
echo 'date.timezone = "Australia/Sydney"' > /etc/opt/rh/rh-php71/php-fpm.d/timezone.ini
@ -382,7 +382,7 @@ export LIEF_TMP=/tmp/LIEF
export LIEF_INSTALL=/tmp/LIEF_INSTALL
export LIEF_BRANCH=master
cd $LIEF_TMP
git clone --depth 3 --branch $LIEF_BRANCH --single-branch https://github.com/lief-project/LIEF.git LIEF
git clone --branch $LIEF_BRANCH --single-branch https://github.com/lief-project/LIEF.git LIEF
11.04/ Compile lief and install
cd $LIEF_TMP/LIEF

View File

@ -66,7 +66,7 @@ sudo -u www-data git checkout tags/$(git describe --tags `git rev-list --tags --
sudo -u www-data git config core.filemode false
# install Mitre's STIX and its dependencies by running the following commands:
sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev python-setuptools
sudo apt-get install python-dev python-pip python3-pip libxml2-dev libxslt1-dev zlib1g-dev python-setuptools
cd /var/www/MISP/app/files/scripts
sudo -u www-data git clone https://github.com/CybOXProject/python-cybox.git
sudo -u www-data git clone https://github.com/STIXProject/python-stix.git

2
PyMISP

@ -1 +1 @@
Subproject commit 62fb26fafdb751baa666ca7aa0e90d23656b1afe
Subproject commit f805171c51d778d334a8c555fb50718dc3ad1c2b

View File

@ -55,7 +55,7 @@ MISP, Malware Information Sharing Platform and Threat Sharing, core functionalit
- **Expansion modules in Python** to expand MISP with your own services or activate already available [misp-modules](https://github.com/MISP/misp-modules).
- **Sighting support** to get observations from organizations concerning shared indicators and attributes. Sighting [can be contributed](https://www.circl.lu/doc/misp/automation/index.html#sightings-api) via MISP user-interface, API as MISP document or STIX sighting documents.
- **STIX support**: export data in the STIX format (XML and JSON). Additional STIX import and export is supported by [MISP-STIX-Converter](https://github.com/MISP/MISP-STIX-Converter) or [MISP-Taxii-Server](https://github.com/MISP/MISP-Taxii-Server).
- **Integrated encryption and signing of the notifications** via PGP and/or S/MIME depending of the user preferences.
- **Integrated encryption and signing of the notifications** via GnuPG and/or S/MIME depending of the user preferences.
Exchanging info results in *faster detection* of targeted attacks and improves the detection ratio while reducing the false positives. We also avoid reversing similar malware as we know very fast that others team or organizations who already analyzed a specific malware.

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":88}
{"major":2, "minor":4, "hotfix":89}

View File

@ -58,4 +58,30 @@ class AdminShell extends AppShell
$this->Job->saveField('message', 'Job done.');
$this->Job->saveField('status', 4);
}
public function getSetting() {
$param = empty($this->args[0]) ? 'all' : $this->args[0];
$settings = $this->Server->serverSettingsRead();
$result = $settings;
if (!empty($param)) {
$result = 'No valid setting found for ' . $param;
foreach ($settings as $setting) {
if ($setting['setting'] == $param) {
$result = $setting;
break;
}
}
}
echo json_encode($result, JSON_PRETTY_PRINT) . PHP_EOL;
}
public function setSetting() {
$setting = empty($this->args[0]) ? null : $this->args[0];
$value = empty($this->args[1]) ? null : $this->args[1];
if (empty($setting) || $value === null) {
echo 'Invalid parameters. Usage: ' . APP . 'Console/cake Admin setSetting [setting_name] [setting_value]';
} else {
$this->Server->serverSettingsSaveValue($setting, $value);
}
}
}

View File

@ -476,7 +476,7 @@ class EventShell extends AppShell
$this->Job->save($job);
$log = ClassRegistry::init('Log');
$log->create();
$log->createLogEntry($user, 'publish', 'Event', $id, 'Event (' . $id . '): published.', 'publised () => (1)');
$log->createLogEntry($user, 'publish', 'Event', $id, 'Event (' . $id . '): published.', 'published () => (1)');
}
}

View File

@ -20,7 +20,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
// TODO GPG encryption has issues when keys are expired
// TODO GnuPG encryption has issues when keys are expired
App::uses('ConnectionManager', 'Model');
App::uses('Controller', 'Controller');
@ -46,8 +46,8 @@ class AppController extends Controller {
public $helpers = array('Utility', 'OrgImg');
private $__queryVersion = '31';
public $pyMispVersion = '2.4.87';
private $__queryVersion = '33';
public $pyMispVersion = '2.4.89';
public $phpmin = '5.6.5';
public $phprec = '7.0.16';
@ -282,6 +282,18 @@ class AppController extends Controller {
$this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => false));
}
}
$this->set('default_memory_limit', ini_get('memory_limit'));
if (isset($this->Auth->user('Role')['memory_limit'])) {
if ($this->Auth->user('Role')['memory_limit'] !== '') {
ini_set('memory_limit', $this->Auth->user('Role')['memory_limit']);
}
}
$this->set('default_max_execution_time', ini_get('max_execution_time'));
if (isset($this->Auth->user('Role')['max_execution_time'])) {
if ($this->Auth->user('Role')['max_execution_time'] !== '') {
ini_set('max_execution_time', $this->Auth->user('Role')['max_execution_time']);
}
}
} else {
if (!($this->params['controller'] === 'users' && $this->params['action'] === 'login')) $this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => false));
}

View File

@ -125,7 +125,11 @@ class AttributesController extends AppController {
$this->set('categoryDefinitions', $this->Attribute->categoryDefinitions);
}
public function add($eventId) {
public function add($eventId = false) {
if ($this->request->is('get') && $this->_isRest()) {
return $this->RestResponse->describe('Attributes', 'add', false, $this->response->type());
}
if ($eventId === false) throw new MethodNotAllowedException('No event ID set.');
if (!$this->userRole['perm_add']) {
throw new MethodNotAllowedException('You don\'t have permissions to create attributes');
}
@ -742,6 +746,9 @@ class AttributesController extends AppController {
public function edit($id = null) {
if ($this->request->is('get') && $this->_isRest()) {
return $this->RestResponse->describe('Attributes', 'edit', false, $this->response->type());
}
if (Validation::uuid($id)) {
$this->Attribute->recursive = -1;
$temp = $this->Attribute->findByUuid($id);

View File

@ -193,6 +193,7 @@ class ACLComponent extends Component {
'event_index' => array('*'),
'maxDateActivity' => array('*'),
'returnDates' => array('*'),
'testForStolenAttributes' => array(),
'pruneUpdateLogs' => array()
),
'modules' => array(

View File

@ -13,6 +13,18 @@ class RestResponseComponent extends Component {
private $__descriptions = array(
'Attribute' => array(
'add' => array(
'description' => "POST a MISP Attribute JSON to this API to create an Attribute.",
'mandatory' => array('value', 'type'),
'optional' => array('category', 'to_ids', 'uuid', 'distribution', 'sharing_group_id', 'timestamp', 'comment'),
'params' => array('event_id')
),
'edit' => array(
'description' => "POST a MISP Attribute JSON to this API to update an Attribute. If the timestamp is set, it has to be newer than the existing Attribute.",
'mandatory' => array(),
'optional' => array('value', 'type', 'category', 'to_ids', 'uuid', 'distribution', 'sharing_group_id', 'timestamp', 'comment'),
'params' => array('event_id')
),
'deleteSelected' => array(
'description' => "POST a list of attribute IDs in JSON format to this API
to delete the given attributes. This API also expects an event ID passed via
@ -25,6 +37,20 @@ class RestResponseComponent extends Component {
'params' => array('event_id')
)
),
'Event' => array(
'add' => array(
'description' => "POST a MISP Event JSON to this API to create an Event. Contained objects can also be included (such as attributes, objects, tags, etc).",
'mandatory' => array('info'),
'optional' => array('threat_level_id', 'analysis', 'distribution', 'sharing_group_id', 'uuid', 'published', 'timestamp', 'date', 'Attribute', 'Object', 'Shadow_Attribute', 'EventTag'),
'params' => array()
),
'edit' => array(
'description' => "POST a MISP Event JSON to this API to update an Event. Contained objects can also be included (such as attributes, objects, tags, etc). If the timestamp is set, it has to be newer than the existing Attribute.",
'mandatory' => array(),
'optional' => array('info', 'threat_level_id', 'analysis', 'distribution', 'sharing_group_id', 'uuid', 'published', 'timestamp', 'date', 'Attribute', 'Object', 'Shadow_Attribute', 'EventTag'),
'params' => array('event_id')
)
),
'Organisation' => array(
'admin_add' => array(
'description' => "POST an Organisation object in JSON format to this API to create a new organsiation.",

View File

@ -259,7 +259,7 @@ class EventsController extends AppController {
// list the events
$passedArgsArray = array();
$urlparams = "";
$overrideAbleParams = array('all', 'attribute', 'published', 'eventid', 'Datefrom', 'Dateuntil', 'org', 'eventinfo', 'tag', 'distribution', 'sharinggroup', 'analysis', 'threatlevel', 'email', 'hasproposal', 'timestamp', 'publishtimestamp', 'publish_timestamp', 'minimal');
$overrideAbleParams = array('all', 'attribute', 'published', 'eventid', 'Datefrom', 'Dateuntil', 'org', 'eventinfo', 'tag', 'tags', 'distribution', 'sharinggroup', 'analysis', 'threatlevel', 'email', 'hasproposal', 'timestamp', 'publishtimestamp', 'publish_timestamp', 'minimal');
$passedArgs = $this->passedArgs;
if (isset($this->request->data)) {
if (isset($this->request->data['request'])) $this->request->data = $this->request->data['request'];
@ -328,15 +328,19 @@ class EventsController extends AppController {
break;
case 'timestamp':
if ($v == "") continue 2;
if (preg_match('/^[0-9]+[mhdw]$/i', $v)) $v = $this->Event->resolveTimeDelta($v);
$this->paginate['conditions']['AND'][] = array('Event.timestamp >=' => $v);
break;
case 'publish_timestamp':
case 'publishtimestamp':
if ($v == "") continue 2;
if (is_array($v) && isset($v[0]) && isset($v[1])) {
if (preg_match('/^[0-9]+[mhdw]$/i', $v[0])) $v[0] = $this->Event->resolveTimeDelta($v[0]);
if (preg_match('/^[0-9]+[mhdw]$/i', $v[1])) $v[1] = $this->Event->resolveTimeDelta($v[1]);
$this->paginate['conditions']['AND'][] = array('Event.publish_timestamp >=' => $v[0]);
$this->paginate['conditions']['AND'][] = array('Event.publish_timestamp <=' => $v[1]);
} else {
if (preg_match('/^[0-9]+[mhdw]$/i', $v)) $v = $this->Event->resolveTimeDelta($v);
$this->paginate['conditions']['AND'][] = array('Event.publish_timestamp >=' => $v);
}
break;
@ -403,7 +407,8 @@ class EventsController extends AppController {
}
$this->paginate['conditions']['AND'][] = $test;
break;
case 'tag' :
case 'tag':
case 'tags':
if (!$v || !Configure::read('MISP.tagging') || $v === 0) continue 2;
$pieces = explode('|', $v);
$filterString = "";
@ -668,20 +673,20 @@ class EventsController extends AppController {
}
if (!$this->Event->User->getPGP($this->Auth->user('id')) && Configure::read('GnuPG.onlyencrypted')) {
// No GPG
// No GnuPG
if (Configure::read('SMIME.enabled') && !$this->Event->User->getCertificate($this->Auth->user('id'))) {
// No GPG and No SMIME
$this->Session->setFlash(__('No x509 certificate or GPG key set in your profile. To receive emails, submit your public certificate or GPG key in your profile.'));
// No GnuPG and No SMIME
$this->Session->setFlash(__('No x509 certificate or GnuPG key set in your profile. To receive emails, submit your public certificate or GnuPG key in your profile.'));
} else if (!Configure::read('SMIME.enabled')) {
$this->Session->setFlash(__('No GPG key set in your profile. To receive emails, submit your public key in your profile.'));
$this->Session->setFlash(__('No GnuPG key set in your profile. To receive emails, submit your public key in your profile.'));
}
} else if ($this->Auth->user('autoalert') && !$this->Event->User->getPGP($this->Auth->user('id')) && Configure::read('GnuPG.bodyonlyencrypted')) {
// No GPG & autoalert
// No GnuPG & autoalert
if ($this->Auth->user('autoalert') && Configure::read('SMIME.enabled') && !$this->Event->User->getCertificate($this->Auth->user('id'))) {
// No GPG and No SMIME & autoalert
$this->Session->setFlash(__('No x509 certificate or GPG key set in your profile. To receive attributes in emails, submit your public certificate or GPG key in your profile.'));
// No GnuPG and No SMIME & autoalert
$this->Session->setFlash(__('No x509 certificate or GnuPG key set in your profile. To receive attributes in emails, submit your public certificate or GnuPG key in your profile.'));
} else if (!Configure::read('SMIME.enabled')) {
$this->Session->setFlash(__('No GPG key set in your profile. To receive attributes in emails, submit your public key in your profile.'));
$this->Session->setFlash(__('No GnuPG key set in your profile. To receive attributes in emails, submit your public key in your profile.'));
}
}
$this->set('eventDescriptions', $this->Event->fieldDescriptions);
@ -1026,7 +1031,7 @@ class EventsController extends AppController {
if (!empty($event['RelatedAttribute'])) {
foreach ($event['RelatedAttribute'] as $key => $relatedAttribute) {
foreach ($relatedAttribute as $key2 => $relation) {
$event['RelatedAttribute'][$key][$key2]['date'] = $relatedDates[$relation['id']];
if (!empty($relatedDates[$relation['id']])) $event['RelatedAttribute'][$key][$key2]['date'] = $relatedDates[$relation['id']];
}
}
}
@ -1275,6 +1280,7 @@ class EventsController extends AppController {
}
// rearrange the response if the event came from an export
if (isset($this->request->data['response'])) $this->request->data = $this->request->data['response'];
if (!isset($this->request->data['Event'])) $this->request->data['Event'] = $this->request->data;
// Distribution, reporter for the events pushed will be the owner of the authentication key
$this->request->data['Event']['user_id'] = $this->Auth->user('id');
@ -1386,6 +1392,8 @@ class EventsController extends AppController {
}
}
}
} else if ($this->_isRest()) {
return $this->RestResponse->describe('Events', 'add', false, $this->response->type());
}
$this->request->data['Event']['date'] = date('Y-m-d');
@ -1478,7 +1486,7 @@ class EventsController extends AppController {
}
}
public function upload_stix() {
public function upload_stix($stix_version = '1') {
if (!$this->userRole['perm_modify']) {
throw new UnauthorizedException('You do not have permission to do that.');
}
@ -1489,7 +1497,7 @@ class EventsController extends AppController {
$tempFile = new File($tmpDir . DS . $randomFileName, true, 0644);
$tempFile->write($this->request->input());
$tempFile->close();
$result = $this->Event->upload_stix($this->Auth->user(), $randomFileName);
$result = $this->Event->upload_stix($this->Auth->user(), $randomFileName, $stix_version);
if (is_array($result)) {
return $this->RestResponse->saveSuccessResponse('Events', 'upload_stix', false, $this->response->type(), 'STIX document imported, event\'s created: ' . implode(', ', $result) . '.');
} else if (is_numeric($result)) {
@ -1507,7 +1515,7 @@ class EventsController extends AppController {
$randomFileName = $this->Event->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts" . DS . "tmp";
move_uploaded_file($this->data['Event']['stix']['tmp_name'], $tmpDir . DS . $randomFileName);
$result = $this->Event->upload_stix($this->Auth->user(), $randomFileName);
$result = $this->Event->upload_stix($this->Auth->user(), $randomFileName, $stix_version);
if (is_array($result)) {
$this->Session->setFlash(__('STIX document imported, event\'s created: ' . implode(', ', $result) . '.'));
$this->redirect(array('action' => 'index'));
@ -1524,37 +1532,14 @@ class EventsController extends AppController {
}
}
}
}
/*
public function upload_stix2() {
if (!$this->userRole['perm_modify']) {
throw new UnauthorizedException('You do not have permission to do that.');
}
if ($this->request->is('post')) {
if ($this->_isRest()) {
$randomFileName = $this->Event->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts" . DS . "tmp";
$tempFile = new File($tmpDir . DS . $randomFileName, true, 0644);
$tempFile->write($this->request->input());
$tempFile->close();
$result = $this->Event->upload_stix2($this->Auth->user(), $randomFileName);
} else {
if (isset($this->data['Event']['stix']) && $this->data['Event']['stix']['size'] > 0 && is_uploaded_file($this->data['Event']['stix']['tmp_name'])) {
$randomFileName = $this->Event->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts" . DS . "tmp";
move_uploaded_file($this->data['Event']['stix']['tmp_name'], $tmpDir . DS . $randomFileName);
$result = $this->Event->upload_stix($this->Auth->user(), $randomFileName);
} else {
$max_size = intval(ini_get('post_max_size'));
if (intval(ini_get('upload_max_filesize')) < $max_size) $max_size = intval(ini_get('upload_max_filesize'));
throw new UnauthorizedException('File upload failed. Make sure that you select a stix file to be uploaded and that the file doesn\'t exceed the maximum file size of ' . $max_size . '.');
}
}
if ($stix_version == 2) {
$stix_version = '2.x JSON';
} else {
$stix_version = '1.x XML';
}
$this->set('stix_version', $stix_version);
}
*/
public function merge($target_id = null) {
$this->Event->id = $target_id;
@ -1629,6 +1614,9 @@ class EventsController extends AppController {
}
public function edit($id = null) {
if ($this->request->is('get') && $this->_isRest()) {
return $this->RestResponse->describe('Events', 'edit', false, $this->response->type());
}
if (Validation::uuid($id)) {
$temp = $this->Event->find('first', array('recursive' => -1, 'fields' => array('Event.id'), 'conditions' => array('Event.uuid' => $id)));
if (empty($temp)) throw new NotFoundException('Invalid event');
@ -1650,12 +1638,10 @@ class EventsController extends AppController {
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->_isRest()) {
if ($this->_isRest()) {
if (isset($this->request->data['response'])) {
$this->request->data = $this->Event->updateXMLArray($this->request->data, true);
} else {
$this->request->data = $this->Event->updateXMLArray($this->request->data, false);
}
if (isset($this->request->data['response'])) {
$this->request->data = $this->Event->updateXMLArray($this->request->data, true);
} else {
$this->request->data = $this->Event->updateXMLArray($this->request->data, false);
}
// Workaround for different structure in XML/array than what CakePHP expects
if (isset($this->request->data['response'])) $this->request->data = $this->request->data['response'];
@ -1895,7 +1881,7 @@ class EventsController extends AppController {
}
// Send out an alert email to all the users that wanted to be notified.
// Users with a GPG key will get the mail encrypted, other users will get the mail unencrypted
// Users with a GnuPG key will get the mail encrypted, other users will get the mail unencrypted
public function alert($id = null) {
$this->Event->id = $id;
$this->Event->recursive = 0;
@ -1971,7 +1957,7 @@ class EventsController extends AppController {
}
// Send out an contact email to the person who posted the event.
// Users with a GPG key will get the mail encrypted, other users will get the mail unencrypted
// Users with a GnuPG key will get the mail encrypted, other users will get the mail unencrypted
public function contact($id = null) {
$this->Event->id = $id;
if (!$this->Event->exists()) {
@ -3055,7 +3041,6 @@ class EventsController extends AppController {
$eventCount = count($eventIds);
$i = 0;
foreach ($eventIds as $k => $currentEventId) {
$i++;
$result = $this->Event->fetchEvent(
$this->Auth->user(),
array(
@ -3070,12 +3055,14 @@ class EventsController extends AppController {
);
if (!empty($result)) {
$result = $this->Whitelist->removeWhitelistedFromArray($result, false);
$final .= $converter->convert($result[0]);
if ($i < $eventCount) {
if ($i != 0) {
$final .= ',' . PHP_EOL;
}
$final .= $converter->convert($result[0]);
$i++;
}
}
if ($i > 0) $final .= PHP_EOL;
$final .= $converter->generateBottom($responseType, $final);
$extension = $responseType;
if ($key == 'openioc') {
@ -3689,7 +3676,7 @@ class EventsController extends AppController {
}
if ($failed > 0) {
if ($failed == 1) {
$flashMessage = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. Reason for the failure: ' . $this->Event->objectType->validationErrors;
$flashMessage = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. Reason for the failure: ' . json_encode($this->Event->$objectType->validationErrors);
} else {
$flashMessage = $saved . ' ' . $messageScope . ' created' . $emailResult . '. ' . $failed . ' ' . $messageScope . ' could not be saved. This may be due to attributes with similar values already existing.';
}
@ -4066,12 +4053,18 @@ class EventsController extends AppController {
$imports = array(
'MISP' => array(
'url' => '/events/add_misp_export',
'text' => 'MISP standard (recommended exchange format)',
'text' => 'MISP standard (recommended exchange format - lossless)',
'ajax' => false,
'bold' => true
),
'STIX' => array(
'url' => '/events/upload_stix',
'text' => 'STIX 1.1.1 format',
'text' => 'STIX 1.1.1 format (lossy)',
'ajax' => false,
),
'STIX2' => array(
'url' => '/events/upload_stix/2',
'text' => 'STIX 2.0 format (lossy)',
'ajax' => false,
)
);
@ -4305,7 +4298,6 @@ class EventsController extends AppController {
$data = $this->request->is('post') ? $this->request->data : array();
$grapher->construct($this->Event, $this->Taxonomy, $this->GalaxyCluster, $this->Auth->user(), $data);
$json = $grapher->buildGraphJson($id, $type);
array_walk_recursive($json, function(&$item, $key){
if(!mb_detect_encoding($item, 'utf-8', true)){
$item = utf8_encode($item);
@ -4452,7 +4444,7 @@ class EventsController extends AppController {
}
}
}
$data = array('module' => $module, $attribute[0]['Attribute']['type'] => $attribute[0]['Attribute']['value'], 'event_id' => $attribute[0]['Attribute']['event_id']);
$data = array('module' => $module, $attribute[0]['Attribute']['type'] => $attribute[0]['Attribute']['value'], 'event_id' => $attribute[0]['Attribute']['event_id'], 'attribute_uuid' => $attribute[0]['Attribute']['uuid']);
if ($this->Event->Attribute->typeIsAttachment($attribute[0]['Attribute']['type'])) {
$data['data'] = $this->Event->Attribute->base64EncodeAttachment($attribute[0]['Attribute']);
}

View File

@ -31,7 +31,10 @@ class FeedsController extends AppController {
if ($scope !== 'all') {
if ($scope == 'enabled') {
$this->paginate['conditions'][] = array(
'Feed.enabled' => 1
'OR' => array(
'Feed.enabled' => 1,
'Feed.caching_enabled' => 1
)
);
} else {
$this->paginate['conditions'][] = array(
@ -210,7 +213,7 @@ class FeedsController extends AppController {
$this->request->data['Feed']['settings']['delimiter'] = ',';
}
$this->request->data['Feed']['settings'] = json_encode($this->request->data['Feed']['settings']);
$fields = array('id', 'name', 'provider', 'enabled', 'rules', 'url', 'distribution', 'sharing_group_id', 'tag_id', 'fixed_event', 'event_id', 'publish', 'delta_merge', 'source_format', 'override_ids', 'settings', 'input_source', 'delete_local_file', 'lookup_visible', 'headers');
$fields = array('id', 'name', 'provider', 'enabled', 'caching_enabled','rules', 'url', 'distribution', 'sharing_group_id', 'tag_id', 'fixed_event', 'event_id', 'publish', 'delta_merge', 'source_format', 'override_ids', 'settings', 'input_source', 'delete_local_file', 'lookup_visible', 'headers');
$feed = array();
foreach ($fields as $field) {
if (isset($this->request->data['Feed'][$field])) {
@ -686,7 +689,8 @@ class FeedsController extends AppController {
}
}
public function toggleSelected($enable = false, $feedList = false) {
public function toggleSelected($enable = false, $cache = false, $feedList = false) {
$field = $cache ? 'caching_enabled' : 'enabled';
if (!empty($enable)) $enable = 1;
else $enable = 0;
try {
@ -702,8 +706,8 @@ class FeedsController extends AppController {
));
$count = 0;
foreach ($feeds as $feed) {
if ($feed['Feed']['enabled'] != $enable) {
$feed['Feed']['enabled'] = $enable;
if ($feed['Feed'][$field] != $enable) {
$feed['Feed'][$field] = $enable;
$this->Feed->save($feed);
$count++;
}

View File

@ -346,4 +346,31 @@ class LogsController extends AppController {
}
$this->redirect($this->referer());
}
public function testForStolenAttributes() {
$logs = $this->Log->find('list', array(
'recursive' => -1,
'conditions' => array(
'Log.model' => 'Attribute',
'Log.action' => 'edit'
),
'fields' => array('Log.title')
));
$ids = array();
foreach ($logs as $log) {
preg_match('/Attribute \(([0-9]+?)\)/', $log, $attribute_id);
preg_match('/Event \(([0-9]+?)\)/', $log, $event_id);
if (!isset($attribute_id[1])) continue;
if (empty($ids[$attribute_id[1]]) || !in_array($event_id[1], $ids[$attribute_id[1]])) {
$ids[$attribute_id[1]][] = $event_id[1];
}
}
$issues = array();
foreach ($ids as $aid => $eids) {
if (count($eids) > 1) {
$issues[$aid] = $eids;
}
}
$this->set('issues', $issues);
}
}

View File

@ -708,7 +708,7 @@ class ServersController extends AppController {
);
$writeableErrors = array(0 => 'OK', 1 => 'not found', 2 => 'is not writeable');
$readableErrors = array(0 => 'OK', 1 => 'not readable');
$gpgErrors = array(0 => 'OK', 1 => 'FAIL: settings not set', 2 => 'FAIL: Failed to load GPG', 3 => 'FAIL: Issues with the key/passphrase', 4 => 'FAIL: encrypt failed');
$gpgErrors = array(0 => 'OK', 1 => 'FAIL: settings not set', 2 => 'FAIL: Failed to load GnuPG', 3 => 'FAIL: Issues with the key/passphrase', 4 => 'FAIL: encrypt failed');
$proxyErrors = array(0 => 'OK', 1 => 'not configured (so not tested)', 2 => 'Getting URL via proxy failed');
$zmqErrors = array(0 => 'OK', 1 => 'not enabled (so not tested)', 2 => 'Python ZeroMQ library not installed correctly.', 3 => 'ZeroMQ script not running.');
$stixOperational = array(0 => 'STIX or CyBox or mixbox library not installed correctly', 1 => 'OK');
@ -821,7 +821,7 @@ class ServersController extends AppController {
// check if the STIX and Cybox libraries are working and the correct version using the test script stixtest.py
$stix = $this->Server->stixDiagnostics($diagnostic_errors, $stixVersion, $cyboxVersion, $mixboxVersion);
// if GPG is set up in the settings, try to encrypt a test message
// if GnuPG is set up in the settings, try to encrypt a test message
$gpgStatus = $this->Server->gpgDiagnostics($diagnostic_errors);
// if the message queue pub/sub is enabled, check whether the extension works

View File

@ -490,7 +490,12 @@ class UsersController extends AppController {
$this->loadModel('Role');
$this->Role->recursive = -1;
$chosenRole = $this->Role->findById($this->request->data['User']['role_id']);
if ($chosenRole['Role']['perm_site_admin'] == 1 || $chosenRole['Role']['perm_regexp_access'] == 1 || $chosenRole['Role']['perm_sync'] == 1) {
if (
$chosenRole['Role']['perm_site_admin'] == 1 ||
$chosenRole['Role']['perm_regexp_access'] == 1 ||
$chosenRole['Role']['perm_sync'] == 1 ||
$chosenRole['Role']['restricted_to_site_admin'] == 1
) {
throw new Exception('You are not authorised to assign that role to a user.');
}
}
@ -617,7 +622,7 @@ class UsersController extends AppController {
$params = array('conditions' => array(
'OR' => array(
'AND' => array(
'perm_site_admin' => 0, 'perm_sync' => 0, 'perm_regexp_access' => 0
'perm_site_admin' => 0, 'perm_sync' => 0, 'perm_regexp_access' => 0, 'restricted_to_site_admin' => 0
),
'id' => $allowedRole,
)

View File

@ -192,67 +192,111 @@ class ComplexTypeTool {
128 => array('single' => array('sha512'), 'composite' => array('filename|sha512'))
);
private function __resolveType($input) {
$input = trim($input);
if (strpos($input, '|')) {
$compositeParts = explode('|', $input);
if (count($compositeParts) == 2) {
if ($this->__resolveFilename($compositeParts[0])) {
foreach ($this->__hexHashTypes as $k => $v) {
if (strlen($compositeParts[1]) == $k && preg_match("#[0-9a-f]{" . $k . "}$#i", $compositeParts[1])) return array('types' => $v['composite'], 'to_ids' => true, 'default_type' => $v['composite'][0], 'value' => $input);
}
if (preg_match('#^[0-9]+:[0-9a-zA-Z\/\+]+:[0-9a-zA-Z\/\+]+$#', $compositeParts[1]) && !preg_match('#^[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$#', $compositeParts[1])) {
return array('types' => array('filename|ssdeep'), 'to_ids' => true, 'default_type' => 'filename|ssdeep', 'value' => $input);
// algorithms to run through in order
private $__checks = array('Hashes', 'Email', 'IP', 'DomainOrFilename', 'SimpleRegex');
private function __resolveType($raw_input) {
$input = array(
'raw' => trim($raw_input)
);
$input = $this->__refangInput($input);
$input = $this->__extractPort($input);
foreach ($this->__checks as $check) {
$result = $this->{'__checkFor' . $check}($input);
if ($result) return $result;
}
return false;
}
private function __checkForEmail($input) {
// quick filter for an @ to see if we should validate a potential e-mail address
if (strpos($input['refanged'], '@') !== false) {
if (filter_var($input['refanged'], 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['refanged']);
}
return false;
}
private function __checkForHashes($input) {
// handle prepared composite values with the filename|hash format
if (strpos($input['raw'], '|')) {
$compositeParts = explode('|', $input['raw']);
if (count($compositeParts) == 2) {
if ($this->__resolveFilename($compositeParts[0])) {
foreach ($this->__hexHashTypes as $k => $v) {
if (strlen($compositeParts[1]) == $k && preg_match("#[0-9a-f]{" . $k . "}$#i", $compositeParts[1])) return array('types' => $v['composite'], 'to_ids' => true, 'default_type' => $v['composite'][0], 'value' => $input['raw']);
}
if (preg_match('#^[0-9]+:[0-9a-zA-Z\/\+]+:[0-9a-zA-Z\/\+]+$#', $compositeParts[1]) && !preg_match('#^[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$#', $compositeParts[1])) {
return array('types' => array('filename|ssdeep'), 'to_ids' => true, 'default_type' => 'filename|ssdeep', 'value' => $input['raw']);
}
}
}
}
}
// check for hashes
foreach ($this->__hexHashTypes as $k => $v) {
if (strlen($input) == $k && preg_match("#[0-9a-f]{" . $k . "}$#i", $input)) return array('types' => $v['single'], 'to_ids' => true, 'default_type' => $v['single'][0], 'value' => $input);
}
if (preg_match('#^[0-9]+:[0-9a-zA-Z\/\+]+:[0-9a-zA-Z\/\+]+$#', $input) && !preg_match('#^[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$#', $input)) return array('types' => array('ssdeep'), 'to_ids' => true, 'default_type' => 'ssdeep', 'value' => $input);
$inputRefanged = $input;
foreach ($this->__refangRegexTable as $regex => $replacement) {
$inputRefanged = preg_replace($regex, $replacement , $inputRefanged);
}
$inputRefanged = rtrim($inputRefanged, ".");
if (strpos($inputRefanged, '@') !== false) {
if (filter_var($inputRefanged, FILTER_VALIDATE_EMAIL)) return array('types' => array('email-src', 'email-dst', 'target-email', 'whois-registrant-email'), 'to_ids' => true, 'default_type' => 'email-src', 'value' => $inputRefanged);
}
// check for hashes
foreach ($this->__hexHashTypes as $k => $v) {
if (strlen($input['raw']) == $k && preg_match("#[0-9a-f]{" . $k . "}$#i", $input['raw'])) return array('types' => $v['single'], 'to_ids' => true, 'default_type' => $v['single'][0], 'value' => $input['raw']);
}
// ssdeep has a different pattern
if (preg_match('#^[0-9]+:[0-9a-zA-Z\/\+]+:[0-9a-zA-Z\/\+]+$#', $input['raw']) && !preg_match('#^[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$#', $input['raw'])) return array('types' => array('ssdeep'), 'to_ids' => true, 'default_type' => 'ssdeep', 'value' => $input['raw']);
return false;
}
private function __extractPort($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
$comment = false;
if (preg_match('/(:[0-9]{2,5})$/', $inputRefanged, $port)) {
$comment = 'On port ' . substr($port[0], 1);
$inputRefangedNoPort = str_replace($port[0], '', $inputRefanged);
$port = substr($port[0], 1);
$input['comment'] = false;
if (preg_match('/(:[0-9]{2,5})$/', $input['refanged'], $input['port'])) {
$input['comment'] = 'On port ' . substr($input['port'][0], 1);
$input['refanged_no_port'] = str_replace($input['port'][0], '', $input['refanged']);
$input['port'] = substr($input['port'][0], 1);
} else {
unset($port);
$inputRefangedNoPort = $inputRefanged;
unset($input['port']);
$input['refanged_no_port'] = $input['refanged'];
}
// check for IP
if (filter_var($inputRefangedNoPort, FILTER_VALIDATE_IP)) {
if (isset($port)) {
return array('types' => array('ip-dst|port', 'ip-src|port', 'ip-src|port/ip-dst|port'), 'to_ids' => true, 'default_type' => 'ip-dst|port', 'comment' => $comment, 'value' => $inputRefangedNoPort . '|' . $port);
return $input;
}
private function __refangInput($input) {
$input['refanged'] = $input['raw'];
foreach ($this->__refangRegexTable as $regex => $replacement) {
$input['refanged'] = preg_replace($regex, $replacement , $input['refanged']);
}
$input['refanged'] = rtrim($input['refanged'], ".");
return $input;
}
private function __checkForSimpleRegex($input) {
// CVE numbers
if (preg_match("#^cve-[0-9]{4}-[0-9]{4,9}$#i", $input['raw'])) return array('types' => array('vulnerability'), 'categories' => array('External analysis'), 'to_ids' => false, 'default_type' => 'vulnerability', 'value' => $input['raw']);
// Phone numbers
if (preg_match("#^(\+)?([0-9]{1,3}(\(0\))?)?[0-9\/\-]{5,}[0-9]$#i", $input['raw'])) return array('types' => array('phone-number', 'prtn', 'whois-registrant-phone'), 'categories' => array('Other'), 'to_ids' => false, 'default_type' => 'phone-number', 'value' => $input['raw']);
}
private function __checkForIP($input) {
if (filter_var($input['refanged_no_port'], FILTER_VALIDATE_IP)) {
if (isset($input['port'])) {
return array('types' => array('ip-dst|port', 'ip-src|port', 'ip-src|port/ip-dst|port'), 'to_ids' => true, 'default_type' => 'ip-dst|port', 'comment' => $input['comment'], 'value' => $input['refanged_no_port'] . '|' . $input['port']);
} else {
return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
}
}
if (strpos($inputRefangedNoPort, '/')) {
$temp = explode('/', $inputRefangedNoPort);
// it could still be a CIDR block
if (strpos($input['refanged_no_port'], '/')) {
$temp = explode('/', $input['refanged_no_port']);
if (count($temp) == 2) {
if (filter_var($temp[0], FILTER_VALIDATE_IP) && is_numeric($temp[1])) return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $comment, 'value' => $inputRefangedNoPort);
if (filter_var($temp[0], FILTER_VALIDATE_IP) && is_numeric($temp[1])) return array('types' => array('ip-dst', 'ip-src', 'ip-src/ip-dst'), 'to_ids' => true, 'default_type' => 'ip-dst', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
}
}
// check for domain name, hostname, filename
if (strpos($inputRefanged, '.') !== false) {
$temp = explode('.', $inputRefanged);
}
private function __checkForDomainOrFilename($input) {
if (strpos($input['refanged'], '.') !== false) {
$temp = explode('.', $input['refanged']);
// TODO: use a more flexible matching approach, like the one below (that still doesn't support non-ASCII domains)
//if (filter_var($input, FILTER_VALIDATE_URL)) {
$domainDetection = true;
if (preg_match('/^([-\pL\pN]+\.)+[a-z]+(:[0-9]{2,5})?$/iu', $inputRefanged)) {
if (preg_match('/^([-\pL\pN]+\.)+[a-z]+(:[0-9]{2,5})?$/iu', $input['refanged'])) {
if (empty($this->__tlds) || count($this->__tlds) == 1) {
$this->__generateTLDList();
}
@ -265,42 +309,37 @@ class ComplexTypeTool {
}
if ($domainDetection) {
if (count($temp) > 2) {
return array('types' => array('hostname', 'domain', 'url'), 'to_ids' => true, 'default_type' => 'hostname', 'comment' => $comment, 'value' => $inputRefangedNoPort);
return array('types' => array('hostname', 'domain', 'url'), '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' => $comment, 'value' => $inputRefangedNoPort);
return array('types' => array('domain'), 'to_ids' => true, 'default_type' => 'domain', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
}
} else {
// check if it is a URL
// Adding http:// infront of the input in case it was left off. github.com/MISP/MISP should still be counted as a valid link
if (count($temp) > 1 && (filter_var($inputRefangedNoPort, FILTER_VALIDATE_URL) || filter_var('http://' . $inputRefangedNoPort, FILTER_VALIDATE_URL))) {
// TODO: add comment explaining why there is a check for a specific domain
if (preg_match('/^https:\/\/(www.)?virustotal.com\//i', $inputRefangedNoPort)) return array('types' => array('link'), 'to_ids' => false, 'default_type' => 'link', 'comment' => $comment, 'value' => $inputRefangedNoPort);
if (preg_match('/^https:\/\/www\.hybrid-analysis\.com\//i', $inputRefangedNoPort)) return array('types' => array('link'), 'categories' => array('External analysis'), 'to_ids' => false, 'default_type' => 'link', 'comment' => $comment, 'value' => $inputRefangedNoPort);
if (strpos($inputRefangedNoPort, '/')) return array('types' => array('url'), 'to_ids' => true, 'default_type' => 'url', 'comment' => $comment, 'value' => $inputRefangedNoPort);
if (count($temp) > 1 && (filter_var($input['refanged_no_port'], FILTER_VALIDATE_URL) || filter_var('http://' . $input['refanged_no_port'], FILTER_VALIDATE_URL))) {
// Even though some domains are valid, we want to exclude them as they are known security vendors / etc
// TODO, replace that with the appropriate warninglist.
if (preg_match('/^https:\/\/(www.)?virustotal.com\//i', $input['refanged_no_port'])) return array('types' => array('link'), 'to_ids' => false, 'default_type' => 'link', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
if (preg_match('/^https:\/\/www\.hybrid-analysis\.com\//i', $input['refanged_no_port'])) return array('types' => array('link'), 'categories' => array('External analysis'), 'to_ids' => false, 'default_type' => 'link', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
if (strpos($input['refanged_no_port'], '/')) return array('types' => array('url'), 'to_ids' => true, 'default_type' => 'url', 'comment' => $input['comment'], 'value' => $input['refanged_no_port']);
}
if ($this->__resolveFilename($input)) return array('types' => array('filename'), 'to_ids' => true, 'default_type' => 'filename', 'value' => $input);
if ($this->__resolveFilename($input['raw'])) return array('types' => array('filename'), 'to_ids' => true, 'default_type' => 'filename', 'value' => $input['raw']);
}
}
if (strpos($input, '\\') !== false) {
$temp = explode('\\', $input);
if (strpos($input['raw'], '\\') !== false) {
$temp = explode('\\', $input['raw']);
if (strpos($temp[count($temp)-1], '.') || preg_match('/^.:/i', $temp[0])) {
if ($this->__resolveFilename($temp[count($temp)-1])) return array('types' => array('filename'), 'categories' => array('Payload installation'), 'to_ids' => true, 'default_type' => 'filename', 'value' => $input);
if ($this->__resolveFilename($temp[count($temp)-1])) return array('types' => array('filename'), 'categories' => array('Payload installation'), 'to_ids' => true, 'default_type' => 'filename', 'value' => $input['raw']);
} else {
return array('types' => array('regkey'), 'to_ids' => false, 'default_type' => 'regkey', 'value' => $input);
return array('types' => array('regkey'), 'to_ids' => false, 'default_type' => 'regkey', 'value' => $input['raw']);
}
}
// check for CVE
if (preg_match("#^cve-[0-9]{4}-[0-9]{4,9}$#i", $input)) return array('types' => array('vulnerability'), 'categories' => array('External analysis'), 'to_ids' => false, 'default_type' => 'vulnerability', 'value' => $input);
if (preg_match("#^(\+)?([0-9]{1,3}(\(0\))?)?[0-9\/\-]{5,}[0-9]$#i", $input)) return array('types' => array('phone-number', 'prtn', 'whois-registrant-phone'), 'categories' => array('Other'), 'to_ids' => false, 'default_type' => 'phone-number', 'value' => $input);
return false;
}
private function __resolveFilename($input) {
if ((preg_match('/^.:/', $input) || strpos($input, '.') !=0)) {
$parts = explode('.', $input);
private function __resolveFilename($param) {
if ((preg_match('/^.:/', $param) || strpos($param, '.') !=0)) {
$parts = explode('.', $param);
if (!is_numeric($parts[count($parts)-1]) && ctype_alnum($parts[count($parts)-1])) return true;
}
return false;

View File

@ -89,19 +89,19 @@ msgid "Event Blacklisting is not currently enabled on this instance."
msgstr ""
#: Controller/EventsController.php:610
msgid "No x509 certificate or GPG key set in your profile. To receive emails, submit your public certificate or GPG key in your profile."
msgid "No x509 certificate or GnuPG key set in your profile. To receive emails, submit your public certificate or GnuPG key in your profile."
msgstr ""
#: Controller/EventsController.php:612
msgid "No GPG key set in your profile. To receive emails, submit your public key in your profile."
msgid "No GnuPG key set in your profile. To receive emails, submit your public key in your profile."
msgstr ""
#: Controller/EventsController.php:618
msgid "No x509 certificate or GPG key set in your profile. To receive attributes in emails, submit your public certificate or GPG key in your profile."
msgid "No x509 certificate or GnuPG key set in your profile. To receive attributes in emails, submit your public certificate or GnuPG key in your profile."
msgstr ""
#: Controller/EventsController.php:620
msgid "No GPG key set in your profile. To receive attributes in emails, submit your public key in your profile."
msgid "No GnuPG key set in your profile. To receive attributes in emails, submit your public key in your profile."
msgstr ""
#: Controller/EventsController.php:1052
@ -2649,16 +2649,16 @@ msgstr ""
#: View/Elements/healthElements/diagnostics.ctp:324;326
#: View/Pages/administration.ctp:17
msgid "Verify PGP keys"
msgid "Verify GnuPG keys"
msgstr ""
#: View/Elements/healthElements/diagnostics.ctp:325
msgid "Run a full validation of all PGP keys within this instance's userbase. The script will try to identify possible issues with each key and report back on the results."
msgid "Run a full validation of all GnuPG keys within this instance's userbase. The script will try to identify possible issues with each key and report back on the results."
msgstr ""
#: View/Elements/healthElements/diagnostics.ctp:326
#: View/Pages/administration.ctp:17
msgid "Check whether every user's PGP key is usable"
msgid "Check whether every user's GnuPG key is usable"
msgstr ""
#: View/Elements/healthElements/diagnostics.ctp:327
@ -6111,7 +6111,7 @@ msgid "GnuPG settings"
msgstr ""
#: View/Pages/doc/administration.ctp:34
msgid "GPG related settings."
msgid "GnuPG related settings."
msgstr ""
#: View/Pages/doc/administration.ctp:35
@ -6139,7 +6139,7 @@ msgid "Diagnostics"
msgstr ""
#: View/Pages/doc/administration.ctp:38
msgid "The diagnostics tool checks if all directories that MISP uses to store data are writeable by the apache user. Also, the tool checks whether the STIX libraries and GPG are working as intended."
msgid "The diagnostics tool checks if all directories that MISP uses to store data are writeable by the apache user. Also, the tool checks whether the STIX libraries and GnuPG are working as intended."
msgstr ""
#: View/Pages/doc/administration.ctp:39
@ -6393,7 +6393,7 @@ msgid "Nids ID, not yet implemented."
msgstr ""
#: View/Pages/doc/administration.ctp:96;127
msgid "Gpgkey"
msgid "GnuPGkey"
msgstr ""
#: View/Pages/doc/administration.ctp:96;127
@ -6443,7 +6443,7 @@ msgid "Shows whether the user has the subscription to contact reporter e-mails d
msgstr ""
#: View/Pages/doc/administration.ctp:107
msgid "Shows whether the user has entered a Gpgkey yet."
msgid "Shows whether the user has entered a GnuPG key yet."
msgstr ""
#: View/Pages/doc/administration.ctp:108
@ -6510,7 +6510,7 @@ msgid "Contacting a user"
msgstr ""
#: View/Pages/doc/administration.ctp:130
msgid "Site admins can use the \"Contact users\" feature to send all or an individual user an e-mail. Users that have a PGP key set will receive their e-mails encrypted. When clicking this button on the left, you'll be presented with a form that allows you to specify the type of the e-mail, who it should reach and what the content is using the following options"
msgid "Site admins can use the \"Contact users\" feature to send all or an individual user an e-mail. Users that have a GnuPG key set will receive their e-mails encrypted. When clicking this button on the left, you'll be presented with a form that allows you to specify the type of the e-mail, who it should reach and what the content is using the following options"
msgstr ""
#: View/Pages/doc/administration.ctp:131
@ -6536,7 +6536,7 @@ msgid "Recipient"
msgstr ""
#: View/Pages/doc/administration.ctp:134
msgid "The recipient toggle lets you contact all your users, a single user (which creates a second drop-down list with all the e-mail addresses of the users) and potential future users (which opens up a text field for the e-mail address and a text area field for a PGP public key)."
msgid "The recipient toggle lets you contact all your users, a single user (which creates a second drop-down list with all the e-mail addresses of the users) and potential future users (which opens up a text field for the e-mail address and a text area field for a GnuPG public key)."
msgstr ""
#: View/Pages/doc/administration.ctp:135;136
@ -6558,7 +6558,7 @@ msgid "This is available for password resets, you can either write your own mess
msgstr ""
#: View/Pages/doc/administration.ctp:139
msgid "Keep in mind that all e-mails sent through this system will, in addition to your own message, will be signed in the name of the instance's host organisation's support team, will include the e-mail address of the instance's support (if the contact field is set in the bootstrap file), and will include the instance's PGP signature for users that have a PGP key set (and thus are eligible for an encrypted e-mail)."
msgid "Keep in mind that all e-mails sent through this system will, in addition to your own message, will be signed in the name of the instance's host organisation's support team, will include the e-mail address of the instance's support (if the contact field is set in the bootstrap file), and will include the instance's GnuPG signature for users that have a GnuPG key set (and thus are eligible for an encrypted e-mail)."
msgstr ""
#: View/Pages/doc/administration.ctp:141
@ -7468,11 +7468,11 @@ msgid "After accepting the ToU, you'll be prompted to change your password, but
msgstr ""
#: View/Pages/doc/user_management.ctp:27;44
msgid "Setting up the GPG Key"
msgid "Setting up the GnuPG Key"
msgstr ""
#: View/Pages/doc/user_management.ctp:27
msgid "In order for the system to be able to encrypt the messages that you send through it, it needs to know your GPG key. Navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the Gpgkey field and click submit."
msgid "In order for the system to be able to encrypt the messages that you send through it, it needs to know your GnuPG key. Navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the GnuPG key field and click submit."
msgstr ""
#: View/Pages/doc/user_management.ctp:28;42
@ -7536,7 +7536,7 @@ msgid "Turning this feature on will allow you to receive e-mails addressed to yo
msgstr ""
#: View/Pages/doc/user_management.ctp:44
msgid "In order for the system to be able to encrypt the messages that you send through it, it needs to know your GPG key. You can acquire this by clicking on the PGP/GPG key link at the bottom left of the screen. Copy the entirety of the key and navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the Gpgkey field and click submit."
msgid "In order for the system to be able to encrypt the messages that you send through it, it needs to know your GnuPG key. You can acquire this by clicking on the GnuPG key link at the bottom left of the screen. Copy the entirety of the key and navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the GnuPG key field and click submit."
msgstr ""
#: View/Pages/doc/user_management.ctp:45
@ -10157,23 +10157,23 @@ msgstr ""
#: View/Users/admin_add.ctp:70
#: View/Users/admin_edit.ctp:64
msgid "GPG key"
msgid "GnuPG key"
msgstr ""
#: View/Users/admin_add.ctp:70
#: View/Users/admin_edit.ctp:64
msgid "Paste the user's PGP key here or try to retrieve it from the MIT key server by clicking on \"Fetch GPG key\" below."
msgid "Paste the user's GnuPG key here or try to retrieve it from the MIT key server by clicking on \"Fetch GnuPG key\" below."
msgstr ""
#: View/Users/admin_add.ctp:72
#: View/Users/admin_edit.ctp:66
msgid "Fetch the user's PGP key"
msgid "Fetch the user's GnuPG key"
msgstr ""
#: View/Users/admin_add.ctp:72
#: View/Users/admin_edit.ctp:66
#: View/Users/edit.ctp:25
msgid "Fetch GPG key"
msgid "Fetch GnuPG key"
msgstr ""
#: View/Users/admin_add.ctp:74
@ -10238,7 +10238,7 @@ msgid "You can then specify (if eligible) what the e-mail address of the target
msgstr ""
#: View/Users/admin_email.ctp:12
msgid "In the case of a new user, you can specify the future user's gpg key, to send his/her new key in an encrypted e-mail."
msgid "In the case of a new user, you can specify the future user's GnuPG key, to send his/her new key in an encrypted e-mail."
msgstr ""
#: View/Users/admin_email.ctp:13
@ -10328,17 +10328,17 @@ msgstr ""
#: View/Users/admin_view.ctp:67
#: View/Users/view.ctp:60
msgid "PGP key"
msgid "GnuPG key"
msgstr ""
#: View/Users/admin_view.ctp:74
#: View/Users/view.ctp:67
msgid "PGP fingerprint"
msgid "GnuPG fingerprint"
msgstr ""
#: View/Users/admin_view.ctp:80
#: View/Users/view.ctp:73
msgid "PGP status"
msgid "GnuPG status"
msgstr ""
#: View/Users/admin_view.ctp:90
@ -10355,7 +10355,7 @@ msgid "Password change"
msgstr ""
#: View/Users/check_and_correct_pgps.ctp:2
msgid "Failed GPGs?"
msgid "Failed GnuPGs?"
msgstr ""
#: View/Users/check_and_correct_pgps.ctp:4
@ -10363,7 +10363,7 @@ msgid "No failed composites"
msgstr ""
#: View/Users/edit.ctp:25
msgid "Fetch PGP key"
msgid "Fetch GnuPG key"
msgstr ""
#: View/Users/edit.ctp:27
@ -10481,7 +10481,7 @@ msgid "Certificates validation"
msgstr ""
#: View/Users/verify_g_p_g.ctp:2
msgid "GPG key validation"
msgid "GnuPG key validation"
msgstr ""
#: View/Users/view.ctp:45
@ -10509,7 +10509,7 @@ msgid "Associated E-mail addresses"
msgstr ""
#: View/Users/ajax/fetchpgpkey.ctp:12
msgid "Select pgp key"
msgid "Select GnuPG key"
msgstr ""
#: View/Users/ajax/passwordResetConfirmationForm.ctp:3

View File

@ -60,7 +60,7 @@ class AppModel extends Model {
);
public $db_changes = array(
1 => false, 2 => false, 3 => false
1 => false, 2 => false, 3 => false, 4 => true, 5 => false
);
function afterSave($created, $options = array()) {
@ -134,6 +134,11 @@ class AppModel extends Model {
$this->MispObject->removeOrphanedObjects();
$this->updateDatabase($command);
break;
case 5:
$this->updateDatabase($command);
$this->Feed = Classregistry::init('Feed');
$this->Feed->setEnableFeedCachingDefaults();
break;
default:
$this->updateDatabase($command);
break;
@ -862,7 +867,6 @@ class AppModel extends Model {
$indexArray[] = array('attributes', 'deleted');
break;
case '2.4.86':
break;
case '2.4.87':
$sqlArray[] = "ALTER TABLE `feeds` ADD `headers` TEXT COLLATE utf8_bin;";
@ -886,6 +890,14 @@ class AppModel extends Model {
$this->__addIndex('fuzzy_correlate_ssdeep', 'chunk');
$this->__addIndex('fuzzy_correlate_ssdeep', 'attribute_id');
break;
case 4:
$sqlArray[] = 'ALTER TABLE `roles` ADD `memory_limit` VARCHAR(255) COLLATE utf8_bin DEFAULT "";';
$sqlArray[] = 'ALTER TABLE `roles` ADD `max_execution_time` VARCHAR(255) COLLATE utf8_bin DEFAULT "";';
$sqlArray[] = "ALTER TABLE `roles` ADD `restricted_to_site_admin` tinyint(1) NOT NULL DEFAULT 0;";
break;
case 5:
$sqlArray[] = "ALTER TABLE `feeds` ADD `caching_enabled` BOOLEAN NOT NULL DEFAULT 0;";
break;
case 'fixNonEmptySharingGroupID':
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';

View File

@ -118,7 +118,7 @@ class Attribute extends AppModel {
'email-attachment' => array('desc' => "File name of the email attachment.", 'default_category' => 'Payload delivery', 'to_ids' => 1),
'email-body' => array('desc' => 'Email body', 'default_category' => 'Payload delivery', 'to_ids' => 0),
'float' => array('desc' => "A floating point value.", 'default_category' => 'Other', 'to_ids' => 0),
'url' => array('desc' => 'url', 'default_category' => 'External analysis', 'to_ids' => 1),
'url' => array('desc' => 'url', 'default_category' => 'Network activity', 'to_ids' => 1),
'http-method' => array('desc' => "HTTP method used by the malware (e.g. POST, GET, ...).", 'default_category' => 'Network activity', 'to_ids' => 0),
'user-agent' => array('desc' => "The user-agent used by the malware in the HTTP request.", 'default_category' => 'Network activity', 'to_ids' => 0),
'regkey' => array('desc' => "Registry key or value", 'default_category' => 'Persistence mechanism', 'to_ids' => 1),
@ -386,6 +386,8 @@ class Attribute extends AppModel {
'financial' => array('btc', 'iban', 'bic', 'bank-account-nr', 'aba-rtn', 'bin', 'cc-number', 'prtn', 'phone-number')
);
private $__fTool = false;
public $order = array("Attribute.event_id" => "DESC");
public $validate = array(
@ -1213,7 +1215,6 @@ class Attribute extends AppModel {
case 'sha512':
case 'sha512/224':
case 'sha512/256':
case 'domain':
case 'hostname':
case 'pehash':
case 'authentihash':
@ -1225,8 +1226,14 @@ class Attribute extends AppModel {
case 'whois-registrant-email':
$value = strtolower($value);
break;
case 'domain':
$value = strtolower($value);
$value = trim($value, '.');
break;
case 'domain|ip':
$value = strtolower($value);
$parts = explode('|', $value);
$parts[0] = trim($parts[0], '.');
if (filter_var($parts[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
// convert IPv6 address to compressed format
$parts[1] = inet_ntop(inet_pton($value));
@ -3128,6 +3135,7 @@ class Attribute extends AppModel {
$attribute['data'] = $result['data'];
$attribute['value'] = $attribute['value'] . '|' . $result['md5'];
}
unset($attribute['id']);
if (isset($attribute['uuid'])) {
$existingAttribute = $this->find('first', array(
'conditions' => array('Attribute.uuid' => $attribute['uuid']),
@ -3262,4 +3270,13 @@ class Attribute extends AppModel {
}
return true;
}
public function attachValidationWarnings($adata) {
if (!$this->__fTool) {
$this->__fTool = new FinancialTool();
}
if (!$this->__fTool->validateRouter($adata['type'], $adata['value'])) {
$adata['validationIssue'] = true;
}
return $adata;
}
}

View File

@ -1701,6 +1701,9 @@ class Event extends AppModel {
unset($event['Attribute'][$key]);
continue;
}
if ($event['Attribute'][$key]['category'] === 'Financial fraud') {
$event['Attribute'][$key] = $this->Attribute->attachValidationWarnings($event['Attribute'][$key]);
}
if (isset($options['includeAttachments']) && $options['includeAttachments']) {
if ($this->Attribute->typeIsAttachment($attribute['type'])) {
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
@ -1742,6 +1745,11 @@ class Event extends AppModel {
foreach ($event['Object'] as $objectKey => $objectValue) {
if (!empty($event['Object'][$objectKey]['Attribute'])) {
$event['Object'][$objectKey]['Attribute'] = $this->__attachSharingGroups(!$options['sgReferenceOnly'], $event['Object'][$objectKey]['Attribute'], $sharingGroupData);
foreach ($event['Object'][$objectKey]['Attribute'] as $akey => $adata) {
if ($adata['category'] === 'Financial fraud') {
$event['Object'][$objectKey]['Attribute'][$akey] = $this->Attribute->attachValidationWarnings($adata);
}
}
}
if ($event['Attribute'][$key]['object_id'] == $objectValue['id']) {
$event['Object'][$objectKey]['Attribute'][] = $event['Attribute'][$key];
@ -2243,7 +2251,7 @@ class Event extends AppModel {
$body .= "\n";
$body .= "You can reach him at " . $user['User']['email'] . "\n";
if (!$user['User']['gpgkey'])
$body .= "His GPG/PGP key is added as attachment to this email. \n";
$body .= "His GnuPG key is added as attachment to this email. \n";
if (!$user['User']['certif_public'])
$body .= "His Public certificate is added as attachment to this email. \n";
$body .= "\n";
@ -4064,17 +4072,28 @@ class Event extends AppModel {
return $this->save($event);
}
public function upload_stix($user, $filename) {
public function upload_stix($user, $filename, $stix_version) {
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');
$scriptFile = APP . 'files/scripts/stix2misp.py';
$tempFilePath = APP . 'files/scripts/tmp/' . $filename;
$result = shell_exec('python3 ' . $scriptFile . ' ' . $filename . ' 2>' . APP . 'tmp/logs/exec-errors.log');
if ($stix_version == '2') {
$scriptFile = APP . 'files/scripts/stix2/stix2misp.py';
$tempFilePath = APP . 'files/scripts/tmp/' . $filename;
$shell_command = 'python3 ' . $scriptFile . ' ' . $tempFilePath . ' 2>' . APP . 'tmp/logs/exec-errors.log';
$output_path = $tempFilePath . '.stix2';
} else if ($stix_version == '1' || $stix_version == '1.1' || $stix_version == '1.2') {
$scriptFile = APP . 'files/scripts/stix2misp.py';
$tempFilePath = APP . 'files/scripts/tmp/' . $filename;
$shell_command = 'python3 ' . $scriptFile . ' ' . $filename . ' 2>' . APP . 'tmp/logs/exec-errors.log';
$output_path = $tempFilePath . '.json';
} else {
throw new MethodNotAllowedException('Invalid STIX version');
}
$result = shell_exec($shell_command);
unlink($tempFilePath);
if (trim($result) == '1') {
$data = file_get_contents($tempFilePath . '.json');
$data = file_get_contents($output_path);
$data = json_decode($data, true);
unlink($tempFilePath . '.json');
unlink($output_path);
$created_id = false;
$validationIssues = false;
$result = $this->_add($data, true, $user, '', null, false, null, $created_id, $validationIssues);

View File

@ -714,6 +714,7 @@ class Feed extends AppModel {
'provider' => $newFeed['provider'],
'url' => $newFeed['url'],
'enabled' => $newFeed['enabled'],
'caching_enabled' => !empty($newFeed['caching_enabled']) ? $newFeed['caching_enabled'] : 0,
'distribution' => 3,
'sharing_group_id' => 0,
'tag_id' => 0,
@ -912,7 +913,7 @@ class Feed extends AppModel {
public function cacheFeedInitiator($user, $jobId = false, $scope = 'freetext') {
$params = array(
'conditions' => array('enabled' => 1),
'conditions' => array('caching_enabled' => 1),
'recursive' => -1,
'fields' => array('source_format', 'input_source', 'url', 'id', 'settings')
);
@ -1179,4 +1180,19 @@ class Feed extends AppModel {
$this->importFeeds($json, $user, true);
return true;
}
public function setEnableFeedCachingDefaults() {
$feeds = $this->find('all', array(
'conditions' => array(
'Feed.enabled' => 1
),
'recursive' => -1
));
if (empty($feeds)) return true;
foreach ($feeds as $feed) {
$feed['Feed']['caching_enabled'] = 1;
$this->save($feed);
}
return true;
}
}

View File

@ -160,6 +160,11 @@ class Module extends AppModel {
'Content-Type' => 'application/json',
)
);
if ($moduleFamily == 'Cortex') {
if (!empty(Configure::read('Plugin.' . $moduleFamily . '_authkey'))) {
$request['header']['Authorization'] = 'bearer ' . Configure::read('Plugin.' . $moduleFamily . '_authkey');
}
}
try {
if ($post) $response = $httpSocket->post($url . $uri, $post, $request);
else $response = $httpSocket->get($url . $uri);

View File

@ -55,19 +55,84 @@ class Role extends AppModel {
);
public $permFlags = array(
'perm_admin' => array('id' => 'RolePermAdmin', 'text' => 'Admin', 'readonlyenabled' => false),
'perm_site_admin' => array('id' => 'RolePermSiteAdmin', 'text' => 'Site Admin', 'readonlyenabled' => false),
'perm_sync' => array('id' => 'RolePermSync', 'text' => 'Sync Actions', 'readonlyenabled' => true),
'perm_audit' => array('id' => 'RolePermAudit', 'text' => 'Audit Actions', 'readonlyenabled' => true),
'perm_auth' => array('id' => 'RolePermAuth', 'text' => 'Auth key access', 'readonlyenabled' => true),
'perm_regexp_access' => array('id' => 'RolePermRegexpAccess', 'text' => 'Regex Actions', 'readonlyenabled' => false),
'perm_tagger' => array('id' => 'RolePermTagger', 'text' => 'Tagger', 'readonlyenabled' => false),
'perm_tag_editor' => array('id' => 'RolePermTagEditor', 'text' => 'Tag Editor', 'readonlyenabled' => false),
'perm_template' => array('id' => 'RolePermTemplate', 'text' => 'Template Editor', 'readonlyenabled' => false),
'perm_sharing_group' => array('id' => 'RolePermSharingGroup', 'text' => 'Sharing Group Editor', 'readonlyenabled' => false),
'perm_delegate' => array('id' => 'RolePermDelegate', 'text' => 'Delegations Access', 'readonlyenabled' => false),
'perm_sighting' => array('id' => 'RolePermSighting', 'text' => 'Sighting Creator', 'readonlyenabled' => true),
'perm_object_template' => array('id' => 'RolePermObjectTemplate', 'text' => 'Object Template Editor', 'readonlyenabled' => false),
'perm_site_admin' => array(
'id' => 'RolePermSiteAdmin',
'text' => 'Site Admin',
'readonlyenabled' => false,
'title' => 'Unrestricted access to any data and functionality on this instance.'
),
'perm_admin' => array(
'id' => 'RolePermAdmin',
'text' => 'Org Admin',
'readonlyenabled' => false,
'title' => 'Limited organisation admin - create, manage users of their own organisation'
),
'perm_sync' => array(
'id' => 'RolePermSync',
'text' => 'Sync Actions',
'readonlyenabled' => true,
'title' => 'Synchronisation permission, can be used to connect two MISP instances create data on behalf of other users. Make sure that the role with this permission has also access to tagging and tag editing rights.'
),
'perm_audit' => array(
'id' => 'RolePermAudit',
'text' => 'Audit Actions',
'readonlyenabled' => true,
'title' => 'Access to the audit logs of the user\'s organisation.'
),
'perm_auth' => array(
'id' => 'RolePermAuth',
'text' => 'Auth key access',
'readonlyenabled' => true,
'title' => 'Users with this permission have access to authenticating via their Auth keys, granting them access to the API.'
),
'perm_regexp_access' => array(
'id' => 'RolePermRegexpAccess',
'text' => 'Regex Actions',
'readonlyenabled' => false,
'title' => 'Users with this role can modify the regex rules affecting how data is fed into MISP. Make sure that caution is advised with handing out roles that include this permission, user controlled executed regexes are dangerous.'
),
'perm_tagger' => array(
'id' => 'RolePermTagger',
'text' => 'Tagger',
'readonlyenabled' => false,
'title' => 'Users with roles that include this permission can attach or detach existing tags to and from events/attributes.'
),
'perm_tag_editor' => array(
'id' => 'RolePermTagEditor',
'text' => 'Tag Editor',
'readonlyenabled' => false,
'title' => 'This permission gives users the ability to create, modify or remove tags.'
),
'perm_template' => array(
'id' => 'RolePermTemplate',
'text' => 'Template Editor',
'readonlyenabled' => false,
'title' => 'Create or modify templates, to be used when populating events.'
),
'perm_sharing_group' => array(
'id' => 'RolePermSharingGroup',
'text' => 'Sharing Group Editor',
'readonlyenabled' => false,
'title' => 'Permission to create or modify sharing groups.'
),
'perm_delegate' => array(
'id' => 'RolePermDelegate',
'text' => 'Delegations Access',
'readonlyenabled' => false,
'title' => 'Allow users to create delegation requests for their own org only events to trusted third parties.'
),
'perm_sighting' => array(
'id' => 'RolePermSighting',
'text' => 'Sighting Creator',
'readonlyenabled' => true,
'title' => 'Permits the user to push feedback on attributes into MISP by providing sightings.'
),
'perm_object_template' => array(
'id' => 'RolePermObjectTemplate',
'text' => 'Object Template Editor',
'readonlyenabled' => false,
'title' => 'Create or modify MISP Object templates'
)
);
public $premissionLevelName = array('Read Only', 'Manage Own Events', 'Manage Organisation Events', 'Manage and Publish Organisation Events');
@ -119,6 +184,20 @@ class Role extends AppModel {
$this->data['Role'][$permFlag] = 0;
}
}
if (!isset($this->data['Role']['max_execution_time'])) {
$this->data['Role']['max_execution_time'] = '';
} else if ($this->data['Role']['max_execution_time'] !== '') {
$this->data['Role']['max_execution_time'] = intval($this->data['Role']['max_execution_time']);
}
if (!isset($this->data['Role']['memory_limit'])) {
$this->data['Role']['memory_limit'] = '';
} else if (
$this->data['Role']['memory_limit'] !== '' &&
!preg_match('/^[0-9]+[MG]$/i', $this->data['Role']['memory_limit']) &&
$this->data['Role']['memory_limit'] != -1
) {
$this->data['Role']['memory_limit'] = '';
}
}
return true;
}

View File

@ -433,7 +433,7 @@ class Server extends AppModel {
),
'extended_alert_subject' => array(
'level' => 1,
'description' => 'enabling this flag will allow the event description to be transmitted in the alert e-mail\'s subject. Be aware that this is not encrypted by PGP, so only enable it if you accept that part of the event description will be sent out in clear-text.',
'description' => 'enabling this flag will allow the event description to be transmitted in the alert e-mail\'s subject. Be aware that this is not encrypted by GnuPG, so only enable it if you accept that part of the event description will be sent out in clear-text.',
'value' => false,
'errorMessage' => '',
'test' => 'testBool',
@ -804,7 +804,7 @@ class Server extends AppModel {
'branch' => 1,
'binary' => array(
'level' => 2,
'description' => 'The location of the GPG executable. If you would like to use a different gpg executable than /usr/bin/gpg, you can set it here. If the default is fine, just keep the setting suggested by MISP.',
'description' => 'The location of the GnuPG executable. If you would like to use a different GnuPG executable than /usr/bin/gpg, you can set it here. If the default is fine, just keep the setting suggested by MISP.',
'value' => '/usr/bin/gpg',
'errorMessage' => '',
'test' => 'testForGPGBinary',
@ -812,7 +812,7 @@ class Server extends AppModel {
),
'onlyencrypted' => array(
'level' => 0,
'description' => 'Allow (false) unencrypted e-mails to be sent to users that don\'t have a PGP key.',
'description' => 'Allow (false) unencrypted e-mails to be sent to users that don\'t have a GnuPG key.',
'value' => '',
'errorMessage' => '',
'test' => 'testBool',
@ -828,7 +828,7 @@ class Server extends AppModel {
),
'sign' => array(
'level' => 2,
'description' => 'Enable the signing of GPG emails. By default, GPG emails are signed',
'description' => 'Enable the signing of GnuPG emails. By default, GnuPG emails are signed',
'value' => 'true',
'errorMessage' => '',
'test' => 'testBool',
@ -836,7 +836,7 @@ class Server extends AppModel {
),
'email' => array(
'level' => 0,
'description' => 'The e-mail address that the instance\'s PGP key is tied to.',
'description' => 'The e-mail address that the instance\'s GnuPG key is tied to.',
'value' => '',
'errorMessage' => '',
'test' => 'testForEmpty',
@ -844,7 +844,7 @@ class Server extends AppModel {
),
'password' => array(
'level' => 1,
'description' => 'The password (if it is set) of the PGP key of the instance.',
'description' => 'The password (if it is set) of the GnuPG key of the instance.',
'value' => '',
'errorMessage' => '',
'test' => 'testForEmpty',
@ -853,7 +853,7 @@ class Server extends AppModel {
),
'homedir' => array(
'level' => 0,
'description' => 'The location of the GPG homedir.',
'description' => 'The location of the GnuPG homedir.',
'value' => '',
'errorMessage' => '',
'test' => 'testForEmpty',
@ -1517,6 +1517,15 @@ class Server extends AppModel {
'test' => 'testBool',
'type' => 'boolean'
),
'Cortex_authkey' => array(
'level' => 1,
'description' => 'Set an authentication key to be passed to Cortex',
'value' => '',
'errorMessage' => '',
'test' => 'testForEmpty',
'type' => 'string',
'null' => true
),
'Cortex_timeout' => array(
'level' => 1,
'description' => 'Set a timeout for the import services',
@ -2390,6 +2399,8 @@ class Server extends AppModel {
}
public function testBaseURL($value) {
// only run this check via the GUI, via the CLI it won't work
if (php_sapi_name() == 'cli') return true;
if ($this->testForEmpty($value) !== true) return $this->testForEmpty($value);
if ($value != strtolower($this->getProto()) . '://' . $this->getHost()) return false;
return true;
@ -2481,7 +2492,7 @@ class Server extends AppModel {
public function testForGPGBinary($value) {
if (empty($value)) $value = $this->serverSettings['GnuPG']['binary']['value'];
if (file_exists($value)) return true;
return 'Could not find the gnupg executable at the defined location.';
return 'Could not find the GnuPG executable at the defined location.';
}
public function testForRPZDuration($value) {

View File

@ -123,7 +123,7 @@ class User extends AppModel {
'gpgkey' => array(
'gpgvalidation' => array(
'rule' => array('validateGpgkey'),
'message' => 'GPG key not valid, please enter a valid key.',
'message' => 'GnuPG key not valid, please enter a valid key.',
),
),
'certif_public' => array(
@ -290,7 +290,7 @@ class User extends AppModel {
return true;
}
// Checks if the GPG key is a valid key, but also import it in the keychain.
// Checks if the GnuPG key is a valid key, but also import it in the keychain.
// TODO: this will NOT fail on keys that can only be used for signing but not encryption!
// the method in verifyUsers will fail in that case.
public function validateGpgkey($check) {
@ -499,7 +499,7 @@ class User extends AppModel {
$sortedKeys['valid']++;
}
if (!$sortedKeys['valid']) {
$result[2] = 'The user\'s PGP key does not include a valid subkey that could be used for encryption.';
$result[2] = 'The user\'s GnuPG key does not include a valid subkey that could be used for encryption.';
if ($sortedKeys['expired']) $result[2] .= ' Found ' . $sortedKeys['expired'] . ' subkey(s) that have expired.';
if ($sortedKeys['noEncrypt']) $result[2] .= ' Found ' . $sortedKeys['noEncrypt'] . ' subkey(s) that are sign only.';
$result[0] = true;
@ -765,8 +765,8 @@ class User extends AppModel {
$failureReason = " the message could not be encrypted because the provided key is either expired or cannot be used for encryption.";
}
} catch (Exception $e) {
// despite the user having a PGP key and the signing already succeeding earlier, we get an exception. This must mean that there is an issue with the user's key.
$failureReason = " the message could not be encrypted because there was an issue with the user's PGP key. The following error message was returned by gpg: " . $e->getMessage();
// despite the user having a GnuPG key and the signing already succeeding earlier, we get an exception. This must mean that there is an issue with the user's key.
$failureReason = " the message could not be encrypted because there was an issue with the user's GnuPG key. The following error message was returned by gpg: " . $e->getMessage();
$this->log($e->getMessage());
$failed = true;
}

View File

@ -69,7 +69,6 @@
<div class="input clear"></div>
<?php
echo $this->Form->input('to_ids', array(
'checked' => false,
'label' => __('for Intrusion Detection System'),
));
echo $this->Form->input('batch_import', array(

View File

@ -89,7 +89,7 @@
foreach ($object['warnings'][$component] as $warning) $temp .= '<span class=\'bold\'>' . h($valueParts[$valuePart]) . '</span>: <span class=\'red\'>' . h($warning) . '</span><br />';
}
}
echo ' <span class="icon-warning-sign" data-placement="right" data-toggle="popover" data-content="' . h($temp) . '" data-trigger="hover">&nbsp;</span>';
echo ' <span class="icon-warning-sign" data-placement="right" data-toggle="popover" data-content="' . h($temp) . '" data-trigger="hover" data-placement="right">&nbsp;</span>';
}
?>
</div>

View File

@ -82,11 +82,11 @@
if ($mayModify && empty($object['deleted'])):
?>
<a href="<?php echo $baseurl;?>/objects/edit/<?php echo $object['id']; ?>" title="Edit" class="icon-edit icon-white useCursorPointer"></a>
<span class="icon-trash icon-white useCursorPointer" title="<?php echo __('Permanently delete object');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete object');?>" onClick="deleteObject('objects', 'delete', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<span class="icon-trash icon-white useCursorPointer" title="<?php echo __('Soft delete object');?>" role="button" tabindex="0" aria-label="<?php echo __('Soft delete object');?>" onClick="deleteObject('objects', 'delete', '<?php echo h($object['id']); ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<?php
elseif ($mayModify):
?>
<span class="icon-trash icon-white useCursorPointer" title="<?php echo __('Soft delete object');?>" role="button" tabindex="0" aria-label="<?php echo __('Soft delete attribute');?>" onClick="deleteObject('objects', 'delete', '<?php echo h($object['id']) . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<span class="icon-trash icon-white useCursorPointer" title="<?php echo __('Permanently delete object');?>" role="button" tabindex="0" aria-label="<?php echo __('Permanently delete attribute');?>" onClick="deleteObject('objects', 'delete', '<?php echo h($object['id']) . '/true'; ?>', '<?php echo h($event['Event']['id']); ?>');"></span>
<?php
endif;
?>

View File

@ -1,6 +1,6 @@
<span class="bold"><?php echo __('References: ');?></span>
<?php
$refCount = count($object['ObjectReference']);
$refCount = empty($object['ObjectReference']) ? 0 : count($object['ObjectReference']);
echo $refCount . ' ';
if (!empty($object['ObjectReference'])):
?>
@ -10,25 +10,25 @@
?>
<div id="Object_<?php echo $object['uuid']; ?>_references_collapsible" class="collapse">
<?php
foreach ($object['ObjectReference'] as $reference):
if (!empty($reference['Object'])) {
$uuid = $reference['Object']['uuid'];
$output = ' (' . $reference['Object']['name'] . ': ' . $reference['Object']['name'] . ')';
$objectType = 'Object';
} else {
$uuid = $reference['Attribute']['uuid'];
$output = ' (' . $reference['Attribute']['category'] . '/' . $reference['Attribute']['type'] . ': "' . $reference['Attribute']['value'] . '")';
$objectType = 'Attribute';
}
$uuid = empty($reference['Object']) ? $reference['Attribute']['uuid'] : $reference['Object']['uuid'];
$idref = $reference['uuid'];
if (!empty($object['ObjectReference'])):
foreach ($object['ObjectReference'] as $reference):
if (!empty($reference['Object'])) {
$uuid = $reference['Object']['uuid'];
$output = ' (' . $reference['Object']['name'] . ': ' . $reference['Object']['name'] . ')';
$objectType = 'Object';
} else {
$uuid = $reference['referenced_uuid'];
$output = '';
$objectType = 'Attribute';
}
$uuid = $reference['referenced_uuid'];
$idref = $reference['uuid'];
?>
&nbsp;&nbsp;
<div class="bold white useCursorPointer">
<?php echo h($reference['relationship_type']) . ' ' . $objectType . ' ' . $reference['referenced_uuid'] . h($output);?>
</div>
<br />
<div class="bold white useCursorPointer">
&nbsp;&nbsp;<?php echo h($reference['relationship_type']) . ' ' . $objectType . ' ' . $reference['referenced_uuid'] . h($output);?>
</div>
<?php
endforeach;
endforeach;
endif;
?>
</div>

View File

@ -4,11 +4,11 @@
echo $refCount;
if (!empty($object['referenced_by'])):
?>
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo h($object['id']); ?>_referenced_by_collapsible"></span>
<span class="fa fa-expand useCursorPointer" title="<?php echo __('Expand or Collapse');?>" role="button" tabindex="0" aria-label="<?php echo __('Expand or Collapse');?>" data-toggle="collapse" data-target="#Object_<?php echo h($object['uuid']); ?>_referenced_by_collapsible"></span>
<?php
endif;
?>
<div id="Object_<?php echo $object['id']; ?>_referenced_by_collapsible" class="collapse">
<div id="Object_<?php echo $object['uuid']; ?>_referenced_by_collapsible" class="collapse">
<?php
foreach ($object['referenced_by'] as $type => $reference):
foreach ($reference as $ref):
@ -21,9 +21,9 @@
}
?>
&nbsp;&nbsp;
<a class="bold white useCursorPointer" onClick="pivotObjectReferences('<?php echo h($currentUri); ?>', '<?php echo $uuid; ?>')">
<?php echo h($ref['relationship_type']) . ' ' . ucfirst($type) . ' ' . h($ref['id']) . h($output);?>
</a>
<span class="bold white useCursorPointer">
<?php echo h($ref['relationship_type']) . ' ' . ucfirst($type) . ' ' . h($output);?>
</span>
<br />
<?php
endforeach;

View File

@ -39,13 +39,22 @@
?>
<div class="value_select_with_manual_entry">
<?php
$choice = '';
if (!empty($element['value'])) {
if (in_array($element['value'], $list)) {
$choice = $element['value'];
} else {
$choice = 'Enter value manually';
}
}
echo $this->Form->input('Attribute.' . $k . '.value_select', array(
'class' => 'Attribute_value_select',
'style' => 'width:414px;margin-bottom:0px;',
'options' => array_combine($list, $list),
'label' => false,
'div' => false,
'value' => empty($element['value']) ? '' : $element['value']
'value' => $choice
));
?>
<br />
@ -55,7 +64,7 @@
'type' => 'textarea',
'required' => false,
'allowEmpty' => true,
'style' => 'height:20px;width:400px;display:none;',
'style' => 'height:20px;width:400px;' . (($choice == 'Enter value manually') ? '' : 'display:none;'),
'label' => false,
'div' => false,
'value' => empty($element['value']) ? '' : $element['value']

View File

@ -1,5 +1,5 @@
<div class="footer <?php echo $debugMode;?>">
<div id="shortcutsListContainer">
<div id="shortcutsListContainer" class="<?php echo $debugMode ? 'hidden': ''; ?>">
<div id="triangle"></div>
<div id="shortcutsList">
<span> <?php echo __('Keyboard shortcuts for this page'); ?>:</span><br />
@ -12,9 +12,9 @@
<?php
$gpgpath = ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.'gpg.asc';
if (file_exists($gpgpath) && is_file($gpgpath)){ ?>
<span>Download: <?php echo $this->Html->link('PGP/GPG key', $this->webroot.'gpg.asc');?></span>
<span>Download: <?php echo $this->Html->link('GnuPG key', $this->webroot.'gpg.asc');?></span>
<?php } else { ?>
<span>Could not locate the PGP/GPG public key.</span>
<span>Could not locate the GnuPG public key.</span>
<?php }
if (Configure::read('SMIME.enabled')):
$smimepath = ROOT.DS.APP_DIR.DS.WEBROOT_DIR.DS.'public_certificate.pem';

View File

@ -324,9 +324,9 @@
</div><br />
<span class="btn btn-inverse" role="button" tabindex="0" aria-label="<?php echo __('Check for orphaned attribute');?>" title="<?php echo __('Check for orphaned attributes');?>" style="padding-top:1px;padding-bottom:1px;" onClick="checkOrphanedAttributes();"><?php echo __('Check for orphaned attributes');?></span><br /><br />
<?php echo $this->Form->postButton(__('Remove orphaned attributes'), $baseurl . '/attributes/pruneOrphanedAttributes', $options = array('class' => 'btn btn-primary', 'style' => 'padding-top:1px;padding-bottom:1px;')); ?>
<h3><?php echo __('Verify PGP keys');?></h3>
<p><?php echo __('Run a full validation of all PGP keys within this instance\'s userbase. The script will try to identify possible issues with each key and report back on the results.');?></p>
<span class="btn btn-inverse" onClick="location.href='<?php echo $baseurl;?>/users/verifyGPG';"><?php echo __('Verify PGP keys');?></span> (<?php echo __('Check whether every user\'s PGP key is usable');?>)</li>
<h3><?php echo __('Verify GnuPG keys');?></h3>
<p><?php echo __('Run a full validation of all GnuPG keys within this instance\'s userbase. The script will try to identify possible issues with each key and report back on the results.');?></p>
<span class="btn btn-inverse" onClick="location.href='<?php echo $baseurl;?>/users/verifyGPG';"><?php echo __('Verify GnuPG keys');?></span> (<?php echo __('Check whether every user\'s GnuPG key is usable');?>)</li>
<h3><?php echo __('Database cleanup scripts');?></h3>
<p><?php echo __('If you run into an issue with an infinite upgrade loop (when upgrading from version ~2.4.50) that ends up filling your database with upgrade script log messages, run the following script.');?></p>
<?php echo $this->Form->postButton(__('Prune upgrade logs'), $baseurl . '/logs/pruneUpdateLogs', $options = array('class' => 'btn btn-primary', 'style' => 'padding-top:1px;padding-bottom:1px;')); ?>

View File

@ -35,7 +35,7 @@
if (isset($errors[$element_id])) $error = $errors[$element_id];
if ($element['batch']) {
if ($element['complex']) {
$placeholder = __('Describe the %s using one or several (separated by a line-break) of the following types: %s' , h($element['name'], $types));
$placeholder = __('Describe the %s using one or several (separated by a line-break) of the following types: %s' , h($element['name']), $types);
} else {
$placeholder = __('Describe the %s using one or several %s\s (separated by a line-break) ' , h($element['name']) , h($element['type']));
}

View File

@ -25,5 +25,5 @@
<script type="text/javascript">
var i_<?php echo h($element_id); ?> = 0;
var element_id_<?php echo h($element_id); ?> = <?php echo h($element_id); ?>;
var batch_<?php echo h($element_id); ?> = "<?php echo ($element['batch'] ? '<?php echo __('yes');?>' : '<?php echo __('no');?>'); ?>";
var batch_<?php echo h($element_id); ?> = "<?php echo ($element['batch'] ? 'yes': 'no'); ?>";
</script>

View File

@ -4,7 +4,7 @@
<table style="width:100%;">
<?php foreach ($imports as $k => $import): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td role="button" tabindex="0" aria-label="<?php echo __('Import %s', h($import['text'])); ?>" style="padding-left:10px; text-align:center;width:100%;" onClick="importChoiceSelect('<?php echo h($import['url']); ?>', '<?php echo h($k); ?>', '<?php echo $import['ajax'] ? h($import['target']) : "false"; ?>')"><?php echo h($import['text']); ?></td>
<td class="<?php echo !empty($import['bold']) ? 'bold' : ''; ?>" role="button" tabindex="0" aria-label="<?php echo __('Import %s', h($import['text'])); ?>" style="padding-left:10px; text-align:center;width:100%;" onClick="importChoiceSelect('<?php echo h($import['url']); ?>', '<?php echo h($k); ?>', '<?php echo $import['ajax'] ? h($import['target']) : "false"; ?>')"><?php echo h($import['text']); ?></td>
</tr>
<?php endforeach; ?>
</table>

View File

@ -143,8 +143,8 @@
<?php
if (!empty($item['types'])) {
foreach ($item['types'] as $type) {
echo '<option value="' . $type . '" ';
echo ($type == $item['default_type'] ? 'selected="selected"' : '') . '>' . $type . '</option>';
echo '<option value="' . h($type) . '" ';
echo ($type == $item['default_type'] ? 'selected="selected"' : '') . '>' . h($type) . '</option>';
}
}
?>
@ -167,17 +167,17 @@
<select id = "<?php echo 'Attribute' . $k . 'SharingGroupId'; ?>" class='sgToggle' style='padding:0px;height:20px;margin-top:3px;margin-bottom:0px;'>
<?php
foreach ($sgs as $sgKey => $sgValue) {
echo '<option value="' . $sgKey . '">' . $sgValue . '</option>';
echo '<option value="' . h($sgKey) . '">' . h($sgValue) . '</option>';
}
?>
</select>
</div>
</td>
<td class="short">
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . $item['comment'] . '"'?>/>
<input type="text" class="freetextCommentField" id="<?php echo 'Attribute' . $k . 'Comment'; ?>" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (isset($item['comment']) && $item['comment'] !== false) echo 'value="' . h($item['comment']) . '"'?>/>
</td>
<td class="short">
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . htmlspecialchars(implode(",",$item['tags'])) . '"'?>/>
<input type="text" class="freetextTagField" id="<?php echo 'Attribute' . $k . 'Tags'; ?>" style="padding:0px;height:20px;margin-bottom:0px;"<?php if (isset($item['tags']) && $item['tags'] !== false) echo 'value="' . h(implode(",",$item['tags'])) . '"'?>/>
</td>
<td class="action short">
<span class="icon-remove pointer" title="<?php echo __('Remove resolved attribute');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove resolved attribute');?>" onClick="freetextRemoveRow('<?php echo $k; ?>', '<?php echo $event['Event']['id']; ?>');"></span>
@ -206,7 +206,7 @@
<?php
foreach (array_keys($optionsRearranged) as $fromElement):
?>
<option><?php echo $fromElement; ?></option>
<option><?php echo h($fromElement); ?></option>
<?php
endforeach;
?>

View File

@ -1,13 +1,12 @@
<div class="events form">
<?php
echo $this->Form->create('Event', array('type' => 'file'));
$stixVersion = 'STIX 1.1.1 XML';
?>
<fieldset>
<legend><?php echo __('Import %s file', $stixVersion); ?></legend>
<legend><?php echo __('Import %s file', $stix_version); ?></legend>
<?php
echo $this->Form->input('Event.stix', array(
'label' => '<b>' . __('%s file', $stixVersion) . '</b>',
'label' => '<b>' . __('%s file', $stix_version) . '</b>',
'type' => 'file',
));
?>

View File

@ -164,6 +164,11 @@
<dd class="green bold published <?php echo ($event['Event']['published'] == 0) ? 'hidden' : ''; ?>"><?php echo __('Yes');?></dd>
<dt><?php echo __('#Attributes');?></dt>
<dd><?php echo h($attribute_count);?></dd>
<dt><?php echo __('Last change');?></dt>
<dd>
<?php echo date('Y/m/d h:i:s', $event['Event']['timestamp']);; ?>
&nbsp;
</dd>
<dt><?php echo __('Sightings');?></dt>
<dd style="word-wrap: break-word;">
<span id="eventSightingCount" class="bold sightingsCounter" data-toggle="popover" data-trigger="hover" data-content="<?php echo $sightingPopover; ?>"><?php echo count($event['Sighting']); ?></span>

View File

@ -5,6 +5,7 @@
<p><?php echo __('Add a new MISP feed source.');?></p>
<?php
echo $this->Form->input('enabled', array());
echo $this->Form->input('caching_enabled', array());
?>
<div class="input clear"></div>
<?php

View File

@ -5,70 +5,78 @@
?>
<div class="feed index">
<h2><?php echo __('Feed overlap analysis matrix');?></h2>
<div>
<table class="table table-striped table-hover table-condensed" style="width:100px;">
<tr>
<th>&nbsp;</th>
<?php
<?php
if (count($feeds) > 2):
?>
<div>
<table class="table table-striped table-hover table-condensed" style="width:100px;">
<tr>
<th>&nbsp;</th>
<?php
foreach ($feeds as $item):
$popover = '';
foreach ($feedTemplate as $element):
$popover .= '<span class=\'bold\'>' . Inflector::humanize($element) . '</span>: <span class=\'bold blue\'>' . h($item['Feed'][$element]) . '</span><br />';
endforeach;
?>
<th>
<div data-toggle="popover" data-content="<?php echo $popover; ?>" data-trigger="hover">
<?php echo h($item['Feed']['id']); ?>
</div>
</th>
<?php
endforeach;
?>
</tr>
<?php
foreach ($feeds as $item):
$popover = '';
foreach ($feedTemplate as $element):
$popover .= '<span class=\'bold\'>' . Inflector::humanize($element) . '</span>: <span class=\'bold blue\'>' . h($item['Feed'][$element]) . '</span><br />';
endforeach;
?>
<th>
<div data-toggle="popover" data-content="<?php echo $popover; ?>" data-trigger="hover">
<?php echo h($item['Feed']['id']); ?>
</div>
</th>
<tr>
<td class="short">
<div data-toggle="popover" data-content="<?php echo $popover;?>" data-trigger="hover">
<?php echo h($item['Feed']['id']) . ' ' . h($item['Feed']['name']); ?>&nbsp;
</div>
</td>
<?php
foreach ($feeds as $item2):
$percentage = -1;
$class = 'bold';
foreach ($item['Feed']['ComparedFeed'] as $k => $v):
if ($item2['Feed']['id'] == $v['id']):
$percentage = $v['overlap_percentage'];
if ($percentage <= 5) $class .= ' green';
else if ($percentage <= 50) $class .= ' orange';
else $class .= ' red';
break;
endif;
endforeach;
$title = '';
if ($percentage == 0) $popover = __('None or less than 1% of the data of %s is contained in %s (%s matching values)', $item['Feed']['name'], $item2['Feed']['name'], $v['overlap_count']);
else if ($percentage > 0) $popover = __('%s\% of the data of %s is contained in %s (%s matching values)',$percentage, $item['Feed']['name'], $item2['Feed']['name'], $v['overlap_count'])
?>
<td class="<?php echo h($class); ?>">
<div data-toggle="popover" data-content="<?php echo h($popover);?>" data-trigger="hover">
<?php echo (($percentage == -1) ? '-' : h($percentage) . '%');?>
</div>
</td>
<?php
endforeach;
?>
</tr>
<?php
endforeach;
?>
</tr>
<?php
foreach ($feeds as $item):
$popover = '';
foreach ($feedTemplate as $element):
$popover .= '<span class=\'bold\'>' . Inflector::humanize($element) . '</span>: <span class=\'bold blue\'>' . h($item['Feed'][$element]) . '</span><br />';
endforeach;
?>
<tr>
<td class="short">
<div data-toggle="popover" data-content="<?php echo $popover;?>" data-trigger="hover">
<?php echo h($item['Feed']['id']) . ' ' . h($item['Feed']['name']); ?>&nbsp;
</div>
</td>
<?php
foreach ($feeds as $item2):
$percentage = -1;
$class = 'bold';
foreach ($item['Feed']['ComparedFeed'] as $k => $v):
if ($item2['Feed']['id'] == $v['id']):
$percentage = $v['overlap_percentage'];
if ($percentage <= 5) $class .= ' green';
else if ($percentage <= 50) $class .= ' orange';
else $class .= ' red';
break;
endif;
endforeach;
$title = '';
if ($percentage == 0) $popover = __('None or less than 1% of the data of %s is contained in %s (%s matching values)', $item['Feed']['name'], $item2['Feed']['name'], $v['overlap_count']);
else if ($percentage > 0) $popover = __('%s\% of the data of %s is contained in %s (%s matching values)',$percentage, $item['Feed']['name'], $item2['Feed']['name'], $v['overlap_count'])
?>
<td class="<?php echo h($class); ?>">
<div data-toggle="popover" data-content="<?php echo h($popover);?>" data-trigger="hover">
<?php echo (($percentage == -1) ? '-' : h($percentage) . '%');?>
</div>
</td>
<?php
endforeach;
?>
</tr>
<?php
endforeach;
?>
</table>
</div>
</table>
</div>
<?php
else:
echo '<p class="red bold">Not enough feeds cached. Make sure you have at least 2 feeds that are cached and available.</p>';
endif;
?>
</div>
<script type="text/javascript">
$(document).ready(function(){

View File

@ -5,6 +5,7 @@
<p><?php echo __('Edit a new MISP feed source.');?></p>
<?php
echo $this->Form->input('enabled', array());
echo $this->Form->input('caching_enabled', array());
?>
<div class="input clear"></div>
<?php

View File

@ -24,9 +24,10 @@
</ul>
</div>
<div class="tabMenuFixedContainer" style="display:inline-block;">
<span id="multi-delete-button" role="button" tabindex="0" aria-label="<?php echo __('Default feeds filter');?>" title="<?php echo __('Default feeds');?>" class=" hidden tabMenuFixed mass-select tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onClick="multiSelectToggleFeeds(1);"><?php echo __('Enable Selected');?></span>
<span id="multi-delete-button" role="button" tabindex="0" aria-label="<?php echo __('Default feeds filter');?>" title="<?php echo __('Default feeds');?>" class=" hidden tabMenuFixed mass-select tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onClick="multiSelectToggleFeeds(0);"><?php echo __('Disable Selected');?></span>
<span role="button" tabindex="0" aria-label="<?php echo __('Default feeds filter');?>" title="<?php echo __('Default feeds');?>" class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onclick="window.location='/feeds/index/scope:default'"><?php echo __('Default feeds');?></span>
<span id="multi-delete-button" role="button" tabindex="0" aria-label="<?php echo __('Enable selected');?>" title="<?php echo __('Enable selected');?>" class=" hidden tabMenuFixed mass-select tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onClick="multiSelectToggleFeeds(1, 0);"><?php echo __('Enable Selected');?></span>
<span id="multi-delete-button" role="button" tabindex="0" aria-label="<?php echo __('Disable selected');?>" title="<?php echo __('Disable selected');?>" class=" hidden tabMenuFixed mass-select tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onClick="multiSelectToggleFeeds(0, 0);"><?php echo __('Disable Selected');?></span>
<span id="multi-delete-button" role="button" tabindex="0" aria-label="<?php echo __('Enable caching for selected');?>" title="<?php echo __('Enable caching for selected');?>" class=" hidden tabMenuFixed mass-select tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onClick="multiSelectToggleFeeds(1, 1);"><?php echo __('Enable Caching for Selected');?></span>
<span id="multi-delete-button" role="button" tabindex="0" aria-label="<?php echo __('Disable caching for selected');?>" title="<?php echo __('Disable caching for selected');?>" class=" hidden tabMenuFixed mass-select tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onClick="multiSelectToggleFeeds(0, 1);"><?php echo __('Disable Caching for Selected');?></span> <span role="button" tabindex="0" aria-label="<?php echo __('Default feeds filter');?>" title="<?php echo __('Default feeds');?>" class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'default' ? 'tabMenuActive' : ''; ?>" onclick="window.location='/feeds/index/scope:default'"><?php echo __('Default feeds');?></span>
<span role="button" tabindex="0" aria-label="<?php echo __('Custom feeds filter');?>" title="<?php echo __('Custom feeds');?>" class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'custom' ? 'tabMenuActive' : ''; ?> " onclick="window.location='/feeds/index/scope:custom'"><?php echo __('Custom Feeds');?></span>
<span role="button" tabindex="0" aria-label="<?php echo __('All feeds');?>" title="<?php echo __('All feeds');?>" class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'all' ? 'tabMenuActive' : ''; ?> " onclick="window.location='/feeds/index/scope:all'"><?php echo __('All Feeds');?></span>
<span role="button" tabindex="0" aria-label="<?php echo __('Enabled feeds');?>" title="<?php echo __('Enabled feeds');?>" class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php echo $scope == 'enabled' ? 'tabMenuActive' : ''; ?> " onclick="window.location='/feeds/index/scope:enabled'"><?php echo __('Enabled Feeds');?></span>
@ -42,6 +43,7 @@
<?php endif;?>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('enabled');?></th>
<th><?php echo $this->Paginator->sort('caching_enabled');?></th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('source_format', __('Feed Format'));?></th>
<th><?php echo $this->Paginator->sort('provider');?></th>
@ -105,6 +107,10 @@ foreach ($feeds as $item):
>
(<?php echo __('Rules');?>)
</span>
</td>
<td class="short">
<span class="<?php echo ($item['Feed']['caching_enabled'] ? 'icon-ok' : 'icon-remove'); ?>"></span>
</td>
<td>
<?php
echo h($item['Feed']['name']);
@ -190,7 +196,7 @@ foreach ($feeds as $item):
else:
echo __('Not cached');
endif;
if ($item['Feed']['enabled']):
if ($item['Feed']['caching_enabled']):
?>
<a href="<?php echo $baseurl;?>/feeds/cacheFeeds/<?php echo h($item['Feed']['id']); ?>" title="Cache feed"><span class="icon-download-alt"></span></a>
<?php

View File

@ -3,6 +3,7 @@
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<?php echo $this->Html->charset(); ?>
<meta name="viewport" content="width=device-width" />
<title>
<?php echo $title_for_layout, ' - '. h(Configure::read('MISP.title_text') ? Configure::read('MISP.title_text') : 'MISP'); ?>
</title>

View File

@ -0,0 +1,16 @@
<div class="index">
<h3><?php echo __('Stolen attribute validation');?></h3>
<ul>
<?php
if (empty($issues)) {
echo '<span class="blue bold">' . __('Nothing to see here, move along.') . '</span>';
} else {
foreach ($issues as $aid => $eids) {
echo '<div>' . __('Attribute (%s) associated to events: %s', $aid, implode(', ', $eids)) . '</div>';
}
}
?>
</div>
<?php
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'adminTools'));
?>

View File

@ -67,8 +67,7 @@
'required' => false,
'allowEmpty' => true,
'label' => false,
'div' => false,
'value' => empty($template['Object']['comment']) ? '' : $template['Object']['comment']
'div' => false
));
?>
</dd>

View File

@ -14,7 +14,7 @@ if (!$isSiteAdmin) exit();
<li><?php echo $this->Form->postLink(__('Reset the attribute counts'), $baseurl . '/events/generateCount');?> (<?php echo __('Events need to have no validation issues');?>)</li>
<li><?php echo $this->Form->postLink('Recorrelate attributes', $baseurl . '/attributes/generateCorrelation');?></li>
<li><?php echo $this->Form->postLink('Recorrelate proposals', $baseurl . '/shadow_attributes/generateCorrelation');?></li>
<li><a href="<?php echo $baseurl;?>/users/verifyGPG"><?php echo __('Verify PGP keys');?></a> (<?php echo __('Check whether every user\'s PGP key is usable');?>)</li>
<li><a href="<?php echo $baseurl;?>/users/verifyGPG"><?php echo __('Verify GnuPG keys');?></a> (<?php echo __('Check whether every user\'s GnuPG key is usable');?>)</li>
<li><a href="<?php echo $baseurl;?>/users/verifyCertificate"><?php echo __('Verify Certificates');?></a> (<?php echo __('Check whether every user\'s certificate is usable');?>)</li>
<li><?php echo $this->Form->postLink(__('Extend Organization length'), $baseurl . '/servers/updateDatabase/extendServerOrganizationLength');?> (<?php echo __('Hotfix 2.3.57: Increase the max length of the organization field when adding a new server connection.');?>)</li>
<li><?php echo $this->Form->postLink('Convert log fields to text', $baseurl . '/servers/updateDatabase/convertLogFieldsToText');?> (<?php echo __('Hotfix 2.3.78: Some of the log fields that were varchar(255) ended up truncating the data. This function will change them to "text"');?>)</li>

View File

@ -31,11 +31,11 @@
<ul>
<li><b><?php echo __('Overview');?></b>: <?php echo __('General overview of the current state of your MISP installation');?></li>
<li><b><?php echo __('MISP settings');?></b>: <?php echo __('Basic MISP settings. This includes the way MISP handles the default settings for distribution settings, whether background jobs are enabled, etc');?></li>
<li><b><?php echo __('GnuPG settings');?></b>: <?php echo __('GPG related settings.');?></li>
<li><b><?php echo __('GnuPG settings');?></b>: <?php echo __('GnuPG related settings.');?></li>
<li><b><?php echo __('Proxy settings');?></b>: <?php echo __('HTTP proxy related settings.');?></li>
<li><b><?php echo __('Security settings');?></b>: <?php echo __('Settings controlling the brute-force protection and the application\'s salt key.');?></li>
<li><b><?php echo __('Misc settings');?></b>: <?php echo __('You change the debug options here, but make sure that debug is always disabled on a production system.');?></li>
<li><b><?php echo __('Diagnostics');?></b>: <?php echo __('The diagnostics tool checks if all directories that MISP uses to store data are writeable by the apache user. Also, the tool checks whether the STIX libraries and GPG are working as intended.');?></li>
<li><b><?php echo __('Diagnostics');?></b>: <?php echo __('The diagnostics tool checks if all directories that MISP uses to store data are writeable by the apache user. Also, the tool checks whether the STIX libraries and GnuPG are working as intended.');?></li>
<li><b><?php echo __('Workers');?></b>: <?php echo __('Shows the background workers (if enabled) and shows a warning if they are not running. Admins can also restart the workers here.');?></li>
<li><b><?php echo __('Download report');?></b>: <?php echo __('Download a report in JSON format, compiled of all of the settings visible in the tool.');?></li>
</ul>
@ -93,7 +93,7 @@
<li><b><?php echo __('Receive alerts from "contact reporter" requests');?>:</b> <?php echo __('This option will subscribe the new user to e-mails that are generated when another user tries to get in touch with an event\'s reporting organisation that matches that of the new user.');?><br /></li>
<li><b><?php echo __('Authkey');?>:</b> <?php echo __('This is assigned automatically and is the unique authentication key of the user (he/she will be able to reset this and receive a new key). It is used for exports and for connecting one server to another, but it requires the user to be assigned to a role that has auth permission enabled.');?><br /></li>
<li><b><?php echo __('NIDS Sid');?>:</b> <?php echo __('Nids ID, not yet implemented.');?><br /></li>
<li><b><?php echo __('Gpgkey');?>:</b> <?php echo __('The key used for encrypting e-mails sent through the system.');?> <br /></li>
<li><b><?php echo __('GnuPGkey');?>:</b> <?php echo __('The key used for encrypting e-mails sent through the system.');?> <br /></li>
</ul>
<h3><?php echo __('Listing all users');?>:</h3>
<?php echo __('To list all current users of the system, just click on List Users under the administration menu to the left. A view will be loaded with a list of all users and the following columns of information');?>:<br />
@ -103,8 +103,8 @@
<li><b>Org:</b> <?php echo __('The organisation that the user belongs to.');?><br /></li>
<li><b><?php echo __('Email');?>:</b> <?php echo __('The e-mail address (and login name) of the user.');?><br /></li>
<li><b><?php echo __('Autoalert');?>:</b> <?php echo __('Shows whether the user has subscribed to auto-alerts and is always receiving the mass-emails regarding newly published events that he/she is eligible for.');?><br /></li>
<li><b>ontactalert:</b> <?php echo __('Shows whether the user has the subscription to contact reporter e-mails directed at his/her organisation turned on or off.');?><br /></li>
<li><b>Gpgkey:</b> <?php echo __('Shows whether the user has entered a Gpgkey yet.');?><br /></li>
<li><b>Contactalert:</b> <?php echo __('Shows whether the user has the subscription to contact reporter e-mails directed at his/her organisation turned on or off.');?><br /></li>
<li><b>GnuPGkey:</b> <?php echo __('Shows whether the user has entered a GnuPGkey yet.');?><br /></li>
<li><b>Nids Sid:</b> <?php echo __('Shows the currently assigned NIDS ID.');?><br /></li>
<li><b><?php echo __('Termsaccepted');?>:</b> <?php echo __('This flag indicates whether the user has accepted the terms of use or not.');?><br /></li>
<li><b><?php echo __('Newsread');?>:</b> <?php echo __('The last point in time when the user has looked at the news section of the system.');?><br /></li>
@ -124,19 +124,19 @@
<li><b><?php echo __('NIDS Sid');?>:</b> <?php echo __('Nids ID, not yet implemented.');?><br /></li>
<li><b><?php echo __('Termsaccepted');?>:</b> <?php echo __('Indicates whether the user has accepted the terms of use already or not.');?><br /></li>
<li><b><?php echo __('Change Password');?>:</b> <?php echo __('Setting this flag will require the user to change password after the next login.');?><br /></li>
<li><b><?php echo __('Gpgkey');?>:</b> <?php echo __('The key used for encrypting e-mails sent through the system.');?> <br /></li>
<li><b><?php echo __('GnuPGkey');?>:</b> <?php echo __('The key used for encrypting e-mails sent through the system.');?> <br /></li>
</ul>
<h3><?php echo __('Contacting a user');?>:</h3>
<?php echo __('Site admins can use the "Contact users" feature to send all or an individual user an e-mail. Users that have a PGP key set will receive their e-mails encrypted. When clicking this button on the left, you\'ll be presented with a form that allows you to specify the type of the e-mail, who it should reach and what the content is using the following options');?>:<br />
<?php echo __('Site admins can use the "Contact users" feature to send all or an individual user an e-mail. Users that have a GnuPG key set will receive their e-mails encrypted. When clicking this button on the left, you\'ll be presented with a form that allows you to specify the type of the e-mail, who it should reach and what the content is using the following options');?>:<br />
<img src="<?php echo $baseurl;?>/img/doc/contact.png" alt = "<?php echo __('Contact');?>" title = "<?php echo __('Contact your users here.');?>"/><br />
<ul>
<li><b><?php echo __('Action');?>:</b> <?php echo __('This defines the type of the e-mail, which can be a custom message or a password reset. Password resets automatically include a new temporary password at the bottom of the message and will automatically change the user\'s password accordingly.');?><br /></li>
<li><b><?php echo __('Recipient');?>:</b> <?php echo __('The recipient toggle lets you contact all your users, a single user (which creates a second drop-down list with all the e-mail addresses of the users) and potential future users (which opens up a text field for the e-mail address and a text area field for a PGP public key).');?><br /></li>
<li><b><?php echo __('Recipient');?>:</b> <?php echo __('The recipient toggle lets you contact all your users, a single user (which creates a second drop-down list with all the e-mail addresses of the users) and potential future users (which opens up a text field for the e-mail address and a text area field for a GnuPG public key).');?><br /></li>
<li><b><?php echo __('Subject');?>:</b> <?php echo __('In the case of a custom e-mail, you can enter a subject line here.');?><br /></li>
<li><b><?php echo __('Subject');?>:</b> <?php echo __('In the case of a custom e-mail, you can enter a subject line here.');?><br /></li>
<li><b><?php echo __('Custom message checkbox');?>:</b> <?php echo __('This is available for password resets, you can either write your own message (which will be appended with a temporary key and the signature), or let the system generate one automatically.');?><br /></li>
</ul>
<?php echo __('Keep in mind that all e-mails sent through this system will, in addition to your own message, will be signed in the name of the instance\'s host organisation\'s support team, will include the e-mail address of the instance\'s support (if the contact field is set in the bootstrap file), and will include the instance\'s PGP signature for users that have a PGP key set (and thus are eligible for an encrypted e-mail).');?>
<?php echo __('Keep in mind that all e-mails sent through this system will, in addition to your own message, will be signed in the name of the instance\'s host organisation\'s support team, will include the e-mail address of the instance\'s support (if the contact field is set in the bootstrap file), and will include the instance\'s GnuPG signature for users that have a GnuPG key set (and thus are eligible for an encrypted e-mail).');?>
<hr />
<h2><a id="roles"></a><?php echo __('Managing the roles');?></h2>
<?php echo __('Privileges are assigned to users by assigning them to rule groups, which use one of four options determining what they can do with events and four additional privilege elevating settings. The four options for event manipulation are: Read Only, Manage My Own Events, Manage Organisation Events, Manage &amp; Publish Organisation Events. The extra privileges are admin, sync, authentication key usage and audit permission');?><br />

View File

@ -24,7 +24,7 @@
<li><b><?php echo __('Accepting the Terms of use');?>:</b> <?php echo __('The terms of use are shown immediately after logging in for the first time, make sure to read through this page before clicking "Accept Terms" at the bottom of the page.');?><br /><br /></li>
<li><b><?php echo __('Changing the password');?>:</b> <?php echo __('After accepting the ToU, you\'ll be prompted to change your password, but keep in mind that it has to be at least 6 characters long, it has to include at least one upper-case and one lower-case character in addition to a digit or a special character. Enter the same password into the confirm password field, before clicking submit to finalise the change.');?><br /><br />
<p><img src="<?php echo $baseurl;?>/img/doc/password.png" alt = "" title="<?php echo __('Changing the password');?>"></p><br /></li>
<li><b><?php echo __('Setting up the GPG Key');?>:</b> <?php echo __('In order for the system to be able to encrypt the messages that you send through it, it needs to know your GPG key. Navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the Gpgkey field and click submit.');?><br /><br /></li>
<li><b><?php echo __('Setting up the GnuPG Key');?>:</b> <?php echo __('In order for the system to be able to encrypt the messages that you send through it, it needs to know your GnuPG key. Navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the GnuPG field and click submit.');?><br /><br /></li>
<li><b><?php echo __('Subscribing to Auto-alerts');?>:</b> <?php echo __('Turning auto-alerts on will allow the system to send you e-mail notifications about any new public events entered into the system by other users and private events added by members of your organisation. To turn this on, navigate to the Edit profile view (My profile on the left navigation menu -&gt; Edit profile in the top right corner). Tick the auto-alert checkbox and click submit to enable this feature.');?><br /><br />
<p><img src="<?php echo $baseurl;?>/img/doc/alerts.png" alt = "" title="<?php echo __('Use these checkboxes to subscribe to auto-alerts and contact reporter e-mails.');?>"></p><br /></li>
<li><b><?php echo __('Subscribing to e-mails sent via the "Contact Reporter" functionality');?>:</b> <?php echo __('This feature is turned on right below the autoalerts and will allow you to receive e-mails addressed to your organisation whenever a user tries to ask about an event that was posted by a user of your organisation. Keep in mind that you can still be addressed by such a request even when this setting is turned off, if someone tries to contact you as the event creator directly or your organisation for an event that you personally have created then you will be notified.');?><br /><br />
@ -41,7 +41,7 @@
<li><b><?php echo __('Changing the password');?>:</b> <?php echo __('As a next step, change the password provided by your administrator to something of your own choosing. Click on My profile on the left navigation menu, under Global Actions, which will bring up the User view. Click on Edit User on the left navigation menu or Edit Profile in the top right corner. This next screen, allows you to edit your details, including your password, by filling out the password field. Keep in mind that the password has to be at least 6 characters long, has to include at least one upper-case and one lower-case character in addition to a digit or a special character. Enter the same password into the confirm password field, before clicking submit to finalise the change.');?><br /><br /></li>
<li><b><?php echo __('Subscribing to Auto-alerts');?>:</b> <?php echo __('Turning auto-alerts on will allow the system to send you e-mail notifications about any new public events entered into the system by other users and private events added by members of your organisation. To turn this on, navigate to the Edit profile view (My profile on the left navigation menu -&gt; Edit profile in the top right corner). Tick the auto-alert checkbox and click submit to enable this feature.');?><br /><br /></li>
<li><b><?php echo __('Subscribing to e-mails sent via the "Contact Reporter" functionality');?>:</b> <?php echo __('Turning this feature on will allow you to receive e-mails addressed to your organisation whenever a user tries to ask about an event that was posted by a user of your organisation. Keep in mind that you can still be addressed by such a request even when this setting is turned off, if someone tries to contact the person that reported an event that you yourself have created.');?><br /><br /></li>
<li><b><?php echo __('Setting up the GPG Key');?>:</b> <?php echo __('In order for the system to be able to encrypt the messages that you send through it, it needs to know your GPG key. You can acquire this by clicking on the PGP/GPG key link at the bottom left of the screen. Copy the entirety of the key and navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the Gpgkey field and click submit.');?><br /><br /></li>
<li><b><?php echo __('Setting up the GnuPG Key');?>:</b> <?php echo __('In order for the system to be able to encrypt the messages that you send through it, it needs to know your GnuPG key. You can acquire this by clicking on the GnuPG key link at the bottom left of the screen. Copy the entirety of the key and navigate to the Edit profile view (My Profile on the left -&gt; Edit profile in the top right corner). Paste the key into the GnuPG field and click submit.');?><br /><br /></li>
<li><b><?php echo __('Requesting a new authentication key');?>:</b> <?php echo __('It is possible to make the system generate a new authentication key for you (for example if your previous one gets compromised. This can be accessed by clicking on the My Profile button and then clicking the reset key next to the currently active authentication code. The old key will become invalid when the new one is generated.');?><br /><br />
<p><img src="<?php echo $baseurl;?>/img/doc/reset.png" alt = "" title="<?php echo __('Clicking on reset will generate a new key for you and invalidate the old one, blocking it from being used.');?>"></p></li></ul>
<hr />

View File

@ -2,9 +2,23 @@
<?php echo $this->Form->create('Role'); ?>
<fieldset>
<legend><?php echo __('Add Role');?></legend>
<?php
echo $this->Form->input('name');?>
<?php echo $this->Form->input('permission', array('type' => 'select', 'options' => $options), array('value' => '3'));?>
<?php
echo $this->Form->input('restricted_to_site_admin', array(
'type' => 'checkbox',
'class' => 'checkbox readonlyenabled',
'label' => __('Restrict to site admins')
));
?>
<div class = 'input clear'></div>
<?php
echo $this->Form->input('name');
echo $this->Form->input('permission', array('type' => 'select', 'options' => $options), array('value' => '3'));
?>
<div class = 'input clear'></div>
<?php
echo $this->Form->input('memory_limit', array('label' => __('Memory limit') . ' (' . h($default_memory_limit) . ')'));
echo $this->Form->input('max_execution_time', array('label' => __('Maximum execution time') . ' (' . h($default_max_execution_time) . ')'));
?>
<div class = 'input clear'></div>
<?php
$counter = 1;

View File

@ -2,10 +2,23 @@
<?php echo $this->Form->create('Role');?>
<fieldset>
<legend><?php echo __('Edit Role'); ?></legend>
<?php
echo $this->Form->input('restricted_to_site_admin', array(
'type' => 'checkbox',
'class' => 'checkbox readonlyenabled',
'label' => __('Restrict to site admins')
));
?>
<div class = 'input clear'></div>
<?php
echo $this->Form->input('name');?>
<?php echo $this->Form->input('permission', array('label' => __('Permissions'), 'type' => 'select', 'options' => $options), array('value' => '3'));?>
<div class = 'input clear'></div>
<?php
echo $this->Form->input('memory_limit', array('label' => __('Memory limit') . ' (' . h($default_memory_limit) . ')'));
echo $this->Form->input('max_execution_time', array('label' => __('Maximum execution time') . ' (' . h($default_max_execution_time) . ')'));
?>
<div class = 'input clear'></div>
<?php
$counter = 1;
foreach ($permFlags as $k => $flag):

View File

@ -21,14 +21,17 @@
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo __('Default');?></th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('restricted_to_site_admin');?></th>
<th><?php echo $this->Paginator->sort('permission', 'Permission');?></th>
<?php
foreach ($permFlags as $k => $flags):
?>
<th><?php echo $this->Paginator->sort($k, $flags['text']);?></th>
<th title="<?php echo h($flags['title']); ?>"><?php echo $this->Paginator->sort($k, $flags['text']);?></th>
<?php
endforeach;
?>
<th><?php echo $this->Paginator->sort('memory_limit');?></th>
<th><?php echo $this->Paginator->sort('max_execution_time');?></th>
<th class="actions"><?php echo __('Actions');?></th>
</tr><?php
foreach ($list as $item): ?>
@ -36,10 +39,29 @@ foreach ($list as $item): ?>
<td><?php echo $this->Html->link(h($item['Role']['id']), array('admin' => true, 'action' => 'edit', $item['Role']['id'])); ?>&nbsp;</td>
<td class="short" style="text-align:center;width:20px;"><input class="servers_default_role_checkbox" type="checkbox" data-id="<?php echo h($item['Role']['id']); ?>" <?php if ($default_role_id && $default_role_id == $item['Role']['id']) echo 'checked'; ?>></td>
<td><?php echo h($item['Role']['name']); ?>&nbsp;</td>
<td class="short"><span class="<?php if ($item['Role']['restricted_to_site_admin']) echo 'icon-ok'; ?>"></span>&nbsp;</td>
<td><?php echo h($options[$item['Role']['permission']]); ?>&nbsp;</td>
<?php foreach ($permFlags as $k => $flags): ?>
<td class="short"><span class="<?php if ($item['Role'][$k]) echo 'icon-ok'; ?>"></span>&nbsp;</td>
<?php endforeach; ?>
<td class="short">
<?php
if (empty($item['Role']['memory_limit'])) {
echo h($default_memory_limit);
} else {
echo h($item['Role']['memory_limit']);
}
?>
</td>
<td class="short">
<?php
if (empty($item['Role']['max_execution_time'])) {
echo h($default_max_execution_time);
} else {
echo h($item['Role']['max_execution_time']);
}
?>
</td>
<td class="short action-links">
<?php echo $this->Html->link('', array('admin' => true, 'action' => 'edit', $item['Role']['id']), array('class' => 'icon-edit', 'title' => 'Edit')); ?>
<?php echo $this->Form->postLink('', array('admin' => true, 'action' => 'delete', $item['Role']['id']), array('class' => 'icon-trash', 'title' => __('Delete')), __('Are you sure you want to delete %s?', $item['Role']['name'])); ?>

View File

@ -25,7 +25,7 @@
<?php
foreach ($permFlags as $k => $flags):
?>
<th><?php echo $this->Paginator->sort($k, $flags['text']);?></th>
<th title="<?php echo h($flags['title']); ?>"><?php echo $this->Paginator->sort($k, $flags['text']);?></th>
<?php
endforeach;
?>

View File

@ -67,9 +67,9 @@
?>
</div>
<?php
echo $this->Form->input('gpgkey', array('label' => __('GPG key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s PGP key here or try to retrieve it from the MIT key server by clicking on "Fetch GPG key" below.')));
echo $this->Form->input('gpgkey', array('label' => __('GnuPG key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s GnuPG key here or try to retrieve it from the MIT key server by clicking on "Fetch GnuPG key" below.')));
?>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch the user\'s PGP key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GPG key');?></span></div>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch the user\'s GnuPG key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GnuPG key');?></span></div>
<?php
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => __('SMIME key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s SMIME public key in PEM format here.')));
echo $this->Form->input('autoalert', array('label' => __('Receive alerts when events are published'), 'type' => 'checkbox', 'checked' => true));

View File

@ -37,7 +37,7 @@
$passwordPopover = '<span class=\"blue bold\">Length</span>: ' . h($length) . '<br />';
$passwordPopover .= '<span class=\"blue bold\">Complexity</span>: ' . h($complexity);
echo $this->Form->input('password', array(
'label' => __('Password') . '<span id = "PasswordPopover" class="icon-info-sign" ></span>'
'label' => __('Password') . ' <span id = "PasswordPopover" class="icon-info-sign" ></span>'
));
echo $this->Form->input('confirm_password', array('type' => 'password', 'div' => array('class' => 'input password required')));
?>
@ -61,9 +61,9 @@
?>
</div>
<?php
echo $this->Form->input('gpgkey', array('label' => __('GPG key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s PGP key here or try to retrieve it from the MIT key server by clicking on "Fetch GPG key" below.')));
echo $this->Form->input('gpgkey', array('label' => __('GnuPG key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s GnuPG key here or try to retrieve it from the MIT key server by clicking on "Fetch GnuPG key" below.')));
?>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch the user\'s PGP key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GPG key');?></span></div>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch the user\'s GnuPG key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GnuPG key');?></span></div>
<?php
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => __('SMIME key'), 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => __('Paste the user\'s SMIME public key in PEM format here.')));
echo $this->Form->input('termsaccepted', array('label' => __('Terms accepted')));

View File

@ -9,7 +9,7 @@
<li><?php echo __('When adding a new user to the system, or when you want to manually reset the password for a user, just use the "Send temporary password" setting.');?></li>
<li><?php echo __('After selecting the action, choose who the target of the e-mails should be (all users, a single user or a user not yet in the system).');?></li>
<li><?php echo __('You can then specify (if eligible) what the e-mail address of the target is (for existing users you can choose from a dropdown menu).');?></li>
<li><?php echo __('In the case of a new user, you can specify the future user\'s gpg key, to send his/her new key in an encrypted e-mail.');?></li>
<li><?php echo __('In the case of a new user, you can specify the future user\'s GnuPG key, to send his/her new key in an encrypted e-mail.');?></li>
<li><?php echo __('The system will automatically generate a message for you, but it is also possible to write a custom message if you tick the check-box,
but don\'t worry about assigning a temporary password manually, the system will do that for you, right after your custom message.');?></li>
</ul>

View File

@ -64,20 +64,20 @@ $buttonModifyStatus = $mayModify ? 'button_on':'button_off';
?>
&nbsp;
</dd>
<dt><?php echo __('PGP key'); ?></dt>
<dt><?php echo __('GnuPG key'); ?></dt>
<dd class="quickSelect <?php echo $user['User']['gpgkey'] ? 'green' : 'bold red'; ?>">
<?php echo $user['User']['gpgkey'] ? nl2br(h($user['User']['gpgkey'])) : "N/A"; ?>
</dd>
<?php
if (!empty($user['User']['gpgkey'])):
?>
<dt><?php echo __('PGP fingerprint');?></dt>
<dt><?php echo __('GnuPG fingerprint');?></dt>
<dd class="quickSelect bold <?php echo $user['User']['fingerprint'] ? 'green': 'red'; ?>">
<?php
echo $user['User']['fingerprint'] ? chunk_split(h($user['User']['fingerprint']), 4, ' ') : 'N/A';
?>
</dd>
<dt><?php echo __('PGP status');?></dt>
<dt><?php echo __('GnuPG status');?></dt>
<dd class="bold <?php echo (empty($user['User']['pgp_status']) || $user['User']['pgp_status'] != __('OK')) ? 'red': 'green'; ?>">
<?php
echo !empty($user['User']['pgp_status']) ? h($user['User']['pgp_status']) : __('N/A');

View File

@ -9,7 +9,7 @@
</tr>
<?php foreach ($keys as $k => $key): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td role="button" tabindex="0" aria-label="<?php echo __('Select pgp key');?>" style="padding-left:10px; text-align:left;width:20%;" title="<?php echo h($key['fingerprint']); ?>" onClick="pgpChoiceSelect('<?php echo h($key['uri']); ?>')"><?php echo h($key['key_id']); ?></td>
<td role="button" tabindex="0" aria-label="<?php echo __('Select GnuPG key');?>" style="padding-left:10px; text-align:left;width:20%;" title="<?php echo h($key['fingerprint']); ?>" onClick="pgpChoiceSelect('<?php echo h($key['uri']); ?>')"><?php echo h($key['key_id']); ?></td>
<td style="text-align:left;width:20%;" title="<?php echo h($key['fingerprint']); ?>" onClick="pgpChoiceSelect('<?php echo h($key['uri']); ?>')"><?php echo h($key['date']); ?></td>
<td style="padding-right:10px; text-align:left;width:60%;" title="<?php echo h($key['fingerprint']); ?>" onClick="pgpChoiceSelect('<?php echo h($key['uri']); ?>')">
<span class="bold">

View File

@ -24,6 +24,16 @@ echo $this->Form->button(__('Submit'), array('class' => 'btn btn-primary'));
echo $this->Form->end();
?>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#PasswordPopover').popover("destroy").popover({
placement: 'right',
html: 'true',
trigger: 'hover',
content: '<?php echo $passwordPopover; ?>'
});
});
</script>
<?php
echo $this->element('side_menu', array('menuList' => 'globalActions', 'menuItem' => 'news'));
?>

View File

@ -1,5 +1,5 @@
<div class="composites index">
<h2><?php echo __('Failed GPGs?');?></h2><?php
<h2><?php echo __('Failed GnuPGs?');?></h2><?php
if (0 == count($fails)):?>
<p><?php echo __('No failed composites');?></p>
<?php else:?>

View File

@ -20,9 +20,9 @@
?>
<div class="input clear"></div>
<?php
echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('gpgkey', array('label' => 'GnuPG key', 'div' => 'clear', 'class' => 'input-xxlarge'));
?>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch PGP key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GPG key');?></span></div>
<div class="clear"><span role="button" tabindex="0" aria-label="<?php echo __('Fetch GnuPG key');?>" onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;"><?php echo __('Fetch GnuPG key');?></span></div>
<?php
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => __('SMIME Public certificate (PEM format)'), 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('autoalert', array('label' => __('Receive alerts when events are published'), 'type' => 'checkbox'));

View File

@ -1,5 +1,5 @@
<div class="index">
<h3><?php echo __('GPG key validation');?></h3>
<h3><?php echo __('GnuPG key validation');?></h3>
<ul>
<?php foreach ($users as $k => $user) {
echo '<a href="'.$baseurl.'/admin/users/view/' . $k . '">' . $k . ' (' . h($user[1]) . ')</a>:';

View File

@ -57,20 +57,20 @@
<?php echo h((0 == $user['User']['termsaccepted'])? __('No') : __('Yes')); ?>
&nbsp;
</dd>
<dt><?php echo __('PGP key'); ?></dt>
<dt><?php echo __('GnuPG key'); ?></dt>
<dd class="quickSelect <?php echo $user['User']['gpgkey'] ? 'green' : 'bold red'; ?>">
<?php echo $user['User']['gpgkey'] ? nl2br(h($user['User']['gpgkey'])) : __("N/A"); ?>
</dd>
<?php
if (!empty($user['User']['gpgkey'])):
?>
<dt><?php echo __('PGP fingerprint');?></dt>
<dt><?php echo __('GnuPG fingerprint');?></dt>
<dd class="quickSelect bold <?php echo $user['User']['fingerprint'] ? 'green': 'red'; ?>">
<?php
echo $user['User']['fingerprint'] ? chunk_split(h($user['User']['fingerprint']), 4, ' ') : 'N/A';
?>
</dd>
<dt><?php echo __('PGP status');?></dt>
<dt><?php echo __('GnuPG status');?></dt>
<dd class="bold <?php echo (empty($user['User']['pgp_status']) || $user['User']['pgp_status'] != 'OK') ? 'red': 'green'; ?>">
<?php
echo !empty($user['User']['pgp_status']) ? h($user['User']['pgp_status']) : 'N/A';

View File

@ -181,40 +181,7 @@
"hide_tag": false
}
},
{
"Feed": {
"id": "6",
"name": "Binary Defense Systems Artillery Threat Intelligence Feed and Banlist Feed",
"provider": "Binary Defense Systems",
"url": "https://www.trustedsec.com/banlist.txt",
"rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]}}",
"enabled": true,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "615",
"default": false,
"source_format": "csv",
"fixed_event": true,
"delta_merge": true,
"event_id": "5153",
"publish": false,
"override_ids": true,
"settings": "{\"csv\":{\"value\":\"1\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": false,
"cache_timestamp": "1495871960"
},
"Tag": {
"id": "615",
"name": "osint:source-type=\"block-or-filter-list\"",
"colour": "#004f89",
"exportable": true,
"org_id": "0",
"hide_tag": false
}
},
{
{
"Feed": {
"id": "7",
"name": "malwaredomainlist",
@ -569,39 +536,6 @@
"hide_tag": false
}
},
{
"Feed": {
"id": "25",
"name": "openbl.org base",
"provider": "openbl.org",
"url": "http://www.openbl.org/lists/base.txt",
"rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]}}",
"enabled": true,
"distribution": "0",
"sharing_group_id": "0",
"tag_id": "615",
"default": false,
"source_format": "freetext",
"fixed_event": true,
"delta_merge": true,
"event_id": "6293",
"publish": true,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": true,
"cache_timestamp": "1495871996"
},
"Tag": {
"id": "615",
"name": "osint:source-type=\"block-or-filter-list\"",
"colour": "#004f89",
"exportable": true,
"org_id": "0",
"hide_tag": false
}
},
{
"Feed": {
"id": "27",
@ -1455,5 +1389,38 @@
"lookup_visible": true,
"headers": ""
}
},
{
"Feed": {
"id": "69",
"name": "URLHaus Malware URLs",
"provider": "Abuse.ch",
"url": "https:\/\/urlhaus.abuse.ch\/downloads\/csv\/",
"rules": "{\"tags\":{\"OR\":[],\"NOT\":[]},\"orgs\":{\"OR\":[],\"NOT\":[]}}",
"enabled": true,
"distribution": "3",
"sharing_group_id": "0",
"tag_id": "615",
"default": false,
"source_format": "csv",
"fixed_event": false,
"delta_merge": false,
"event_id": "0",
"publish": false,
"override_ids": false,
"settings": "{\"csv\":{\"value\":\"3\",\"delimiter\":\",\"},\"common\":{\"excluderegex\":\"\"}}",
"input_source": "network",
"delete_local_file": false,
"lookup_visible": true,
"headers": ""
},
"Tag": {
"id": "615",
"name": "osint:source-type=\"block-or-filter-list\"",
"colour": "#004f89",
"exportable": true,
"org_id": "0",
"hide_tag": false
}
}
]

@ -1 +1 @@
Subproject commit 9fa4d37803de84fbb708ab1ce78b18f423eaa15f
Subproject commit f4d7fe01666607c5606ab11da81a8054974e886a

@ -1 +1 @@
Subproject commit cee578dce19f5b4f87af3272e40772d752836c3d
Subproject commit c92ee2e46179f2b30ff1011950f16af38e0f94fc

View File

@ -22,8 +22,6 @@ from misp2stix2_dictionaries import *
from copy import deepcopy
from collections import defaultdict
namespace = ['https://github.com/MISP/MISP', 'MISP']
not_implemented_attributes = ['yara', 'pattern-in-traffic', 'pattern-in-memory']
non_indicator_attributes = ['text', 'comment', 'other', 'link', 'target-user', 'target-email',
@ -770,11 +768,6 @@ def generateEventPackage(event, SDOs):
def main(args):
pathname = os.path.dirname(args[0])
if len(sys.argv) > 3:
namespace[0] = sys.argv[3]
if len(sys.argv) > 4:
namespace[1] = sys.argv[4].replace(" ", "_")
namespace[1] = re.sub('[\W]+', '', namespace[1])
misp = pymisp.MISPEvent(None, False)
misp.load_file(os.path.join(pathname, args[1]))
if 'Attribute' not in dir(misp):

View File

@ -31,14 +31,16 @@ def loadEvent(args, pathname):
def fillReportInfo(mispDict, report):
mispDict['info'] = report.get('name')
mispDict['publish_timestamp'] = getTimestampfromDate(report.get('published'))
if report.get('published'):
mispDict['publish_timestamp'] = getTimestampfromDate(report.get('published'))
labels = report.get('labels')
Tag = []
for l in labels:
label = {'exportable': True, 'hide_tag': False}
label['name'] = l
Tag.append(label)
mispDict['Tag'] = Tag
if labels:
Tag = []
for l in labels:
label = {'exportable': True, 'hide_tag': False}
label['name'] = l
Tag.append(label)
mispDict['Tag'] = Tag
def buildMispDict(event):
mispDict = {}
@ -148,7 +150,7 @@ def fillAttributes(attr, attrLabels, Attribute):
def fillCustom(attr, attrLabels, Attribute):
attribute = {}
attribute['type'] = attr.get('type').split('x-misp-object-')[1]
attribute['timestamp'] = int(time.mktime(time.strptime(attr.get('x_misp_timestamp'), "%Y-%m-%d %H:%M:%S")))
attribute['timestamp'] = getTimestampfromDate(attr.get('x_misp_timestamp'))
attribute['to_ids'] = bool(attrLabels[1].split('=')[1])
attribute['value'] = attr.get('x_misp_value')
attribute['category'] = getMispCategory(attrLabels)
@ -175,6 +177,8 @@ def fillCustomFromObject(attr, attrLabels, Object):
def getTimestampfromDate(date):
if '.' in date:
return int(time.mktime(time.strptime(date.split('.')[0], "%Y-%m-%dT%H:%M:%S")))
elif '+' in date:
return int(time.mktime(time.strptime(date.split('+')[0], "%Y-%m-%d %H:%M:%S")))
else:
return int(time.mktime(time.strptime(date, "%Y-%m-%dT%H:%M:%SZ")))
@ -517,7 +521,7 @@ def checkIfFromMISP(stix2Event):
return False
def main(args):
pathname = os.path.dirname(sys.argv[0])
pathname = os.path.dirname(args[0])
stix2Event = loadEvent(args, pathname)
stix2Event = stix2Event.get('objects')
if checkIfFromMISP(stix2Event):

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017 CIRCL Computer Incident Response Center Luxembourg (smile gie)
# Copyright (C) 2017 Christian Studer
# Copyright (C) 2017-2018 CIRCL Computer Incident Response Center Luxembourg (smile gie)
# Copyright (C) 2017-2018 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
@ -16,412 +16,561 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, json, os, time
import pymisp
from pymisp import MISPEvent, MISPObject, MISPAttribute, __path__
from stix.core import STIXPackage
eventTypes = {"ipv4-addr": {"src": "ip-src", "dst": "ip-dst", "value": "address_value", "relation": "ip"},
"ipv6-addr": {"src": "ip-src", "dst": "ip-dst", "value": "address_value", "relation": "ip"},
"URIObjectType": {"type": "url", "value": "value", "relation": "url"},
"FileObjectType": {"type": "filename", "value": "file_name", "relation": "filename"},
"DomainNameObjectType": {"type": "domain", "value": "value", "relation": "domain"},
"HostnameObjectType": {"type": "hostname", "value": "hostname_value", "relation": "host"},
"PortObjectType": {"type": "port", "value": "port_value", "relation": "port"},
"HTTPSessionObjectType": {"type": "", "value": "", "relation": ""},
"AddressObjectType": {"email": "email-src", "": ""},
"to": {"type": "email-dst", "value": "address_value", "relation": "to"},
"from": {"type": "email-src", "value": "value", "relation": "from"},
"subject": {"type": "email-subject", "value": "value", "relation": "subject"},
"email-attachment": {"value": "file_name", "relation": "attachment"},
"user_agent": "user-agent"}
file_object_type = {"type": "filename", "relation": "filename"}
descFilename = os.path.join(pymisp.__path__[0], 'data/describeTypes.json')
eventTypes = {"ArtifactObjectType": {"type": "attachment", "relation": "attachment"},
"DomainNameObjectType": {"type": "domain", "relation": "domain"},
"FileObjectType": file_object_type,
"HostnameObjectType": {"type": "hostname", "relation": "host"},
"MutexObjectType": {"type": "mutex", "relation": "mutex"},
"PDFFileObjectType": file_object_type,
"PortObjectType": {"type": "port", "relation": "port"},
"URIObjectType": {"type": "url", "relation": "url"},
"WindowsExecutableFileObjectType": file_object_type,
"WindowsRegistryKeyObjectType": {"type": "regkey", "relation": ""}}
descFilename = os.path.join(__path__[0], 'data/describeTypes.json')
with open(descFilename, 'r') as f:
categories = json.loads(f.read())['result'].get('categories')
def loadEvent(args, pathname):
try:
filename = '{}/tmp/{}'.format(pathname, args[1])
tempFile = open(filename, 'r')
fromMISP = True
stixJson = True
class StixParser():
def __init__(self):
self.misp_event = MISPEvent()
def loadEvent(self, args, pathname):
try:
event = json.loads(tempFile.read())
isJson = True
except:
filename = '{}/tmp/{}'.format(pathname, args[1])
event = STIXPackage.from_xml(filename)
try:
event = json.loads(event.to_json())
except:
stixJson = False
if args[1].startswith('misp.'):
event = event['related_packages']['related_packages'][0]
if "CIRCL:Package" in event.id_ and "CIRCL MISP" in event.stix_header.title:
fromMISP = True
else:
fromMISP = False
isJson = False
return event, isJson, fromMISP, stixJson
except:
print(json.dumps({'success': 0, 'message': 'The temporary STIX export file could not be read'}))
sys.exit(0)
def getTimestampfromDate(date):
try:
try:
dt = date.split('+')[0]
d = int(time.mktime(time.strptime(dt, "%Y-%m-%dT%H:%M:%S")))
except:
dt = date.split('.')[0]
d = int(time.mktime(time.strptime(dt, "%Y-%m-%dT%H:%M:%S")))
except AttributeError:
d = int(time.mktime(date.timetuple()))
return d
def buildMispDict(stixEvent):
mispDict = {}
stixTimestamp = stixEvent.get("timestamp")
dictTimestampAndDate(mispDict, stixTimestamp)
event = stixEvent["incidents"][0]
eventInfo(mispDict, event)
indicators = event["related_indicators"]["indicators"]
mispDict["Attribute"] = []
mispDict["Object"] = []
for indic in indicators:
try:
indicator = indic.get("indicator")
timestamp = indicator.get("timestamp").split("+")[0]
category = indic.get("relationship")
observable = indicator["observable"]
except:
continue
try:
properties = observable["object"]
attribute = {'timestamp': getTimestampfromDate(timestamp)}
attrType, attribute['value'], relation = fillMispAttribute(properties, category)
attribute['type'] = attrType
if category in categories:
attribute['category'] = category
mispDict["Attribute"].append(attribute)
if fromMISP:
self.event = event.related_packages.related_package[0].item.incidents[0]
else:
name = indicator.get('description').split(' ')[0]
defineRelation(attribute, attrType, name, relation)
obj = {'timestamp': getTimestampfromDate(timestamp), 'meta-category': category,
'Attribute': [attribute]}
obj['name'] = name
mispDict["Object"].append(obj)
self.event = event
self.fromMISP = fromMISP
self.filename = filename
self.load_mapping()
except:
observables = observable['observable_composition'].get('observables')
if category in categories:
domain = False
for obs in observables:
properties = obs['object']
tmpType, tmpValue, _ = fillMispAttribute(properties, category)
if tmpType == 'domain':
domainType = tmpType
domainVal = tmpValue
domain = True
elif tmpType in ('filename', 'regkey', 'hostname', 'ip-src', 'ip-dst'):
type1 = tmpType
value1 = tmpValue
else:
type2 = tmpType
value2 = tmpValue
if domain == True:
type2 = type1.split('-')[0]
type1 = domainType
value2 = value1
value1 = domainVal
attribute = {'timestamp': getTimestampfromDate(timestamp),
'type': '{}|{}'.format(type1, type2),
'value': '{}|{}'.format(value1, value2)}
mispDict['Attribute'].append(attribute)
else:
attributes = []
name = indicator.get('description').split(' ')[0]
for obs in observables:
properties = obs['object']
attribute = {'timestamp': getTimestampfromDate(timestamp)}
attrType, attribute['value'], relation = fillMispAttribute(properties, category)
if '|' in attrType:
attribute['type'] = "malware-sample"
attribute['object_relation'] = "malware-sample"
else:
attribute['type'] = attrType
defineRelation(attribute, attrType, name, relation)
attributes.append(attribute)
obj = {'timestamp': getTimestampfromDate(timestamp), 'meta-category': category,
'Attribute': attributes}
obj['name'] = name
mispDict["Object"].append(obj)
return mispDict
print(json.dumps({'success': 0, 'message': 'The temporary STIX export file could not be read'}))
sys.exit(0)
def dictTimestampAndDate(mispDict, stixTimestamp):
try:
date = stixTimestamp.split("T")[0]
except AttributeError:
date = stixTimestamp
mispDict["date"] = date
timestamp = getTimestampfromDate(stixTimestamp)
mispDict["timestamp"] = timestamp
def load_mapping(self):
self.attribute_types_mapping = {
'AddressObjectType': self.handle_address,
"ArtifactObjectType": self.handle_attachment,
'DomainNameObjectType': self.handle_domain_or_url,
'EmailMessageObjectType': self.handle_email_attribute,
'FileObjectType': self.handle_file,
'HostnameObjectType': self.handle_hostname,
'HTTPSessionObjectType': self.handle_http,
'MutexObjectType': self.handle_mutex,
'PDFFileObjectType': self.handle_file,
'PortObjectType': self.handle_port,
'SocketAddressObjectType': self.handle_socket_address,
'URIObjectType': self.handle_domain_or_url,
"WhoisObjectType": self.handle_whois,
'WindowsRegistryKeyObjectType': self.handle_regkey,
"WindowsExecutableFileObjectType": self.handle_pe
}
def eventInfo(mispDict, event):
try:
mispDict["info"] = event["title"]
except:
mispDict["info"] = "Imported from external STIX event"
try:
orgSource = event["information_source"]["identity"]["name"]
mispDict["Org"] = {}
mispDict["Org"]["name"] = orgSource
except:
pass
try:
orgReporter = event["reporter"]["identity"]["name"]
mispDict["Orgc"] = {}
mispDict["Orgc"]["name"] = orgReporter
except:
pass
def defineRelation(attribute, attrType, name, relation):
if attrType in ('md5', 'sha1', 'sha256') and name == 'x509':
attribute['object_relation'] = "x509-fingerprint-{}".format(attrType)
else:
attribute['object_relation'] = relation
def buildExternalDict(stixEvent):
mispDict = {}
stixTimestamp = stixEvent.get("timestamp")
dictTimestampAndDate(mispDict, stixTimestamp)
header = stixEvent.get('stix_header')
eventInfo(mispDict, header)
mispDict['Attribute'] = []
mispDict['Object'] = []
if 'indicators' in stixEvent:
indicators = stixEvent.get('indicators')
parseAttributes(indicators, mispDict, True)
if 'observables' in stixEvent:
observables = stixEvent['observables'].get('observables')
parseAttributes(observables, mispDict, False)
if 'ttps' in stixEvent:
ttps = stixEvent['ttps'].get('ttps')
parseTTPS(ttps, mispDict)
return mispDict
def buildExternalDict_fromPackage(stixEvent):
mispDict = {}
dictTimestampAndDate(mispDict, stixEvent.timestamp)
eventInfo(mispDict, stixEvent.stix_header)
mispDict['Attribute'] = []
mispDict['Object'] = []
if stixEvent.indicators:
parseAttributes(stixEvent.indicators.to_dict(), mispDict, True)
if stixEvent.observables:
parseAttributes(stixEvent.observables.to_dict()['observables'], mispDict, False)
if stixEvent.ttps:
parseTTPS(stixEvent.ttps.to_dict()['ttps'], mispDict)
return mispDict
def parseAttributes(attributes, mispDict, indic):
for attr in attributes:
if 'observable' in attr:
observable = attr.get('observable')
obj = observable.get('object')
def handler(self):
self.outputname = '{}.json'.format(self.filename)
if self.fromMISP:
# STIX format coming from a MISP export
self.buildMispDict()
else:
obj = attr.get('object')
try:
properties = obj.get('properties')
if 'hashes' in properties and len(properties.get('hashes')) > 1:
parseFileObject(properties, mispDict)
continue
elif properties.get('xsi:type') == 'WhoisObjectType':
continue
except:
if 'description' in attr:
attribute = {'type': 'text', 'value': attr.get('description')}
mispDict['Attribute'].append(attribute)
continue
try:
attrTimestamp = attr['timestamp'].split('+')[0]
attribute = {'timestamp': getTimestampfromDate(attrTimestamp)}
except:
attribute = {}
attribute['type'], attribute['value'] = fillExternalAttribute(properties)
attribute['to_ids'] = indic
mispDict['Attribute'].append(attribute)
# external STIX format file
self.buildExternalDict()
def parseFileObject(properties, mispDict):
obj = {'name': 'file', 'Attribute': []}
if 'file_name' in properties:
obj['Attribute'].append({'type': 'filename', 'object_relation': 'filename', 'value': properties.get('file_name')})
if 'peak_entropy' in properties:
obj['Attribute'].append({'type': 'float', 'object_relation': 'entropy', 'value': properties.get('peak_entropy')})
if 'size_in_bytes' in properties:
obj['Attribute'].append({'type': 'size-in-bytes', 'object_relation': 'size-in-bytes',
'value': properties.get('size_in_bytes')})
for h in properties.get('hashes'):
h_type = h.get('type').lower()
obj['Attribute'].append({'type': h_type, 'object_relation': h_type, 'value': h.get('simple_hash_value')})
mispDict['Object'].append(obj)
def buildMispDict(self):
self.dictTimestampAndDate()
self.eventInfo()
for indicator in self.event.related_indicators.indicator:
self.parse_misp_indicator(indicator)
def parseTTPS(ttps, mispDict):
mispDict['Galaxy'] = []
for ttp in ttps:
try:
behavior = ttp['behavior']
except KeyError:
continue
if 'malware_instances' in behavior:
attr = behavior['malware_instances'][0]
def buildExternalDict(self):
self.dictTimestampAndDate()
self.eventInfo()
if self.event.indicators:
self.parse_external_indicator(self.event.indicators)
if self.event.observables:
self.parse_external_observable(self.event.observables.observables)
# if self.event.ttps:
# self.parse_ttps(self.event.ttps.ttps)
def dictTimestampAndDate(self):
if self.event.timestamp:
stixTimestamp = self.event.timestamp
try:
attrType = attr['types'][0].get('value')
date = stixTimestamp.split("T")[0]
except AttributeError:
date = stixTimestamp
self.misp_event.date = date
self.misp_event.timestamp = self.getTimestampfromDate(stixTimestamp)
@staticmethod
def getTimestampfromDate(date):
try:
try:
dt = date.split('+')[0]
d = int(time.mktime(time.strptime(dt, "%Y-%m-%dT%H:%M:%S")))
except:
dt = date.split('.')[0]
d = int(time.mktime(time.strptime(dt, "%Y-%m-%dT%H:%M:%S")))
except AttributeError:
d = int(time.mktime(date.timetuple()))
return d
def eventInfo(self):
try:
try:
info = self.event.stix_header.title
except:
info = self.event.title
if info:
self.misp_event.info = info
else:
raise Exception("Imported from external STIX event")
except Exception as noinfo:
self.misp_event.info = str(noinfo)
def parse_misp_indicator(self, indicator):
# define is an indicator will be imported as attribute or object
if indicator.relationship in categories:
self.parse_misp_attribute(indicator)
else:
self.parse_misp_object(indicator)
def parse_misp_attribute(self, indicator):
misp_attribute = {'category': str(indicator.relationship)}
item = indicator.item
misp_attribute['timestamp'] = self.getTimestampfromDate(item.timestamp)
if item.observable:
observable = item.observable
try:
properties = observable.object_.properties
if properties:
attribute_type, attribute_value, _ = self.handle_attribute_type(properties)
self.misp_event.add_attribute(attribute_type, attribute_value, **misp_attribute)
except AttributeError:
attribute_dict = {}
for observables in observable.observable_composition.observables:
properties = observables.object_.properties
attribute_type, attribute_value, _ = self.handle_attribute_type(properties)
attribute_dict[attribute_type] = attribute_value
attribute_type, attribute_value = self.composite_type(attribute_dict)
self.misp_event.add_attribute(attribute_type, attribute_value, **misp_attribute)
@staticmethod
def composite_type(attributes):
if "port" in attributes:
if "ip-src" in attributes:
return "ip-src|port", "{}|{}".format(attributes["ip-src"], attributes["port"])
elif "ip-dst" in attributes:
return "ip-dst|port", "{}|{}".format(attributes["ip-dst"], attributes["port"])
elif "hostname" in attributes:
return "hostname|port", "{}|{}".format(attributes["hostname"], attributes["port"])
elif "domain" in attributes:
if "ip-src" in attributes:
ip_value = attributes["ip-src"]
elif "ip-dst" in attributes:
ip_value = attributes["ip-dst"]
return "domain|ip", "{}|{}".format(attributes["domain"], ip_value)
def handle_attribute_type(self, properties, is_object=False, title=None):
xsi_type = properties._XSI_TYPE
try:
args = [properties]
if xsi_type in ("FileObjectType", "PDFFileObjectType"):
args.append(is_object)
elif xsi_type == "ArtifactObjectType":
args.append(title)
return self.attribute_types_mapping[xsi_type](*args)
except AttributeError:
# ATM USED TO TEST TYPES
print("Unparsed type: {}".format(xsi_type))
sys.exit(1)
@staticmethod
def handle_address(properties):
if properties.is_source:
ip_type = "ip-src"
else:
ip_type = "ip-dst"
return ip_type, properties.address_value.value, "ip"
@staticmethod
def handle_attachment(properties, title):
return eventTypes[properties._XSI_TYPE]['type'], title, properties.raw_artifact.value
@staticmethod
def handle_domain_or_url(properties):
event_types = eventTypes[proprties._XSI_TYPE]
return event_types['type'], properties.value.value, event_types['relation']
def handle_email_attribute(self, properties):
try:
if properties.from_:
return "email-src", properties.from_.address_value.value, "from"
except:
pass
try:
if properties.to:
return "email-dst", properties.to[0].address_value.value, "to"
except:
pass
try:
if properties.subject:
return "email-subject", properties.subject.value, "subject"
except:
pass
try:
if properties.attachments:
return self.handle_email_attachment(properties.parent)
except:
pass
else:
# ATM USED TO TEST EMAIL PROPERTIES
print("Unsupported Email property")
sys.exit(1)
@staticmethod
def handle_email_attachment(indicator_object):
properties = indicator_object.related_objects[0].properties
return "email-attachment", properties.file_name.value, "attachment"
def handle_file(self, properties, is_object):
b_hash, b_file = False, False
attributes = []
if properties.hashes:
b_hash = True
for h in properties.hashes:
attributes.append(self.handle_hashes_attribute(h))
if properties.file_format and properties.file_format.value:
attributes.append(["mime-type", properties.file_format.value, "mimetype"])
if properties.file_name or properties.file_path:
try:
value = properties.file_name.value
except AttributeError:
value = properties.file_path.value
if value:
b_file = True
event_types = eventTypes[properties._XSI_TYPE]
attributes.append([event_types['type'], value, event_types['relation']])
if properties.byte_runs:
attribute_type = "pattern-in-file"
attributes.append([attribute_type, properties.byte_runs[0].byte_run_data, attribute_type])
if properties.size_in_bytes and properties.size_in_bytes.value:
attribute_type = "size-in-bytes"
attributes.append([attribute_type, properties.size_in_bytes.value, attribute_type])
if properties.peak_entropy and properties.peak_entropy.value:
attributes.append(["float", properties.peak_entropy.value, "entropy"])
if len(attributes) == 1:
return attributes[0]
if len(attributes) == 2:
if b_hash and b_file:
return self.handle_filename_object(attributes, is_object)
return "file", self.return_attributes(attributes), ""
@staticmethod
def handle_filename_object(attributes, is_object):
for attribute in attributes:
attribute_type, attribute_value, _ = attribute
if attribute_type == "filename":
filename_value = attribute_value
else:
hash_type, hash_value = attribute_type, attribute_value
value = "{}|{}".format(filename_value, hash_value)
if is_object:
# file object attributes cannot be filename|hash, so it is malware-sample
attr_type = "malware-sample"
return attr_type, value, attr_type
else:
# it could be malware-sample as well, but STIX is losing this information
return "filename|{}".format(hash_type), value, ""
@staticmethod
def handle_hashes_attribute(properties):
hash_type = properties.type_.value.lower()
try:
hash_value = properties.simple_hash_value.value
except AttributeError:
hash_value = properties.fuzzy_hash_value.value
return hash_type, hash_value, hash_type
@staticmethod
def handle_hostname(properties):
event_types = eventTypes[properties._XSI_TYPE]
return event_types['type'], properties.hostname_value.value, event_types['relation']
@staticmethod
def handle_http(properties):
client_request = properties.http_request_response[0].http_client_request
if client_request.http_request_header:
request_header = client_request.http_request_header
if request_header.parsed_header:
value = request_header.parsed_header.user_agent.value
return "user-agent", value, "user-agent"
elif request_header.raw_header:
value = request_header.raw_header.value
return "http-method", value, "method"
elif client_request.http_request_line:
value = client_request.http_request_line.http_method.value
return "http-method", value, "method"
@staticmethod
def handle_mutex(properties):
event_types = eventTypes[properties._XSI_TYPE]
return event_types['type'], properties.name.value, event_types['relation']
@staticmethod
def handle_port(properties):
event_types = eventTypes[properties._XSI_TYPE]
return event_types['type'], properties.port_value.value, event_types['relation']
@staticmethod
def handle_regkey(properties):
event_types = eventTypes[properties._XSI_TYPE]
return event_types['type'], properties.key.value, event_types['relation']
def handle_socket_address(self, properties):
if properties.ip_address:
type1, value1, _ = self.handle_address(properties.ip_address)
elif properties.hostname:
type1 = "hostname"
value1 = properties.hostname.hostname_value.value
return "{}|port".format(type1), "{}|{}".format(value1, properties.port.port_value.value), ""
def handle_whois(self, properties):
required_one_of = False
attributes = []
if properties.remarks:
attribute_type = "text"
attributes.append([attribute_type, properties.remarks.value, attribute_type])
required_one_of = True
if properties.registrar_info:
attribute_type = "whois-registrar"
attributes.append([attribute_type, properties.registrar_info.value, attribute_type])
required_one_of = True
if properties.registrants:
# ATM: need to see how it looks like in a real example
print(dir(properties.registrants))
if properties.creation_date:
attributes.append(["datetime", properties.creation_date.value, "creation-date"])
required_one_of = True
if properties.updated_date:
attributes.append(["datetime", properties.updated_date.value, "modification-date"])
if properties.expiration_date:
attributes.append(["datetime", properties.expiration_date.value, "expiration-date"])
if properties.nameservers:
for nameserver in properties.nameservers:
attributes.append(["hostname", nameserver.value.value, "nameserver"])
if properties.ip_address:
attributes.append(["ip-dst", properties.ip_address.value, "ip-address"])
required_one_of = True
if properties.domain_name:
attribute_type = "domain"
attributes.append([attribute_type, properties.domain_name.value, attribute_type])
required_one_of = True
# Testing if we have the required attribute types for Object whois
if required_one_of:
# if yes, we return the object type and the attributes
return "whois", self.return_attributes(attributes), ""
else:
# otherwise, attributes are added in the event, and one attribute is returned to not make the function crash
if len(attributes) == 1:
return attributes[0]
last_attribute = attributes.pop(-1)
for attribute in attributes:
attribute_type, attribute_value, attribute_relation = attribute
misp_attributes = {"comment": "Whois {}".format(attribute_relation)}
self.misp_event.add_attribute(attribute_type, attribute_value, **misp_attributes)
return last_attribute
def handle_pe(self, properties):
pe_uuid = self.parse_pe(properties)
file_type, file_value, _ = self.handle_file(properties, False)
return file_type, file_value, pe_uuid
def parse_pe(self, properties):
misp_object = MISPObject('pe')
filename = properties.file_name.value
for attr in ('internal-filename', 'original-filename'):
misp_object.add_attribute(**dict(zip(('type', 'value', 'object_relation'),('filename', filename, attr))))
if properties.headers:
headers = properties.headers
header_object = MISPObject('pe-section')
if headers.entropy:
header_object.add_attribute(**{"type": "float", "object_relation": "entropy",
"value": headers.entropy.value.value})
file_header = headers.file_header
misp_object.add_attribute(**{"type": "counter", "object_relation": "number-sections",
"value": file_header.number_of_sections.value})
for h in file_header.hashes:
hash_type, hash_value, hash_relation = self.handle_hashes_attribute(h)
header_object.add_attribute(**{"type": hash_type, "value": hash_value, "object_relation": hash_relation})
if file_header.size_of_optional_header:
header_object.add_attribute(**{"type": "size-in-bytes", "object_relation": "size-in-bytes",
"value": file_header.size_of_optional_header.value})
self.misp_event.add_object(**header_object)
misp_object.add_reference(header_object.uuid, 'pe-section')
if properties.sections:
for section in properties.sections:
section_uuid = self.parse_pe_section(section)
misp_object.add_reference(section_uuid, 'pe-section')
self.misp_event.add_object(**misp_object)
return {"pe_uuid": misp_object.uuid}
def parse_pe_section(self, section):
section_object = MISPObject('pe-section')
header_hashes = section.header_hashes
for h in header_hashes:
hash_type, hash_value, hash_relation = self.handle_hashes_attribute(h)
section_object.add_attribute(**{"type": hash_type, "value": hash_value, "object_relation": hash_relation})
if section.entropy:
section_object.add_attribute(**{"type": "float", "object_relation": "entropy",
"value": section.entropy.value.value})
if section.section_header:
section_header = section.section_header
section_object.add_attribute(**{"type": "text", "object_relation": "name",
"value": section_header.name.value})
section_object.add_attribute(**{"type": "size-in-bytes", "object_relation": "size-in-bytes",
"value": section_header.size_of_raw_data.value})
self.misp_event.add_object(**section_object)
return section_object.uuid
def parse_misp_object(self, indicator):
object_type = str(indicator.relationship)
if object_type == 'file':
item = indicator.item
self.fill_misp_object(item, object_type)
elif object_type == 'network':
item = indicator.item
name = item.title.split(' ')[0]
if name not in ('passive-dns'):
self.fill_misp_object(item, name)
else:
if object_type != "misc":
print("Unparsed Object type: {}".format(name))
def fill_misp_object(self, item, name):
misp_object = MISPObject(name)
misp_object.timestamp = self.getTimestampfromDate(item.timestamp)
try:
observables = item.observable.observable_composition.observables
for observable in observables:
properties = observable.object_.properties
self.parse_observable(properties, misp_object)
except AttributeError:
properties = item.observable.object_.properties
self.parse_observable(properties, misp_object)
self.misp_event.add_object(**misp_object)
def parse_observable(self, properties, misp_object):
misp_attribute = MISPAttribute()
misp_attribute.type, misp_attribute.value, misp_attribute.object_relation = self.handle_attribute_type(properties, is_object=True)
misp_object.add_attribute(**misp_attribute)
def parse_external_indicator(self, indicators):
for indicator in indicators:
try:
properties = indicator.observable.object_.properties
except:
self.parse_description(indicator)
continue
attribute = {'type': attrType, 'GalaxyCluster': []}
cluster = {'type': attrType}
if properties:
attribute_type, attribute_value, compl_data = self.handle_attribute_type(properties)
if type(attribute_value) is str:
# if the returned value is a simple value, we build an attribute
attribute = {'to_ids': True}
if indicator.timestamp:
attribute['timestamp'] = self.getTimestampfromDate(indicator.timestamp)
self.handle_attribute_case(attribute_type, attribute_value, compl_data, attribute)
else:
# otherwise, it is a dictionary of attributes, so we build an object
self.handle_object_case(attribute_type, attribute_value, compl_data)
def parse_external_observable(self, observables):
for observable in observables:
title = observable.title
try:
cluster['description'] = attr['short_description']
properties = observable.object_.properties
except:
cluster['description'] = attr.get('description')
if 'names' in attr:
synonyms = []
for name in attr.get('names'):
synonyms.append(name)
cluster['meta'] = {'synonyms': synonyms}
cluster['value'] = ttp.get('title')
attribute['GalaxyCluster'].append(cluster)
mispDict['Galaxy'].append(attribute)
self.parse_description(observable)
continue
if properties:
attribute_type, attribute_value, compl_data = self.handle_attribute_type(properties, title=title)
attr_type = type(attribute_value)
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}
self.handle_attribute_case(attribute_type, attribute_value, compl_data, attribute)
else:
# otherwise, it is a dictionary of attributes, so we build an object
self.handle_object_case(attribute_type, attribute_value, compl_data)
def fillExternalAttribute(properties):
if 'hashes' in properties:
hashes = properties['hashes'][0]
try:
typeVal = hashes.get('type').lower()
except:
typeVal = hashes['type'].get('value').lower()
value = hashes.get('simple_hash_value')
if type(value) is dict:
value = value.get('value')
else:
attrType = properties.get('xsi:type')
if attrType == 'AddressObjectType':
if 'email' in properties.get('category'):
typeVal = eventTypes[attrType]['email']
else:
try:
if properties.get('is_source') == 'false':
typeVal = eventTypes[properties.get('category')].get('dst')
else:
typeVal = eventTypes[properties.get('category')].get('src')
except:
typeVal = "ip-src"
elif attrType == 'HTTPSessionObjectType':
return "http-method", properties['http_request_response'][0]['http_client_request']['http_request_header']['raw_header']
else:
typeVal = eventTypes[properties.get('xsi:type')].get('type')
if 'address_value' in properties:
try:
value = properties['address_value'].get('value')
except:
value = properties.get('address_value')
else:
value = properties.get('value')
return typeVal, value
def parse_description(self, stix_object):
if stix_object.description:
misp_attribute = {}
if stix_object.timestamp:
misp_attribute['timestamp'] = self.getTimestampfromDate(stix_object.timestamp)
self.misp_event.add_attribute("text", stix_object.description.value, **misp_attribute)
def fillMispAttribute(prop, category):
properties = prop['properties']
try:
cat = properties["category"]
except:
cat = properties["xsi:type"]
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"]
relation = 'ip'
elif cat == 'EmailMessageObjectType':
try:
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)
relation = eventTypes[emailType]['relation']
except:
attachmentProp = prop['related_objects'][0]['properties']
if attachmentProp.get('xsi:type') == 'FileObjectType':
typeVal = 'email-attachment'
propCat = eventTypes[typeVal]['value']
valueVal = attachmentProp[propCat].get('value')
relation = eventTypes[typeVal]['relation']
elif cat == "FileObjectType" and "hashes" in properties:
hashes = properties['hashes'][0]
if 'file_name' in properties:
type2 = hashes["type"].get("value").lower()
typeVal = 'filename|{}'.format(type2)
value1 = properties['file_name'].get('value')
value2 = hashes["simple_hash_value"].get("value")
valueVal = '{}|{}'.format(value1, value2)
relation = None
else:
if category == 'Network activity':
typeVal = 'x509-fingerprint-sha1'
else:
typeVal = hashes["type"].get("value").lower()
valueVal = hashes["simple_hash_value"].get("value")
relation = typeVal
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]
relation = 'user-agent'
elif cat == "WindowsRegistryKeyObjectType":
valueVal = ""
if properties['hive'].get('value') == "HKEY_LOCAL_MACHINE":
valueVal += "HKLM\\"
valueVal += properties['key'].get('value')
typeVal = "regkey"
relation = "key"
else:
value = eventTypes[cat]["value"]
typeVal = eventTypes[cat]["type"]
valueVal = properties[value]["value"]
relation = eventTypes[cat]["relation"]
return typeVal, valueVal, relation
def handle_attribute_case(self, attribute_type, attribute_value, data, attribute):
if attribute_type == 'attachment':
attribute['data'] = data
self.misp_event.add_attribute(attribute_type, attribute_value, **attribute)
def handle_object_case(self, attribute_type, attribute_value, compl_data):
misp_object = MISPObject(attribute_type)
for attribute in attribute_value:
misp_object.add_attribute(**attribute)
if type(compl_data) is dict and "pe_uuid" in compl_data:
# if some complementary data is a dictionary containing an uuid,
# it means we are using it to add an object reference of a pe object
# in a file object
misp_object.add_reference(compl_data['pe_uuid'], 'pe')
self.misp_event.add_object(**misp_object)
def saveFile(namefile, pathname, misp):
filepath = "{}/tmp/{}".format(pathname, namefile)
eventDict = misp.to_json()
with open(filepath, 'w') as f:
f.write(eventDict)
def parse_ttps(self, ttps):
galaxies = []
for ttp in ttps:
if ttp.behavior and ttp.behavior.malware_instances:
mi = ttp.behavior.malware_instances[0]
if mi.types:
mi_type = mi.types[0].value
galaxy = {'type': mi_type, 'GalaxyCluster': []}
cluster = {'type': mi_type}
if mi.description:
cluster['description'] = mi.description.value
cluster['value'] = ttp.title
galaxy['GalaxyCluster'].append(cluster)
galaxies.append(galaxy)
self.misp_event['Galaxy'] = galaxies
@staticmethod
def return_attributes(attributes):
return_attributes = []
for attribute in attributes:
return_attributes.append(dict(zip(('type', 'value', 'object_relation'), attribute)))
return return_attributes
def saveFile(self):
eventDict = self.misp_event.to_json()
with open(self.outputname, 'w') as f:
f.write(eventDict)
def main(args):
pathname = os.path.dirname(args[0])
stixEvent, isJson, fromMISP, stixJson = loadEvent(args, pathname)
if isJson:
namefile = args[1]
else:
namefile = '{}.json'.format(args[1])
if fromMISP:
stixEvent = stixEvent["package"]
mispDict = buildMispDict(stixEvent)
else:
if stixJson:
mispDict = buildExternalDict(stixEvent)
else:
mispDict = buildExternalDict_fromPackage(stixEvent)
misp = pymisp.MISPEvent(None, False)
misp.from_dict(**mispDict)
saveFile(namefile, pathname, misp)
stix_parser = StixParser()
stix_parser.loadEvent(args, pathname)
stix_parser.handler()
stix_parser.saveFile()
print(1)
if __name__ == "__main__":

@ -1 +1 @@
Subproject commit 1b4cb19909c32f3c721e48d123e9ffbd43ea4336
Subproject commit 4996ebb4a2ebbf70ddb2714b32458d62fcd0d5c1

@ -1 +1 @@
Subproject commit 42c5cf055c26119bc3931399f98a8a3c7bd0253d
Subproject commit f54d241f2b159114224db2e8447e2c8bcf36ed8e

View File

@ -31,7 +31,7 @@ class EventGraph {
this.mapping_meta_fa.set('file', {"meta-category": "file","fa_text": "file","fa-hex": "f15b"});
this.mapping_meta_fa.set('financial', {"meta-category": "financial","fa_text": "money-bil-alt","fa-hex": "f3d1"});
this.mapping_meta_fa.set('network', {"meta-category": "network","fa_text": "server","fa-hex": "f233"});
this.mapping_meta_fa.set('misc', {"meta-category": "misc","fa_text": "cube","fa-hex": "f1b2"});
this.mapping_meta_fa.set('misc', {"meta-category": "misc","fa_text": "cube","fa-hex": "f1b2"}); // Also considered as default
// FIXME
this.network_options = network_options;
this.globalCounter = 0;
@ -77,6 +77,11 @@ class EventGraph {
get_node_color(uuid) {
return this.nodes.get(uuid).icon.color;
}
get_FA_icon(metaCateg) {
var dict = this.mapping_meta_fa.get(metaCateg);
dict = dict === undefined ? this.mapping_meta_fa.get('misc') : dict; // if unknown meta-categ, take default
return String.fromCharCode(parseInt(dict['fa-hex'], 16))
}
getUniqId() {
this.globalCounter++;
return this.globalCounter-1;
@ -347,7 +352,7 @@ class EventGraph {
icon: {
color: getRandomColor(),
face: 'FontAwesome',
code: String.fromCharCode(parseInt(this.mapping_meta_fa.get(node['meta-category'])['fa-hex'], 16)),
code: this.get_FA_icon(node['meta-category']),
}
};
dataHandler.mapping_value_to_nodeID.set(striped_value, node.id);

View File

@ -639,7 +639,7 @@ function multiSelectDeleteEvents() {
});
}
function multiSelectToggleFeeds(on) {
function multiSelectToggleFeeds(on, cache) {
var selected = [];
$(".select").each(function() {
if ($(this).is(":checked")) {
@ -649,7 +649,7 @@ function multiSelectToggleFeeds(on) {
}
}
});
$.get("/feeds/toggleSelected/" + on + "/" + JSON.stringify(selected), function(data) {
$.get("/feeds/toggleSelected/" + on + "/" + cache + "/" + JSON.stringify(selected), function(data) {
$("#confirmation_box").html(data);
openPopup("#confirmation_box");
});
@ -1268,7 +1268,7 @@ function simplePopup(url) {
error:function() {
$(".loading").hide();
$("#gray_out").fadeOut();
showMessage('fail', 'Could not fetch the given PGP key.');
showMessage('fail', 'Could not fetch the given GnuPG key.');
},
url: url,
});