mirror of https://github.com/MISP/MISP
Merge remote-tracking branch 'origin/2.4' into decaying
commit
6ba45b27f8
|
@ -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
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit 1dce91af8f6768f800e3f9602cd80d5f87dc3732
|
||||
Subproject commit a3140f37739b4a8a63f9b224aaaa2209611a33fe
|
|
@ -1 +1 @@
|
|||
{"major":2, "minor":4, "hotfix":111}
|
||||
{"major":2, "minor":4, "hotfix":112}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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') . '.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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'],
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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'])) {
|
||||
|
|
|
@ -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'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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')
|
||||
));
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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'];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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']);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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']) {
|
||||
|
|
|
@ -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>
|
||||
</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']); ?>
|
||||
</td>
|
||||
|
|
|
@ -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']) {
|
||||
|
|
|
@ -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']) {
|
||||
|
|
|
@ -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 = ' ';
|
||||
}
|
||||
}
|
||||
$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(
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 %s</span>',
|
||||
'<span class="white" title="%s">%s%s %s</span>',
|
||||
h($me['email']),
|
||||
$this->UserName->prepend($me['email']),
|
||||
h($loggedInUserName),
|
||||
sprintf(
|
||||
'<i class="fa fa-envelope %s"></i>',
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 = '';
|
||||
|
|
|
@ -174,6 +174,7 @@ foreach($tabs as $tabName => $column):
|
|||
$td .= ' data-target-id="'.h($target_id).'"';
|
||||
}
|
||||
$td .= ' title="' . h($externalId) . (strlen($shortDescription) > 0 ? ': ' . h($shortDescription) : '') . '"';
|
||||
$td .= ' tabindex="0" aria-label="' . h($externalId) . '"';
|
||||
$td .= '>' . h($name);
|
||||
|
||||
} else { // empty cell
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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'])) { ?>
|
||||
|
|
|
@ -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> ';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -43,7 +43,7 @@
|
|||
)
|
||||
)
|
||||
);
|
||||
echo $this->Form->create('Server');
|
||||
echo $this->Form->create('Server', array('novalidate' => true));
|
||||
?>
|
||||
<fieldset>
|
||||
<?php
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
@ -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')
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
@ -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 > [Policies] > Windows Settings > Security Settings > Local Policies > 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 > [Policies] > Windows Settings > Security Settings > Local Policies > 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
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue