Merge remote-tracking branch 'origin/2.4' into decaying

pull/5032/head
mokaddem 2019-08-13 16:32:58 +02:00
commit 6ba45b27f8
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
76 changed files with 10104 additions and 2301 deletions

View File

@ -613,7 +613,7 @@ CREATE TABLE IF NOT EXISTS `object_template_elements` (
-- Table structure for table `organisations`
--
CREATE TABLE `organisations` (
CREATE TABLE IF NOT EXISTS `organisations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_bin NOT NULL,
`date_created` datetime NOT NULL,

2
PyMISP

@ -1 +1 @@
Subproject commit 1dce91af8f6768f800e3f9602cd80d5f87dc3732
Subproject commit a3140f37739b4a8a63f9b224aaaa2209611a33fe

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":111}
{"major":2, "minor":4, "hotfix":112}

View File

@ -24,7 +24,8 @@ $config = array(
'cached_attachments' => true,
'email' => 'email@address.com',
'contact' => 'email@address.com',
'cveurl' => 'http://cve.circl.lu/cve/',
'cveurl' => 'https://cve.circl.lu/cve/',
'cweurl' => 'https://cve.circl.lu/cwe/',
'disablerestalert' => false,
'default_event_distribution' => '1',
'default_attribute_distribution' => 'event',

View File

@ -499,4 +499,11 @@ class AdminShell extends AppShell
echo __('DB was never successfully updated or we are on a fresh install') . PHP_EOL;
}
}
public function cleanCaches()
{
echo 'Cleaning caches...' . PHP_EOL;
$this->Server->cleanCacheFiles();
echo '...caches lost in time, like tears in rain.' . PHP_EOL;
}
}

View File

@ -4,180 +4,181 @@ App::uses('File', 'Utility');
require_once 'AppShell.php';
class ServerShell extends AppShell
{
public $uses = array('Server', 'Task', 'Job', 'User', 'Feed');
public $uses = array('Server', 'Task', 'Job', 'User', 'Feed');
public function pull() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['pull'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($this->args[1])) die();
$serverId = $this->args[1];
if (!empty($this->args[2])) {
$technique = $this->args[2];
} else {
$technique = 'full';
}
if (!empty($this->args[3])) {
$jobId = $this->args[3];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'pull',
'job_input' => 'Server: ' . $serverId,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Pulling.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Server->id = $serverId;
$server = $this->Server->read(null, $serverId);
$result = $this->Server->pull($user, $serverId, $technique, $server, $jobId);
$this->Job->id = $jobId;
$this->Job->save(array(
'id' => $jobId,
'message' => 'Job done.',
'progress' => 100,
'status' => 4
));
if (is_array($result)) {
$message = sprintf(__('Pull completed. %s events pulled, %s events could not be pulled, %s proposals pulled.', count($result[0]), count($result[1]), $result[2]));
} else {
$message = sprintf(__('ERROR: %s'), $result);
}
$this->Job->saveField('message', $message);
echo $message . PHP_EOL;
}
public function pull() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['pull'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($this->args[1])) die();
$serverId = $this->args[1];
if (!empty($this->args[2])) {
$technique = $this->args[2];
} else {
$technique = 'full';
}
if (!empty($this->args[3])) {
$jobId = $this->args[3];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'pull',
'job_input' => 'Server: ' . $serverId,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Pulling.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Server->id = $serverId;
$server = $this->Server->read(null, $serverId);
$result = $this->Server->pull($user, $serverId, $technique, $server, $jobId);
$this->Job->id = $jobId;
$this->Job->save(array(
'id' => $jobId,
'message' => 'Job done.',
'progress' => 100,
'status' => 4
));
if (is_array($result)) {
$message = sprintf(__('Pull completed. %s events pulled, %s events could not be pulled, %s proposals pulled.', count($result[0]), count($result[1]), $result[2]));
} else {
$message = sprintf(__('ERROR: %s'), $result);
}
$this->Job->saveField('message', $message);
echo $message . PHP_EOL;
}
public function push() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['push'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) die('Invalid user.' . PHP_EOL);
$serverId = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'push',
'job_input' => 'Server: ' . $serverId,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Pushing.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Job->read(null, $jobId);
$server = $this->Server->read(null, $serverId);
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
$result = $this->Server->push($serverId, 'full', $jobId, $HttpSocket, $user);
$message = 'Job done.';
if ($result !== true && !is_array($result)) $message = 'Job failed. Reason: ' . $result;
$this->Job->save(array(
'id' => $jobId,
'message' => $message,
'progress' => 100,
'status' => 4
));
if (isset($this->args[4])) {
$this->Task->id = $this->args[5];
$message = 'Job(s) started at ' . date('d/m/Y - H:i:s') . '.';
$this->Task->saveField('message', $message);
echo $message . PHP_EOL;
}
}
public function push() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['push'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) die('Invalid user.' . PHP_EOL);
$serverId = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'push',
'job_input' => 'Server: ' . $serverId,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Pushing.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$technique = empty($this->args[3]) ? 'full' : $this->args[3];
$this->Job->read(null, $jobId);
$server = $this->Server->read(null, $serverId);
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
$result = $this->Server->push($serverId, $technique, $jobId, $HttpSocket, $user);
$message = 'Job done.';
if ($result !== true && !is_array($result)) $message = 'Job failed. Reason: ' . $result;
$this->Job->save(array(
'id' => $jobId,
'message' => $message,
'progress' => 100,
'status' => 4
));
if (isset($this->args[4])) {
$this->Task->id = $this->args[5];
$message = 'Job(s) started at ' . date('d/m/Y - H:i:s') . '.';
$this->Task->saveField('message', $message);
echo $message . PHP_EOL;
}
}
public function fetchFeed() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['fetchFeed'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) {
echo 'Invalid user.';
die();
}
$feedId = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'fetch_feeds',
'job_input' => 'Feed: ' . $feedId,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Starting fetch from Feed.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Job->read(null, $jobId);
$outcome = array(
'id' => $jobId,
'message' => 'Job done.',
'progress' => 100,
'status' => 4
);
if ($feedId == 'all') {
$feedIds = $this->Feed->find('list', array(
'fields' => array('Feed.id', 'Feed.id'),
'conditions' => array('Feed.enabled' => 1)
));
$feedIds = array_values($feedIds);
$successes = 0;
$fails = 0;
foreach ($feedIds as $k => $feedId) {
$jobStatus = array(
'id' => $jobId,
'message' => 'Fetching feed: ' . $feedId,
'progress' => 100 * $k / count($feedIds),
'status' => 0
);
$this->Job->id = $jobId;
$this->Job->save($jobStatus);
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user);
if ($result) {
$successes++;
} else {
$fails++;
}
}
$outcome['message'] = 'Job done. ' . $successes . ' feeds pulled successfuly, ' . $fails . ' feeds could not be pulled.';
} else {
$temp = $this->Feed->find('first', array(
'fields' => array('Feed.id', 'Feed.id'),
'conditions' => array('Feed.enabled' => 1, 'Feed.id' => $feedId)
));
if (!empty($temp)) {
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user, $jobId);
if (!$result) {
$outcome['progress'] = 0;
$outcome['status'] = 3;
$outcome['message'] = 'Job failed.';
}
}
}
$this->Job->id = $jobId;
$this->Job->save($outcome);
echo $outcome['message'] . PHP_EOL;
}
public function fetchFeed() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['fetchFeed'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) {
echo 'Invalid user.';
die();
}
$feedId = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'fetch_feeds',
'job_input' => 'Feed: ' . $feedId,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Starting fetch from Feed.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Job->read(null, $jobId);
$outcome = array(
'id' => $jobId,
'message' => 'Job done.',
'progress' => 100,
'status' => 4
);
if ($feedId == 'all') {
$feedIds = $this->Feed->find('list', array(
'fields' => array('Feed.id', 'Feed.id'),
'conditions' => array('Feed.enabled' => 1)
));
$feedIds = array_values($feedIds);
$successes = 0;
$fails = 0;
foreach ($feedIds as $k => $feedId) {
$jobStatus = array(
'id' => $jobId,
'message' => 'Fetching feed: ' . $feedId,
'progress' => 100 * $k / count($feedIds),
'status' => 0
);
$this->Job->id = $jobId;
$this->Job->save($jobStatus);
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user);
if ($result) {
$successes++;
} else {
$fails++;
}
}
$outcome['message'] = 'Job done. ' . $successes . ' feeds pulled successfuly, ' . $fails . ' feeds could not be pulled.';
} else {
$temp = $this->Feed->find('first', array(
'fields' => array('Feed.id', 'Feed.id'),
'conditions' => array('Feed.enabled' => 1, 'Feed.id' => $feedId)
));
if (!empty($temp)) {
$result = $this->Feed->downloadFromFeedInitiator($feedId, $user, $jobId);
if (!$result) {
$outcome['progress'] = 0;
$outcome['status'] = 3;
$outcome['message'] = 'Job failed.';
}
}
}
$this->Job->id = $jobId;
$this->Job->save($outcome);
echo $outcome['message'] . PHP_EOL;
}
public function cacheServer() {
if (empty($this->args[0]) || empty($this->args[1])) {
@ -227,123 +228,123 @@ class ServerShell extends AppShell
}
public function cacheFeed() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['cacheFeed'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) die('Invalid user.' . PHP_EOL);
$scope = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'cache_feeds',
'job_input' => 'Feed: ' . $scope,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Starting feed caching.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Job->read(null, $jobId);
$result = $this->Feed->cacheFeedInitiator($user, $jobId, $scope);
$this->Job->id = $jobId;
if ($result !== true) {
$message = 'Job Failed. Reason: ';
$this->Job->save(array(
'id' => $jobId,
'message' => $message . $result,
'progress' => 0,
'status' => 3
));
} else {
$message = 'Job done.';
$this->Job->save(array(
'id' => $jobId,
'message' => $message,
'progress' => 100,
'status' => 4
));
}
echo $message . PHP_EOL;
}
public function cacheFeed() {
if (empty($this->args[0]) || empty($this->args[1])) {
die('Usage: ' . $this->Server->command_line_functions['console_automation_tasks']['data']['cacheFeed'] . PHP_EOL);
}
$userId = $this->args[0];
$user = $this->User->getAuthUser($userId);
if (empty($user)) die('Invalid user.' . PHP_EOL);
$scope = $this->args[1];
if (!empty($this->args[2])) {
$jobId = $this->args[2];
} else {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'cache_feeds',
'job_input' => 'Feed: ' . $scope,
'status' => 0,
'retries' => 0,
'org' => $user['Organisation']['name'],
'message' => 'Starting feed caching.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
}
$this->Job->read(null, $jobId);
$result = $this->Feed->cacheFeedInitiator($user, $jobId, $scope);
$this->Job->id = $jobId;
if ($result !== true) {
$message = 'Job Failed. Reason: ';
$this->Job->save(array(
'id' => $jobId,
'message' => $message . $result,
'progress' => 0,
'status' => 3
));
} else {
$message = 'Job done.';
$this->Job->save(array(
'id' => $jobId,
'message' => $message,
'progress' => 100,
'status' => 4
));
}
echo $message . PHP_EOL;
}
public function enqueuePull() {
$timestamp = $this->args[0];
$userId = $this->args[1];
$taskId = $this->args[2];
$task = $this->Task->read(null, $taskId);
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueuePull', $userId, $taskId);
$user = $this->User->getAuthUser($userId);
$servers = $this->Server->find('all', array('recursive' => -1, 'conditions' => array('pull' => 1)));
$count = count($servers);
$failCount = 0;
foreach ($servers as $k => $server) {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'pull',
'job_input' => 'Server: ' . $server['Server']['id'],
'retries' => 0,
'org' => $user['Organisation']['name'],
'org_id' => $user['org_id'],
'process_id' => 'Part of scheduled pull',
'message' => 'Pulling.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$result = $this->Server->pull($user, $server['Server']['id'], 'full', $server, $jobId);
$this->Job->save(array(
'id' => $jobId,
'message' => 'Job done.',
'progress' => 100,
'status' => 4
));
if (is_numeric($result[0])) {
switch ($result[0]) {
case '1' :
$this->Job->saveField('message', 'Not authorised. This is either due to an invalid auth key, or due to the sync user not having authentication permissions enabled on the remote server.');
break;
case '2' :
$this->Job->saveField('message', $result[1]);
break;
case '3' :
$this->Job->saveField('message', 'Sorry, incremental pushes are not yet implemented.');
break;
case '4' :
$this->Job->saveField('message', 'Invalid technique chosen.');
break;
public function enqueuePull() {
$timestamp = $this->args[0];
$userId = $this->args[1];
$taskId = $this->args[2];
$task = $this->Task->read(null, $taskId);
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueuePull', $userId, $taskId);
$user = $this->User->getAuthUser($userId);
$servers = $this->Server->find('all', array('recursive' => -1, 'conditions' => array('pull' => 1)));
$count = count($servers);
$failCount = 0;
foreach ($servers as $k => $server) {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'pull',
'job_input' => 'Server: ' . $server['Server']['id'],
'retries' => 0,
'org' => $user['Organisation']['name'],
'org_id' => $user['org_id'],
'process_id' => 'Part of scheduled pull',
'message' => 'Pulling.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$result = $this->Server->pull($user, $server['Server']['id'], 'full', $server, $jobId);
$this->Job->save(array(
'id' => $jobId,
'message' => 'Job done.',
'progress' => 100,
'status' => 4
));
if (is_numeric($result[0])) {
switch ($result[0]) {
case '1' :
$this->Job->saveField('message', 'Not authorised. This is either due to an invalid auth key, or due to the sync user not having authentication permissions enabled on the remote server.');
break;
case '2' :
$this->Job->saveField('message', $result[1]);
break;
case '3' :
$this->Job->saveField('message', 'Sorry, incremental pushes are not yet implemented.');
break;
case '4' :
$this->Job->saveField('message', 'Invalid technique chosen.');
break;
}
$failCount++;
}
}
$this->Task->id = $task['Task']['id'];
$this->Task->saveField('message', count($servers) . ' job(s) completed at ' . date('d/m/Y - H:i:s') . '. Failed jobs: ' . $failCount . '/' . $count);
}
}
$failCount++;
}
}
$this->Task->id = $task['Task']['id'];
$this->Task->saveField('message', count($servers) . ' job(s) completed at ' . date('d/m/Y - H:i:s') . '. Failed jobs: ' . $failCount . '/' . $count);
}
public function enqueueFeedFetch() {
$timestamp = $this->args[0];
$userId = $this->args[1];
$taskId = $this->args[2];
$task = $this->Task->read(null, $taskId);
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueueFeedFetch', $userId, $taskId);
$user = $this->User->getAuthUser($userId);
$failCount = 0;
public function enqueueFeedFetch() {
$timestamp = $this->args[0];
$userId = $this->args[1];
$taskId = $this->args[2];
$task = $this->Task->read(null, $taskId);
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueueFeedFetch', $userId, $taskId);
$user = $this->User->getAuthUser($userId);
$failCount = 0;
$feeds = $this->Feed->find('all', array(
'recursive' => -1,
'conditions' => array('enabled' => true)
@ -375,9 +376,9 @@ class ServerShell extends AppShell
}
$this->Task->id = $task['Task']['id'];
$this->Task->saveField('message', count($feeds) . ' job(s) completed at ' . date('d/m/Y - H:i:s') . '. Failed jobs: ' . $failCount . '/' . count($feeds));
}
}
public function enqueueFeedCache() {
public function enqueueFeedCache() {
$timestamp = $this->args[0];
$userId = $this->args[1];
$taskId = $this->args[2];
@ -385,7 +386,7 @@ class ServerShell extends AppShell
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueueFeedCache', $userId, $taskId);
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueueFeedCache', $userId, $taskId);
$user = $this->User->getAuthUser($userId);
$this->Job->create();
$data = array(
@ -410,41 +411,41 @@ class ServerShell extends AppShell
$this->Task->saveField('message', 'Job completed at ' . date('d/m/Y - H:i:s'));
}
public function enqueuePush() {
$timestamp = $this->args[0];
$taskId = $this->args[1];
$userId = $this->args[2];
$this->Task->id = $taskId;
$task = $this->Task->read(null, $taskId);
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueuePush', $userId, $taskId);
public function enqueuePush() {
$timestamp = $this->args[0];
$taskId = $this->args[1];
$userId = $this->args[2];
$this->Task->id = $taskId;
$task = $this->Task->read(null, $taskId);
if ($timestamp != $task['Task']['next_execution_time']) {
return;
}
if ($task['Task']['timer'] > 0) $this->Task->reQueue($task, 'default', 'ServerShell', 'enqueuePush', $userId, $taskId);
$this->User->recursive = -1;
$user = $this->User->getAuthUser($userId);
$servers = $this->Server->find('all', array('recursive' => -1, 'conditions' => array('push' => 1)));
foreach ($servers as $k => $server) {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'push',
'job_input' => 'Server: ' . $server['Server']['id'],
'retries' => 0,
'org' => $user['Organisation']['name'],
'org_id' => $user['org_id'],
'process_id' => 'Part of scheduled push',
'message' => 'Pushing.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
$result = $this->Server->push($server['Server']['id'], 'full', $jobId, $HttpSocket, $user);
}
$this->Task->id = $task['Task']['id'];
$this->Task->saveField('message', count($servers) . ' job(s) completed at ' . date('d/m/Y - H:i:s') . '.');
}
$this->User->recursive = -1;
$user = $this->User->getAuthUser($userId);
$servers = $this->Server->find('all', array('recursive' => -1, 'conditions' => array('push' => 1)));
foreach ($servers as $k => $server) {
$this->Job->create();
$data = array(
'worker' => 'default',
'job_type' => 'push',
'job_input' => 'Server: ' . $server['Server']['id'],
'retries' => 0,
'org' => $user['Organisation']['name'],
'org_id' => $user['org_id'],
'process_id' => 'Part of scheduled push',
'message' => 'Pushing.',
);
$this->Job->save($data);
$jobId = $this->Job->id;
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
$result = $this->Server->push($server['Server']['id'], 'full', $jobId, $HttpSocket, $user);
}
$this->Task->id = $task['Task']['id'];
$this->Task->saveField('message', count($servers) . ' job(s) completed at ' . date('d/m/Y - H:i:s') . '.');
}
}

View File

@ -44,10 +44,10 @@ class AppController extends Controller
public $debugMode = false;
public $helpers = array('Utility', 'OrgImg', 'FontAwesome');
public $helpers = array('Utility', 'OrgImg', 'FontAwesome', 'UserName');
private $__queryVersion = '81';
public $pyMispVersion = '2.4.111';
private $__queryVersion = '82';
public $pyMispVersion = '2.4.112';
public $phpmin = '7.0';
public $phprec = '7.2';
public $isApiAuthed = false;
@ -104,6 +104,7 @@ class AppController extends Controller
public function beforeFilter()
{
$this->__sessionMassage();
if (Configure::read('Security.allow_cors')) {
// Add CORS headers
$this->response->cors($this->request,
@ -170,10 +171,11 @@ class AppController extends Controller
$this->Auth->authenticate['Form']['userFields'] = $auth_user_fields;
}
$versionArray = $this->{$this->modelClass}->checkMISPVersion();
if (!empty($this->params['named']['disable_background_processing'])) {
Configure::write('MISP.background_jobs', 0);
}
$this->mispVersion = implode('.', array_values($versionArray));
$this->Security->blackHoleCallback = 'blackHole';
// Let us access $baseurl from all views
$baseurl = Configure::read('MISP.baseurl');
if (substr($baseurl, -1) == '/') {
@ -202,6 +204,7 @@ class AppController extends Controller
if ($this->_isRest()) {
$this->Security->unlockedActions = array($this->action);
}
if (!$userLoggedIn) {
// REST authentication
if ($this->_isRest() || $this->_isAutomation()) {
@ -377,7 +380,6 @@ class AppController extends Controller
$this->Flash->error('Warning: MISP is currently disabled for all users. Enable it in Server Settings (Administration -> Server Settings -> MISP tab -> live). An update might also be in progress, you can see the progress in ' , array('params' => array('url' => $baseurl . '/servers/advancedUpdate/', 'urlName' => 'Advanced Update'), 'clear' => 1));
}
}
if ($this->Session->check(AuthComponent::$sessionKey)) {
if ($this->action !== 'checkIfLoggedIn' || $this->request->params['controller'] !== 'users') {
$this->User->id = $this->Auth->user('id');
@ -992,4 +994,23 @@ class AppController extends Controller
$this->Flash->success('Caches cleared.');
$this->redirect(array('controller' => 'servers', 'action' => 'serverSettings', 'diagnostics'));
}
private function __sessionMassage()
{
if (!empty(Configure::read('MISP.uuid'))) {
Configure::write('Session.cookie', 'MISP-' . Configure::read('MISP.uuid'));
}
if (!empty(Configure::read('Session.cookieTimeout')) || !empty(Configure::read('Session.timeout'))) {
$session = Configure::read('Session');
if (!empty($session['cookieTimeout'])) {
$value = 60 * intval($session['cookieTimeout']);
} else if (!empty($session['timeout'])) {
$value = 60 * intval($session['timeout']);
} else {
$value = 3600;
}
$session['ini']['session.gc_maxlifetime'] = $value;
Configure::write('Session', $session);
}
}
}

View File

@ -58,24 +58,25 @@ class AttributesController extends AppController
public function index()
{
$this->Attribute->recursive = -1;
if (!$this->_isRest()) {
$this->paginate['recursive'] = -1;
$this->paginate['contain'] = array(
'Event' => array(
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.info', 'Event.user_id', 'Event.date'),
'Orgc' => array('fields' => array('Orgc.id', 'Orgc.name')),
'Org' => array('fields' => array('Org.id', 'Org.name'))
),
'AttributeTag' => array('Tag'),
'Object' => array(
'fields' => array('Object.id', 'Object.distribution', 'Object.sharing_group_id')
)
);
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
}
$this->paginate['recursive'] = -1;
$this->paginate['contain'] = array(
'Event' => array(
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.info', 'Event.user_id', 'Event.date'),
'Orgc' => array('fields' => array('Orgc.id', 'Orgc.name')),
'Org' => array('fields' => array('Org.id', 'Org.name'))
),
'AttributeTag' => array('Tag'),
'Object' => array(
'fields' => array('Object.id', 'Object.distribution', 'Object.sharing_group_id')
)
);
$this->Attribute->contain(array('AttributeTag' => array('Tag')));
$this->set('isSearch', 0);
$attributes = $this->paginate();
if ($this->_isRest()) {
foreach ($attributes as $k => $attribute) {
$attributes[$k] = $attribute['Attribute'];
}
return $this->RestResponse->viewData($attributes, $this->response->type());
}
$org_ids = array();
@ -179,111 +180,49 @@ class AttributesController extends AppController
}
$uuids = array();
$this->Warninglist = ClassRegistry::init('Warninglist');
$warnings = array();
foreach ($attributes as $k => $attribute) {
if (isset($attribute['id'])) {
unset($attribute['id']);
}
$attributes[$k]['event_id'] = $eventId;
if (isset($attribute['uuid'])) {
$uuids[$k] = $attribute['uuid'];
if (!isset($attribute['timestamp'])) {
$attributes[$k]['timestamp'] = $date->getTimestamp();
}
if (isset($attribute['base64'])) {
$attributes[$k]['data'] = $attribute['base64'];
}
}
if (isset($attribute['type']) && !isset($attribute['category'])) {
$attributes[$k]['category'] = $this->Attribute->typeDefinitions[$attribute['type']]['default_category'];
}
if (!isset($attribute['to_ids'])) {
$attributes[$k]['to_ids'] = $this->Attribute->typeDefinitions[$attribute['type']]['to_ids'];
}
if (!empty($attributes[$k]['enforceWarninglist']) || !empty($this->params['named']['enforceWarninglist'])) {
if (empty($warninglists)) {
$warninglists = $this->Warninglist->fetchForEventView();
}
if (!$this->Warninglist->filterWarninglistAttributes($warninglists, $attributes[$k])) {
$attributes[$k]['blocked'] = true;
}
}
}
$fails = array();
$successes = 0;
$attributeCount = count($attributes);
if (!empty($uuids)) {
$existingAttributes = $this->Attribute->find('list', array(
'recursive' => -1,
'fields' => array('Attribute.uuid'),
'conditions' => array('Attribute.uuid' => array_values($uuids))
));
if (!empty($existingAttributes)) {
foreach ($uuids as $k => $uuid) {
if (in_array($uuid, $existingAttributes)) {
unset($attributes[$k]);
$fails["attribute_$k"] = array('uuid' => array('An attribute with this uuid already exists.'));
unset($uuids[$k]);
}
}
}
}
// deduplication
$duplicates = 0;
$inserted_ids = array();
foreach ($attributes as $k => $attribute) {
foreach ($attributes as $k2 => $attribute2) {
if ($k == $k2) {
continue;
}
if (
(
!empty($attribute['uuid']) &&
!empty($attribute2['uuid']) &&
$attribute['uuid'] == $attribute2['uuid']
) || (
$attribute['value'] == $attribute2['value'] &&
$attribute['type'] == $attribute2['type'] &&
$attribute['category'] == $attribute2['category']
)
) {
$duplicates++;
unset($attributes[$k]);
break;
}
}
}
foreach ($attributes as $k => $attribute) {
if (empty($attribute['blocked'])) {
if (!empty($attribute['encrypt'])) {
$attribute = $this->Attribute->onDemandEncrypt($attribute);
}
$attributes[$k] = $attribute;
$this->Attribute->set($attribute);
$result = $this->Attribute->validates();
if (!$result) {
$fails["attribute_$k"] = $this->Attribute->validationErrors;
unset($attributes[$k]);
} else {
$successes++;
}
$validationErrors = array();
$this->Attribute->captureAttribute($attribute, $eventId, $this->Auth->user(), false, false, false, $validationErrors, $this->params['named']);
if (empty($validationErrors)) {
$inserted_ids[] = $this->Attribute->id;
$successes +=1;
} else {
$fails["attribute_$k"] = 'Attribute blocked due to warninglist';
unset($attributes[$k]);
$fails["attribute_" . $k] = $validationErrors;
}
}
if (!empty($successes)) {
$this->Event->unpublishEvent($eventId);
}
$atomic = Configure::read('MISP.deadlock_avoidance') ? false : true;
$result = $this->Attribute->saveMany($attributes, array('atomic' => $atomic));
if ($this->_isRest()) {
if (!empty($successes)) {
$attributes = $this->Attribute->find('all', array(
'recursive' => -1,
'conditions' => array('Attribute.id' => $this->Attribute->inserted_ids)
'conditions' => array('Attribute.id' => $inserted_ids),
'contain' => array(
'AttributeTag' => array(
'Tag' => array('fields' => array('Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value'))
)
)
));
if (count($attributes) == 1) {
$attributes = $attributes[0];
} else {
$result = array('Attribute' => array());
foreach ($attributes as $attribute) {
$temp = $attribute['Attribute'];
if (!empty($attribute['AttributeTag'])) {
foreach ($attribute['AttributeTag'] as $at) {
$temp['Tag'][] = $at['Tag'];
}
}
$result['Attribute'][] = $temp;
}
$attributes = $result;
unset($result);
}
return $this->RestResponse->viewData($attributes, $this->response->type(), $fails);
} else {
@ -309,11 +248,8 @@ class AttributesController extends AppController
$message = sprintf('Attributes saved, however, %s attributes could not be saved. Click %s for more info', count($fails), '$flashErrorMessage');
} else {
if (!empty($fails["attribute_0"])) {
foreach ($fails["attribute_0"] as $k => $v) {
$failed = 1;
$message = $k . ': ' . $v[0];
break;
}
$failed = 1;
$message = '0: ' . $v[0];
} else {
$failed = 1;
$message = 'Attribute could not be saved.';
@ -978,7 +914,7 @@ class AttributesController extends AppController
$saved_attribute = $this->Attribute->find('first', array(
'conditions' => array('id' => $this->Attribute->id),
'recursive' => -1,
'fields' => array('id', 'type', 'to_ids', 'category', 'uuid', 'event_id', 'distribution', 'timestamp', 'comment', 'value', 'disable_correlation'),
'fields' => $this->Attribute->defaultFields
));
$response = array('response' => array('Attribute' => $saved_attribute['Attribute']));
$this->set('response', $response);
@ -1934,7 +1870,8 @@ class AttributesController extends AppController
'value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp',
'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'event_timestamp', 'threat_level_id', 'includeEventTags',
'includeProposals', 'returnFormat', 'published', 'limit', 'page', 'requested_attributes', 'includeContext', 'headerless',
'includeWarninglistHits', 'attackGalaxy', 'object_relation', 'includeDecayScore', 'decayingModel', 'excludeDecayed'
'includeWarninglistHits', 'attackGalaxy', 'object_relation', 'includeSightings', 'includeCorrelations', 'includeDecayScore',
'decayingModel', 'excludeDecayed'
);
$filterData = array(
'request' => $this->request,
@ -3037,7 +2974,7 @@ class AttributesController extends AppController
if ($id === 'selected') {
$idList = json_decode($this->request->data['attribute_ids'], true);
}
$local = !empty($this->params['named']['local']);
$local = empty($this->params['named']['local']) ? 0 : 1;
if (!$this->request->is('post')) {
$this->set('local', $local);
$this->set('object_id', $id);
@ -3107,9 +3044,11 @@ class AttributesController extends AppController
if (empty($attribute)) {
throw new NotFoundException(__('Invalid attribute'));
}
if (!$this->_isSiteAdmin() && $attribute['Event']['orgc_id'] !== $this->Auth->user('org_id')) {
$fails++;
continue;
if ((!$this->userRole['perm_sync'] && !$this->_isSiteAdmin()) && $attribute['Event']['orgc_id'] !== $this->Auth->user('org_id')) {
if (Configure::read('MISP.host_org_id') != $this->Auth->user('org_id') || !$local) {
$fails++;
continue;
}
}
$eventId = $attribute['Attribute']['event_id'];
$event = $this->Attribute->Event->find('first', array(

View File

@ -292,40 +292,9 @@ class EventsController extends AppController
return $result;
}
public function index()
private function __setIndexFilterConditions($passedArgs, $urlparams)
{
// list the events
$passedArgsArray = array();
$urlparams = "";
$overrideAbleParams = array('all', 'attribute', 'published', 'eventid', 'datefrom', 'dateuntil', 'org', 'eventinfo', 'tag', 'tags', 'distribution', 'sharinggroup', 'analysis', 'threatlevel', 'email', 'hasproposal', 'timestamp', 'publishtimestamp', 'publish_timestamp', 'minimal');
$paginationParams = array('limit', 'page', 'sort', 'direction', 'order');
$passedArgs = $this->passedArgs;
if (isset($this->request->data)) {
if (isset($this->request->data['request'])) {
$this->request->data = $this->request->data['request'];
}
foreach ($this->request->data as $k => $v) {
if (substr($k, 0, 6) === 'search' && in_array(strtolower(substr($k, 6)), $overrideAbleParams)) {
unset($this->request->data[$k]);
$this->request->data[strtolower(substr($k, 6))] = $v;
} else if (in_array(strtolower($k), $overrideAbleParams)) {
unset($this->request->data[$k]);
$this->request->data[strtolower($k)] = $v;
}
}
foreach ($overrideAbleParams as $oap) {
if (isset($this->request->data[$oap])) {
$passedArgs['search' . $oap] = $this->request->data[$oap];
}
}
foreach ($paginationParams as $paginationParam) {
if (isset($this->request->data[$paginationParam])) {
$passedArgs[$paginationParam] = $this->request->data[$paginationParam];
}
}
}
$this->set('passedArgs', json_encode($passedArgs));
// check each of the passed arguments whether they're a filter (could also be a sort for example) and if yes, add it to the pagination conditions
foreach ($passedArgs as $k => $v) {
if (substr($k, 0, 6) === 'search') {
if (!is_array($v)) {
@ -688,6 +657,43 @@ class EventsController extends AppController
$passedArgsArray[$searchTerm] = $v;
}
}
return $passedArgsArray;
}
public function index()
{
// list the events
$urlparams = "";
$overrideAbleParams = array('all', 'attribute', 'published', 'eventid', 'datefrom', 'dateuntil', 'org', 'eventinfo', 'tag', 'tags', 'distribution', 'sharinggroup', 'analysis', 'threatlevel', 'email', 'hasproposal', 'timestamp', 'publishtimestamp', 'publish_timestamp', 'minimal');
$paginationParams = array('limit', 'page', 'sort', 'direction', 'order');
$passedArgs = $this->passedArgs;
if (isset($this->request->data)) {
if (isset($this->request->data['request'])) {
$this->request->data = $this->request->data['request'];
}
foreach ($this->request->data as $k => $v) {
if (substr($k, 0, 6) === 'search' && in_array(strtolower(substr($k, 6)), $overrideAbleParams)) {
unset($this->request->data[$k]);
$this->request->data[strtolower(substr($k, 6))] = $v;
} else if (in_array(strtolower($k), $overrideAbleParams)) {
unset($this->request->data[$k]);
$this->request->data[strtolower($k)] = $v;
}
}
foreach ($overrideAbleParams as $oap) {
if (isset($this->request->data[$oap])) {
$passedArgs['search' . $oap] = $this->request->data[$oap];
}
}
foreach ($paginationParams as $paginationParam) {
if (isset($this->request->data[$paginationParam])) {
$passedArgs[$paginationParam] = $this->request->data[$paginationParam];
}
}
}
$this->set('passedArgs', json_encode($passedArgs));
// check each of the passed arguments whether they're a filter (could also be a sort for example) and if yes, add it to the pagination conditions
$passedArgsArray = $this->__setIndexFilterConditions($passedArgs, $urlparams);
if (!$this->_isRest()) {
$this->paginate['contain'] = array_merge($this->paginate['contain'], array('User.email', 'EventTag'));
} else {
@ -732,6 +738,14 @@ class EventsController extends AppController
$rules[$paginationRule] = $passedArgs[$paginationRule];
}
}
$counting_rules = $rules;
if (!empty($counting_rules['limit'])) {
unset($counting_rules['limit']);
}
if (!empty($counting_rules['page'])) {
unset($counting_rules['page']);
}
$absolute_total = $this->Event->find('count', $counting_rules);
if (empty($rules['limit'])) {
$events = array();
$i = 1;
@ -819,12 +833,12 @@ class EventsController extends AppController
if ($this->response->type() === 'application/xml') {
$events = array('Event' => $events);
}
return $this->RestResponse->viewData($events, $this->response->type());
return $this->RestResponse->viewData($events, $this->response->type(), false, false, false, array('X-Result-Count' => $absolute_total));
} else {
foreach ($events as $key => $event) {
$events[$key] = $event['Event'];
}
return $this->RestResponse->viewData($events, $this->response->type());
return $this->RestResponse->viewData($events, $this->response->type(), false, false, false, array('X-Result-Count' => $absolute_total));
}
} else {
$events = $this->paginate();
@ -2324,6 +2338,15 @@ class EventsController extends AppController
public function delete($id = null)
{
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'));
}
$id = $temp['Event']['id'];
} elseif (!is_numeric($id)) {
throw new NotFoundException(__('Invalid event'));
}
if ($this->request->is('post') || $this->request->is('put') || $this->request->is('delete')) {
if (isset($this->request->data['id'])) {
$this->request->data['Event'] = $this->request->data;
@ -3346,7 +3369,7 @@ class EventsController extends AppController
'value', 'type', 'category', 'object_relation', 'org', 'tag', 'tags', 'searchall', 'from', 'to', 'last', 'eventid', 'withAttachments',
'metadata', 'uuid', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'sgReferenceOnly', 'returnFormat',
'limit', 'page', 'requested_attributes', 'includeContext', 'headerless', 'includeWarninglistHits', 'attackGalaxy', 'deleted',
'excludeLocalTags'
'excludeLocalTags', 'date'
);
$filterData = array(
'request' => $this->request,
@ -3663,8 +3686,15 @@ class EventsController extends AppController
$tag_id = $this->request->data['tag'];
}
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $event['Event']['orgc_id'])) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
if (
!$this->userRole['perm_tagger'] ||
(
$this->Auth->user('org_id') !== $event['Event']['orgc_id']
)
) {
if (Configure::read('MISP.host_org_id') != $this->Auth->user('org_id') || !$local) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
}
}
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)));
@ -4021,7 +4051,10 @@ class EventsController extends AppController
$attributes[$k] = $attribute;
}
// actually save the attribute now
$this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, '', false, $adhereToWarninglists);
$temp = $this->Event->processFreeTextDataRouter($this->Auth->user(), $attributes, $id, '', false, $adhereToWarninglists, empty(Configure::read('MISP.background_jobs')));
if (empty(Configure::read('MISP.background_jobs'))) {
$attributes = $temp;
}
// FIXME $attributes does not contain the onteflyattributes
$attributes = array_values($attributes);
return $this->RestResponse->viewData($attributes, $this->response->type());

View File

@ -71,6 +71,7 @@ class ObjectReferencesController extends AppController
'referenced_type' => $referenced_type,
'uuid' => CakeText::uuid()
);
$object_uuid = $object['Object']['uuid'];
$this->ObjectReference->create();
$result = $this->ObjectReference->save(array('ObjectReference' => $data));
if ($result) {
@ -80,6 +81,7 @@ class ObjectReferencesController extends AppController
'recursive' => -1,
'conditions' => array('ObjectReference.id' => $this->ObjectReference->id)
));
$object['ObjectReference']['object_uuid'] = $object_uuid;
return $this->RestResponse->viewData($object, $this->response->type());
} elseif ($this->request->is('ajax')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Object reference added.')),'status'=>200, 'type' => 'json'));

View File

@ -528,8 +528,9 @@ class ObjectsController extends AppController
if (isset($this->request->data['Object']['data'])) {
$this->request->data = json_decode($this->request->data['Object']['data'], true);
}
if (!isset($this->request->data['Attribute'])) {
$this->request->data = array('Attribute' => $this->request->data);
if (isset($this->request->data['Object'])) {
$this->request->data = array_merge($this->request->data, $this->request->data['Object']);
unset($this->request->data['Object']);
}
$objectToSave = $this->MispObject->attributeCleanup($this->request->data);
$objectToSave = $this->MispObject->deltaMerge($object, $objectToSave);
@ -542,7 +543,11 @@ class ObjectsController extends AppController
$objectToSave = $this->MispObject->find('first', array(
'recursive' => -1,
'conditions' => array('Object.id' => $id),
'contain' => array('Attribute')
'contain' => array(
'Attribute' => array(
'fields' => $this->MispObject->Attribute->defaultFields
)
)
));
if (!empty($objectToSave)) {
$objectToSave['Object']['Attribute'] = $objectToSave['Attribute'];

View File

@ -150,6 +150,13 @@ class OrganisationsController extends AppController
public function admin_edit($id)
{
if (Validation::uuid($id)) {
$temp = $this->Organisation->find('first', array('recursive' => -1, 'fields' => array('Organisation.id'), 'conditions' => array('Organisation.uuid' => $id)));
if (empty($temp)) {
throw new NotFoundException(__('Invalid organisation.'));
}
$id = $temp['Organisation']['id'];
}
$this->Organisation->id = $id;
if (!$this->Organisation->exists()) {
throw new NotFoundException(__('Invalid organisation'));

View File

@ -110,16 +110,28 @@ class ServersController extends AppController
$combinedArgs['sort'] = 'timestamp';
$combinedArgs['direction'] = 'desc';
}
$events = $this->Server->previewIndex($id, $this->Auth->user(), $combinedArgs);
if (empty($combinedArgs['page'])) {
$combinedArgs['page'] = 1;
}
if (empty($combinedArgs['limit'])) {
$combinedArgs['limit'] = 60;
}
$total_count = 0;
$events = $this->Server->previewIndex($id, $this->Auth->user(), $combinedArgs, $total_count);
$this->loadModel('Event');
$threat_levels = $this->Event->ThreatLevel->find('all');
$this->set('threatLevels', Set::combine($threat_levels, '{n}.ThreatLevel.id', '{n}.ThreatLevel.name'));
App::uses('CustomPaginationTool', 'Tools');
$customPagination = new CustomPaginationTool();
$params = $customPagination->createPaginationRules($events, $this->passedArgs, $this->alias);
if (!empty($total_count)) {
$params['pageCount'] = ceil($total_count / $params['limit']);
}
$this->params->params['paging'] = array($this->modelClass => $params);
if (is_array($events)) {
$customPagination->truncateByPagination($events, $params);
if (count($events) > 60) {
$customPagination->truncateByPagination($events, $params);
}
} else ($events = array());
$this->set('events', $events);
$this->set('eventDescriptions', $this->Event->fieldDescriptions);
@ -586,7 +598,7 @@ class ServersController extends AppController
public function delete($id = null)
{
if (!$this->request->is('post')) {
throw new MethodNotAllowedException();
throw new MethodNotAllowedException(__('This endpoint expects POST requests.'));
}
$this->Server->id = $id;
if (!$this->Server->exists()) {
@ -594,14 +606,31 @@ class ServersController extends AppController
}
$s = $this->Server->read(null, $id);
if (!$this->_isSiteAdmin()) {
$this->redirect(array('controller' => 'servers', 'action' => 'index'));
$message = __('You don\'t have the privileges to do that.');
if ($this->_isRest()) {
throw new MethodNotAllowedException($message);
} else {
$this->Flash->error($message);
$this->redirect(array('controller' => 'servers', 'action' => 'index'));
}
}
if ($this->Server->delete()) {
$this->Flash->success(__('Server deleted'));
$message = __('Server deleted');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Servers', 'delete', $message, $this->response->type());
} else {
$this->Flash->success($message);
$this->redirect(array('controller' => 'servers', 'action' => 'index'));
}
}
$message = __('Server was not deleted');
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Servers', 'delete', $id, $message, $this->response->type());
} else {
$this->Flash->error($message);
$this->redirect(array('action' => 'index'));
}
$this->Flash->error(__('Server was not deleted'));
$this->redirect(array('action' => 'index'));
}
/**
@ -613,7 +642,13 @@ class ServersController extends AppController
*/
public function pull($id = null, $technique='full')
{
$this->Server->id = $id;
if (!empty($id)) {
$this->Server->id = $id;
} else if (!empty($this->request->data['id'])) {
$this->Server->id = $this->request->data['id'];
} else {
throw new NotFoundException(__('Invalid server'));
}
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
@ -682,7 +717,16 @@ class ServersController extends AppController
public function push($id = null, $technique=false)
{
$this->Server->id = $id;
if (!empty($id)) {
$this->Server->id = $id;
} else if (!empty($this->request->data['id'])) {
$this->Server->id = $this->request->data['id'];
} else {
throw new NotFoundException(__('Invalid server'));
}
if (!empty($this->request->data['technique'])) {
$technique = $this->request->data['technique'];
}
if (!$this->Server->exists()) {
throw new NotFoundException(__('Invalid server'));
}
@ -1225,6 +1269,9 @@ class ServersController extends AppController
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, 'Invalid input. Expected: {"value": "new_setting"}', $this->response->type());
}
}
if (!empty($this->request->data['Server']['force'])) {
$forceSave = $this->request->data['Server']['force'];
}
if (trim($this->request->data['Server']['value']) === '*****') {
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Servers', 'serverSettingsEdit', false, 'No change.', $this->response->type());
@ -1275,6 +1322,9 @@ class ServersController extends AppController
throw new MethodNotAllowedException();
}
$this->Server->restartWorkers($this->Auth->user());
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Server', 'restartWorkers', false, $this->response->type(), __('Restarting workers.'));
}
$this->redirect(array('controller' => 'servers', 'action' => 'serverSettings', 'workers'));
}
@ -1728,6 +1778,7 @@ class ServersController extends AppController
if (!empty($request['skip_ssl_validation'])) {
$params['ssl_verify_peer'] = false;
$params['ssl_verify_host'] = false;
$params['ssl_verify_peer_name'] = false;
$params['ssl_allow_self_signed'] = true;
}
$params['timeout'] = 300;
@ -1942,14 +1993,27 @@ misp.direct_call(relative_path, body)
$baseurl = Router::url('/', true);
}
}
$host_org_id = Configure::read('MISP.host_org_id');
if (empty($host_org_id)) {
throw new MethodNotAllowedException(__('Cannot create sync config - no host org ID configured for the instance.'));
}
$this->loadModel('Organisation');
$host_org = $this->Organisation->find('first', array(
'conditions' => array('Organisation.id' => $host_org_id),
'recursive' => -1,
'fields' => array('name', 'uuid')
));
if (empty($host_org)) {
throw new MethodNotAllowedException(__('Configured host org not found. Please make sure that the setting is current on the instance.'));
}
$server = array(
'Server' => array(
'url' => $baseurl,
'uuid' => Configure::read('MISP.uuid'),
'authkey' => $this->Auth->user('authkey'),
'Organisation' => array(
'name' => $this->Auth->user('Organisation')['name'],
'uuid' => $this->Auth->user('Organisation')['uuid']
'name' => $host_org['Organisation']['name'],
'uuid' => $host_org['Organisation']['uuid'],
)
)
);

View File

@ -693,6 +693,9 @@ class ShadowAttributesController extends AppController
if (isset($this->request->data['request'])) {
$this->request->data = $this->request->data['request'];
}
if (!isset($this->request->data['ShadowAttribute'])) {
$this->request->data['ShadowAttribute'] = $this->request->data;
}
// rearrange the request in case someone didn't RTFM
$invalidNames = array('Attribute', 'Proposal');
foreach ($invalidNames as $iN) {
@ -917,7 +920,7 @@ class ShadowAttributesController extends AppController
if (isset($this->request['named']['all'])) {
$all = $this->request['named']['all'];
} else {
$all = false;
$all = 1;
}
if ($eventId && is_numeric($eventId)) {
$conditions['ShadowAttribute.event_id'] = $eventId;

View File

@ -48,15 +48,27 @@ class SharingGroupsController extends AppController
'recursive' => -1,
'fields' => array('id', 'name', 'uuid')
));
if ($this->request->is('post')) {
if ($this->_isRest()) {
$sg = $this->request->data;
if (isset($this->request->data['SharingGroup'])) {
$this->request->data = $this->request->data['SharingGroup'];
}
$sg = $this->request->data;
$id = $this->SharingGroup->captureSG($this->request->data, $this->Auth->user());
if ($id) {
if (empty($sg['roaming']) && empty($sg['SharingGroupServer'])) {
$this->SharingGroup->SharingGroupServer->create();
$this->SharingGroup->SharingGroupServer->save(array(
'sharing_group_id' => $this->SharingGroup->id,
'server_id' => 0,
'all_orgs' => 0
));
}
$sg = $this->SharingGroup->fetchAllAuthorised($this->Auth->user(), 'simplified', false, $id);
if (!empty($sg)) {
$sg = empty($sg) ? array() : $sg[0];
}
return $this->RestResponse->viewData($sg, $this->response->type());
} else {
return $this->RestResponse->saveFailResponse('SharingGroup', 'add', false, 'Could not save sharing group.', $this->response->type());
@ -72,6 +84,8 @@ class SharingGroupsController extends AppController
}
}
$this->SharingGroup->create();
$sg['active'] = $sg['active'] ? 1: 0;
$sg['roaming'] = $sg['roaming'] ? 1: 0;
$sg['organisation_uuid'] = $this->Auth->user('Organisation')['uuid'];
$sg['local'] = 1;
$sg['org_id'] = $this->Auth->user('org_id');
@ -87,7 +101,7 @@ class SharingGroupsController extends AppController
));
}
}
if (!$sg['roaming'] && !empty($sg['Server'])) {
if (empty($sg['roaming']) && !empty($sg['Server'])) {
foreach ($sg['Server'] as $server) {
$this->SharingGroup->SharingGroupServer->create();
$this->SharingGroup->SharingGroupServer->save(array(
@ -116,7 +130,7 @@ class SharingGroupsController extends AppController
return $this->RestResponse->describe('SharingGroup', 'add', false, $this->response->type());
}
$this->set('orgs', $orgs);
$this->set('localInstance', Configure::read('MISP.baseurl'));
$this->set('localInstance', empty(Configure::read('MISP.external_baseurl')) ? Configure::read('MISP.baseurl') : Configure::read('MISP.external_baseurl'));
// We just pass true and allow the user to edit, since he/she is just about to create the SG. This is needed to reuse the view for the edit
$this->set('user', $this->Auth->user());
}
@ -209,7 +223,7 @@ class SharingGroupsController extends AppController
$this->set('sharingGroup', $sharingGroup);
$this->set('id', $id);
$this->set('orgs', $orgs);
$this->set('localInstance', Configure::read('MISP.baseurl'));
$this->set('localInstance', empty(Configure::read('MISP.external_baseurl')) ? Configure::read('MISP.baseurl') : Configure::read('MISP.external_baseurl'));
// We just pass true and allow the user to edit, since he/she is just about to create the SG. This is needed to reuse the view for the edit
$this->set('user', $this->Auth->user());
}
@ -310,7 +324,11 @@ class SharingGroupsController extends AppController
if (isset($sg['SharingGroupServer'])) {
foreach ($sg['SharingGroupServer'] as $key => $sgs) {
if ($sgs['server_id'] == 0) {
$sg['SharingGroupServer'][$key]['Server'] = array('id' => "0", 'name' => 'Local instance', 'url' => Configure::read('MISP.baseurl'));
$sg['SharingGroupServer'][$key]['Server'] = array(
'id' => "0",
'name' => 'Local instance',
'url' => empty(Configure::read('MISP.external_baseurl')) ? Configure::read('MISP.baseurl') : Configure::read('MISP.external_baseurl')
);
}
}
}
@ -406,7 +424,7 @@ class SharingGroupsController extends AppController
$addOrg = true;
if (!empty($sg['SharingGroupOrg'])) {
foreach ($sg['SharingGroupOrg'] as $sgo) {
if ($sgo['org_id'] == $org['Organisation']['id']) {
if ($sgo['org_id'] == $org['id']) {
$addOrg = false;
}
}
@ -417,7 +435,7 @@ class SharingGroupsController extends AppController
$this->SharingGroup->SharingGroupOrg->create();
$sgo = array(
'SharingGroupOrg' => array(
'org_id' => $org['Organisation']['id'],
'org_id' => $org['id'],
'sharing_group_id' => $sg['SharingGroup']['id'],
'extend' => $extend ? 1:0
)
@ -436,7 +454,7 @@ class SharingGroupsController extends AppController
$removeOrg = false;
if (!empty($sg['SharingGroupOrg'])) {
foreach ($sg['SharingGroupOrg'] as $sgo) {
if ($sgo['org_id'] == $org['Organisation']['id']) {
if ($sgo['org_id'] == $org['id']) {
$removeOrg = $sgo['id'];
break;
}

View File

@ -310,9 +310,15 @@ class SightingsController extends AppController
return $this->RestResponse->viewData($sightings, $responseType, false, true);
}
public function listSightings($id, $context = 'attribute', $org_id = false)
public function listSightings($id = false, $context = 'attribute', $org_id = false)
{
$rawId = $id;
$parameters = array('id', 'context', 'org_id');
foreach ($parameters as $parameter) {
if ($this->request->is('post') && isset($this->request->data[$parameter])) {
${$parameter} = $this->request->data[$parameter];
}
}
$sightings = $this->Sighting->listSightings($this->Auth->user(), $id, $context, $org_id);
$this->set('org_id', $org_id);
$this->set('rawId', $rawId);

View File

@ -262,9 +262,17 @@ class TaxonomiesController extends AppController
$result = $this->Taxonomy->addTags($this->request->data['Tag']['taxonomy_id'], $this->request->data['Tag']['nameList']);
}
if ($result) {
$this->Flash->success(__('The tag(s) has been saved.'));
$message = __('The tag(s) has been saved.');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('Taxonomy', 'addTag', $taxonomy_id, $this->response->type(), $message);
}
$this->Flash->success($message);
} else {
$this->Flash->error(__('The tag(s) could not be saved. Please, try again.'));
$message = __('The tag(s) could not be saved. Please, try again.');
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('Taxonomy', 'addTag', $taxonomy_id, $message, $this->response->type());
}
$this->Flash->error($message);
}
$this->redirect($this->referer());
}

View File

@ -1200,7 +1200,9 @@ class UsersController extends AppController
));
$orgs = array(0 => 'All organisations');
foreach ($org_ids as $v) {
$orgs[$v] = $orgs_temp[$v];
if (!empty($orgs_temp[$v])) {
$orgs[$v] = $orgs_temp[$v];
}
}
$data = array();
$max = 1;

View File

@ -201,7 +201,7 @@ class CsvExport
foreach ($requested_obj_attributes as $obj_att) {
$this->requested_fields[] = $obj_att;
}
if (isset($options['filters']['includeContext'])) {
if (!empty($options['filters']['includeContext'])) {
foreach ($this->event_context_fields as $event_context_field) {
$this->requested_fields[] = $event_context_field;
}
@ -220,6 +220,9 @@ class CsvExport
$options['flatten'] = 1;
}
$headers = implode(',', $headers) . PHP_EOL;
if (!empty($options['filters']['headerless'])) {
return '';
}
return $headers;
}

View File

@ -14,7 +14,11 @@ class QueryTool
{
$db = $model->getDataSource();
$connection = $db->getConnection();
$query = $connection->prepare('DELETE FROM ' . $table . ' WHERE ' . $field . ' = :value');
if ($db->config['datasource'] == 'Database/Mysql' ) {
$query = $connection->prepare('DELETE FROM ' . $table . ' WHERE ' . $field . ' = :value');
} elseif ($db->config['datasource'] == 'Database/Postgres' ) {
$query = $connection->prepare('DELETE FROM "' . $table . '" WHERE "' . $field . '" = :value');
}
$query->bindValue(':value', $value, $this->__pdoMap[$db->introspectType($value)]);
$query->execute();
}

View File

@ -34,6 +34,10 @@ class Attribute extends AppModel
'distribution' => array('desc' => 'Describes who will have access to the event.')
);
public $defaultFields = array(
'id', 'event_id', 'object_id', 'object_relation', 'category', 'type', 'value', 'to_ids', 'uuid', 'timestamp', 'distribution', 'sharing_group_id', 'comment', 'deleted', 'disable_correlation'
);
public $distributionDescriptions = array(
0 => array('desc' => 'This field determines the current distribution of the event', 'formdesc' => "This setting will only allow members of your organisation on this server to see it."),
1 => array('desc' => 'This field determines the current distribution of the event', 'formdesc' => "Organisations that are part of this MISP community will be able to see the event."),
@ -64,6 +68,9 @@ class Attribute extends AppModel
5 => __('Inherit event')
);
//
// NOTE WHEN MODIFYING: please ensure to run the script 'tools/gen_misp_types_categories.py' to update the new definitions everywhere. (docu, website, RFC, ...)
//
$this->categoryDefinitions = array(
'Internal reference' => array(
'desc' => __('Reference used by the publishing party (e.g. ticket number)'),
@ -82,7 +89,7 @@ class Attribute extends AppModel
'Payload delivery' => array(
'desc' => __('Information about how the malware is delivered'),
'formdesc' => __('Information about the way the malware payload is initially delivered, for example information about the email or web-site, vulnerability used, originating IP etc. Malware sample itself should be attached here.'),
'types' => array('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy', 'authentihash', 'pehash', 'tlsh', 'cdhash', 'filename', 'filename|md5', 'filename|sha1', 'filename|sha224', 'filename|sha256', 'filename|sha384', 'filename|sha512', 'filename|sha512/224', 'filename|sha512/256', 'filename|authentihash', 'filename|ssdeep', 'filename|tlsh', 'filename|imphash','filename|impfuzzy', 'filename|pehash', 'mac-address', 'mac-eui-64', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'hostname', 'domain', 'email-src', 'email-dst', 'email-subject', 'email-attachment', 'email-body', 'url', 'user-agent', 'AS', 'pattern-in-file', 'pattern-in-traffic', 'stix2-pattern', 'yara', 'sigma', 'mime-type', 'attachment', 'malware-sample', 'link', 'malware-type', 'comment', 'text', 'hex', 'vulnerability', 'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'ja3-fingerprint-md5', 'hassh-md5', 'hasshserver-md5', 'other', 'hostname|port', 'email-dst-display-name', 'email-src-display-name', 'email-header', 'email-reply-to', 'email-x-mailer', 'email-mime-boundary', 'email-thread-index', 'email-message-id', 'mobile-application-id', 'whois-registrant-email', 'anonymised')
'types' => array('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy', 'authentihash', 'pehash', 'tlsh', 'cdhash', 'filename', 'filename|md5', 'filename|sha1', 'filename|sha224', 'filename|sha256', 'filename|sha384', 'filename|sha512', 'filename|sha512/224', 'filename|sha512/256', 'filename|authentihash', 'filename|ssdeep', 'filename|tlsh', 'filename|imphash','filename|impfuzzy', 'filename|pehash', 'mac-address', 'mac-eui-64', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'hostname', 'domain', 'email-src', 'email-dst', 'email-subject', 'email-attachment', 'email-body', 'url', 'user-agent', 'AS', 'pattern-in-file', 'pattern-in-traffic', 'stix2-pattern', 'yara', 'sigma', 'mime-type', 'attachment', 'malware-sample', 'link', 'malware-type', 'comment', 'text', 'hex', 'vulnerability', 'weakness', 'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'ja3-fingerprint-md5', 'hassh-md5', 'hasshserver-md5', 'other', 'hostname|port', 'email-dst-display-name', 'email-src-display-name', 'email-header', 'email-reply-to', 'email-x-mailer', 'email-mime-boundary', 'email-thread-index', 'email-message-id', 'mobile-application-id', 'whois-registrant-email', 'anonymised')
),
'Artifacts dropped' => array(
'desc' => __('Any artifact (files, registry keys etc.) dropped by the malware or other modifications to the system'),
@ -91,7 +98,7 @@ class Attribute extends AppModel
'Payload installation' => array(
'desc' => __('Info on where the malware gets installed in the system'),
'formdesc' => __('Location where the payload was placed in the system and the way it was installed. For example, a filename|md5 type attribute can be added here like this: c:\\windows\\system32\\malicious.exe|41d8cd98f00b204e9800998ecf8427e.'),
'types' => array('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy', 'authentihash', 'pehash', 'tlsh', 'cdhash', 'filename', 'filename|md5', 'filename|sha1', 'filename|sha224', 'filename|sha256', 'filename|sha384', 'filename|sha512', 'filename|sha512/224', 'filename|sha512/256', 'filename|authentihash', 'filename|ssdeep', 'filename|tlsh', 'filename|imphash', 'filename|impfuzzy', 'filename|pehash', 'pattern-in-file', 'pattern-in-traffic', 'pattern-in-memory', 'stix2-pattern', 'yara', 'sigma', 'vulnerability', 'attachment', 'malware-sample', 'malware-type', 'comment', 'text', 'hex', 'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'mobile-application-id', 'other', 'mime-type', 'anonymised')
'types' => array('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha512/224', 'sha512/256', 'ssdeep', 'imphash', 'impfuzzy', 'authentihash', 'pehash', 'tlsh', 'cdhash', 'filename', 'filename|md5', 'filename|sha1', 'filename|sha224', 'filename|sha256', 'filename|sha384', 'filename|sha512', 'filename|sha512/224', 'filename|sha512/256', 'filename|authentihash', 'filename|ssdeep', 'filename|tlsh', 'filename|imphash', 'filename|impfuzzy', 'filename|pehash', 'pattern-in-file', 'pattern-in-traffic', 'pattern-in-memory', 'stix2-pattern', 'yara', 'sigma', 'vulnerability', 'weakness', 'attachment', 'malware-sample', 'malware-type', 'comment', 'text', 'hex', 'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'mobile-application-id', 'other', 'mime-type', 'anonymised')
),
'Persistence mechanism' => array(
'desc' => __('Mechanisms used by the malware to start at boot'),
@ -100,7 +107,7 @@ class Attribute extends AppModel
),
'Network activity' => array(
'desc' => __('Information about network traffic generated by the malware'),
'types' => array('ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'port', 'hostname', 'domain', 'domain|ip', 'mac-address', 'mac-eui-64', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-file', 'stix2-pattern', 'pattern-in-traffic', 'attachment', 'comment', 'text', 'x509-fingerprint-md5', 'x509-fingerprint-sha1', 'x509-fingerprint-sha256', 'ja3-fingerprint-md5', 'hassh-md5', 'hasshserver-md5', 'other', 'hex', 'cookie', 'hostname|port', 'bro', 'zeek', 'anonymised', 'community-id')
'types' => array('ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'port', 'hostname', 'domain', 'domain|ip', 'mac-address', 'mac-eui-64', 'email-dst', 'url', 'uri', 'user-agent', 'http-method', 'AS', 'snort', 'pattern-in-file', 'stix2-pattern', 'pattern-in-traffic', 'attachment', 'comment', 'text', 'x509-fingerprint-md5', 'x509-fingerprint-sha1', 'x509-fingerprint-sha256', 'ja3-fingerprint-md5', 'hassh-md5', 'hasshserver-md5', 'other', 'hex', 'cookie', 'hostname|port', 'bro', 'zeek', 'anonymised', 'community-id', 'email-subject')
),
'Payload type' => array(
'desc' => __('Information about the final payload(s)'),
@ -114,7 +121,7 @@ class Attribute extends AppModel
'External analysis' => array(
'desc' => __('Any other result from additional analysis of the malware like tools output'),
'formdesc' => __('Any other result from additional analysis of the malware like tools output Examples: pdf-parser output, automated sandbox analysis, reverse engineering report.'),
'types' => array('md5', 'sha1', 'sha256','filename', 'filename|md5', 'filename|sha1', 'filename|sha256', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'mac-address', 'mac-eui-64', 'hostname', 'domain', 'domain|ip', 'url', 'user-agent', 'regkey', 'regkey|value', 'AS', 'snort', 'bro', 'zeek', 'pattern-in-file', 'pattern-in-traffic', 'pattern-in-memory', 'vulnerability', 'attachment', 'malware-sample', 'link', 'comment', 'text', 'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'ja3-fingerprint-md5', 'hassh-md5', 'hasshserver-md5', 'github-repository', 'other', 'cortex', 'anonymised', 'community-id')
'types' => array('md5', 'sha1', 'sha256','filename', 'filename|md5', 'filename|sha1', 'filename|sha256', 'ip-src', 'ip-dst', 'ip-dst|port', 'ip-src|port', 'mac-address', 'mac-eui-64', 'hostname', 'domain', 'domain|ip', 'url', 'user-agent', 'regkey', 'regkey|value', 'AS', 'snort', 'bro', 'zeek', 'pattern-in-file', 'pattern-in-traffic', 'pattern-in-memory', 'vulnerability', 'weakness', 'attachment', 'malware-sample', 'link', 'comment', 'text', 'x509-fingerprint-sha1', 'x509-fingerprint-md5', 'x509-fingerprint-sha256', 'ja3-fingerprint-md5', 'hassh-md5', 'hasshserver-md5', 'github-repository', 'other', 'cortex', 'anonymised', 'community-id')
),
'Financial fraud' => array(
'desc' => __('Financial Fraud indicators'),
@ -140,6 +147,9 @@ class Attribute extends AppModel
)
);
//
// NOTE WHEN MODIFYING: please ensure to run the script 'tools/gen_misp_types_categories.py' to update the new definitions everywhere. (docu, website, RFC, ...)
//
$this->typeDefinitions = array(
'md5' => array('desc' => __('A checksum in md5 format'), 'formdesc' => __("You are encouraged to use filename|md5 instead. A checksum in md5 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'sha1' => array('desc' => __('A checksum in sha1 format'), 'formdesc' => __("You are encouraged to use filename|sha1 instead. A checksum in sha1 format, only use this if you don't know the correct filename"), 'default_category' => 'Payload delivery', 'to_ids' => 1),
@ -184,6 +194,7 @@ class Attribute extends AppModel
'identity-card-number' => array('desc' => __('Identity card number'), 'default_category' => 'Person', 'to_ids' => 0),
'cookie' => array('desc' => __('HTTP cookie as often stored on the user web client. This can include authentication cookie or session cookie.'), 'default_category' => 'Network activity', 'to_ids' => 0),
'vulnerability' => array('desc' => __('A reference to the vulnerability used in the exploit'), 'default_category' => 'External analysis', 'to_ids' => 0),
'weakness' => array('desc'=> __('A reference to the weakness used in the exploit'), 'default_category' => 'External analysis', 'to_ids' => 0),
'attachment' => array('desc' => __('Attachment with external information'), 'formdesc' => __("Please upload files using the <em>Upload Attachment</em> button."), 'default_category' => 'External analysis', 'to_ids' => 0),
'malware-sample' => array('desc' => __('Attachment containing encrypted malware sample'), 'formdesc' => __("Please upload files using the <em>Upload Attachment</em> button."), 'default_category' => 'Payload delivery', 'to_ids' => 1),
'link' => array('desc' => __('Link to an external information'), 'default_category' => 'External analysis', 'to_ids' => 0),
@ -644,6 +655,12 @@ class Attribute extends AppModel
$passedEvent = $options['parentEvent'];
}
parent::afterSave($created, $options);
// add attributeTags via the shorthand ID list
if (!empty($this->data['Attribute']['tag_ids'])) {
foreach ($this->data['Attribute']['tag_ids'] as $tag_id) {
$this->AttributeTag->attachTagToAttribute($this->id, $this->data['Attribute']['event_id'], $tag_id);
}
}
// update correlation...
if (isset($this->data['Attribute']['deleted']) && $this->data['Attribute']['deleted']) {
$this->__beforeSaveCorrelation($this->data['Attribute']);
@ -770,7 +787,6 @@ class Attribute extends AppModel
public function beforeValidate($options = array())
{
parent::beforeValidate();
if (!isset($this->data['Attribute']['type'])) {
return false;
}
@ -787,7 +803,6 @@ class Attribute extends AppModel
}
// remove leading and trailing blanks
$this->data['Attribute']['value'] = trim($this->data['Attribute']['value']);
// make some last changes to the inserted value
$this->data['Attribute']['value'] = $this->modifyBeforeValidation($this->data['Attribute']['type'], $this->data['Attribute']['value']);
@ -1181,6 +1196,14 @@ class Attribute extends AppModel
$returnValue = __('Invalid format. Expected: CVE-xxxx-xxxx...');
}
break;
case 'weakness':
$value = str_replace('', '-', $value);
if (preg_match("#^(CWE-)[0-9]{1,}$#", $value)) {
$returnValue = true;
} else {
$returnValue = __('Invalid format. Expected: CWE-x...');
}
break;
case 'named pipe':
if (!preg_match("#\n#", $value)) {
$returnValue = true;
@ -1517,7 +1540,7 @@ class Attribute extends AppModel
return $this->data['Event']['org_id'] === $org;
}
public function getRelatedAttributes($attribute, $fields=array())
public function getRelatedAttributes($attribute, $fields=array(), $includeEventData = false)
{
// LATER getRelatedAttributes($attribute) this might become a performance bottleneck
@ -1561,14 +1584,36 @@ class Attribute extends AppModel
if (empty($fields)) {
$fields = array('Attribute.*');
}
$params = array(
'conditions' => $conditions,
'fields' => $fields,
'recursive' => 0,
'group' => array('Attribute.event_id'),
'order' => 'Attribute.event_id DESC'
);
if (!empty($includeEventData)) {
$params['contain'] = array(
'Event' => array(
'fields' => array(
'Event.id', 'Event.uuid', 'Event.threat_level_id', 'Event.analysis', 'Event.info', 'Event.extends_uuid', 'Event.distribution', 'Event.sharing_group_id', 'Event.published', 'Event.date', 'Event.orgc_id', 'Event.org_id'
)
)
);
}
$similarEvents = $this->find(
'all',
array('conditions' => $conditions,
'fields' => $fields,
'recursive' => 0,
'group' => array('Attribute.event_id'),
'order' => 'Attribute.event_id DESC', )
$params
);
if (!empty($includeEventData)) {
foreach ($similarEvents as $k => $similarEvent) {
$similarEvents[$k] = array_merge(
$similarEvent['Attribute'],
array(
'Event' => $similarEvent['Event']
)
);
}
}
return $similarEvents;
}
@ -2969,7 +3014,13 @@ class Attribute extends AppModel
'Event' => array(
'fields' => array('id', 'info', 'org_id', 'orgc_id', 'uuid'),
),
'AttributeTag' => array('Tag' => array()),
'AttributeTag' => array(
'Tag' => array(
'fields' => array(
'id', 'name', 'colour', 'numerical_value'
)
)
),
'Object' => array(
'fields' => array('id', 'distribution', 'sharing_group_id')
)
@ -3011,6 +3062,25 @@ class Attribute extends AppModel
if (empty($options['includeAllTags'])) {
$params['contain']['AttributeTag']['Tag']['conditions']['exportable'] = 1;
}
if (!empty($options['includeContext'])) {
$params['contain']['Event'] = array(
'fields' => array(
'id','orgc_id','org_id','date','threat_level_id','info','published','uuid','analysis','timestamp','distribution','publish_timestamp','sharing_group_id','extends_uuid'
),
'EventTag' => array(
'Tag' => array(
'fields' => array(
'Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value'
)
)
),
'Orgc' => array(
'fields' => array(
'Orgc.id', 'Orgc.uuid', 'Orgc.name'
)
)
);
}
if (isset($options['contain'])) {
$params['contain'] = array_merge_recursive($params['contain'], $options['contain']);
}
@ -3145,6 +3215,22 @@ class Attribute extends AppModel
$results[$k]['AttributeTag'] = array_values($results[$k]['AttributeTag']);
}
}
if (isset($result['Event']['EventTag'])) {
$results[$k]['Event']['Tag'] = array();
foreach ($result['Event']['EventTag'] as $et) {
$results[$k]['Event']['Tag'][] = $et['Tag'];
}
unset($results[$k]['Event']['EventTag']);
}
if (!empty($options['includeSightings'])) {
$temp = $result['Attribute'];
$temp['Event'] = $result['Event'];
$results[$k]['Attribute']['Sighting'] = $this->Sighting->attachToEvent($temp, $user, $temp['id']);
}
if (!empty($options['includeCorrelations'])) {
$attributeFields = array('id', 'event_id', 'object_id', 'object_relation', 'category', 'type', 'value', 'uuid', 'timestamp', 'distribution', 'sharing_group_id', 'to_ids', 'comment');
$results[$k]['Attribute']['RelatedAttribute'] = ($this->getRelatedAttributes($results[$k]['Attribute'], $attributeFields, true));
}
}
if (!$loop) {
if (!empty($params['limit']) && count($results) < $params['limit']) {
@ -3707,14 +3793,44 @@ class Attribute extends AppModel
// gets an attribute, saves it
// handles encryption, attaching to event/object, logging of issues, tag capturing
public function captureAttribute($attribute, $eventId, $user, $objectId = false, $log = false, $parentEvent = false)
public function captureAttribute($attribute, $eventId, $user, $objectId = false, $log = false, $parentEvent = false, &$validationErrors = false, $params = array())
{
if ($log == false) {
$log = ClassRegistry::init('Log');
}
$attribute['event_id'] = $eventId;
$attribute['object_id'] = $objectId ? $objectId : 0;
if (!isset($attribute['to_ids'])) {
$attribute['to_ids'] = $this->typeDefinitions[$attribute['type']]['to_ids'];
}
$attribute['to_ids'] = $attribute['to_ids'] ? 1 : 0;
$attribute['disable_correlation'] = empty($attribute['disable_correlation']) ? 0 : 1;
unset($attribute['id']);
if (isset($attribute['base64'])) {
$attribute['data'] = $attribute['base64'];
}
if (!empty($attribute['enforceWarninglist']) || !empty($params['enforceWarninglist'])) {
$this->Warninglist = ClassRegistry::init('Warninglist');
if (empty($this->warninglists)) {
$this->warninglists = $this->Warninglist->fetchForEventView();
}
if (!$this->Warninglist->filterWarninglistAttributes($warninglists, $attributes[$k])) {
$this->validationErrors['warninglist'] = 'Attribute could not be saved as it trips over a warninglist and enforceWarninglist is enforced.';
$validationErrors = $this->validationErrors['warninglist'];
$log->create();
$log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Attribute',
'model_id' => 0,
'email' => $user['email'],
'action' => 'add',
'user_id' => $user['id'],
'title' => 'Attribute dropped due to validation for Event ' . $eventId . ' failed: ' . $attribute_short,
'change' => 'Validation errors: ' . json_encode($this->validationErrors) . ' Full Attribute: ' . json_encode($attribute),
));
return $attribute;
}
}
if (isset($attribute['encrypt'])) {
$result = $this->handleMaliciousBase64($eventId, $attribute['value'], $attribute['data'], array('md5'));
$attribute['data'] = $result['data'];
@ -3759,6 +3875,9 @@ class Attribute extends AppModel
}
}
if (isset($attribute['Tag'])) {
if (!empty($attribute['Tag']['name'])) {
$attribute['Tag'] = array($attribute['Tag']);
}
foreach ($attribute['Tag'] as $tag) {
$tag_id = $this->AttributeTag->Tag->captureTag($tag, $user);
if ($tag_id) {
@ -3912,7 +4031,7 @@ class Attribute extends AppModel
$tag_id = $this->AttributeTag->Tag->captureTag($tag, $user);
if ($tag_id) {
// fix the IDs here
$this->AttributeTag->attachTagToAttribute($this->id, $this->id, $tag_id);
$this->AttributeTag->attachTagToAttribute($this->id, $attribute['event_id'], $tag_id);
} else {
// If we couldn't attach the tag it is most likely because we couldn't create it - which could have many reasons
// However, if a tag couldn't be added, it could also be that the user is a tagger but not a tag editor
@ -4128,6 +4247,9 @@ class Attribute extends AppModel
'includeEventTags' => !empty($filters['includeEventTags']) ? $filters['includeEventTags'] : 0,
'includeProposals' => !empty($filters['includeProposals']) ? $filters['includeProposals'] : 0,
'includeWarninglistHits' => !empty($filters['includeWarninglistHits']) ? $filters['includeWarninglistHits'] : 0,
'includeContext' => !empty($filters['includeContext']) ? $filters['includeContext'] : 0,
'includeSightings' => !empty($filters['includeSightings']) ? $filters['includeSightings'] : 0,
'includeCorrelations' => !empty($filters['includeCorrelations']) ? $filters['includeCorrelations'] : 0,
'includeDecayScore' => !empty($filters['includeDecayScore']) ? $filters['includeDecayScore'] : 0
);
if (!empty($filters['attackGalaxy'])) {

View File

@ -264,16 +264,18 @@ class AttributeTag extends AppModel
}
}
foreach ($event['Object'] as $i => $object) {
foreach ($object['Attribute'] as $j => $object_attribute) {
if ($to_extract == 'tags' || $to_extract == 'both') {
foreach ($object_attribute['AttributeTag'] as $tag) {
$attribute_tags_name['tags'][] = $tag['Tag']['name'];
if (!empty($object['Attribute'])) {
foreach ($object['Attribute'] as $j => $object_attribute) {
if ($to_extract == 'tags' || $to_extract == 'both') {
foreach ($object_attribute['AttributeTag'] as $tag) {
$attribute_tags_name['tags'][] = $tag['Tag']['name'];
}
}
}
if ($to_extract == 'clusters' || $to_extract == 'both') {
foreach ($object_attribute['Galaxy'] as $galaxy) {
foreach ($galaxy['GalaxyCluster'] as $cluster) {
$attribute_tags_name['clusters'][] = $cluster['tag_name'];
if ($to_extract == 'clusters' || $to_extract == 'both') {
foreach ($object_attribute['Galaxy'] as $galaxy) {
foreach ($galaxy['GalaxyCluster'] as $cluster) {
$attribute_tags_name['clusters'][] = $cluster['tag_name'];
}
}
}
}

View File

@ -255,6 +255,7 @@ class Event extends AppModel
'info' => array(
'valueNotEmpty' => array(
'rule' => array('valueNotEmpty'),
'required' => true
),
),
'user_id' => array(
@ -1111,6 +1112,8 @@ class Event extends AppModel
if (!$found) {
return 403;
}
} else if (empty($event['SharingGroup']['roaming'])) {
return 403;
}
}
$serverModel = ClassRegistry::init('Server');
@ -1179,6 +1182,16 @@ class Event extends AppModel
$request = $this->setupSyncRequest($server);
$uri = $url . '/events' . $this->__getLastUrlPathComponent($urlPath);
$data = json_encode($event);
if (!empty(Configure::read('Security.sync_audit'))) {
$pushLogEntry = sprintf(
"==============================================================\n\n[%s] Pushing Event #%d to Server #%d:\n\n%s\n\n",
date("Y-m-d H:i:s"),
$event['Event']['id'],
$server['Server']['id'],
$data
);
file_put_contents(APP . 'files/scripts/tmp/debug_server_' . $server['Server']['id'] . '.log', $pushLogEntry, FILE_APPEND);
}
$response = $HttpSocket->post($uri, $data, $request);
return $this->__handleRestfulEventToServerResponse($response, $newLocation, $newTextBody);
}
@ -1205,7 +1218,7 @@ class Event extends AppModel
{
if (!empty($data[$dataType . 'Tag'])) {
foreach ($data[$dataType . 'Tag'] as $k => $tag) {
if (!$tag['Tag']['exportable']) {
if (!$tag['Tag']['exportable'] || !empty($tag['local'])) {
unset($data[$dataType . 'Tag'][$k]);
} else {
unset($tag['org_id']);
@ -1243,7 +1256,7 @@ class Event extends AppModel
if (empty($data['Object'][$key])) {
unset($data['Object'][$key]);
} else {
$data['Object'][$key]['Attribute'] = $this->__prepareAttributesForSync($data['Object'][$key]['Attribute'], $server);
$data['Object'][$key] = $this->__prepareAttributesForSync($data['Object'][$key], $server);
}
}
$data['Object'] = array_values($data['Object']);
@ -2270,7 +2283,7 @@ class Event extends AppModel
'contain' => array(
'Tag' => array(
'fields' => array(
'Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value', 'Tag.local'
'Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value'
)
)
),
@ -2319,7 +2332,7 @@ class Event extends AppModel
'contain' => array(
'Tag' => array(
'fields' => array(
'Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value', 'Tag.local'
'Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value'
)
)
),
@ -2814,18 +2827,26 @@ class Event extends AppModel
public function sendAlertEmailRouter($id, $user, $oldpublish = null)
{
if (Configure::read('MISP.block_old_event_alert') && !empty(Configure::read('MISP.block_old_event_alert_age') && is_numeric(Configure::read('MISP.block_old_event_alert_age')))) {
if (Configure::read('MISP.block_old_event_alert')) {
$oldest = time() - (Configure::read('MISP.block_old_event_alert_age') * 86400);
$oldest_date = time() - (Configure::read('MISP.block_old_event_alert_by_date') * 86400);
$event = $this->find('first', array(
'conditions' => array('Event.id' => $id),
'recursive' => -1,
'fields' => array('Event.timestamp')
'fields' => array('Event.timestamp', 'Event.date')
));
if (empty($event)) {
return false;
}
if (intval($event['Event']['timestamp']) < $oldest) {
return true;
if (!empty(Configure::read('MISP.block_old_event_alert_age')) && is_numeric(Configure::read('MISP.block_old_event_alert_age'))) {
if (intval($event['Event']['timestamp']) < $oldest) {
return true;
}
}
if (!empty(Configure::read('MISP.block_old_event_alert_by_date')) && is_numeric(Configure::read('MISP.block_old_event_alert_by_date'))) {
if (strtotime($event['Event']['date']) < $oldest_date) {
return true;
}
}
}
if (Configure::read('MISP.block_event_alert') && Configure::read('MISP.block_event_alert_tag') && !empty(Configure::read('MISP.block_event_alert_tag'))) {
@ -3366,6 +3387,22 @@ class Event extends AppModel
return 'Blocked by blacklist';
}
}
if (empty($data['Event']['Attribute']) && empty($data['Event']['Object']) && !empty($data['Event']['published'])) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$validationErrors['Event'] = 'Received a published event that was empty. Event add process blocked.';
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Event',
'model_id' => 0,
'email' => $user['email'],
'action' => 'add',
'user_id' => $user['id'],
'title' => $validationErrors['Event'],
'change' => ''
));
return json_encode($validationErrors);
}
$this->create();
// force check userid and orgname to be from yourself
$data['Event']['user_id'] = $user['id'];
@ -3465,39 +3502,39 @@ class Event extends AppModel
return json_encode($validationErrors);
}
$fieldList = array(
'Event' => array(
'org_id',
'orgc_id',
'date',
'threat_level_id',
'analysis',
'info',
'user_id',
'published',
'uuid',
'timestamp',
'distribution',
'sharing_group_id',
'locked',
'disable_correlation',
'extends_uuid'
),
'Attribute' => $this->Attribute->captureFields,
'Object' => array(
'name',
'meta-category',
'description',
'template_uuid',
'template_version',
'event_id',
'uuid',
'timestamp',
'distribution',
'sharing_group_id',
'comment',
'deleted'
),
'ObjectRelation' => array()
'Event' => array(
'org_id',
'orgc_id',
'date',
'threat_level_id',
'analysis',
'info',
'user_id',
'published',
'uuid',
'timestamp',
'distribution',
'sharing_group_id',
'locked',
'disable_correlation',
'extends_uuid'
),
'Attribute' => $this->Attribute->captureFields,
'Object' => array(
'name',
'meta-category',
'description',
'template_uuid',
'template_version',
'event_id',
'uuid',
'timestamp',
'distribution',
'sharing_group_id',
'comment',
'deleted'
),
'ObjectRelation' => array()
);
$saveResult = $this->save(array('Event' => $data['Event']), array('fieldList' => $fieldList['Event']));
$this->Log = ClassRegistry::init('Log');
@ -4047,8 +4084,7 @@ class Event extends AppModel
'includeAttachments' => true,
'includeAllTags' => true,
'deleted' => array(0,1),
'excludeGalaxy' => 1,
'excludeLocalTags' => 1
'excludeGalaxy' => 1
));
$event = $this->fetchEvent($elevatedUser, $params);
$event = $event[0];
@ -4123,6 +4159,9 @@ class Event extends AppModel
$this->id = $id;
$this->recursive = 0;
$event = $this->read(null, $id);
if (empty($event)) {
return false;
}
if ($jobId) {
$this->Behaviors->unload('SysLogLogable.SysLogLogable');
} else {
@ -4389,7 +4428,7 @@ class Event extends AppModel
foreach ($eventArray as $k => &$event) {
$uuidsToCheck[$event['uuid']] = $k;
}
$localEvents = $this->find('list', array('recursive' => -1, 'fields' => array('Event.uuid', 'Event.timestamp')));
$localEvents = array();
$temp = $this->find('all', array('recursive' => -1, 'fields' => array('Event.uuid', 'Event.timestamp', 'Event.locked')));
foreach ($temp as $e) {
$localEvents[$e['Event']['uuid']] = array('timestamp' => $e['Event']['timestamp'], 'locked' => $e['Event']['locked']);
@ -6008,13 +6047,17 @@ class Event extends AppModel
return false;
}
public function processFreeTextData($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false, $jobId = false)
public function processFreeTextData($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false, $jobId = false, $returnRawResults = false)
{
$event = $this->find('first', array(
'conditions' => array('id' => $id),
'recursive' => -1,
'fields' => array('orgc_id', 'id', 'distribution', 'published', 'uuid'),
));
if (empty($event)) {
return false;
}
$results = array();
if (!$user['Role']['perm_site_admin'] && !empty($event) && $event['Event']['orgc_id'] != $user['org_id']) {
$objectType = 'ShadowAttribute';
} elseif ($user['Role']['perm_site_admin'] && isset($force) && $force) {
@ -6082,7 +6125,7 @@ class Event extends AppModel
// adhere to the warninglist
if ($adhereToWarninglists) {
if (!$this->Warninglist->filterWarninglistAttributes($warninglists, $attribute)) {
if ($adhereToWarninglists == 'soft') {
if ($adhereToWarninglists === 'soft') {
$attribute['to_ids'] = 0;
} else {
// just ignore the attribute
@ -6090,15 +6133,16 @@ class Event extends AppModel
}
}
}
$AttributSave = $this->$objectType->save($attribute);
if ($AttributSave) {
$saved_attribute = $this->$objectType->save($attribute);
if ($saved_attribute) {
$results[] = $saved_attribute;
// If Tags, attach each tags to attribute
if (!empty($attribute['tags'])) {
foreach (explode(",", $attribute['tags']) as $tagName) {
$this->Tag = ClassRegistry::init('Tag');
$TagId = $this->Tag->captureTag(array('name' => $tagName), array('Role' => $user['Role']));
$this->AttributeTag = ClassRegistry::init('AttributeTag');
if (!$this->AttributeTag->attachTagToAttribute($AttributSave['Attribute']['id'], $id, $TagId)) {
if (!$this->AttributeTag->attachTagToAttribute($saved_attribute['Attribute']['id'], $id, $TagId)) {
throw new MethodNotAllowedException(__('Could not add tags.'));
}
}
@ -6137,7 +6181,7 @@ class Event extends AppModel
}
}
}
$messageScopeSaved = $this-> __apply_inflector($saved, $messageScope);
$messageScopeSaved = $this->__apply_inflector($saved, $messageScope);
if ($failed > 0) {
if ($failed == 1) {
$messageScopeFailed = Inflector::singularize($messageScope);
@ -6154,6 +6198,9 @@ class Event extends AppModel
$this->Job->saveField('progress', 100);
}
}
if (!empty($returnRawResults)) {
return $results;
}
return $message;
}
@ -6189,6 +6236,9 @@ class Event extends AppModel
if (empty($attribute['comment'])) {
$attribute['comment'] = $default_comment;
}
if (!empty($attribute['data']) && !empty($attribute['encrypt'])) {
$attribute = $this->Attribute->onDemandEncrypt($attribute);
}
$attribute['event_id'] = $id;
if ($this->Attribute->save($attribute)) {
$saved_attributes++;
@ -6233,6 +6283,9 @@ class Event extends AppModel
$object['meta-category'] = $object['meta_category'];
unset($object['meta_category']);
}
if (empty($object['comment'])) {
$object['comment'] = $default_comment;
}
$object['event_id'] = $id;
if (isset($object['id']) && $object['id'] == $initial_object_id) {
$initial_object = $resolved_data['initialObject'];
@ -6488,6 +6541,9 @@ class Event extends AppModel
if (empty($attribute['comment'])) {
$attribute['comment'] = $default_comment;
}
if (!empty($attribute['data']) && !empty($attribute['encrypt'])) {
$attribute = $this->Attribute->onDemandEncrypt($attribute);
}
$this->Attribute->create();
$attribute_save = $this->Attribute->save($attribute);
if ($attribute_save) {
@ -6503,7 +6559,7 @@ class Event extends AppModel
return $attribute_save;
}
public function processFreeTextDataRouter($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false)
public function processFreeTextDataRouter($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false, $returnRawResults = false)
{
if (Configure::read('MISP.background_jobs')) {
list($job, $randomFileName, $tempFile) = $this->__initiateProcessJob($user, $id);
@ -6519,7 +6575,7 @@ class Event extends AppModel
$writeResult = $tempFile->write(json_encode($tempData));
if (!$writeResult) {
return ($this->processFreeTextData($user, $attributes, $id, $default_comment = '', $force = false, $adhereToWarninglists = false));
return ($this->processFreeTextData($user, $attributes, $id, $default_comment, $force, $adhereToWarninglists, false, $returnRawResults));
}
$tempFile->close();
$process_id = CakeResque::enqueue(
@ -6531,7 +6587,7 @@ class Event extends AppModel
$job->saveField('process_id', $process_id);
return 'Freetext ingestion queued for background processing. Attributes will be added to the event as they are being processed.';
} else {
return $this->processFreeTextData($user, $resolved_data, $id, $default_comment);
return $this->processFreeTextData($user, $attributes, $id, $default_comment, $force, $adhereToWarninglists, false, $returnRawResults);
}
}

View File

@ -190,7 +190,7 @@ class EventTag extends AppModel
'conditions' => array('name' => $allowedTags)
)
),
'group' => 'tag_id',
'group' => array('tag_id', 'Tag.name', 'Tag.id'),
'fields' => array('Tag.name', 'EventTag.tag_id', 'count(EventTag.tag_id) as score')
));
}

View File

@ -142,7 +142,7 @@ class GalaxyCluster extends AppModel
*/
public function getCluster($name)
{
$conditions = array('GalaxyCluster.tag_name ' => $name);
$conditions = array('LOWER(GalaxyCluster.tag_name)' => strtolower($name));
if (is_numeric($name)) {
$conditions = array('GalaxyCluster.id' => $name);
}
@ -173,7 +173,7 @@ class GalaxyCluster extends AppModel
'first',
array(
'conditions' => array(
'Tag.name' => $cluster['GalaxyCluster']['tag_name']
'LOWER(Tag.name)' => strtolower($cluster['GalaxyCluster']['tag_name'])
),
'recursive' => -1,
'fields' => array('Tag.id')

View File

@ -90,10 +90,17 @@ class Log extends AppModel
if (!isset($this->data['Log']['org']) || empty($this->data['Log']['org'])) {
$this->data['Log']['org'] = 'SYSTEM';
}
// truncate the description if it would exceed the allowed size in mysql
if (!empty($this->data['Log']['description'] && strlen($this->data['Log']['description']) > 65536)) {
$this->data['Log']['description'] = substr($this->data['Log']['description'], 0, 65535);
}
}
public function beforeSave($options = array())
{
if (!empty(Configure::read('MISP.log_skip_db_logs_completely'))) {
return false;
}
if (Configure::read('MISP.log_client_ip') && isset($_SERVER['REMOTE_ADDR'])) {
$this->data['Log']['ip'] = $_SERVER['REMOTE_ADDR'];
}

View File

@ -454,7 +454,7 @@ class MispObject extends AppModel
public function attributeCleanup($attributes)
{
if (empty($attributes['Attribute'])) {
return 'No attribute data found';
return $attributes;
}
foreach ($attributes['Attribute'] as $k => $attribute) {
if (isset($attribute['save']) && $attribute['save'] == 0) {
@ -521,58 +521,60 @@ class MispObject extends AppModel
$object['Object']['timestamp'] = $date->getTimestamp();
$this->save($object);
$checkFields = array('category', 'value', 'to_ids', 'distribution', 'sharing_group_id', 'comment', 'disable_correlation');
foreach ($objectToSave['Attribute'] as $newKey => $newAttribute) {
foreach ($object['Attribute'] as $origKey => $originalAttribute) {
if (!empty($newAttribute['uuid'])) {
if ($newAttribute['uuid'] == $originalAttribute['uuid']) {
$different = false;
foreach ($checkFields as $f) {
if ($f == 'sharing_group_id' && empty($newAttribute[$f])) {
$newAttribute[$f] = 0;
if (!empty($objectToSave['Attribute'])) {
foreach ($objectToSave['Attribute'] as $newKey => $newAttribute) {
foreach ($object['Attribute'] as $origKey => $originalAttribute) {
if (!empty($newAttribute['uuid'])) {
if ($newAttribute['uuid'] == $originalAttribute['uuid']) {
$different = false;
foreach ($checkFields as $f) {
if ($f == 'sharing_group_id' && empty($newAttribute[$f])) {
$newAttribute[$f] = 0;
}
if ($newAttribute[$f] != $originalAttribute[$f]) {
$different = true;
}
}
if ($newAttribute[$f] != $originalAttribute[$f]) {
$different = true;
if ($different) {
$newAttribute['id'] = $originalAttribute['id'];
$newAttribute['event_id'] = $object['Object']['event_id'];
$newAttribute['object_id'] = $object['Object']['id'];
$newAttribute['timestamp'] = $date->getTimestamp();
$result = $this->Event->Attribute->save(array('Attribute' => $newAttribute), array(
'category',
'value',
'to_ids',
'distribution',
'sharing_group_id',
'comment',
'timestamp',
'object_id',
'event_id',
'disable_correlation'
));
}
unset($object['Attribute'][$origKey]);
continue 2;
}
if ($different) {
$newAttribute['id'] = $originalAttribute['id'];
$newAttribute['event_id'] = $object['Object']['event_id'];
$newAttribute['object_id'] = $object['Object']['id'];
$newAttribute['timestamp'] = $date->getTimestamp();
$result = $this->Event->Attribute->save(array('Attribute' => $newAttribute), array(
'category',
'value',
'to_ids',
'distribution',
'sharing_group_id',
'comment',
'timestamp',
'object_id',
'event_id',
'disable_correlation'
));
}
unset($object['Attribute'][$origKey]);
continue 2;
}
}
}
$this->Event->Attribute->create();
$newAttribute['event_id'] = $object['Object']['event_id'];
$newAttribute['object_id'] = $object['Object']['id'];
if (!isset($newAttribute['timestamp'])) {
$newAttribute['distribution'] = Configure::read('MISP.default_attribute_distribution');
if ($newAttribute['distribution'] == 'event') {
$newAttribute['distribution'] = 5;
$this->Event->Attribute->create();
$newAttribute['event_id'] = $object['Object']['event_id'];
$newAttribute['object_id'] = $object['Object']['id'];
if (!isset($newAttribute['timestamp'])) {
$newAttribute['distribution'] = Configure::read('MISP.default_attribute_distribution');
if ($newAttribute['distribution'] == 'event') {
$newAttribute['distribution'] = 5;
}
}
$this->Event->Attribute->save($newAttribute);
$attributeArrays['add'][] = $newAttribute;
unset($objectToSave['Attribute'][$newKey]);
}
foreach ($object['Attribute'] as $origKey => $originalAttribute) {
$originalAttribute['deleted'] = 1;
$this->Event->Attribute->save($originalAttribute);
}
$this->Event->Attribute->save($newAttribute);
$attributeArrays['add'][] = $newAttribute;
unset($objectToSave['Attribute'][$newKey]);
}
foreach ($object['Attribute'] as $origKey => $originalAttribute) {
$originalAttribute['deleted'] = 1;
$this->Event->Attribute->save($originalAttribute);
}
return $this->id;
}

View File

@ -135,6 +135,8 @@ class Organisation extends AppModel
foreach ($results as $k => $organisation) {
if (!empty($organisation['Organisation']['restricted_to_domain'])) {
$results[$k]['Organisation']['restricted_to_domain'] = json_decode($organisation['Organisation']['restricted_to_domain'], true);
} else if (isset($organisation['Organisation']['restricted_to_domain'])){
$results[$k]['Organisation']['restricted_to_domain'] = array();
}
}
return $results;

View File

@ -49,6 +49,11 @@ class Server extends AppModel
'authkey' => array(
'rule' => array('validateAuthkey')
),
'name' => array(
'rule' => array('notBlank'),
'allowEmpty' => false,
'required' => true
),
'org_id' => array(
'numeric' => array(
'rule' => array('valueIsID'),
@ -520,7 +525,15 @@ class Server extends AppModel
'cveurl' => array(
'level' => 1,
'description' => __('Turn Vulnerability type attributes into links linking to the provided CVE lookup'),
'value' => '',
'value' => 'http://cve.circl.lu/cve/',
'errorMessage' => '',
'test' => 'testForEmpty',
'type' => 'string',
),
'cweurl' => array(
'level' => 1,
'description' => __('Turn Weakness type attributes into links linking to the provided CWE lookup'),
'value' => 'http://cve.circl.lu/cwe/',
'errorMessage' => '',
'test' => 'testForEmpty',
'type' => 'string',
@ -723,6 +736,15 @@ class Server extends AppModel
'test' => 'testBool',
'type' => 'boolean',
),
'log_skip_db_logs_completely' => array(
'level' => 0,
'description' => __('This functionality allows you to completely disable any logs from being saved in your SQL backend. This is HIGHLY advised against, you lose all the functionalities provided by the audit log subsystem along with the event history (as these are built based on the logs on the fly). Only enable this if you understand and accept the associated risks.'),
'value' => false,
'errorMessage' => __('Logging has now been disabled - your audit logs will not capture failed authentication attempts, your event history logs are not being populated and no system maintenance messages are being logged.'),
'test' => 'testBoolFalse',
'type' => 'boolean',
'null' => true
),
'log_paranoid' => array(
'level' => 0,
'description' => __('If this functionality is enabled all page requests will be logged. Keep in mind this is extremely verbose and will become a burden to your database.'),
@ -843,7 +865,16 @@ class Server extends AppModel
),
'block_old_event_alert_age' => array(
'level' => 1,
'description' => __('If the MISP.block_old_event_alert setting is set, this setting will control how old an event can be for it to be alerted on. The "Date" field of the event is used. Expected format: integer, in days'),
'description' => __('If the MISP.block_old_event_alert setting is set, this setting will control how old an event can be for it to be alerted on. The "timestamp" field of the event is used. Expected format: integer, in days'),
'value' => false,
'errorMessage' => '',
'test' => 'testForNumeric',
'type' => 'numeric',
'null' => false,
),
'block_old_event_alert_by_date' => array(
'level' => 1,
'description' => __('If the MISP.block_old_event_alert setting is set, this setting will control the threshold for the event.date field, indicating how old an event can be for it to be alerted on. The "date" field of the event is used. Expected format: integer, in days'),
'value' => false,
'errorMessage' => '',
'test' => 'testForNumeric',
@ -1210,6 +1241,15 @@ class Server extends AppModel
'test' => 'testForEmpty',
'type' => 'string',
'null' => true
),
'sync_audit' => array(
'level' => 1,
'description' => __('Enable this setting to create verbose logs of synced event data for debugging reasons. Logs are saved in your MISP directory\'s app/files/scripts/tmp/ directory.'),
'value' => false,
'errorMessage' => '',
'test' => 'testBoolFalse',
'type' => 'boolean',
'null' => true
)
),
'SecureAuth' => array(
@ -1271,7 +1311,7 @@ class Server extends AppModel
'description' => __('The expiration of the cookie (in MINUTES). The session timeout gets refreshed frequently, however the cookies do not. Generally it is recommended to have a much higher cookie_timeout than timeout.'),
'value' => '',
'errorMessage' => '',
'test' => 'testForNumeric',
'test' => 'testForCookieTimeout',
'type' => 'numeric'
)
),
@ -2957,7 +2997,7 @@ class Server extends AppModel
{
if (isset($setting)) {
if (!empty($leafValue['test'])) {
$result = $this->{$leafValue['test']}($setting);
$result = $this->{$leafValue['test']}($setting, empty($leafValue['errorMessage']) ? false : $leafValue['errorMessage']);
if ($result !== true) {
$leafValue['error'] = 1;
if ($result !== false) {
@ -2992,7 +3032,7 @@ class Server extends AppModel
{
$languages = $this->loadAvailableLanguages();
if (!isset($languages[$value])) {
return 'Invalid language.';
return __('Invalid language.');
}
return true;
}
@ -3013,7 +3053,7 @@ class Server extends AppModel
{
$tag_collections = $this->loadTagCollections();
if (!isset($tag_collections[intval($value)])) {
return 'Invalid tag_collection.';
return __('Invalid tag_collection.');
}
return true;
}
@ -3021,7 +3061,19 @@ class Server extends AppModel
public function testForNumeric($value)
{
if (!is_numeric($value)) {
return 'This setting has to be a number.';
return __('This setting has to be a number.');
}
return true;
}
public function testForCookieTimeout($value)
{
$numeric = $this->testForNumeric($value);
if ($numeric !== true) {
return $numeric;
}
if ($value < Configure::read('Session.timeout') && $value !== 0) {
return __('The cookie timeout is currently lower than the session timeout. This will invalidate the cookie before the session expires.');
}
return true;
}
@ -3246,20 +3298,26 @@ class Server extends AppModel
return true;
}
public function testBool($value)
public function testBool($value, $errorMessage = false)
{
if ($value !== true && $value !== false) {
if ($errorMessage) {
return $errorMessage;
}
return 'Value is not a boolean, make sure that you convert \'true\' to true for example.';
}
return true;
}
public function testBoolFalse($value)
public function testBoolFalse($value, $errorMessage = false)
{
if (!$this->testBool($value)) {
return $this->testBool($value);
if ($this->testBool($value, $errorMessage) !== true) {
return $this->testBool($value, $errorMessage);
}
if ($value !== false) {
if ($errorMessage) {
return $errorMessage;
}
return 'It is highly recommended that this setting is disabled. Make sure you understand the impact of having this setting turned on.';
} else {
return true;
@ -3728,7 +3786,7 @@ class Server extends AppModel
}
$settingsToSave = array(
'debug', 'MISP', 'GnuPG', 'SMIME', 'Proxy', 'SecureAuth',
'Security', 'Session.defaults', 'Session.timeout', 'Session.cookie_timeout',
'Security', 'Session.defaults', 'Session.timeout', 'Session.cookieTimeout',
'Session.autoRegenerate', 'Session.checkAgent', 'site_admin_debug',
'Plugin', 'CertAuth', 'ApacheShibbAuth', 'ApacheSecureAuth'
);
@ -4531,7 +4589,7 @@ class Server extends AppModel
* 2: no route to host
* 3: empty result set
*/
public function previewIndex($id, $user, $passedArgs)
public function previewIndex($id, $user, $passedArgs, &$total_count = 0)
{
$server = $this->find('first', array(
'conditions' => array('Server.id' => $id),
@ -4541,7 +4599,7 @@ class Server extends AppModel
}
$HttpSocket = $this->setupHttpSocket($server);
$request = $this->setupSyncRequest($server);
$validArgs = array_merge(array('sort', 'direction'), $this->validEventIndexFilters);
$validArgs = array_merge(array('sort', 'direction', 'page', 'limit'), $this->validEventIndexFilters);
$urlParams = '';
foreach ($validArgs as $v) {
if (isset($passedArgs[$v])) {
@ -4550,6 +4608,10 @@ class Server extends AppModel
}
$uri = $server['Server']['url'] . '/events/index' . $urlParams;
$response = $HttpSocket->get($uri, $data = '', $request);
if (!empty($response->headers['X-Result-Count'])) {
$temp = $response->headers['X-Result-Count'];
$total_count = $temp;
}
if ($response->code == 200) {
try {
$events = json_decode($response->body, true);
@ -4655,7 +4717,6 @@ class Server extends AppModel
}
$validServers[] = $server;
}
return $validServers;
}

View File

@ -348,6 +348,10 @@ class ShadowAttribute extends AppModel
$this->data['ShadowAttribute']['uuid'] = CakeText::uuid();
}
if (!empty($this->data['ShadowAttribute']['type']) && empty($this->data['ShadowAttribute']['category'])) {
$this->data['ShadowAttribute']['category'] = $this->Event->Attribute->typeDefinitions[$this->data['ShadowAttribute']['type']]['default_category'];
}
// always return true, otherwise the object cannot be saved
return true;
}

View File

@ -270,7 +270,10 @@ class SharingGroup extends AppModel
if (isset($server['Server'][0])) {
$server['Server'] = $server['Server'][0];
}
if ($server['Server']['url'] == Configure::read('MISP.baseurl')) {
if (
$server['Server']['url'] == Configure::read('MISP.baseurl') ||
(!empty(Configure::read('MISP.external_baseurl')) && Configure::read('MISP.external_baseurl') === $server['Server']['url'])
) {
$serverCheck = true;
if ($user['Role']['perm_sync'] && $server['all_orgs']) {
$orgCheck = true;

View File

@ -479,7 +479,7 @@ class Sighting extends AppModel
public function listSightings($user, $id, $context, $org_id = false, $sightings_type = false, $order_desc = true)
{
$this->Event = ClassRegistry::init('Event');
$id = $this->explodeIdList($id);
$id = is_array($id) ? $id : $this->explodeIdList($id);
if ($context === 'attribute') {
$object = $this->Event->Attribute->fetchAttributes($user, array('conditions' => array('Attribute.id' => $id, 'Attribute.deleted' => 0), 'flatten' => 1));
} else {

View File

@ -317,7 +317,7 @@ class Taxonomy extends AppModel
if (!in_array('name', $skipUpdateFields)) {
$temp['Tag']['name'] = $entry['tag'];
}
if (!in_array('numerical_value', $skipUpdateFields) && isset($entry['numerical_value'])) {
if (!in_array('numerical_value', $skipUpdateFields) && (isset($entry['numerical_value']) && $entry['numerical_value'] !== null)) {
$temp['Tag']['numerical_value'] = $entry['numerical_value'];
}
$this->Tag->save($temp['Tag']);

View File

@ -257,6 +257,33 @@ class Warninglist extends AppModel
return $entries;
}
private function filterCidrList($inputValues)
{
$outputValues = [];
foreach ($inputValues as $v) {
$parts = explode('/', $v, 2);
if (filter_var($parts[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$maximumNetmask = 32;
} else if (filter_var($parts[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$maximumNetmask = 128;
} else {
// IP address part of CIDR is invalid
continue;
}
if (!isset($parts[1])) {
// If CIDR doesnt contains '/', we will consider CIDR as /32 for IPv4 or /128 for IPv6
$v = "$v/$maximumNetmask";
} else if ($parts[1] > $maximumNetmask || $parts[1] < 0) {
// Netmask part of CIDR is invalid
continue;
}
$outputValues[] = $v;
}
return $outputValues;
}
public function fetchForEventView()
{
$warninglists = $this->getWarninglists(array('enabled' => 1));
@ -270,10 +297,12 @@ class Warninglist extends AppModel
foreach ($t['values'] as $vk => $v) {
$t['values'][$vk] = rtrim($v, '.');
}
}
if ($t['Warninglist']['type'] == 'string' || $t['Warninglist']['type'] == 'hostname') {
} else if ($t['Warninglist']['type'] == 'string' || $t['Warninglist']['type'] == 'hostname') {
$t['values'] = array_combine($t['values'], $t['values']);
} else if ($t['Warninglist']['type'] === 'cidr') {
$t['values'] = $this->filterCidrList($t['values']);
}
foreach ($t['WarninglistType'] as &$wt) {
$t['types'][] = $wt['type'];
}
@ -358,7 +387,7 @@ class Warninglist extends AppModel
private function __checkValue($listValues, $value, $type, $listType, $returnVerboseValue = false)
{
if (strpos($type, '|') || $type = 'malware-sample') {
if ($type === 'malware-sample' || strpos($type, '|') !== false) {
$value = explode('|', $value);
} else {
$value = array($value);
@ -382,9 +411,8 @@ class Warninglist extends AppModel
if (!empty($result)) {
if ($returnVerboseValue) {
return $value[$component];
} else {
}
return ($component + 1);
return ($component + 1);
}
}
return false;
@ -411,10 +439,9 @@ class Warninglist extends AppModel
$ipv6cidrlist = array();
// separate the CIDR list into IPv4 and IPv6
foreach ($listValues as $lv) {
$base = substr($lv, 0, strpos($lv, '/'));
if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
if (strpos($lv, '.') !== false) { // IPv4 address must contain dot
$ipv4cidrlist[] = $lv;
} elseif (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
} else {
$ipv6cidrlist[] = $lv;
}
}
@ -429,15 +456,11 @@ class Warninglist extends AppModel
private function __evalCIDR($value, $listValues, $function)
{
$found = false;
foreach ($listValues as $lv) {
if ($this->$function($value, $lv)) {
$found = true;
return true;
}
}
if ($found) {
return true;
}
return false;
}
@ -452,29 +475,24 @@ class Warninglist extends AppModel
return ($ip & $mask) == $subnet;
}
// using Snifff's solution from http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet
// Using solution from https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/IpUtils.php
private function __ipv6InCidr($ip, $cidr)
{
$ip = inet_pton($ip);
$binaryip = $this->__inet_to_bits($ip);
list($net, $maskbits) = explode('/', $cidr);
$net = inet_pton($net);
$binarynet = $this->__inet_to_bits($net);
$ip_net_bits = substr($binaryip, 0, $maskbits);
$net_bits = substr($binarynet, 0, $maskbits);
return ($ip_net_bits === $net_bits);
}
// converts inet_pton output to string with bits
private function __inet_to_bits($inet)
{
$unpacked = unpack('A16', $inet);
$unpacked = str_split($unpacked[1]);
$binaryip = '';
foreach ($unpacked as $char) {
$binaryip .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
{
list($address, $netmask) = explode('/', $cidr);
$bytesAddr = unpack('n*', inet_pton($address));
$bytesTest = unpack('n*', inet_pton($ip));
for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) {
$left = $netmask - 16 * ($i - 1);
$left = ($left <= 16) ? $left : 16;
$mask = ~(0xffff >> $left) & 0xffff;
if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) {
return false;
}
}
return $binaryip;
return true;
}
private function __evalString($listValues, $value)

View File

@ -74,6 +74,7 @@
<?php
echo $this->Form->input('to_ids', array(
'label' => __('for Intrusion Detection System'),
'type' => 'checkbox'
));
echo $this->Form->input('batch_import', array(
'type' => 'checkbox'

View File

@ -33,8 +33,11 @@
$object['value'] = implode($separator, $value_pieces);
echo ($object['value']);
} else if ('vulnerability' == $object['type']) {
$cveUrl = (is_null(Configure::read('MISP.cveurl'))) ? "http://www.google.com/search?q=" : Configure::read('MISP.cveurl');
$cveUrl = (is_null(Configure::read('MISP.cveurl'))) ? "http://cve.circl.lu/cve/" : Configure::read('MISP.cveurl');
echo $this->Html->link($sigDisplay, $cveUrl . $sigDisplay, array('target' => '_blank', 'class' => $linkClass));
} else if ('weakness' == $object['type']) {
$cweUrl = (is_null(Configure::read('MISP.cweurl'))) ? "http://cve.circl.lu/cwe/" : Configure::read('MISP.cweurl');
echo $this->Html->link($sigDisplay, $cweUrl . explode("-", $sigDisplay)[1], array('target' => '_blank', 'class' => $linkClass));
} else if ('link' == $object['type'] && (substr($object['value'], 0, 7) === 'http://' || substr($object['value'], 0, 8) === 'https://')) {
echo $this->Html->link($sigDisplay, $sigDisplay, array('class' => $linkClass));
} else if ('cortex' == $object['type']) {

View File

@ -141,7 +141,8 @@
'tagAccess' => false,
'required_taxonomies' => false,
'columnised' => true,
'static_tags_only' => true
'static_tags_only' => 1,
'tag_display_style' => Configure::check('MISP.full_tags_on_event_index') ? Configure::read('MISP.full_tags_on_event_index') : 1
)
)
);
@ -190,7 +191,7 @@
<span style=" white-space: nowrap;"><?php echo $post_count?></span>&nbsp;
</td>
<?php endif;?>
<?php if ('true' == $isSiteAdmin): ?>
<?php if ($isSiteAdmin): ?>
<td class="short" ondblclick="location.href ='<?php echo $baseurl."/events/view/".$event['Event']['id'];?>'">
<?php echo h($event['User']['email']); ?>&nbsp;
</td>

View File

@ -24,8 +24,11 @@
$final_value = h($object['value']);
echo substr_replace(h($object['value']), $separator, $separator_pos, strlen($separator));
} else if ('vulnerability' == $object['type']) {
$cveUrl = (is_null(Configure::read('MISP.cveurl'))) ? "http://www.google.com/search?q=" : Configure::read('MISP.cveurl');
$cveUrl = (is_null(Configure::read('MISP.cveurl'))) ? "http://cve.circl.lu/cve/" : Configure::read('MISP.cveurl');
echo $this->Html->link($sigDisplay, $cveUrl . $sigDisplay, array('target' => '_blank', 'class' => $linkClass));
} else if ('weakness' == $object['type']) {
$cweUrl = (is_null(Configure::read('MISP.cweurl'))) ? "http://cve.circl.lu/cwe/" : Configure::read('MISP.cweurl');
echo $this->Html->link($sigDisplay, $cweUrl . explode("-", $sigDisplay)[1], array('target' => '_blank', 'class' => $linkClass));
} else if ('link' == $object['type']) {
echo $this->Html->link($sigDisplay, $sigDisplay, array('class' => $linkClass));
} else if ('cortex' == $object['type']) {

View File

@ -24,8 +24,11 @@
$final_value = h($object['value']);
echo substr_replace(h($object['value']), $separator, $separator_pos, strlen($separator));
} else if ('vulnerability' == $object['type']) {
$cveUrl = (is_null(Configure::read('MISP.cveurl'))) ? "http://www.google.com/search?q=" : Configure::read('MISP.cveurl');
$cveUrl = (is_null(Configure::read('MISP.cveurl'))) ? "http://cve.circl.lu/cve/" : Configure::read('MISP.cveurl');
echo $this->Html->link($sigDisplay, $cveUrl . $sigDisplay, array('target' => '_blank', 'class' => $linkClass));
} else if ('weakness' == $object['type']) {
$cweUrl = (is_null(Configure::read('MISP.cweurl'))) ? "http://cve.circl.lu/cwe/" : Configure::read('MISP.cweurl');
echo $this->Html->link($sigDisplay, $cweUrl . explode("-", $sigDisplay)[1], array('target' => '_blank', 'class' => $linkClass));
} else if ('link' == $object['type']) {
echo $this->Html->link($sigDisplay, $sigDisplay, array('class' => $linkClass));
} else if ('cortex' == $object['type']) {

View File

@ -46,17 +46,37 @@
}
$aStyle = 'background-color:' . h($tag['Tag']['colour']) . ';color:' . $this->TextColour->getTextColour($tag['Tag']['colour']) . ';';
$aClass = 'tag nowrap';
$aText = h($tag['Tag']['name']);
$aText = trim($tag['Tag']['name']);
$aTextModified = null;
if (isset($tag_display_style)) {
if (!isset($tag_display_style) || $tag_display_style == 1) {
// default behaviour, do nothing for now
} else if ($tag_display_style == 2) {
$separator_pos = strpos($aText, ':');
if ($separator_pos !== false) {
$aTextModified = substr($aText, $separator_pos + 1);
$value_pos = strpos($aTextModified, '=');
if ($value_pos !== false) {
$aTextModified = substr($aTextModified, $value_pos + 1);
$aTextModified = trim($aTextModified, '"');
}
$aTextModified = h($aTextModified);
}
} else if ($tag_display_style === 0 || $tag_display_style === '0') {
$aTextModified = '&nbsp;';
}
}
$aText = h($aText);
$span_scope = sprintf(
'<span class="%s" title="%s" aria-label="%s"><i class="fas fa-%s"></i></span>',
'black-white tag',
$tag['local'] ? __('Local tag') : __('Global tag'),
$tag['local'] ? __('Local tag') : __('Global tag'),
$tag['local'] ? 'user' : 'globe-americas'
!empty($tag['local']) ? __('Local tag') : __('Global tag'),
!empty($tag['local']) ? __('Local tag') : __('Global tag'),
!empty($tag['local']) ? 'user' : 'globe-americas'
);
if (!empty($tag['Tag']['id'])) {
$span_tag = sprintf(
'<a href="%s" style="%s" class="%s">%s</a>',
'<a href="%s" style="%s" class="%s" title="%s">%s</a>',
sprintf(
'%s%s%s',
$baseurl,
@ -65,7 +85,8 @@
),
$aStyle,
$aClass,
$aText
$aText,
isset($aTextModified) ? $aTextModified : $aText
);
} else {
$span_tag = sprintf(

View File

@ -184,6 +184,15 @@
'text' => __('Context'),
'onClick' => 'toggleContextFields'
),
array(
'id' => 'show_related_tags',
'title' => __('Show related tags'),
'fa-icon' => 'project-diagram',
'text' => __('Related Tags'),
'active' => $includeRelatedTags,
'onClick' => 'toggleBoolFilter',
'onClickParams' => array($urlHere, 'includeRelatedTags')
),
array(
'id' => 'advanced_filtering',
'title' => __('Advanced filtering tool'),

View File

@ -128,7 +128,7 @@
);
}
if (
isset($local_tag_off) && !$local_tag_off &&
(!isset($local_tag_off) || !$local_tag_off) &&
($isSiteAdmin || ($isAclTagger && Configure::read('MISP.host_org_id') == $me['org_id']))
) {
echo sprintf(

View File

@ -121,7 +121,7 @@
);
}
if (
isset($local_tag_off) && !$local_tag_off &&
(!isset($local_tag_off) || !$local_tag_off) &&
($isSiteAdmin || ($isAclTagger && Configure::read('MISP.host_org_id') == $me['org_id']))
) {
echo sprintf(

View File

@ -294,7 +294,7 @@
echo $this->element('/genericElements/SideMenu/side_menu_divider');
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'viewProposals',
'url' => '/shadow_attributes/index',
'url' => '/shadow_attributes/index/all:0',
'text' => __('View Proposals')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(

View File

@ -36,7 +36,7 @@
),
array(
'text' => __('View Proposals'),
'url' => '/shadow_attributes/index'
'url' => '/shadow_attributes/index/all:0'
),
array(
'text' => __('Events with proposals'),
@ -371,8 +371,9 @@
'type' => 'root',
'url' => '/users/dashboard',
'html' => sprintf(
'<span class="white" title="%s">%s&nbsp;&nbsp;&nbsp;%s</span>',
'<span class="white" title="%s">%s%s&nbsp;&nbsp;&nbsp;%s</span>',
h($me['email']),
$this->UserName->prepend($me['email']),
h($loggedInUserName),
sprintf(
'<i class="fa fa-envelope %s"></i>',

View File

@ -11,7 +11,7 @@
<?php
if (!empty($file['expected'])):
?>
<b><?php echo __('Files set for each relevant setting');?>:</b>:<br />
<b><?php echo __('Files set for each relevant setting');?>:</b><br />
<ul>
<?php foreach ($file['expected'] as $expectedKey => $expectedValue):
$colour = 'red';

View File

@ -9,7 +9,7 @@
);
if ($setting['type'] == 'boolean') $setting['value'] = ($setting['value'] === true ? 'true' : 'false');
if (isset($setting['options'])) {
$setting['value'] = $setting['options'][$setting['value']];
$setting['value'] = empty($setting['options'][$setting['value']]) ? null : $setting['options'][$setting['value']];
}
if (!empty($setting['redacted'])) {
$setting['value'] = '*****';
@ -68,7 +68,7 @@
'class' => 'live_filter_target'
),
'error' => array(
'html' => isset($setting['error']) ? h($setting['errorMessage']) : ''
'html' => isset($setting['errorMessage']) ? h($setting['errorMessage']) : ''
)
);
$columns = '';

View File

@ -174,6 +174,7 @@ foreach($tabs as $tabName => $column):
$td .= ' data-target-id="'.h($target_id).'"';
}
$td .= ' title="' . h($externalId) . (strlen($shortDescription) > 0 ? ': &#10;' . h($shortDescription) : '') . '"';
$td .= ' tabindex="0" aria-label="' . h($externalId) . '"';
$td .= '>' . h($name);
} else { // empty cell

View File

@ -15,10 +15,17 @@
if (isset($configTypes[$config['type']]['field'])) {
$settings['type'] = $configTypes[$config['type']]['field'];
}
if ($settings['type'] == 'select') {
if (isset($config['options'])) {
$settings['options'] = $config['options'];
}
switch($settings['type']) {
case 'select':
if (isset($config['options'])) {
$settings['options'] = $config['options'];
}
break;
case 'checkbox':
if (isset($config['checked'])) {
$settings['checked'] = $config['checked'];
}
break;
}
?>
<span class="bold">

View File

@ -109,6 +109,17 @@
<span class="bold"><?php echo __('Name: ');?></span><span class="ObjectName"><?php echo h($object['name']); ?></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 $o; ?>_collapsible"></span><br />
<div id="Object_<?php echo $o; ?>_collapsible" class="collapse">
<?php
if (!empty($object['description'])) {
echo '<span class="bold">Description: </span><span class="ObjectDescription">' . h($object['description']) . '</span><br/>';
}
if (!empty($object['template_uuid'])) {
echo '<span class="bold">Template UUID: </span><span class="TemplateUUID">' . h($object['template_uuid']) . '</span><br/>';
}
if (!empty($object['template_version'])) {
echo '<span class="bold">Template version: </span><span class="TemplateVersion">' . h($object['template_version']) . '</span><br/>';
}
?>
<span class="bold"><?php echo __('UUID: ');?></span><span class="ObjectUUID"><?php echo h($object['uuid']); ?></span><br />
<span class="bold"><?php echo __('Meta Category: ');?></span><span class="ObjectMetaCategory"><?php echo h($object['meta-category']); ?></span>
</div>
@ -156,7 +167,9 @@
}
?>
</td>
<td class="ObjectComment shortish"><?php echo (!empty($object['comment']) ? h($object['comment']) : ''); ?></td>
<td class="short">
<input type="text" class="ObjectComment" style="padding:0px;height:20px;margin-bottom:0px;" placeholder="<?php echo h($importComment); ?>" <?php if (!empty($object['comment'])) echo 'value="' . h($object['comment']) . '"';?>/>
</td>
<td style="width:60px;text-align:center;">
<select class="ObjectDistribution" style="padding:0px;height:20px;margin-bottom:0px;">
<?php
@ -189,9 +202,16 @@
<span class="AttributeType"><?php echo h($attribute['type']); ?></span>
</td>
<td class="AttributeValue limitedWidth"><?php echo h($attribute['value']); ?></td>
<?php if (in_array($attribute['type'], $typesWithData) && !empty($attribute['data'])) {?>
<input class='AttributeData' type='hidden' value="<?php echo h($attribute['data']); ?>"/>
<?php } ?>
<?php
if (in_array($attribute['type'], $typesWithData)) {
if (!empty($attribute['data'])) {
echo "<input class='AttributeData' type='hidden' value='" . h($attribute['data']) . "'/>";
}
if (!empty($attribute['encrypt'])) {
echo "<input class='AttributeEncrypt' type='hidden' value='" . h($attribute['encrypt']) . "'/>";
}
}
?>
<td class="AttributeUuid short"><?php echo h($attribute['uuid']); ?></td>
<td style="max-width:150px;width:10px;">
<?php if (!empty($attribute['Tag'])) { ?>
@ -288,9 +308,16 @@
}
?>
<td class="AttributeValue limitedWidth"><?php echo h($attribute['value']); ?></td>
<?php if (in_array($attribute['type'], $typesWithData) && !empty($attribute['data'])) {?>
<input class='AttributeData' type='hidden' value="<?php echo $attribute['data']; ?>"/>
<?php } ?>
<?php
if (in_array($attribute['type'], $typesWithData)) {
if (!empty($attribute['data'])) {
echo "<input class='AttributeData' type='hidden' value='" . h($attribute['data']) . "'/>";
}
if (!empty($attribute['encrypt'])) {
echo "<input class='AttributeEncrypt' type='hidden' value='" . h($attribute['encrypt']) . "'/>";
}
}
?>
<td class="AttributeUuid short"><?php echo h($attribute['uuid']); ?></td>
<td style="max-width:150px;width:10px;">
<?php if (!empty($attribute['Tag'])) { ?>

View File

@ -0,0 +1,18 @@
<?php
App::uses('AppHelper', 'View/Helper');
// prepend user names on the header with some text based on the given rules
class UserNameHelper extends AppHelper {
public function prepend($email) {
$lower_email = strtolower($email);
if (
(strpos($lower_email, 'saad') !== false && strpos($lower_email, 'thehive-project')) ||
strpos($lower_email, 'saad.kadhi') !== false
) {
return '<i class="fas fa-frown white"></i>&nbsp;';
}
return '';
}
}
?>

View File

@ -43,7 +43,7 @@
)
)
);
echo $this->Form->create('Server');
echo $this->Form->create('Server', array('novalidate' => true));
?>
<fieldset>
<?php

View File

@ -155,7 +155,7 @@
servers.push({
id: '<?php echo h($s['server_id']);?>',
name: 'Local instance',
url: '<?php echo h(Configure::read('MISP.baseurl'));?>',
url: '<?php echo empty(Configure::read('MISP.external_baseurl')) ? Configure::read('MISP.baseurl') : Configure::read('MISP.external_baseurl');?>',
all_orgs: '<?php echo h($s['all_orgs']); ?>',
removable:0,
});

View File

@ -85,7 +85,7 @@
?>
<div class="clear"></div>
<?php
echo $this->Form->input('disabled', array('label' => __('Disable this user account')));
echo $this->Form->input('disabled', array('type' => 'checkbox', 'label' => __('Disable this user account')));
echo $this->Form->input('notify', array(
'label' => __('Send credentials automatically'),
'type' => 'checkbox',

View File

@ -66,7 +66,7 @@
<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')));
echo $this->Form->input('termsaccepted', array('type' => 'checkbox', 'label' => __('Terms accepted')));
echo $this->Form->input('change_pw', array('type' => 'checkbox', 'label' => __('Change Password')));
echo $this->Form->input('autoalert', array('label' => __('Receive alerts when events are published'), 'type' => 'checkbox'));
echo $this->Form->input('contactalert', array('label' => __('Receive alerts from "contact reporter" requests'), 'type' => 'checkbox'));
@ -75,7 +75,7 @@
?>
<div class="clear"></div>
<?php
echo $this->Form->input('disabled', array('label' => __('Disable this user account')));
echo $this->Form->input('disabled', array('type' => 'checkbox', 'label' => __('Disable this user account')));
?>
</fieldset>

View File

@ -13,10 +13,10 @@
array('key' => __('Type'), 'value' => $data['type']),
array('key' => __('Accepted attribute types'), 'value' => $text),
array(
'key' => __('Accepted attribute types'),
'key' => __('Enabled'),
'boolean' => $data['enabled'],
'html' => sprintf(
'(<a href="%s/warninglists/enableWarninglist/%s%s" title="%s">%s</a>)',
' (<a href="%s/warninglists/enableWarninglist/%s%s" title="%s">%s</a>)',
$baseurl,
h($warninglist['Warninglist']['id']),
$data['enabled'] ? '' : '/1',

@ -1 +1 @@
Subproject commit 483f048f7fac1045e54a8d7bfc85825a2ff9d58d
Subproject commit d48d2ccd3ee0da65fa52977b34a947ec97d49b3f

@ -1 +1 @@
Subproject commit 56506646658688ee32227fd3ef086c9373f59809
Subproject commit b92243a8db2b21b86e8e77a93dcfc716efcd2573

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
# mappings
status_mapping = {'0' : 'New', '1' : 'Open', '2' : 'Closed'}
threat_level_mapping = {'1' : 'High', '2' : 'Medium', '3' : 'Low', '4' : 'Undefined'}
TLP_order = {'RED' : 4, 'AMBER' : 3, 'GREEN' : 2, 'WHITE' : 1}
confidence_mapping = {False : 'None', True : 'High'}
not_implemented_attributes = ('yara', 'snort', 'pattern-in-traffic', 'pattern-in-memory')
non_indicator_attributes = ('text', 'comment', 'other', 'link', 'target-user', 'target-email', 'target-machine',
'target-org', 'target-location', 'target-external', 'vulnerability')
hash_type_attributes = {"single": ("md5", "sha1", "sha224", "sha256", "sha384", "sha512", "sha512/224", "sha512/256",
"ssdeep", "imphash", "authentihash", "pehash", "tlsh", "cdhash", "x509-fingerprint-sha1"),
"composite": ("filename|md5", "filename|sha1", "filename|sha224", "filename|sha256",
"filename|sha384", "filename|sha512", "filename|sha512/224", "filename|sha512/256",
"filename|authentihash", "filename|ssdeep", "filename|tlsh", "filename|imphash",
"filename|pehash")}
# mapping for the attributes that can go through the simpleobservable script
misp_cybox_name = {"domain" : "DomainName", "hostname" : "Hostname", "url" : "URI", "AS" : "AutonomousSystem", "mutex" : "Mutex",
"named pipe" : "Pipe", "link" : "URI", "network-connection": "NetworkConnection", "windows-service-name": "WinService"}
cybox_name_attribute = {"DomainName" : "value", "Hostname" : "hostname_value", "URI" : "value", "AutonomousSystem" : "number",
"Pipe" : "name", "Mutex" : "name", "WinService": "name"}
misp_indicator_type = {"AS" : "", "mutex" : "Host Characteristics", "named pipe" : "Host Characteristics",
"email-attachment": "Malicious E-mail", "url" : "URL Watchlist"}
misp_indicator_type.update(dict.fromkeys(list(hash_type_attributes["single"]) + list(hash_type_attributes["composite"]) + ["filename"] + ["attachment"], "File Hash Watchlist"))
misp_indicator_type.update(dict.fromkeys(["email-src", "email-dst", "email-subject", "email-reply-to", "email-attachment"], "Malicious E-mail"))
misp_indicator_type.update(dict.fromkeys(["ip-src", "ip-dst", "ip-src|port", "ip-dst|port"], "IP Watchlist"))
misp_indicator_type.update(dict.fromkeys(["domain", "domain|ip", "hostname"], "Domain Watchlist"))
misp_indicator_type.update(dict.fromkeys(["regkey", "regkey|value"], "Host Characteristics"))
cybox_validation = {"AutonomousSystem": "isInt"}
galaxy_types_mapping = dict.fromkeys(['mitre-attack-pattern', 'mitre-enterprise-attack-attack-pattern',
'mitre-mobile-attack-attack-pattern', 'mitre-pre-attack-attack-pattern'],
'parse_attack_pattern_galaxy')
galaxy_types_mapping.update(dict.fromkeys(['mitre-course-of-action',
'mitre-entreprise-attack-course-of-action',
'mitre-mobile-attack-course-of-action'],
'parse_course_of_action_galaxy'))
galaxy_types_mapping.update(dict.fromkeys(['android', 'banker', 'stealer', 'backdoor', 'ransomware', 'mitre-malware',
'mitre-enterprise-attack-malware', 'mitre-mobile-attack-malware'],
'parse_malware_galaxy'))
galaxy_types_mapping.update(dict.fromkeys(['threat-actor', 'microsoft-activity-group'],
'parse_threat_actor_galaxy'))
galaxy_types_mapping.update(dict.fromkeys(['botnet', 'rat', 'exploit-kit', 'tds', 'tool', 'mitre-tool',
'mitre-enterprise-attack-tool', 'mitre-mobile-attack-tool'],
'parse_tool_galaxy'))
# mapping Windows Registry Hives and their abbreviations
# see https://cybox.mitre.org/language/version2.1/xsddocs/objects/Win_Registry_Key_Object_xsd.html#RegistryHiveEnum
# the dict keys must be UPPER CASE and end with \\
misp_reghive = {
"HKEY_CLASSES_ROOT\\" : "HKEY_CLASSES_ROOT",
"HKCR\\" : "HKEY_CLASSES_ROOT",
"HKEY_CURRENT_CONFIG\\" : "HKEY_CURRENT_CONFIG",
"HKCC\\" : "HKEY_CURRENT_CONFIG",
"HKEY_CURRENT_USER\\" : "HKEY_CURRENT_USER",
"HKCU\\" : "HKEY_CURRENT_USER",
"HKEY_LOCAL_MACHINE\\" : "HKEY_LOCAL_MACHINE",
"HKLM\\" : "HKEY_LOCAL_MACHINE",
"HKEY_USERS\\" : "HKEY_USERS",
"HKU\\" : "HKEY_USERS",
"HKEY_CURRENT_USER_LOCAL_SETTINGS\\" : "HKEY_CURRENT_USER_LOCAL_SETTINGS",
"HKCULS\\" : "HKEY_CURRENT_USER_LOCAL_SETTINGS",
"HKEY_PERFORMANCE_DATA\\" : "HKEY_PERFORMANCE_DATA",
"HKPD\\" : "HKEY_PERFORMANCE_DATA",
"HKEY_PERFORMANCE_NLSTEXT\\" : "HKEY_PERFORMANCE_NLSTEXT",
"HKPN\\" : "HKEY_PERFORMANCE_NLSTEXT",
"HKEY_PERFORMANCE_TEXT\\" : "HKEY_PERFORMANCE_TEXT",
"HKPT\\" : "HKEY_PERFORMANCE_TEXT",
}
attack_pattern_object_mapping = {'id': 'capec_id', 'name': 'title', 'summary': 'description'}
course_of_action_object_keys = ('type', 'description', 'objective', 'stage', 'cost', 'impact', 'efficacy')
email_object_mapping = {'from': 'from_', 'reply-to': 'reply_to', 'subject': 'subject',
'x-mailer': 'x_mailer', 'mime-boundary': 'boundary', 'user-agent': 'user_agent'}
file_object_mapping = {'path': 'full_path', 'size-in-bytes': 'size_in_bytes', 'entropy': 'peak_entropy'}
process_object_keys = ('creation-time', 'start-time', 'name', 'pid', 'parent-pid')
regkey_object_mapping = {'name': 'name', 'data': 'data', 'data-type': 'datatype'}
user_account_id_mapping = {'unix': 'user_id', 'windows-domain': 'security_id', 'windows-local': 'security_id'}
user_account_object_mapping = {'username': 'username', 'display-name': 'full_name',
'disabled': 'disabled', 'created': 'creation_date',
'last_login': 'last_login', 'home_dir': 'home_directory',
'shell': 'script_path'}
vulnerability_object_mapping = {'id': 'cve_id', 'summary': 'description', 'published': 'published_datetime'}
weakness_object_mapping = {'id': 'cwe_id', 'description': 'description'}
whois_object_mapping = {'creation-date': 'creation_date', 'modification-date': 'updated_date',
'expiration-date': 'expiration_date'}
whois_registrant_mapping = {'registrant-name': 'name', 'registrant-phone': 'phone_number',
'registrant-email': 'email_address', 'registrant-org': 'organization'}
x509_creation_mapping = {'version': 'contents', 'serial-number': 'contents', 'issuer': 'contents',
'subject': 'contents', 'validity-not-before': 'validity',
'validity-not-after': 'validity', 'pubkey-info-exponent': 'rsa_pubkey',
'pubkey-info-modulus': 'rsa_pubkey', 'raw-base64': 'raw_certificate',
'pem': 'raw_certificate', 'x509-fingerprint-md5': 'signature',
'x509-fingerprint-sha1': 'signature', 'x509-fingerprint-sha256': 'signature',
'pubkey-info-algorithm': 'subject_pubkey'}
x509_object_keys = ('version', 'serial-number', 'issuer', 'subject')

View File

@ -40,11 +40,15 @@ def stix_framing(*args):
"http://cybox.mitre.org/objects#X509CertificateObject-2" : 'X509CertificateObj',
"http://cybox.mitre.org/objects#WhoisObject-2" : 'WhoisObj',
"http://cybox.mitre.org/objects#WinExecutableFileObject-2" : 'WinExecutableFileObj',
"http://cybox.mitre.org/objects#UnixUserAccountObject-2": "UnixUserAccountObj",
"http://cybox.mitre.org/objects#UserAccountObject-2": "UserAccountObj",
"http://cybox.mitre.org/objects#WinUserAccountObject-2": "WinUserAccountObj",
"http://data-marking.mitre.org/Marking-1" : 'marking',
"http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1" : 'tlpMarking',
"http://stix.mitre.org/ExploitTarget-1" : 'et',
"http://stix.mitre.org/Incident-1" : 'incident',
"http://stix.mitre.org/Indicator-2" : 'indicator',
"http://stix.mitre.org/CourseOfAction-1": 'coa',
"http://stix.mitre.org/TTP-1" : 'ttp',
"http://stix.mitre.org/ThreatActor-1" : 'ta',
"http://stix.mitre.org/common-1" : 'stixCommon',
@ -84,11 +88,15 @@ def stix_framing(*args):
'http://cybox.mitre.org/objects#X509CertificateObject-2': 'http://cybox.mitre.org/XMLSchema/objects/X509_Certificate/2.1/X509_Certificate_Object.xsd',
'http://cybox.mitre.org/objects#WhoisObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Whois/2.1/Whois_Object.xsd',
'http://cybox.mitre.org/objects#WinExecutableFileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Executable_File/2.1/Win_Executable_File_Object.xsd',
'http://cybox.mitre.org/objects#UnixUserAccountObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Unix_User_Account/2.1/Unix_User_Account_Object.xsd',
'http://cybox.mitre.org/objects#UserAccountObject-2': 'http://cybox.mitre.org/XMLSchema/objects/User_Account/2.1/User_Account_Object.xsd',
'http://cybox.mitre.org/objects#WinUserAccountObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_User_Account/2.1/Win_User_Account_Object.xsd',
'http://data-marking.mitre.org/Marking-1': 'http://stix.mitre.org/XMLSchema/data_marking/1.1.1/data_marking.xsd',
'http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1': 'http://stix.mitre.org/XMLSchema/extensions/marking/tlp/1.1.1/tlp_marking.xsd',
'http://stix.mitre.org/ExploitTarget-1': 'http://stix.mitre.org/XMLSchema/exploit_target/1.1.1/exploit_target.xsd',
'http://stix.mitre.org/Incident-1': 'http://stix.mitre.org/XMLSchema/incident/1.1.1/incident.xsd',
'http://stix.mitre.org/Indicator-2': 'http://stix.mitre.org/XMLSchema/indicator/2.1.1/indicator.xsd',
'http://stix.mitre.org/CourseOfAction-1': 'http://stix.mitre.org/XMLSchema/course_of_action/1.1.1/course_of_action.xsd',
'http://stix.mitre.org/TTP-1': 'http://stix.mitre.org/XMLSchema/ttp/1.1.1/ttp.xsd',
'http://stix.mitre.org/ThreatActor-1': 'http://stix.mitre.org/XMLSchema/threat_actor/1.1.1/threat_actor.xsd',
'http://stix.mitre.org/common-1': 'http://stix.mitre.org/XMLSchema/common/1.1.1/stix_common.xsd',

View File

@ -397,6 +397,20 @@ class StixBuilder():
attack_pattern = AttackPattern(**a_p_args)
self.append_object(attack_pattern, a_p_id)
def add_attack_pattern_object(self, misp_object, to_ids):
a_p_id = 'attack-pattern--{}'.format(misp_object['uuid'])
attributes_dict = {attribute['object_relation']: attribute['value'] for attribute in misp_object['Attribute']}
a_p_args = {'id': a_p_id, 'type': 'attack-pattern', 'created_by_ref': self.identity_id}
a_p_args['labels'] = self.create_object_labels(misp_object['name'], misp_object['meta-category'], to_ids)
for relation, key in attackPatternObjectMapping.items():
if relation in attributes_dict:
a_p_args[key] = attributes_dict[relation]
if 'id' in attributes_dict:
capec_id = "CAPEC-{}".format(attributes_dict['id'])
a_p_args['external_references'] = [{'source_name': 'capec', 'external_id': capec_id}]
attack_pattern = AttackPattern(**a_p_args)
self.append_object(attack_pattern, a_p_id)
def add_course_of_action(self, misp_object):
coa_args, coa_id = self.generate_galaxy_args(misp_object, False, False, 'course-of-action')
self.add_coa_stix_object(coa_args, coa_id)

View File

@ -279,6 +279,7 @@ network_traffic_dst_ref = "dst_ref.type = '{0}' AND network-traffic:dst_ref.valu
objectsMapping = {'asn': {'to_call': 'handle_usual_object_name',
'observable': {'type': 'autonomous-system'},
'pattern': "autonomous-system:{0} = '{1}' AND "},
'attack-pattern': {'to_call': 'add_attack_pattern_object'},
'course-of-action': {'to_call': 'add_course_of_action_from_object'},
'credential': {'to_call': 'handle_usual_object_name',
'observable': {'type': 'user-account'},
@ -316,6 +317,8 @@ objectsMapping = {'asn': {'to_call': 'handle_usual_object_name',
asnObjectMapping = {'asn': 'number', 'description': 'name', 'subnet-announced': 'value'}
attackPatternObjectMapping = {'name': 'name', 'summary': 'description'}
credentialObjectMapping = {'password': 'credential', 'username': 'user_id'}
domainIpObjectMapping = {'ip-dst': 'resolves_to_refs[*].value', 'domain': 'value'}

View File

@ -41,7 +41,9 @@ from pymisp.mispevent import MISPEvent, MISPObject, MISPAttribute
cybox_to_misp_object = {"Account": "credential", "AutonomousSystem": "asn",
"EmailMessage": "email", "NetworkConnection": "network-connection",
"NetworkSocket": "network-socket", "Process": "process",
"x509Certificate": "x509", "Whois": "whois"}
"UnixUserAccount": "user-account", "UserAccount": "user-account",
"WindowsUserAccount": "user-account", "x509Certificate": "x509",
"Whois": "whois"}
threat_level_mapping = {'High': '1', 'Medium': '2', 'Low': '3', 'Undefined': '4'}
@ -110,12 +112,15 @@ class StixParser():
'ProcessObjectType': self.handle_process,
'SocketAddressObjectType': self.handle_socket_address,
'SystemObjectType': self.handle_system,
'UnixUserAccountObjectType': self.handle_unix_user,
'URIObjectType': self.handle_domain_or_url,
'UserAccountObjectType': self.handle_user,
"WhoisObjectType": self.handle_whois,
"WindowsFileObjectType": self.handle_file,
'WindowsRegistryKeyObjectType': self.handle_regkey,
"WindowsExecutableFileObjectType": self.handle_pe,
"WindowsServiceObjectType": self.handle_windows_service,
'WindowsUserAccountObjectType': self.handle_windows_user,
"X509CertificateObjectType": self.handle_x509
}
@ -490,6 +495,21 @@ class StixParser():
if properties.network_interface_list:
return "mac-address", str(properties.network_interface_list[0].mac), ""
# Parse a user account object
def handle_user(self, properties):
attributes = self.fill_user_account_object(properties)
return 'user-account', self.return_attributes, ''
# Parse a UNIX user account object
def handle_unix_user(self, properties):
attributes = []
if properties.user_id:
attributes.append(['text', properties.user_id.value, 'user-id'])
if properties.group_id:
attributes.append(['text', properties.group_id.value, 'group-id'])
attributes.extend(self.fill_user_account_object(properties))
return 'user-account', self.return_attributes(attributes), ''
# Parse a whois object:
# Return type & attributes of a whois object if we have the required fields
# Otherwise create attributes and return type & value of the last attribute to avoid crashing the parent function
@ -534,6 +554,12 @@ class StixParser():
if properties.name:
return "windows-service-name", properties.name.value, ""
# Parse a windows user account object
def handle_windows_user(self, properties):
attributes = ['text', properties.security_id.value, 'user-id'] if properties.security_id else []
attributes.extend(self.fill_user_account_object(properties))
return 'user-account', self.return_attributes(attributes), ''
def handle_x509(self, properties):
attributes = self.handle_x509_certificate(properties.certificate) if properties.certificate else []
if properties.raw_certificate:
@ -740,6 +766,15 @@ class StixParser():
except Exception:
return str(uuid.uuid4())
@staticmethod
def fill_user_account_object(properties):
attributes = []
for feature, mapping in stix2misp_mapping._user_account_object_mapping.items():
if getattr(properties, feature):
attribute_type, relation = mapping
attributes.append([attribute_type, getattr(properties, feature).value, relation])
return attributes
# Return the attributes that will be added in a MISP object as a list of dictionaries
@staticmethod
def return_attributes(attributes):
@ -838,7 +873,7 @@ class StixFromMISPParser(StixParser):
def parse_misp_attribute_observable(self, observable):
if observable.item:
misp_attribute = {'to_ids': False, 'category': str(observable.relationship),
'uuid': self.fetch_uuid(observable.item.object_.id_)}
'uuid': self.fetch_uuid(observable.item.id_)}
self.parse_misp_attribute(observable.item, misp_attribute)
def parse_misp_attribute(self, observable, misp_attribute, to_ids=False):

View File

@ -49,11 +49,14 @@ _regkey_value_mapping = {'data': ('text', 'data'), 'datatype': ('text', 'data-ty
_socket_mapping = {'ip_address': ('ip-{}', 'address_value', 'ip-{}'),
'port': ('port', 'port_value', '{}-port'),
'hostname': ('hostname', 'hostname_value', 'hostname-{}')}
_user_account_object_mapping = {'username': ('text', 'username'), 'full_name': ('text', 'display-name'),
'disabled': ('boolean', 'disabled'), 'creation_date': ('datetime', 'created'),
'last_login': ('datetime', 'last_login'), 'home_directory': ('text', 'home_dir'),
'script_path': ('text', 'shell')}
_whois_registrant_mapping = {'email_address': ('whois-registrant-email', 'address_value.value', 'registrant-email'),
'name': ('whois-registrant-name', 'value', 'registrant-name'),
'phone_number': ('whois-registrant-phone', 'value', 'registrant-phone'),
'organization': ('whois-registrant-org', 'value', 'registrant-org')}
_whois_mapping = {'registrar_info': ('whois-registrar', 'value', 'whois-registrar'),
'ip_address': ('ip-src', 'address_value.value', 'ip-address'),
'domain_name': ('domain', 'value.value', 'domain')}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
xmlns:cybox="http://cybox.mitre.org/cybox-2"
xmlns:cyboxVocabs="http://cybox.mitre.org/default_vocabularies-2"
xmlns:AccountObj="http://cybox.mitre.org/objects#AccountObject-2"
xmlns:ArtifactObj="http://cybox.mitre.org/objects#ArtifactObject-2"
xmlns:ASObj="http://cybox.mitre.org/objects#ASObject-1"
xmlns:AddressObj="http://cybox.mitre.org/objects#AddressObject-2"
xmlns:PortObj="http://cybox.mitre.org/objects#PortObject-2"
@ -23,11 +24,16 @@
xmlns:ProcessObj="http://cybox.mitre.org/objects#ProcessObject-2"
xmlns:X509CertificateObj="http://cybox.mitre.org/objects#X509CertificateObject-2"
xmlns:WhoisObj="http://cybox.mitre.org/objects#WhoisObject-2"
xmlns:WinExecutableFileObj="http://cybox.mitre.org/objects#WinExecutableFileObject-2"
xmlns:UnixUserAccountObj="http://cybox.mitre.org/objects#UnixUserAccountObject-2"
xmlns:UserAccountObj="http://cybox.mitre.org/objects#UserAccountObject-2"
xmlns:WinUserAccountObj="http://cybox.mitre.org/objects#WinUserAccountObject-2"
xmlns:marking="http://data-marking.mitre.org/Marking-1"
xmlns:tlpMarking="http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1"
xmlns:et="http://stix.mitre.org/ExploitTarget-1"
xmlns:incident="http://stix.mitre.org/Incident-1"
xmlns:indicator="http://stix.mitre.org/Indicator-2"
xmlns:coa="http://stix.mitre.org/CourseOfAction-1"
xmlns:ttp="http://stix.mitre.org/TTP-1"
xmlns:ta="http://stix.mitre.org/ThreatActor-1"
xmlns:stixCommon="http://stix.mitre.org/common-1"
@ -39,31 +45,76 @@
xmlns:xal="urn:oasis:names:tc:ciq:xal:3"
xmlns:xnl="urn:oasis:names:tc:ciq:xnl:3"
xmlns:xpil="urn:oasis:names:tc:ciq:xpil:3"
xmlns:ORGNAME="https://www.misp-project.org"
xmlns:ORGNAME="http://127.0.0.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
id="ORGNAME:Package-6911d6ff-2f60-4039-937f-1c3561f5c11f" version="1.1.1" timestamp="2018-06-19T14:31:41.251914">
id="ORGNAME:Package-77991f8f-2ede-4f96-8ea0-17373bf24e8f" version="1.1.1" timestamp="2019-08-12T16:33:31.108846">
<stix:STIX_Header>
<stix:Title>Export from ORGNAME MISP</stix:Title>
<stix:Package_Intent xsi:type="stixVocabs:PackageIntentVocab-1.0">Threat Report</stix:Package_Intent>
</stix:STIX_Header>
<stix:Related_Packages>
<stix:Related_Package>
<stix:Package id="ORGNAME:STIXPackage-5ac4db18-0c58-4436-a3fa-01ef0a00020f" version="1.1.1" timestamp="2018-06-18T08:09:46+00:00">
<stix:Package id="ORGNAME:STIXPackage-5ac4db18-0c58-4436-a3fa-01ef0a00020f" version="1.1.1" timestamp="2019-08-12T12:30:05">
<stix:STIX_Header>
<stix:Title>Export from ORGNAME MISP</stix:Title>
<stix:Package_Intent xsi:type="stixVocabs:PackageIntentVocab-1.0">Threat Report</stix:Package_Intent>
</stix:STIX_Header>
<stix:TTPs>
<stix:TTP id="ORGNAME:ttp-5ac4db18-0150-4435-b016-01ef0a00020f" timestamp="2018-03-28T12:06:12+00:00" xsi:type='ttp:TTPType'>
<ttp:Title>External analysis: CVE-2010-4444 (MISP Attribute #117)</ttp:Title>
<stix:TTP id="ORGNAME:TTP-dcb864dc-775f-11e7-9fbb-1f41b4996683" timestamp="2019-08-12T14:33:31.374834+00:00" xsi:type='ttp:TTPType'>
<ttp:Title>Attack Pattern: mitre-attack-pattern (MISP GalaxyCluster #7454)</ttp:Title>
<ttp:Behavior>
<ttp:Attack_Patterns>
<ttp:Attack_Pattern capec_id="471" id="ORGNAME:AttackPattern-dcb864dc-775f-11e7-9fbb-1f41b4996683">
<ttp:Title>DLL Search Order Hijacking - T1038</ttp:Title>
<ttp:Description>Windows systems use a common method to look for required DLLs to load into a program. (Citation: Microsoft DLL Search) Adversaries may take advantage of the Windows DLL search order and programs that ambiguously specify DLLs to gain privilege escalation and persistence.
Adversaries may perform DLL preloading, also called binary planting attacks, (Citation: OWASP Binary Planting) by placing a malicious DLL with the same name as an ambiguously specified DLL in a location that Windows searches before the legitimate DLL. Often this location is the current working directory of the program. Remote DLL preloading attacks occur when a program sets its current directory to a remote location such as a Web share before loading a DLL. (Citation: Microsoft 2269637) Adversaries may use this behavior to cause the program to load a malicious DLL.
Adversaries may also directly modify the way a program loads DLLs by replacing an existing DLL or modifying a .manifest or .local redirection file, directory, or junction to cause the program to load a different DLL to maintain persistence or privilege escalation. (Citation: Microsoft DLL Redirection) (Citation: Microsoft Manifests) (Citation: Mandiant Search Order)
If a search order-vulnerable program is configured to run at a higher privilege level, then the adversary-controlled DLL that is loaded will also be executed at the higher level. In this case, the technique could be used for privilege escalation from user to administrator or SYSTEM or from administrator to SYSTEM, depending on the program.
Programs that fall victim to path hijacking may appear to behave normally because malicious DLLs may be configured to also load the legitimate DLLs they were meant to replace.</ttp:Description>
</ttp:Attack_Pattern>
</ttp:Attack_Patterns>
</ttp:Behavior>
</stix:TTP>
<stix:TTP id="ORGNAME:TTP-d752161c-78f6-11e7-a0ea-bfa79b407ce4" timestamp="2019-08-12T14:33:31.376016+00:00" xsi:type='ttp:TTPType'>
<ttp:Title>Malware: mitre-malware (MISP GalaxyCluster #6734)</ttp:Title>
<ttp:Behavior>
<ttp:Malware>
<ttp:Malware_Instance id="ORGNAME:MalwareInstance-d752161c-78f6-11e7-a0ea-bfa79b407ce4">
<ttp:Name>Elise</ttp:Name>
<ttp:Name>BKDR_ESILE</ttp:Name>
<ttp:Name>Page</ttp:Name>
<ttp:Title>Elise - S0081</ttp:Title>
<ttp:Description>[Elise](https://attack.mitre.org/software/S0081) is a custom backdoor Trojan that appears to be used exclusively by [Lotus Blossom](https://attack.mitre.org/groups/G0030). It is part of a larger group of
tools referred to as LStudio, ST Group, and APT0LSTU. (Citation: Lotus Blossom Jun 2015)(Citation: Accenture Dragonfish Jan 2018)</ttp:Description>
</ttp:Malware_Instance>
</ttp:Malware>
</ttp:Behavior>
</stix:TTP>
<stix:TTP id="ORGNAME:TTP-d700dc5c-78f6-11e7-a476-5f748c8e4fe0" timestamp="2019-08-12T14:33:31.376255+00:00" xsi:type='ttp:TTPType'>
<ttp:Title>Tool: mitre-tool (MISP GalaxyCluster #7242)</ttp:Title>
<ttp:Resources>
<ttp:Tools>
<ttp:Tool id="ORGNAME:ToolInformation-d700dc5c-78f6-11e7-a476-5f748c8e4fe0">
<cyboxCommon:Name>ifconfig - S0101</cyboxCommon:Name>
<cyboxCommon:Description>[ifconfig](https://attack.mitre.org/software/S0101) is a Unix-based utility used to gather information about and interact with the TCP/IP settings on a system. (Citation: Wikipedia Ifconfig)</cyboxCommon:Description>
</ttp:Tool>
</ttp:Tools>
</ttp:Resources>
</stix:TTP>
<stix:TTP id="ORGNAME:TTP-5ac4db18-0150-4435-b016-01ef0a00020f" timestamp="2019-08-12T11:50:38" xsi:type='ttp:TTPType'>
<ttp:Title>External analysis: CVE-2017-11774 (MISP Attribute #253573)</ttp:Title>
<ttp:Exploit_Targets>
<ttp:Exploit_Target>
<stixCommon:Exploit_Target id="ORGNAME:et-5ac4db18-0150-4435-b016-01ef0a00020f" timestamp="2018-03-28T12:06:12+00:00" xsi:type='et:ExploitTargetType'>
<et:Title>Vulnerability CVE-2010-4444</et:Title>
<stixCommon:Exploit_Target id="ORGNAME:ExploitTarget-5ac4db18-0150-4435-b016-01ef0a00020f" timestamp="2019-08-12T11:50:38" xsi:type='et:ExploitTargetType'>
<et:Title>Vulnerability CVE-2017-11774</et:Title>
<et:Vulnerability>
<et:CVE_ID>CVE-2010-4444</et:CVE_ID>
<et:CVE_ID>CVE-2017-11774</et:CVE_ID>
<et:References/>
</et:Vulnerability>
</stixCommon:Exploit_Target>
@ -72,18 +123,97 @@
<ttp:Handling>
<marking:Marking>
<marking:Controlled_Structure>../../../descendant-or-self::node()</marking:Controlled_Structure>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="AMBER"/>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="WHITE"/>
</marking:Marking>
</ttp:Handling>
</stix:TTP>
<stix:TTP id="ORGNAME:TTP-6c14bf61-c388-4d10-aeb6-9a0881550a39" timestamp="2019-08-12T12:20:12" xsi:type='ttp:TTPType'>
<ttp:Title>vulnerability: vulnerability (MISP Object #16309)</ttp:Title>
<ttp:Exploit_Targets>
<ttp:Exploit_Target>
<stixCommon:Exploit_Target id="ORGNAME:ExploitTarget-6c14bf61-c388-4d10-aeb6-9a0881550a39" timestamp="2019-08-12T12:20:12" xsi:type='et:ExploitTargetType'>
<et:Vulnerability>
<et:Description>Microsoft Outlook 2010 SP2, Outlook 2013 SP1 and RT SP1, and Outlook 2016 allow an attacker to execute arbitrary commands, due to how Microsoft Office handles objects in memory, aka "Microsoft Outlook Security Feature Bypass Vulnerability."</et:Description>
<et:CVE_ID>CVE-2017-11774</et:CVE_ID>
<et:CVSS_Score>
<et:Overall_Score>6.8</et:Overall_Score>
</et:CVSS_Score>
<et:Published_DateTime precision="second">2017-10-13T09:29:00.427000</et:Published_DateTime>
<et:References>
<stixCommon:Reference>http://www.securityfocus.com/bid/101098</stixCommon:Reference>
<stixCommon:Reference>http://www.securitytracker.com/id/1039542</stixCommon:Reference>
<stixCommon:Reference>https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-11774</stixCommon:Reference>
<stixCommon:Reference>https://sensepost.com/blog/2017/outlook-home-page-another-ruler-vector/</stixCommon:Reference>
</et:References>
</et:Vulnerability>
</stixCommon:Exploit_Target>
</ttp:Exploit_Target>
</ttp:Exploit_Targets>
<ttp:Related_TTPs>
<ttp:Related_TTP>
<stixCommon:Relationship>related-to </stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:TTP-5ac4db18-0150-4435-b016-01ef0a00020f" timestamp="2019-08-12T11:50:38" xsi:type='ttp:TTPType'/>
</ttp:Related_TTP>
<ttp:Related_TTP>
<stixCommon:Relationship>weakened-by </stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:TTP-13f1e6e7-87ab-4ced-bb84-d9461b3eb36a" timestamp="2019-08-12T12:20:13" xsi:type='ttp:TTPType'/>
</ttp:Related_TTP>
<ttp:Related_TTP>
<stixCommon:Relationship>targeted-by </stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:TTP-7edfed6f-7b06-46ea-8aba-9c4075df40d1" timestamp="2019-08-12T12:20:14" xsi:type='ttp:TTPType'/>
</ttp:Related_TTP>
</ttp:Related_TTPs>
<ttp:Handling>
<marking:Marking>
<marking:Controlled_Structure>../../../descendant-or-self::node()</marking:Controlled_Structure>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="WHITE"/>
</marking:Marking>
</ttp:Handling>
</stix:TTP>
<stix:TTP id="ORGNAME:TTP-13f1e6e7-87ab-4ced-bb84-d9461b3eb36a" timestamp="2019-08-12T12:20:13" xsi:type='ttp:TTPType'>
<ttp:Title>vulnerability: weakness (MISP Object #16310)</ttp:Title>
<ttp:Exploit_Targets>
<ttp:Exploit_Target>
<stixCommon:Exploit_Target id="ORGNAME:ExploitTarget-13f1e6e7-87ab-4ced-bb84-d9461b3eb36a" timestamp="2019-08-12T12:20:13" xsi:type='et:ExploitTargetType'>
<et:Weakness>
<et:Description>The software performs operations on a memory buffer, but it can read from or write to a memory location that is outside of the intended boundary of the buffer.The software performs operations on a memory buffer, but it can read from or write to a memory location that is outside of the intended boundary of the buffer.</et:Description>
<et:CWE_ID>CWE-119</et:CWE_ID>
</et:Weakness>
</stixCommon:Exploit_Target>
</ttp:Exploit_Target>
</ttp:Exploit_Targets>
<ttp:Handling>
<marking:Marking>
<marking:Controlled_Structure>../../../descendant-or-self::node()</marking:Controlled_Structure>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="WHITE"/>
</marking:Marking>
</ttp:Handling>
</stix:TTP>
<stix:TTP id="ORGNAME:TTP-7edfed6f-7b06-46ea-8aba-9c4075df40d1" timestamp="2019-08-12T12:20:14" xsi:type='ttp:TTPType'>
<ttp:Title>vulnerability: attack-pattern (MISP Object #16321)</ttp:Title>
<ttp:Behavior>
<ttp:Attack_Patterns>
<ttp:Attack_Pattern capec_id="9" id="ORGNAME:AttackPattern-7edfed6f-7b06-46ea-8aba-9c4075df40d1">
<ttp:Title>Buffer Overflow in Local Command-Line Utilities</ttp:Title>
<ttp:Description>This attack targets command-line utilities available in a number of shells. An attacker can leverage a vulnerability found in a command-line utility to escalate privilege to root.</ttp:Description>
</ttp:Attack_Pattern>
</ttp:Attack_Patterns>
</ttp:Behavior>
<ttp:Handling>
<marking:Marking>
<marking:Controlled_Structure>../../../descendant-or-self::node()</marking:Controlled_Structure>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="WHITE"/>
</marking:Marking>
</ttp:Handling>
</stix:TTP>
</stix:TTPs>
<stix:Incidents>
<stix:Incident id="ORGNAME:incident-5ac4db18-0c58-4436-a3fa-01ef0a00020f" timestamp="2018-06-18T08:11:42+00:00" xsi:type='incident:IncidentType'>
<stix:Incident id="ORGNAME:Incident-5ac4db18-0c58-4436-a3fa-01ef0a00020f" timestamp="2019-08-12T12:44:05" xsi:type='incident:IncidentType'>
<incident:Title>STIX observables test event</incident:Title>
<incident:External_ID source="MISP Event">2</incident:External_ID>
<incident:External_ID source="MISP Event">1256</incident:External_ID>
<incident:Time>
<incident:Incident_Discovery precision="second">2018-03-28T00:00:00</incident:Incident_Discovery>
<incident:Incident_Reported precision="second">2018-06-18T08:11:42+00:00</incident:Incident_Reported>
<incident:Incident_Reported precision="second">2019-08-12T12:44:05</incident:Incident_Reported>
</incident:Time>
<incident:Reporter>
<stixCommon:Identity>
@ -142,10 +272,11 @@
<stixCommon:Observable id="ORGNAME:File-5ac4db18-be00-43c7-9527-01ef0a00020f">
<cybox:Object id="ORGNAME:FileObject-5ac4db18-be00-43c7-9527-01ef0a00020f">
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Name condition="Equals">oui</FileObj:File_Name>
<FileObj:Hashes>
<cyboxCommon:Hash>
<cyboxCommon:Type condition="Equals">Other</cyboxCommon:Type>
<cyboxCommon:Simple_Hash_Value condition="Equals">oui|5898fc860300e228dcd54c0b1045b5fa0dcda502</cyboxCommon:Simple_Hash_Value>
<cyboxCommon:Type condition="Equals" xsi:type="cyboxVocabs:HashNameVocab-1.0">SHA1</cyboxCommon:Type>
<cyboxCommon:Simple_Hash_Value condition="Equals">5898fc860300e228dcd54c0b1045b5fa0dcda502</cyboxCommon:Simple_Hash_Value>
</cyboxCommon:Hash>
</FileObj:Hashes>
</cybox:Properties>
@ -271,11 +402,11 @@
<stixCommon:Observable id="ORGNAME:WinRegistryKey-5ac4db18-598c-48d0-89f2-01ef0a00020f">
<cybox:Object id="ORGNAME:WinRegistryKeyObject-5ac4db18-598c-48d0-89f2-01ef0a00020f">
<cybox:Properties xsi:type="WinRegistryKeyObj:WindowsRegistryKeyObjectType">
<WinRegistryKeyObj:Key condition="Equals">Software\Microsoft\Windows\CurrentVersion\Run </WinRegistryKeyObj:Key>
<WinRegistryKeyObj:Key condition="Equals">Software\Microsoft\Windows\CurrentVersion\Run</WinRegistryKeyObj:Key>
<WinRegistryKeyObj:Hive condition="Equals">HKEY_CURRENT_USER</WinRegistryKeyObj:Hive>
<WinRegistryKeyObj:Values>
<WinRegistryKeyObj:Value>
<WinRegistryKeyObj:Data condition="Equals"> %TEMP%\seagate.exe</WinRegistryKeyObj:Data>
<WinRegistryKeyObj:Data condition="Equals">%TEMP%\seagate.exe</WinRegistryKeyObj:Data>
</WinRegistryKeyObj:Value>
</WinRegistryKeyObj:Values>
</cybox:Properties>
@ -297,10 +428,11 @@
<stixCommon:Observable id="ORGNAME:File-5ac4db18-0d5c-4305-a505-01ef0a00020f">
<cybox:Object id="ORGNAME:FileObject-5ac4db18-0d5c-4305-a505-01ef0a00020f">
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Name condition="Equals">oui</FileObj:File_Name>
<FileObj:Hashes>
<cyboxCommon:Hash>
<cyboxCommon:Type condition="Equals">Other</cyboxCommon:Type>
<cyboxCommon:Simple_Hash_Value condition="Equals">oui|12288:LLaIgXMVvf2u/n42bDaxGrAz1N4QiqPW44NGMJw3:LLFgXMVvf2cDaxG0N4RPK</cyboxCommon:Simple_Hash_Value>
<cyboxCommon:Type condition="Equals" xsi:type="cyboxVocabs:HashNameVocab-1.0">SSDEEP</cyboxCommon:Type>
<cyboxCommon:Fuzzy_Hash_Value condition="Equals">12288:LLaIgXMVvf2u/n42bDaxGrAz1N4QiqPW44NGMJw3:LLFgXMVvf2cDaxG0N4RPK</cyboxCommon:Fuzzy_Hash_Value>
</cyboxCommon:Hash>
</FileObj:Hashes>
</cybox:Properties>
@ -494,7 +626,25 @@
</EmailMessageObj:Reply_To>
<EmailMessageObj:X_Mailer condition="Equals">oui_X-mailer</EmailMessageObj:X_Mailer>
</EmailMessageObj:Header>
<EmailMessageObj:Attachments>
<EmailMessageObj:File object_reference="ORGNAME:File-a915f951-774e-4f92-9e88-2832ba5a17dc"/>
<EmailMessageObj:File object_reference="ORGNAME:File-0c1b8f9f-78c0-470d-8633-9281e0373da6"/>
</EmailMessageObj:Attachments>
</cybox:Properties>
<cybox:Related_Objects>
<cybox:Related_Object id="ORGNAME:File-a915f951-774e-4f92-9e88-2832ba5a17dc">
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Name condition="Equals">oui.jpg</FileObj:File_Name>
</cybox:Properties>
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.1">Contains</cybox:Relationship>
</cybox:Related_Object>
<cybox:Related_Object id="ORGNAME:File-0c1b8f9f-78c0-470d-8633-9281e0373da6">
<cybox:Properties xsi:type="FileObj:FileObjectType">
<FileObj:File_Name condition="Equals">oui.png</FileObj:File_Name>
</cybox:Properties>
<cybox:Relationship xsi:type="cyboxVocabs:ObjectRelationshipVocab-1.1">Contains</cybox:Relationship>
</cybox:Related_Object>
</cybox:Related_Objects>
</cybox:Object>
</stixCommon:Observable>
</incident:Related_Observable>
@ -644,15 +794,15 @@
<URIObj:Value>circl.lu</URIObj:Value>
</WhoisObj:Nameserver>
</WhoisObj:Nameservers>
<WhoisObj:Creation_Date precision="day">2017-05-22</WhoisObj:Creation_Date>
<WhoisObj:Creation_Date condition="Equals" precision="day">2017-05-22</WhoisObj:Creation_Date>
<WhoisObj:Registrants>
<WhoisObj:Registrant>
<WhoisObj:Name>Registrant Name</WhoisObj:Name>
<WhoisObj:Name condition="Equals">Registrant Name</WhoisObj:Name>
<WhoisObj:Email_Address xsi:type="AddressObj:AddressObjectType" category="e-mail">
<AddressObj:Address_Value>registrant@email.com</AddressObj:Address_Value>
<AddressObj:Address_Value condition="Equals">registrant@email.com</AddressObj:Address_Value>
</WhoisObj:Email_Address>
<WhoisObj:Phone_Number>0123456789</WhoisObj:Phone_Number>
<WhoisObj:Organization>Registrant Org</WhoisObj:Organization>
<WhoisObj:Phone_Number condition="Equals">0123456789</WhoisObj:Phone_Number>
<WhoisObj:Organization condition="Equals">Registrant Org</WhoisObj:Organization>
</WhoisObj:Registrant>
</WhoisObj:Registrants>
</cybox:Properties>
@ -664,11 +814,6 @@
<stixCommon:Observable id="ORGNAME:Account-5b1f9adb-6b24-4752-83fe-02030a00020f">
<cybox:Object id="ORGNAME:AccountObject-5b1f9adb-6b24-4752-83fe-02030a00020f">
<cybox:Properties xsi:type="AccountObj:AccountObjectType">
<cyboxCommon:Custom_Properties>
<cyboxCommon:Property name="username">misp</cyboxCommon:Property>
<cyboxCommon:Property name="origin">bruteforce-scanning</cyboxCommon:Property>
<cyboxCommon:Property name="notification">victim-notified</cyboxCommon:Property>
</cyboxCommon:Custom_Properties>
<AccountObj:Description>MISP default credentials</AccountObj:Description>
<AccountObj:Authentication>
<AccountObj:Authentication_Type>password</AccountObj:Authentication_Type>
@ -684,9 +829,6 @@
<AccountObj:Description>clear-text</AccountObj:Description>
</AccountObj:Structured_Authentication_Mechanism>
</AccountObj:Authentication>
<AccountObj:Authentication>
<AccountObj:Authentication_Type>password</AccountObj:Authentication_Type>
</AccountObj:Authentication>
</cybox:Properties>
</cybox:Object>
</stixCommon:Observable>
@ -702,13 +844,47 @@
</cybox:Object>
</stixCommon:Observable>
</incident:Related_Observable>
<incident:Related_Observable>
<stixCommon:Relationship>misc</stixCommon:Relationship>
<stixCommon:Observable id="ORGNAME:UnixUserAccount-5d234f9d-7310-4141-99c8-2f45a964451a">
<cybox:Object id="ORGNAME:UnixUserAccountObject-5d234f9d-7310-4141-99c8-2f45a964451a">
<cybox:Properties xsi:type="UnixUserAccountObj:UnixUserAccountObjectType">
<AccountObj:Authentication>
<AccountObj:Authentication_Data condition="Equals">P4ssw0rd1234!</AccountObj:Authentication_Data>
</AccountObj:Authentication>
<UserAccountObj:Full_Name condition="Equals">Misp</UserAccountObj:Full_Name>
<UserAccountObj:Home_Directory condition="Equals">/home/misp</UserAccountObj:Home_Directory>
<UserAccountObj:Username condition="Equals">misp</UserAccountObj:Username>
<UnixUserAccountObj:Group_ID>1002</UnixUserAccountObj:Group_ID>
</cybox:Properties>
</cybox:Object>
</stixCommon:Observable>
</incident:Related_Observable>
</incident:Related_Observables>
<incident:Leveraged_TTPs>
<incident:Leveraged_TTP>
<stixCommon:Relationship>External analysis</stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:ttp-5ac4db18-0150-4435-b016-01ef0a00020f" timestamp="2018-03-28T12:06:12+00:00" xsi:type='ttp:TTPType'/>
<stixCommon:Relationship>Attack Pattern</stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:TTP-dcb864dc-775f-11e7-9fbb-1f41b4996683" timestamp="2019-08-12T14:33:31.374834+00:00" xsi:type='ttp:TTPType'/>
</incident:Leveraged_TTP>
<incident:Leveraged_TTP>
<stixCommon:Relationship>Malware</stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:TTP-d752161c-78f6-11e7-a0ea-bfa79b407ce4" timestamp="2019-08-12T14:33:31.376016+00:00" xsi:type='ttp:TTPType'/>
</incident:Leveraged_TTP>
<incident:Leveraged_TTP>
<stixCommon:Relationship>Tool</stixCommon:Relationship>
<stixCommon:TTP idref="ORGNAME:TTP-d700dc5c-78f6-11e7-a476-5f748c8e4fe0" timestamp="2019-08-12T14:33:31.376255+00:00" xsi:type='ttp:TTPType'/>
</incident:Leveraged_TTP>
</incident:Leveraged_TTPs>
<incident:Attributed_Threat_Actors>
<incident:Threat_Actor>
<stixCommon:Relationship>ThreatActor</stixCommon:Relationship>
<stixCommon:Threat_Actor idref="ORGNAME:ThreatActor-7cdff317-a673-4474-84ec-4f1754947823" timestamp="2019-08-12T14:33:31.376734+00:00" xsi:type='ta:ThreatActorType'>
</stixCommon:Threat_Actor>
</incident:Threat_Actor>
</incident:Attributed_Threat_Actors>
<incident:COA_Taken>
<incident:Course_Of_Action idref="ORGNAME:CourseOfAction-a8825ae8-6dea-11e7-8d57-7728f3cfe086" timestamp="2019-08-12T14:33:31.376532+00:00" xsi:type='coa:CourseOfActionType'/>
</incident:COA_Taken>
<incident:History>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">Event Threat Level: Undefined</incident:Journal_Entry>
@ -728,6 +904,27 @@
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:mitre-tool="ifconfig"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:mitre-attack-pattern="DLL Search Order Hijacking - T1038"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:mitre-intrusion-set="APT16 - G0023"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:mitre-malware="Elise - S0081"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:mitre-tool="ifconfig - S0101"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: tlp:white</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:mitre-course-of-action="Access Token Manipulation Mitigation - T1134"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">MISP Tag: misp-galaxy:threat-actor="APT 16"</incident:Journal_Entry>
</incident:History_Item>
<incident:History_Item>
<incident:Journal_Entry time_precision="second">attribute[Other][comment]: oui, c'est un comment</incident:Journal_Entry>
</incident:History_Item>
@ -746,13 +943,47 @@
<incident:Handling>
<marking:Marking>
<marking:Controlled_Structure>../../../descendant-or-self::node()</marking:Controlled_Structure>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="AMBER"/>
<marking:Marking_Structure xsi:type='tlpMarking:TLPMarkingStructureType' color="WHITE"/>
</marking:Marking>
</incident:Handling>
</stix:Incident>
</stix:Incidents>
<stix:Courses_Of_Action>
<stix:Course_Of_Action id="ORGNAME:CourseOfAction-a8825ae8-6dea-11e7-8d57-7728f3cfe086" timestamp="2019-08-12T14:33:31.376532+00:00" xsi:type='coa:CourseOfActionType'>
<coa:Title>Access Token Manipulation Mitigation - T1134</coa:Title>
<coa:Description>Access tokens are an integral part of the security system within Windows and cannot be turned off. However, an attacker must already have administrator level access on the local system to make full use of this technique; be sure to restrict users and accounts to the least privileges they require to do their job.
Any user can also spoof access tokens if they have legitimate credentials. Follow mitigation guidelines for preventing adversary use of [Valid Accounts](https://attack.mitre.org/techniques/T1078). Limit permissions so that users and user groups cannot create tokens. This setting should be defined for the local system account only. GPO: Computer Configuration &gt; [Policies] &gt; Windows Settings &gt; Security Settings &gt; Local Policies &gt; User Rights Assignment: Create a token object. (Citation: Microsoft Create Token) Also define who can create a process level token to only the local and network service through GPO: Computer Configuration &gt; [Policies] &gt; Windows Settings &gt; Security Settings &gt; Local Policies &gt; User Rights Assignment: Replace a process level token. (Citation: Microsoft Replace Process Token)
Also limit opportunities for adversaries to increase privileges by limiting Privilege Escalation opportunities.</coa:Description>
</stix:Course_Of_Action>
<stix:Course_Of_Action id="ORGNAME:CourseOfAction-5d515039-9a68-468b-9c78-3affa964451a" timestamp="2019-08-12T14:33:31.385929+00:00" xsi:type='coa:CourseOfActionType'>
<coa:Title>Block traffic to PIVY C2 Server (10.10.10.10)</coa:Title>
<coa:Stage xsi:type="stixVocabs:COAStageVocab-1.0">Response</coa:Stage>
<coa:Objective>
<coa:Description>Block communication between the PIVY agents and the C2 Server</coa:Description>
</coa:Objective>
<coa:Impact timestamp="2019-08-12T14:33:31.386021+00:00">
<stixCommon:Value>Low</stixCommon:Value>
</coa:Impact>
<coa:Cost timestamp="2019-08-12T14:33:31.386004+00:00">
<stixCommon:Value>Low</stixCommon:Value>
</coa:Cost>
<coa:Efficacy timestamp="2019-08-12T14:33:31.386036+00:00">
<stixCommon:Value>High</stixCommon:Value>
</coa:Efficacy>
</stix:Course_Of_Action>
</stix:Courses_Of_Action>
<stix:Threat_Actors>
<stix:Threat_Actor id="ORGNAME:ThreatActor-7cdff317-a673-4474-84ec-4f1754947823" timestamp="2019-08-12T14:33:31.376734+00:00" xsi:type='ta:ThreatActorType'>
<ta:Title>APT 16</ta:Title>
<ta:Description>Between November 26, 2015, and December 1, 2015, known and suspected China-based APT groups launched several spear-phishing attacks targeting Japanese and Taiwanese organizations in the high-tech, government services, media and financial services industries. Each campaign delivered a malicious Microsoft Word document exploiting the aforementioned EPS dict copy use-after-free vulnerability, and the local Windows privilege escalation vulnerability CVE-2015-1701. The successful exploitation of both vulnerabilities led to the delivery of either a downloader that we refer to as IRONHALO, or a backdoor that we refer to as ELMER.</ta:Description>
<ta:Intended_Effect timestamp="2019-08-12T14:33:31.377135+00:00">
<stixCommon:Value>Espionage</stixCommon:Value>
</ta:Intended_Effect>
</stix:Threat_Actor>
</stix:Threat_Actors>
</stix:Package>
</stix:Related_Package>
</stix:Related_Packages>
</stix:STIX_Package>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
Subproject commit 86e83ecab5a2942173092f7af8d03f9a8774b4cd
Subproject commit d5f37d3dc23c8acfe080e7ff04ca5979f3e64625

@ -1 +1 @@
Subproject commit f418427ae0997d5e312fab66dc1cec55c4a9d1f6
Subproject commit 554360add3b90335ec2a058680ae48c4602df1e8

View File

@ -2183,7 +2183,10 @@ eventGraph.update_scope();
dataHandler.fetch_data_and_update(true, function() {
var $select = $('#network-typeahead');
dataHandler.get_typeaheadData_search().forEach(function(element) {
$select.append('<option value="' + element + '">' + element + '</option>');
var $option = $('<option></option>');
$option.text(element);
$option.attr('value', $option.text());
$select.append($option);
});
$('#network-typeahead').chosen(chosen_options).on('change', function(evt, params) {
var value = params.selected;

View File

@ -2500,7 +2500,8 @@ function moduleResultsSubmit(id) {
name: $(this).find('.ObjectName').text(),
meta_category: $(this).find('.ObjectMetaCategory').text(),
distribution: $(this).find('.ObjectDistribution').val(),
sharing_group_id: $(this).find('.ObjectSharingGroup').val()
sharing_group_id: $(this).find('.ObjectSharingGroup').val(),
comment: $(this).find('.ObjectComment').val()
}
if (temp['distribution'] != '4') {
temp['sharing_group_id'] = '0';
@ -2508,6 +2509,9 @@ function moduleResultsSubmit(id) {
if ($(this).has('.ObjectID').length) {
temp['id'] = $(this).find('.ObjectID').text();
}
if ($(this).has('.ObjectDescription').length) {
temp['description'] = $(this).find('.ObjectDescription').text();
}
if ($(this).has('.TemplateVersion').length) {
temp['template_version'] = $(this).find('.TemplateVersion').text();
}
@ -2552,8 +2556,13 @@ function moduleResultsSubmit(id) {
});
attribute['Tag'] = tags;
}
if (typesWithData.indexOf(attribute_type) != -1 && $(this).find('.AttributeData').length) {
attribute['data'] = $(this).find('.AttributeData').val();
if (typesWithData.indexOf(attribute_type) != -1) {
if ($(this).find('.AttributeData').length) {
attribute['data'] = $(this).find('.AttributeData').val();
}
if ($(this).find('.AttributeEncrypt').length) {
attribute['encrypt'] = $(this).find('.AttributeEncrypt').val();
}
}
object_attributes.push(attribute);
});
@ -2599,8 +2608,13 @@ function moduleResultsSubmit(id) {
});
temp['Tag'] = tags;
}
if (typesWithData.indexOf(type_value) != -1 && $(this).find('.AttributeData').length) {
temp['data'] = $(this).find('.AttributeData').val();
if (typesWithData.indexOf(type_value) != -1) {
if ($(this).find('.AttributeData').length) {
temp['data'] = $(this).find('.AttributeData').val();
}
if ($(this).find('.AttributeEncrypt').length) {
temp['encrypt'] = $(this).find('.AttributeEncrypt').val();
}
}
attributes.push(temp);
});

View File

@ -95,16 +95,20 @@ for folder in folders:
# - read the JSON in python
with open('../app/Model/Attribute.php', 'r') as f:
attribute_php_file = f.read()
re_match = re.search(r'\$categoryDefinitions\s?=\s?([^;]+);', attribute_php_file)
php_code = re_match.group(1)
category_definitions_binary = subprocess.run(['php', '-r', 'echo json_encode({});'.format(php_code)], stdout=subprocess.PIPE).stdout
re_match = re.search(r'\$this->categoryDefinitions\s?=\s?([^;]+);', attribute_php_file)
php_code_template = '''
function __($s) {{ return $s; }}
echo json_encode({});
'''
php_code = php_code_template.format(re_match.group(1))
category_definitions_binary = subprocess.run(['php', '-r', php_code], stdout=subprocess.PIPE).stdout
category_definitions = json.loads(category_definitions_binary.decode('utf-8'))
categories = list(category_definitions.keys())
categories.sort()
re_match = re.search(r'\$typeDefinitions\s?=\s?([^;]+);', attribute_php_file)
php_code = re_match.group(1)
type_definitions_binary = subprocess.run(['php', '-r', 'echo json_encode({});'.format(php_code)], stdout=subprocess.PIPE).stdout
re_match = re.search(r'\$this->typeDefinitions\s?=\s?([^;]+);', attribute_php_file)
php_code = php_code_template.format(re_match.group(1))
type_definitions_binary = subprocess.run(['php', '-r', php_code], stdout=subprocess.PIPE).stdout
type_definitions = json.loads(type_definitions_binary.decode('utf-8'))
types = list(type_definitions.keys())
types.sort()
@ -186,7 +190,7 @@ print("Updating MISP RFC - ../../misp-rfc/misp-core-format/raw.md")
misp_rfc = []
rfc_list = []
for category in categories:
rfc_list.append('\n**{}**\n'.format(category))
rfc_list.append('\n{}\n'.format(category))
rfc_list.append(': ')
rfc_list.append(', '.join(category_definitions[category]['types']))
rfc_list.append('\n')
@ -230,8 +234,26 @@ with open('../../PyMISP/pymisp/data/describeTypes.json', 'w') as f:
f.write('\n')
# misp-objects
##############
print("Updating misp-objects - ../../misp-objects/schema_objects.json")
with open('../../misp-objects/schema_objects.json') as f:
schema_objects = json.load(f)
schema_objects['defs']['attribute']['properties']['misp-attribute']['enum'] = types
schema_objects['defs']['attribute']['properties']['categories']['items']['enum'] = categories
with open('../../misp-objects/schema_objects.json', 'w') as f:
json.dump(schema_objects, f, sort_keys=True, indent=2)
f.write('\n')
# print(types)
# print(categories)
print("\nPlease initiate the git commit and push for each repository!")
print("- misp-book")
print("- misp-website")
print("- misp-rfc")
print("- PyMISP")
print("- misp-objects")