mirror of https://github.com/MISP/MISP
Merge branch '2.4' of github.com:MISP/MISP into 2.4
commit
ad4074c1d6
|
@ -2070,6 +2070,10 @@ installCake_RHEL ()
|
|||
sudo scl enable rh-php72 'yes no|pecl install redis'
|
||||
echo "extension=redis.so" |sudo tee /etc/opt/rh/rh-php72/php.d/99-redis.ini
|
||||
|
||||
sudo ln -s /usr/lib64/libfuzzy.so /usr/lib/libfuzzy.so
|
||||
sudo scl enable rh-php72 'pecl install ssdeep'
|
||||
echo "extension=ssdeep.so" |sudo tee /etc/opt/rh/rh-php72/php.d/99-ssdeep.ini
|
||||
|
||||
# Install gnupg extension
|
||||
sudo yum install gpgme-devel -y
|
||||
sudo scl enable rh-php72 'pecl install gnupg'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; Generated by RHash v1.3.9 on 2020-03-18 at 13:56.48
|
||||
; Generated by RHash v1.3.9 on 2020-03-28 at 11:27.22
|
||||
; Written by Kravchenko Aleksey (Akademgorodok) - http://rhash.sf.net/
|
||||
;
|
||||
; 99980 13:56.48 2020-03-18 INSTALL.sh
|
||||
INSTALL.sh 04A834FCD3BC9DA5282EDE8A3D2C459FBC625E46 FBCA1473FEC26AD5A6C1AE6AE3D9AF11E47E7758F30B160BC047ABE9978F4476 7281B13AA7D6B016152096D35619C2CECC7EC49F8F41CF8A3B8284335D950D35F273FA56FEA63EC5ADB3669038239C61 FA17DF3AA0CBC54D2B48AE14FB296C91C12FC6CF8E3704B8AF1B2CB2CDE9C6FAF591A2E42A38C01C299C62390868E7766EF682A6B3B556BAFC469688E8AED6E7
|
||||
; 129017 11:27.22 2020-03-28 INSTALL.sh
|
||||
INSTALL.sh D13A40A737C9FC7BCB6085F7557EAE47E48AF57A FBD4920A02D7811FF6280306FE1ED0CF6ADDD3707B2E0F9D1FF58F808CC92784 66A1518CCBBAC090C84748D59BE0D45CF9EB4882AF3B65CFA0E0F1CD76CE82D928A5EB16B4927A297C29BBE964B104F9 ED28FA2445A350193E6089E44E1451E34DE3C4A49643B8A8F2690488067AD05E806FA5A169044525F4686D3E5171F6A8EE65415EF5BB3DE6884BA93F9EE7BA05
|
||||
|
|
|
@ -1 +1 @@
|
|||
c85dfcbc3da0b6b6331a9ef057e04d1921205d22 INSTALL.sh
|
||||
d13a40a737c9fc7bcb6085f7557eae47e48af57a INSTALL.sh
|
||||
|
|
|
@ -1 +1 @@
|
|||
4665b8df8c1baecda9bc5ef729033c7b2d64e72b6395e3fc260927cce394b16a INSTALL.sh
|
||||
fbd4920a02d7811ff6280306fe1ed0cf6addd3707b2e0f9d1ff58f808cc92784 INSTALL.sh
|
||||
|
|
|
@ -1 +1 @@
|
|||
6bc8ba92099f339152211bee3603553a8647dcd67ec9b1929cf0c489c70b4db8772d8bb31508782d82343770dac06426 INSTALL.sh
|
||||
66a1518ccbbac090c84748d59be0d45cf9eb4882af3b65cfa0e0f1cd76ce82d928a5eb16b4927a297c29bbe964b104f9 INSTALL.sh
|
||||
|
|
|
@ -1 +1 @@
|
|||
32793e6dcf99b32fc8271a8cdda862e60bbbd256eb24a1f6711770a931ddc552ab4dc50a7d841d5030cea43717275d8ebbc6c7c641dc8f02d11f5ea20eeef35c INSTALL.sh
|
||||
ed28fa2445a350193e6089e44e1451e34de3c4a49643b8a8f2690488067ad05e806fa5a169044525f4686d3e5171f6a8ee65415ef5bb3de6884ba93f9ee7ba05 INSTALL.sh
|
||||
|
|
2
PyMISP
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit 64d7c9a24ad9d3a7ccc1b96fb643c235d2b9e02e
|
||||
Subproject commit 5e46724646c0aa779b827678333a21a5e9eb2034
|
|
@ -1 +1 @@
|
|||
{"major":2, "minor":4, "hotfix":123}
|
||||
{"major":2, "minor":4, "hotfix":124}
|
||||
|
|
|
@ -1411,7 +1411,7 @@ class AttributesController extends AppController
|
|||
$event = $this->Attribute->Event->find('first', array(
|
||||
'conditions' => array('id' => $id),
|
||||
'recursive' => -1,
|
||||
'fields' => array('id', 'orgc_id', 'user_id', 'published', 'timestamp', 'info', 'uuid')
|
||||
'fields' => array('id', 'orgc_id', 'org_id', 'user_id', 'published', 'timestamp', 'info', 'uuid')
|
||||
));
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
if ($event['Event']['orgc_id'] != $this->Auth->user('org_id') || (!$this->userRole['perm_modify_org'] && !($this->userRole['perm_modify'] && $event['user_id'] == $this->Auth->user('id')))) {
|
||||
|
@ -1477,7 +1477,23 @@ class AttributesController extends AppController
|
|||
}
|
||||
|
||||
if ($changeInAttribute) {
|
||||
if ($this->Attribute->saveMany($attributes)) {
|
||||
if ($this->request->data['Attribute']['is_proposal']) { // create ShadowAttributes instead
|
||||
$shadowAttributes = array();
|
||||
foreach ($attributes as $attribute) {
|
||||
$shadowAttribute['ShadowAttribute'] = $attribute['Attribute'];
|
||||
unset($shadowAttribute['ShadowAttribute']['id']);
|
||||
$shadowAttribute['ShadowAttribute']['email'] = $this->Auth->user('email');
|
||||
$shadowAttribute['ShadowAttribute']['org_id'] = $this->Auth->user('org_id');
|
||||
$shadowAttribute['ShadowAttribute']['event_uuid'] = $event['Event']['uuid'];
|
||||
$shadowAttribute['ShadowAttribute']['event_org_id'] = $event['Event']['org_id'];
|
||||
$shadowAttribute['ShadowAttribute']['old_id'] = $attribute['Attribute']['id'];
|
||||
$shadowAttributes[] = $shadowAttribute;
|
||||
}
|
||||
$saveSuccess = $this->Attribute->ShadowAttribute->saveMany($shadowAttributes);
|
||||
} else {
|
||||
$saveSuccess = $this->Attribute->saveMany($attributes);
|
||||
}
|
||||
if ($saveSuccess) {
|
||||
if (!$this->_isRest()) {
|
||||
$this->Attribute->Event->insertLock($this->Auth->user(), $id);
|
||||
}
|
||||
|
@ -1662,6 +1678,31 @@ class AttributesController extends AppController
|
|||
);
|
||||
$exception = false;
|
||||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
if (!empty($filters['uuid'])) {
|
||||
if (!is_array($filters['uuid'])) {
|
||||
$filters['uuid'] = array($filters['uuid']);
|
||||
}
|
||||
$uuid = array();
|
||||
$ids = array();
|
||||
foreach ($filters['uuid'] as $k => $filter) {
|
||||
if ($filter[0] === '!') {
|
||||
$filter = substr($filter, 1);
|
||||
}
|
||||
if (Validation::uuid($filter)) {
|
||||
$uuid[] = $filters['uuid'][$k];
|
||||
} else {
|
||||
$ids[] = $filters['uuid'][$k];
|
||||
}
|
||||
}
|
||||
if (empty($uuid)) {
|
||||
unset($filters['uuid']);
|
||||
} else {
|
||||
$filters['uuid'] = $uuid;
|
||||
}
|
||||
if (!empty($ids)) {
|
||||
$filters['eventid'] = $ids;
|
||||
}
|
||||
}
|
||||
unset($filterData);
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
|
|
|
@ -415,7 +415,11 @@ class EventsController extends AppController
|
|||
$orgUuidArray = $this->Event->Org->find('list', array('fields' => array('Org.uuid')));
|
||||
$orgArray = array_map('strtoupper', $orgArray);
|
||||
// if the first character is '!', search for NOT LIKE the rest of the string (excluding the '!' itself of course)
|
||||
$pieces = explode('|', $v);
|
||||
if (!is_array($v)) {
|
||||
$pieces = explode('|', $v);
|
||||
} else {
|
||||
$pieces = $v;
|
||||
}
|
||||
$test = array();
|
||||
foreach ($pieces as $piece) {
|
||||
if ($piece[0] == '!') {
|
||||
|
|
|
@ -246,7 +246,7 @@ class FeedsController extends AppController
|
|||
$this->Flash->success($message);
|
||||
$this->redirect(array('controller' => 'feeds', 'action' => 'index'));
|
||||
} else {
|
||||
$message = __('Feed could not be added. Invalid field: %s', array_keys($this->Feed->validationErrors)[0]);
|
||||
$message = __('Feed could not be added. Reason: %s', json_encode($this->Feed->validationErrors));
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Feeds', 'add', false, $message, $this->response->type());
|
||||
}
|
||||
|
@ -345,7 +345,7 @@ class FeedsController extends AppController
|
|||
$this->Flash->success($message);
|
||||
$this->redirect(array('controller' => 'feeds', 'action' => 'index'));
|
||||
} else {
|
||||
$message = __('Feed could not be updated. Invalid fields: %s', implode(', ', array_keys($this->Feed->validationErrors)));
|
||||
$message = __('Feed could not be updated. Reason: %s', json_encode($this->Feed->validationErrors));
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Feeds', 'add', false, $message, $this->response->type());
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ class ObjectsController extends AppController
|
|||
$this->set('updateable_attribute', $templateData['updateable_attribute']);
|
||||
$this->set('not_updateable_attribute', $templateData['not_updateable_attribute']);
|
||||
if (isset($this->params['named']['revised_object'])) {
|
||||
$revisedData = $this->MispObject->reviseObject($this->params['named']['revised_object'], $object);
|
||||
$revisedData = $this->MispObject->reviseObject($this->params['named']['revised_object'], $object, $template);
|
||||
$this->set('revised_object', $revisedData['revised_object_both']);
|
||||
$object = $revisedData['object'];
|
||||
}
|
||||
|
|
|
@ -638,13 +638,14 @@ class UsersController extends AppController
|
|||
if (isset($this->request->data['User']['password'])) {
|
||||
$this->request->data['User']['confirm_password'] = $this->request->data['User']['password'];
|
||||
}
|
||||
$default_publish_alert = Configure::check('MISP.default_publish_alert') ? Configure::read('MISP.default_publish_alert') : 0;
|
||||
$defaults = array(
|
||||
'external_auth_required' => 0,
|
||||
'external_auth_key' => '',
|
||||
'server_id' => 0,
|
||||
'gpgkey' => '',
|
||||
'certif_public' => '',
|
||||
'autoalert' => 0,
|
||||
'autoalert' => $default_publish_alert,
|
||||
'contactalert' => 0,
|
||||
'disabled' => 0,
|
||||
'newsread' => 0,
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
<?php
|
||||
|
||||
class CsseCovidMapWidget
|
||||
{
|
||||
public $title = 'CSSE Covid-19 map';
|
||||
public $render = 'WorldMap';
|
||||
public $width = 3;
|
||||
public $height = 4;
|
||||
public $params = array(
|
||||
'event_info' => 'World map based on the countries with infections.',
|
||||
'type' => 'Type of data used for the widget (confirmed, death, recovered).',
|
||||
'logarithmic' => 'Use a log10 scale for the graph (set via 0/1).'
|
||||
);
|
||||
public $description = 'Widget mapping the countries showing confirmed cases of COVID-19.';
|
||||
public $placeholder =
|
||||
'{
|
||||
"event_info": "%CSSE COVID-19 daily report%",
|
||||
"type": "confirmed",
|
||||
"logarithmic": 1
|
||||
}';
|
||||
|
||||
public $countryCodes = array(
|
||||
'Afghanistan' => 'AF',
|
||||
'Albania' => 'AL',
|
||||
'Algeria' => 'DZ',
|
||||
'Angola' => 'AO',
|
||||
'Argentina' => 'AR',
|
||||
'Armenia' => 'AM',
|
||||
'Australia' => 'AU',
|
||||
'Austria' => 'AT',
|
||||
'Azerbaijan' => 'AZ',
|
||||
'Bahamas' => 'BS',
|
||||
'Bangladesh' => 'BD',
|
||||
'Belarus' => 'BY',
|
||||
'Belgium' => 'BE',
|
||||
'Belize' => 'BZ',
|
||||
'Benin' => 'BJ',
|
||||
'Bhutan' => 'BT',
|
||||
'Bolivia' => 'BO',
|
||||
'Bosnia and Herz.' => 'BA',
|
||||
'Botswana' => 'BW',
|
||||
'Brazil' => 'BR',
|
||||
'Brunei' => 'BN',
|
||||
'Bulgaria' => 'BG',
|
||||
'Burkina Faso' => 'BF',
|
||||
'Burundi' => 'BI',
|
||||
'Cambodia' => 'KH',
|
||||
'Cameroon' => 'CM',
|
||||
'Canada' => 'CA',
|
||||
'Central African Rep.' => 'CF',
|
||||
'Chad' => 'TD',
|
||||
'Chile' => 'CL',
|
||||
'China' => 'CN',
|
||||
'Colombia' => 'CO',
|
||||
'Congo' => 'CG',
|
||||
'Costa Rica' => 'CR',
|
||||
'Croatia' => 'HR',
|
||||
'Cuba' => 'CU',
|
||||
'Cyprus' => 'CY',
|
||||
'Czech Rep.' => 'CZ',
|
||||
'Côte d\'Ivoire' => 'CI',
|
||||
'Dem. Rep. Congo' => 'CD',
|
||||
'Dem. Rep. Korea' => 'KP',
|
||||
'Denmark' => 'DK',
|
||||
'Djibouti' => 'DJ',
|
||||
'Dominican Rep.' => 'DO',
|
||||
'Ecuador' => 'EC',
|
||||
'Egypt' => 'EG',
|
||||
'El Salvador' => 'SV',
|
||||
'Eq. Guinea' => 'GQ',
|
||||
'Eritrea' => 'ER',
|
||||
'Estonia' => 'EE',
|
||||
'Ethiopia' => 'ET',
|
||||
'Falkland Is.' => 'FK',
|
||||
'Fiji' => 'FJ',
|
||||
'Finland' => 'FI',
|
||||
'Fr. S. Antarctic Lands' => 'TF',
|
||||
'France' => 'FR',
|
||||
'Gabon' => 'GA',
|
||||
'Gambia' => 'GM',
|
||||
'Georgia' => 'GE',
|
||||
'Germany' => 'DE',
|
||||
'Ghana' => 'GH',
|
||||
'Greece' => 'GR',
|
||||
'Greenland' => 'GL',
|
||||
'Guatemala' => 'GT',
|
||||
'Guinea' => 'GN',
|
||||
'Guinea-Bissau' => 'GW',
|
||||
'Guyana' => 'GY',
|
||||
'Haiti' => 'HT',
|
||||
'Honduras' => 'HN',
|
||||
'Hungary' => 'HU',
|
||||
'Iceland' => 'IS',
|
||||
'India' => 'IN',
|
||||
'Indonesia' => 'ID',
|
||||
'Iran' => 'IR',
|
||||
'Iraq' => 'IQ',
|
||||
'Ireland' => 'IE',
|
||||
'Israel' => 'IL',
|
||||
'Italy' => 'IT',
|
||||
'Jamaica' => 'JM',
|
||||
'Japan' => 'JP',
|
||||
'Jordan' => 'JO',
|
||||
'Kazakhstan' => 'KZ',
|
||||
'Kenya' => 'KE',
|
||||
'Korea' => 'KR',
|
||||
'Kuwait' => 'KW',
|
||||
'Kyrgyzstan' => 'KG',
|
||||
'Lao PDR' => 'LA',
|
||||
'Latvia' => 'LV',
|
||||
'Lebanon' => 'LB',
|
||||
'Lesotho' => 'LS',
|
||||
'Liberia' => 'LR',
|
||||
'Libya' => 'LY',
|
||||
'Lithuania' => 'LT',
|
||||
'Luxembourg' => 'LU',
|
||||
'Macedonia' => 'MK',
|
||||
'Madagascar' => 'MG',
|
||||
'Mainland China' => 'CN',
|
||||
'Malawi' => 'MW',
|
||||
'Malaysia' => 'MY',
|
||||
'Mali' => 'ML',
|
||||
'Mauritania' => 'MR',
|
||||
'Mexico' => 'MX',
|
||||
'Moldova' => 'MD',
|
||||
'Mongolia' => 'MN',
|
||||
'Montenegro' => 'ME',
|
||||
'Morocco' => 'MA',
|
||||
'Mozamb' => 'MZ',
|
||||
'Myanmar' => 'MM',
|
||||
'Namibia' => 'NA',
|
||||
'Nepal' => 'NP',
|
||||
'Netherlands' => 'NL',
|
||||
'New Caledonia' => 'NC',
|
||||
'New Zealand' => 'NZ',
|
||||
'Nicaragua' => 'NI',
|
||||
'Niger' => 'NE',
|
||||
'Nigeria' => 'NG',
|
||||
'Norway' => 'NO',
|
||||
'Oman' => 'OM',
|
||||
'Pakistan' => 'PK',
|
||||
'Palestine' => 'PS',
|
||||
'Panama' => 'PA',
|
||||
'Papua New Guinea' => 'PG',
|
||||
'Paraguay' => 'PY',
|
||||
'Peru' => 'PE',
|
||||
'Philippines' => 'PH',
|
||||
'Poland' => 'PL',
|
||||
'Portugal' => 'PT',
|
||||
'Puerto Rico' => 'PR',
|
||||
'Qatar' => 'QA',
|
||||
'Romania' => 'RO',
|
||||
'Russia' => 'RU',
|
||||
'Rwanda' => 'RW',
|
||||
'S. Sudan' => 'SS',
|
||||
'Saudi Arabia' => 'SA',
|
||||
'Senegal' => 'SN',
|
||||
'Serbia' => 'RS',
|
||||
'Sierra Leone' => 'SL',
|
||||
'Slovakia' => 'SK',
|
||||
'Slovenia' => 'SI',
|
||||
'Solomon Is.' => 'SB',
|
||||
'Somalia' => 'SO',
|
||||
'South Africa' => 'ZA',
|
||||
'Spain' => 'ES',
|
||||
'Sri Lanka' => 'LK',
|
||||
'Sudan' => 'SD',
|
||||
'Suriname' => 'SR',
|
||||
'Swaziland' => 'SZ',
|
||||
'Sweden' => 'SE',
|
||||
'Switzerland' => 'CH',
|
||||
'Syria' => 'SY',
|
||||
'Taiwan' => 'TW',
|
||||
'Tajikistan' => 'TJ',
|
||||
'Tanzania' => 'TZ',
|
||||
'Thailand' => 'TH',
|
||||
'Timor-Leste' => 'TL',
|
||||
'Togo' => 'TG',
|
||||
'Trinidad and Tobago' => 'TT',
|
||||
'Tunisia' => 'TN',
|
||||
'Turkey' => 'TR',
|
||||
'Turkmenistan' => 'TM',
|
||||
'Uganda' => 'UG',
|
||||
'Ukraine' => 'UA',
|
||||
'United Arab Emirates' => 'AE',
|
||||
'United Kingdom' => 'GB',
|
||||
'United States' => 'US',
|
||||
'Uruguay' => 'UY',
|
||||
'Uzbekistan' => 'UZ',
|
||||
'Vanuatu' => 'VU',
|
||||
'Venezuela' => 'VE',
|
||||
'Vietnam' => 'VN',
|
||||
'W. Sahara' => 'EH',
|
||||
'Yemen' => 'YE',
|
||||
'Zambia' => 'ZM',
|
||||
'Zimbabwe' => 'ZW'
|
||||
);
|
||||
public $countryCodesReversed = array();
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
$this->countryCodesReversed = array_flip($this->countryCodes);
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$event_info_condition = empty($options['event_info']) ? '%CSSE COVID-19 daily report%' : $options['event_info'];
|
||||
$params = array(
|
||||
'eventinfo' => $event_info_condition,
|
||||
'order' => 'date desc',
|
||||
'limit' => 1,
|
||||
'page' => 1
|
||||
);
|
||||
$eventIds = $this->Event->filterEventIds($user, $params);
|
||||
$params['eventid'] = $eventIds;
|
||||
$data = array();
|
||||
if (empty($options['type'])) {
|
||||
$options['type'] = 'confirmed';
|
||||
}
|
||||
if (!empty($eventIds)) {
|
||||
$events = $this->Event->fetchEvent($user, $params);
|
||||
$data = $this->__handleEvents($events, $options);
|
||||
arsort($data);
|
||||
}
|
||||
$data = array('data' => $data);
|
||||
if (!empty($options['type']) && $options['type'] === 'mortality') {
|
||||
$data['output_decorator'] = 'percentage';
|
||||
}
|
||||
if (!empty($options['logarithmic'])) {
|
||||
$data['logarithmic'] = array();
|
||||
foreach ($data['data'] as $k => $v) {
|
||||
if ($v == 0) {
|
||||
$value = 0;
|
||||
} else if ($v <= 1) {
|
||||
$value = 0.2;
|
||||
} else {
|
||||
$value = log10($v);
|
||||
}
|
||||
$data['logarithmic'][$k] = $value;
|
||||
}
|
||||
}
|
||||
$data['scope'] = Inflector::humanize($options['type']);
|
||||
$data['colour_scale'] = json_encode(array('#F08080', '#8B0000'), true);
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __handleEvents($events, $options)
|
||||
{
|
||||
$data = array();
|
||||
if (!empty($events)) {
|
||||
foreach ($events as $event) {
|
||||
if (!empty($event['Object'])) {
|
||||
$data = $this->__handleObjects($data, $event['Object'], $options);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __handleObjects($data, $objects, $options)
|
||||
{
|
||||
foreach ($objects as $object) {
|
||||
if ($object['name'] === 'covid19-csse-daily-report') {
|
||||
$temp = $this->__interpretObject($object);
|
||||
$data = $this->__rearrangeResults($data, $temp, $options);
|
||||
}
|
||||
}
|
||||
if ($options['type'] === 'mortality') {
|
||||
foreach ($data as $k => $v) {
|
||||
$data[$k] = round(100 * (empty($v['death']) ? 0 : $v['death']) / $v['confirmed'], 2);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __rearrangeResults($data, $temp, $options)
|
||||
{
|
||||
$country = $temp['country-region'];
|
||||
$type = $options['type'];
|
||||
if (!empty($temp[$type])) {
|
||||
$data[$country] = (empty($data[$country]) ? $temp[$type] : ($data[$country] + $temp[$type]));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __interpretObject($object)
|
||||
{
|
||||
$temp = array();
|
||||
$validFields = array('country-region', 'confirmed', 'death', 'recovered');
|
||||
foreach ($object['Attribute'] as $attribute) {
|
||||
if (in_array($attribute['object_relation'], $validFields)) {
|
||||
if ($attribute['object_relation'] === 'country-region') {
|
||||
if (!empty($this->countryCodes[$attribute['value']])) {
|
||||
$temp[$attribute['object_relation']] = $this->countryCodes[$attribute['value']];
|
||||
} elseif (isset($this->countryCodesReversed[$attribute['value']])) {
|
||||
$temp[$attribute['object_relation']] = $attribute['value'];
|
||||
} else {
|
||||
$temp[$attribute['object_relation']] = 'XX';
|
||||
}
|
||||
} else {
|
||||
$attribute['value'] = intval($attribute['value']);
|
||||
$temp[$attribute['object_relation']] = $attribute['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
|
||||
class CsseCovidTrendsWidget
|
||||
{
|
||||
public $title = 'CSSE Covid-19 trends';
|
||||
public $render = 'MultiLineChart';
|
||||
public $width = 4;
|
||||
public $height = 5;
|
||||
public $params = array(
|
||||
'event_info' => 'Substring included in the info field of relevant CSSE COVID-19 events.',
|
||||
'type' => 'Type of data used for the widget - confirmed (default), death, recovered, mortality.',
|
||||
'insight' => 'Insight type - raw (default), growth, percent.',
|
||||
'countries' => 'List of countries to be included (using the names used by the reports, such as Belgium, US, Germany).',
|
||||
'timeframe' => 'Timeframe for events taken into account in days (going back from now, using the date field, default 10).'
|
||||
);
|
||||
public $description = 'Widget showing line charts for the evolution of the various case types.';
|
||||
public $placeholder =
|
||||
'{
|
||||
"event_info": "%CSSE COVID-19 daily report%",
|
||||
"type": "confirmed",
|
||||
"insight": "growth",
|
||||
"countries": ["Luxembourg", "Germany", "Belgium", "France"],
|
||||
"timeframe": 20
|
||||
}';
|
||||
//public $cacheLifetime = 600;
|
||||
public $autoRefreshDelay = false;
|
||||
|
||||
private $__countries = array();
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
if (!isset($options['insight']) || !isset($this->__insightFunctions[$options['insight']])) {
|
||||
$options['Insight'] = 'calculate_growth_rate';
|
||||
}
|
||||
if (empty($options['timeframe'])) {
|
||||
$options['timeframe'] = 10;
|
||||
}
|
||||
if (empty($options['countries'])) {
|
||||
$options['countries'] = array("Luxembourg", "Germany", "Belgium", "France");
|
||||
}
|
||||
if (empty($options['insight'])) {
|
||||
$options['insight'] = 'raw';
|
||||
}
|
||||
$event_info_condition = empty($options['event_info']) ? '%CSSE COVID-19 daily report%' : $options['event_info'];
|
||||
$params = array(
|
||||
'eventinfo' => $event_info_condition,
|
||||
'order' => 'date desc',
|
||||
'date' => (empty($options['timeframe']) ? 10 : $options['timeframe']) . 'd'
|
||||
);
|
||||
$eventIds = $this->Event->filterEventIds($user, $params);
|
||||
$eventIds = array_reverse(array_values($eventIds));
|
||||
$data = array();
|
||||
if (empty($options['type'])) {
|
||||
$options['type'] = 'confirmed';
|
||||
}
|
||||
if (!empty($eventIds)) {
|
||||
$previous = false;
|
||||
foreach ($eventIds as $eventId) {
|
||||
$params = array('eventid' => $eventId);
|
||||
$event = $this->Event->fetchEvent($user, $params);
|
||||
if (!empty($event)) {
|
||||
$data[$event[0]['Event']['date']] = $this->__handleEvent($event[0], $options, $previous);
|
||||
}
|
||||
$previous = $data[$event[0]['Event']['date']];
|
||||
}
|
||||
}
|
||||
$startDate = date('Y-m-d', strtotime('-' . intval($options['timeframe']) . ' days'));
|
||||
//$data = call_user_func_array((array($this, $this->__insightFunctions[$options['Insight']]), array($startDate));
|
||||
$data = array('data' => $data);
|
||||
$data['insight'] = empty($options['insight']) ? 'raw' : $options['insight'];
|
||||
foreach ($data['data'] as $date => $day) {
|
||||
$data['data'][$date]['date'] = $date;
|
||||
foreach ($this->__countries as $country => $temp) {
|
||||
if (empty($data['data'][$date][$country][$data['insight']])) {
|
||||
$data['data'][$date][$country][$data['insight']] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
$data['data'] = array_values($data['data']);
|
||||
$formulaData = array(
|
||||
'insight' => array(
|
||||
'raw' => '',
|
||||
'growth' => 'daily increase in ',
|
||||
'percent' => 'percentage wise daily increase in '
|
||||
),
|
||||
'type' => array(
|
||||
'confirmed' => 'confirmed cases',
|
||||
'death' => 'mortalities',
|
||||
'recovered' => 'recoveries',
|
||||
'mortality' => 'mortality rate'
|
||||
)
|
||||
);
|
||||
$data['formula'] = sprintf(
|
||||
'%s%s',
|
||||
(isset($options['insight']) && !empty($formulaData[$options['insight']])) ?
|
||||
$formulaData['insight'][$options['insight']] :
|
||||
$formulaData['insight']['raw'],
|
||||
(isset($options['type']) && !empty($formulaData['type'][$options['type']])) ?
|
||||
$formulaData['type'][$options['type']] :
|
||||
$formulaData['type']['confirmed']
|
||||
);
|
||||
$data['formula'] = ucfirst($data['formula']);
|
||||
foreach ($data['data'] as &$day) {
|
||||
foreach ($day as $key => &$countryData) {
|
||||
if ($key !== 'date') {
|
||||
$countryData = $countryData[$options['insight']];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __handleEvent($event, $options, $previous)
|
||||
{
|
||||
$data = array();
|
||||
if (!empty($event['Object'])) {
|
||||
$data = $this->__handleObjects($data, $event['Object'], $options, $previous);
|
||||
}
|
||||
$data['date'] = $event['Event']['date'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __handleObjects($data, $objects, $options, $previous)
|
||||
{
|
||||
foreach ($objects as $object) {
|
||||
if ($object['name'] === 'covid19-csse-daily-report') {
|
||||
$temp = $this->__interpretObject($object, $previous);
|
||||
$data = $this->__rearrangeResults($data, $temp, $options, $previous);
|
||||
}
|
||||
}
|
||||
if ($options['type'] === 'mortality') {
|
||||
foreach ($data as $k => $v) {
|
||||
$data[$k]['mortality'] = round(100 * (empty($v['death']) ? 0 : $v['death']) / $v['confirmed'], 2);
|
||||
}
|
||||
}
|
||||
if (!empty($options['insight']) && $options['insight'] !== 'raw') {
|
||||
if ($options['insight'] == 'growth') {
|
||||
foreach ($data as $k => &$countryData) {
|
||||
foreach ($countryData as $type => &$value) {
|
||||
if (empty($previous[$k][$type])) {
|
||||
$previous[$k][$type] = 0;
|
||||
}
|
||||
$data[$k]['growth'] = $data[$k][$type] - $previous[$k][$type];
|
||||
}
|
||||
}
|
||||
} else if ($options['insight'] == 'percent') {
|
||||
foreach ($data as $k => &$countryData) {
|
||||
foreach ($countryData as $type => &$value) {
|
||||
if (empty($previous[$k][$type])) {
|
||||
$previous[$k][$type] = $data[$k][$type];
|
||||
}
|
||||
$data[$k]['percent'] = ($data[$k][$type] - $previous[$k][$type]) / $previous[$k][$type];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($data as $k => &$countryData) {
|
||||
$data[$k]['raw'] = $data[$k][$options['type']];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __rearrangeResults($data, $temp, $options, $previous)
|
||||
{
|
||||
$country = $temp['country-region'];
|
||||
if (!in_array($country, $options['countries'])) {
|
||||
return $data;
|
||||
}
|
||||
$this->__countries[$country] = 1;
|
||||
if ($options['type'] === 'mortality') {
|
||||
foreach (array('confirmed', 'death') as $type) {
|
||||
if (!empty($temp[$type])) {
|
||||
$data[$country][$type] = (empty($data[$country][$type]) ? $temp[$type] : ($data[$country][$type] + $temp[$type]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$type = $options['type'];
|
||||
if (!empty($temp[$type])) {
|
||||
$data[$country][$type] = (empty($data[$country][$type]) ? $temp[$type] : ($data[$country][$type] + $temp[$type]));
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __interpretObject($object, $previous)
|
||||
{
|
||||
$temp = array();
|
||||
$validFields = array('country-region', 'confirmed', 'death', 'recovered');
|
||||
foreach ($object['Attribute'] as $attribute) {
|
||||
if (in_array($attribute['object_relation'], $validFields)) {
|
||||
if ($attribute['object_relation'] !== 'country-region') {
|
||||
$attribute['value'] = intval($attribute['value']);
|
||||
}
|
||||
$temp[$attribute['object_relation']] = $attribute['value'];
|
||||
}
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
class CsseCovidWidget
|
||||
{
|
||||
public $title = 'CSSE Covid-19 data';
|
||||
public $render = 'BarChart';
|
||||
public $width = 3;
|
||||
public $height = 4;
|
||||
public $params = array(
|
||||
'event_info' => 'Substring included in the info field of relevant CSSE COVID-19 events.',
|
||||
'type' => 'Type of data used for the widget (confirmed, death, recovered, mortality).',
|
||||
'logarithmic' => 'Use a log10 scale for the graph (set via 0/1).',
|
||||
'relative' => 'Take the country\'s population size into account (count / 10M)'
|
||||
);
|
||||
public $description = 'Widget visualising the countries ranked by highest count in the chosen category.';
|
||||
public $placeholder =
|
||||
'{
|
||||
"event_info": "%CSSE COVID-19 daily report%",
|
||||
"type": "confirmed",
|
||||
"logarithmic": 1,
|
||||
"relative": 0
|
||||
}';
|
||||
|
||||
public $__nameReplacements = array(
|
||||
'US' => 'United States',
|
||||
'Cote d\'Ivoire' => 'Ivory Coast',
|
||||
'Holy See' => 'Vatican',
|
||||
'Congo (Kinshasa)' => 'Democratic Republic of Congo',
|
||||
'Taiwan*' => 'Taiwan',
|
||||
'Korea, South' => 'South Korea'
|
||||
);
|
||||
|
||||
|
||||
private $__populationData = array();
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$event_info_condition = empty($options['event_info']) ? '%CSSE COVID-19 daily report%' : $options['event_info'];
|
||||
$params = array(
|
||||
'eventinfo' => $event_info_condition,
|
||||
'order' => 'date desc',
|
||||
'limit' => 1,
|
||||
'page' => 1
|
||||
);
|
||||
$eventIds = $this->Event->filterEventIds($user, $params);
|
||||
$params['eventid'] = $eventIds;
|
||||
$data = array();
|
||||
if (empty($options['type'])) {
|
||||
$options['type'] = 'confirmed';
|
||||
}
|
||||
if (!empty($eventIds)) {
|
||||
$events = $this->Event->fetchEvent($user, $params);
|
||||
$data = $this->__handleEvents($events, $options);
|
||||
arsort($data);
|
||||
}
|
||||
$data = array('data' => $data);
|
||||
if (!empty($options['type']) && $options['type'] === 'mortality') {
|
||||
$data['output_decorator'] = 'percentage';
|
||||
}
|
||||
if ($options['type'] !== 'mortality' && !empty($options['relative'])) {
|
||||
$this->__getPopulationData();
|
||||
if (!empty($this->__populationData)) {
|
||||
foreach ($data['data'] as $country => $value) {
|
||||
if (isset($this->__nameReplacements[$country])) {
|
||||
$alias = $this->__nameReplacements[$country];
|
||||
} else {
|
||||
$alias = $country;
|
||||
}
|
||||
if (empty($this->__populationData[$alias])) {
|
||||
unset($data['data'][$country]);
|
||||
} else {
|
||||
$pre = $data['data'][$country];
|
||||
$data['data'][$country] = round(10000000 * $data['data'][$country] / $this->__populationData[$alias]);
|
||||
}
|
||||
}
|
||||
}
|
||||
arsort($data['data']);
|
||||
}
|
||||
if (!empty($options['logarithmic'])) {
|
||||
$data['logarithmic'] = array();
|
||||
foreach ($data['data'] as $k => $v) {
|
||||
if ($v == 0) {
|
||||
$value = 0;
|
||||
} else if ($v <= 1) {
|
||||
$value = 0.2;
|
||||
} else {
|
||||
$value = log10($v);
|
||||
}
|
||||
$data['logarithmic'][$k] = $value;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __getPopulationData()
|
||||
{
|
||||
$this->Galaxy = ClassRegistry::init('Galaxy');
|
||||
$galaxy = $this->Galaxy->find('first', array(
|
||||
'recursive' => -1,
|
||||
'contain' => array('GalaxyCluster' => array('GalaxyElement')),
|
||||
'conditions' => array('Galaxy.name' => 'Country')
|
||||
));
|
||||
if (empty($galaxy)) {
|
||||
return false;
|
||||
}
|
||||
foreach ($galaxy['GalaxyCluster'] as $cluster) {
|
||||
foreach ($cluster['GalaxyElement'] as $element) {
|
||||
if ($element['key'] === 'Population') {
|
||||
$this->__populationData[$cluster['description']] = $element['value'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function __handleEvents($events, $options)
|
||||
{
|
||||
$data = array();
|
||||
if (!empty($events)) {
|
||||
foreach ($events as $event) {
|
||||
if (!empty($event['Object'])) {
|
||||
$data = $this->__handleObjects($data, $event['Object'], $options);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __handleObjects($data, $objects, $options)
|
||||
{
|
||||
foreach ($objects as $object) {
|
||||
if ($object['name'] === 'covid19-csse-daily-report') {
|
||||
$temp = $this->__interpretObject($object);
|
||||
$data = $this->__rearrangeResults($data, $temp, $options);
|
||||
}
|
||||
}
|
||||
if ($options['type'] === 'mortality') {
|
||||
foreach ($data as $k => $v) {
|
||||
if (!isset($v['death']) || empty($v['confirmed'])) {
|
||||
unset($data[$k]);
|
||||
continue;
|
||||
}
|
||||
$data[$k] = round(100 * (empty($v['death']) ? 0 : $v['death']) / $v['confirmed'], 2);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __rearrangeResults($data, $temp, $options)
|
||||
{
|
||||
$country = $temp['country-region'];
|
||||
if ($options['type'] === 'mortality') {
|
||||
foreach (array('confirmed', 'death') as $type) {
|
||||
if (!empty($temp[$type])) {
|
||||
$data[$country][$type] = (empty($data[$country][$type]) ? $temp[$type] : ($data[$country][$type] + $temp[$type]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$type = $options['type'];
|
||||
if (!empty($temp[$type])) {
|
||||
$data[$country] = (empty($data[$country]) ? $temp[$type] : ($data[$country] + $temp[$type]));
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function __interpretObject($object)
|
||||
{
|
||||
$temp = array();
|
||||
$validFields = array('country-region', 'confirmed', 'death', 'recovered');
|
||||
foreach ($object['Attribute'] as $attribute) {
|
||||
if (in_array($attribute['object_relation'], $validFields)) {
|
||||
if ($attribute['object_relation'] !== 'country-region') {
|
||||
$attribute['value'] = intval($attribute['value']);
|
||||
}
|
||||
$temp[$attribute['object_relation']] = $attribute['value'];
|
||||
}
|
||||
}
|
||||
return $temp;
|
||||
}
|
||||
}
|
|
@ -9,11 +9,13 @@ class TrendingTagsWidget
|
|||
public $params = array(
|
||||
'time_window' => 'The time window, going back in seconds, that should be included.',
|
||||
'exclude' => 'List of substrings to exclude tags by - for example "sofacy" would exclude any tag containing sofacy.',
|
||||
'include' => 'List of substrings to include tags by - for example "sofacy" would include any tag containing sofacy.'
|
||||
'include' => 'List of substrings to include tags by - for example "sofacy" would include any tag containing sofacy.',
|
||||
'threshold' => 'Limits the number of displayed tags. Default: 10'
|
||||
);
|
||||
public $placeholder =
|
||||
'{
|
||||
"time_window": "86400",
|
||||
"threshold": 15,
|
||||
"exclude": ["tlp:", "pap:"],
|
||||
"include": ["misp-galaxy:", "my-internal-taxonomy"]
|
||||
}';
|
||||
|
@ -26,6 +28,7 @@ class TrendingTagsWidget
|
|||
'metadata' => 1,
|
||||
'timestamp' => time() - (empty($options['time_window']) ? 8640000 : $options['time_window'])
|
||||
);
|
||||
$threshold = empty($options['threshold']) ? 10 : $options['threshold'];
|
||||
$eventIds = $this->Event->filterEventIds($user, $params);
|
||||
$params['eventid'] = $eventIds;
|
||||
$events = array();
|
||||
|
@ -34,8 +37,6 @@ class TrendingTagsWidget
|
|||
}
|
||||
$tags = array();
|
||||
$tagColours = array();
|
||||
$rules['exclusions'] = empty($options['exclude']) ? array() : $options['exclude'];
|
||||
$rules['inclusions'] = empty($options['exclude']) ? array() : $options['exclude'];
|
||||
foreach ($events as $event) {
|
||||
foreach ($event['EventTag'] as $et) {
|
||||
if ($this->checkTag($options, $et['Tag']['name'])) {
|
||||
|
@ -49,7 +50,7 @@ class TrendingTagsWidget
|
|||
}
|
||||
}
|
||||
arsort($tags);
|
||||
$data['data'] = array_slice($tags, 0, 10);
|
||||
$data['data'] = array_slice($tags, 0, $threshold);
|
||||
$data['colours'] = $tagColours;
|
||||
return $data;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ class Stix2Export extends StixExport
|
|||
$scriptFile = $this->__scripts_dir . $this->__script_name;
|
||||
$filename = $this->__scripts_dir . 'tmp/' . $filename;
|
||||
$my_server = ClassRegistry::init('Server');
|
||||
return shell_exec($my_server->getPythonVersion() . ' ' . $scriptFile . ' ' . $filename . $this->__end_of_cmd);
|
||||
$result = shell_exec($my_server->getPythonVersion() . ' ' . $scriptFile . ' ' . $filename . $this->__end_of_cmd);
|
||||
$result = preg_split("/\r\n|\n|\r/", trim($result));
|
||||
return end($result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d2e1681eb8ec75e6c2819fa113834843fed6995a
|
||||
Subproject commit 5ccb12354dfc08ca1b3e0a430e8668bf1610b5d3
|
|
@ -4426,7 +4426,6 @@ class Attribute extends AppModel
|
|||
'event_timestamp' => array('function' => 'set_filter_timestamp', 'pop' => true),
|
||||
'publish_timestamp' => array('function' => 'set_filter_timestamp'),
|
||||
'org' => array('function' => 'set_filter_org'),
|
||||
'uuid' => array('function' => 'set_filter_uuid'),
|
||||
'published' => array('function' => 'set_filter_published')
|
||||
),
|
||||
'Object' => array(
|
||||
|
@ -4487,7 +4486,6 @@ class Attribute extends AppModel
|
|||
|
||||
$subqueryElements = $this->Event->harvestSubqueryElements($filters);
|
||||
$filters = $this->Event->addFiltersFromSubqueryElements($filters, $subqueryElements);
|
||||
|
||||
$conditions = $this->buildFilterConditions($user, $filters);
|
||||
$params = array(
|
||||
'conditions' => $conditions,
|
||||
|
@ -4617,4 +4615,28 @@ class Attribute extends AppModel
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function set_filter_uuid(&$params, $conditions, $options)
|
||||
{
|
||||
if (!empty($params['uuid'])) {
|
||||
$params['uuid'] = $this->convert_filters($params['uuid']);
|
||||
if (!empty($params['uuid']['OR'])) {
|
||||
$conditions['AND'][] = array(
|
||||
'OR' => array(
|
||||
'Event.uuid' => $params['uuid']['OR'],
|
||||
'Attribute.uuid' => $params['uuid']['OR']
|
||||
)
|
||||
);
|
||||
}
|
||||
if (!empty($params['uuid']['NOT'])) {
|
||||
$conditions['AND'][] = array(
|
||||
'NOT' => array(
|
||||
'Event.uuid' => $params['uuid']['NOT'],
|
||||
'Attribute.uuid' => $params['uuid']['NOT']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class Bruteforce extends AppModel
|
|||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'DELETE FROM bruteforces WHERE `expire` <= "' . $expire . '";';
|
||||
} elseif ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'DELETE FROM bruteforces WHERE expire <= "' . $expire . '";';
|
||||
$sql = 'DELETE FROM bruteforces WHERE expire <= \'' . $expire . '\';';
|
||||
}
|
||||
$this->query($sql);
|
||||
}
|
||||
|
|
|
@ -1667,7 +1667,6 @@ class Event extends AppModel
|
|||
'object_relation' => array('function' => 'set_filter_simple_attribute'),
|
||||
'tags' => array('function' => 'set_filter_tags', 'pop' => true),
|
||||
'ignore' => array('function' => 'set_filter_ignore'),
|
||||
'uuid' => array('function' => 'set_filter_uuid'),
|
||||
'deleted' => array('function' => 'set_filter_deleted'),
|
||||
'to_ids' => array('function' => 'set_filter_to_ids'),
|
||||
'comment' => array('function' => 'set_filter_comment')
|
||||
|
@ -1707,7 +1706,6 @@ class Event extends AppModel
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fields = array('Event.id');
|
||||
if (!empty($params['include_attribute_count'])) {
|
||||
$fields[] = 'Event.attribute_count';
|
||||
|
@ -2582,17 +2580,41 @@ class Event extends AppModel
|
|||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
|
||||
public function set_filter_uuid(&$params, $conditions, $options)
|
||||
{
|
||||
if (!empty($params['uuid'])) {
|
||||
$params['uuid'] = $this->convert_filters($params['uuid']);
|
||||
if (!empty($options['scope']) && $options['scope'] === 'Event') {
|
||||
$conditions = $this->generic_add_filter($conditions, $params['uuid'], 'Event.uuid');
|
||||
}
|
||||
if (!empty($options['scope']) && $options['scope'] === 'Attribute') {
|
||||
$conditions = $this->generic_add_filter($conditions, $params['uuid'], 'Attribute.uuid');
|
||||
if ($options['scope'] === 'Event') {
|
||||
if (!empty($params['uuid'])) {
|
||||
$params['uuid'] = $this->convert_filters($params['uuid']);
|
||||
if (!empty($params['uuid']['OR'])) {
|
||||
$subQueryOptions = array(
|
||||
'conditions' => array('Attribute.uuid' => $params['uuid']['OR']),
|
||||
'fields' => array('event_id')
|
||||
);
|
||||
$attributeSubquery = $this->subQueryGenerator($this->Attribute, $subQueryOptions, 'Event.id');
|
||||
$conditions['AND'][] = array(
|
||||
'OR' => array(
|
||||
'Event.uuid' => $params['uuid']['OR'],
|
||||
$attributeSubquery
|
||||
)
|
||||
);
|
||||
}
|
||||
if (!empty($params['uuid']['NOT'])) {
|
||||
$subQueryOptions = array(
|
||||
'conditions' => array('Attribute.uuid' => $params['uuid']['NOT']),
|
||||
'fields' => array('event_id')
|
||||
);
|
||||
$attributeSubquery = $this->subQueryGenerator($this->Attribute, $subQueryOptions, 'Event.id');
|
||||
$conditions['AND'][] = array(
|
||||
'NOT' => array(
|
||||
'Event.uuid' => $params['uuid']['NOT'],
|
||||
$attributeSubquery
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$conditions = $this->{$options['scope']}->set_filter_uuid($params, $conditions, $options);
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
@ -3078,6 +3100,15 @@ class Event extends AppModel
|
|||
}
|
||||
$body .= $bodyTempOther; // append the 'other' attribute types to the bottom.
|
||||
$body .= '==============================================' . "\n";
|
||||
$body .= sprintf(
|
||||
"You receive this e-mail because the e-mail address %s is set to receive publish alerts on the MISP instance at %s.%s%s",
|
||||
$user['email'],
|
||||
(empty(Configure::read('MISP.external_baseurl')) ? Configure::read('MISP.baseurl') : Configure::read('MISP.external_baseurl')),
|
||||
PHP_EOL,
|
||||
PHP_EOL
|
||||
);
|
||||
$body .= "If you would like to unsubscribe from receiving such alert e-mails, simply\ndisable publish alerts via " . $this->__getAnnounceBaseurl() . '/users/edit' . PHP_EOL;
|
||||
$body .= '==============================================' . "\n";
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,10 @@ class Feed extends AppModel
|
|||
'event_id' => array(
|
||||
'rule' => array('numeric'),
|
||||
'message' => 'Please enter a numeric event ID or leave this field blank.',
|
||||
),
|
||||
'input_source' => array(
|
||||
'rule' => 'validateInputSource',
|
||||
'message' => ''
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -47,6 +51,27 @@ class Feed extends AppModel
|
|||
)
|
||||
);
|
||||
|
||||
public function validateInputSource($fields)
|
||||
{
|
||||
if (!empty($this->data['Feed']['input_source'])) {
|
||||
$localAllowed = empty(Configure::read('Security.disable_local_feed_access'));
|
||||
$validOptions = array('network');
|
||||
if ($localAllowed) {
|
||||
$validOptions[] = 'local';
|
||||
}
|
||||
if (!in_array($this->data['Feed']['input_source'], $validOptions)) {
|
||||
return __(
|
||||
'Invalid input source. The only valid options are %s. %s',
|
||||
implode(', ', $validOptions),
|
||||
(!$localAllowed && $this->data['Feed']['input_source'] === 'local') ?
|
||||
__('Security.disable_local_feed_access is currently enabled, local feeds are thereby not allowed.') :
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function urlOrExistingFilepath($fields)
|
||||
{
|
||||
if ($this->isFeedLocal($this->data)) {
|
||||
|
@ -1162,7 +1187,7 @@ class Feed extends AppModel
|
|||
'recursive' => -1,
|
||||
'fields' => array('id', 'url', 'name'),
|
||||
'contain' => array('RemoteOrg' => array('fields' => array('RemoteOrg.id', 'RemoteOrg.name'))),
|
||||
'conditions' => array('Server.caching_enabled')
|
||||
'conditions' => array('Server.caching_enabled' => 1)
|
||||
));
|
||||
foreach ($servers as $k => $server) {
|
||||
if (!$redis->exists('misp:server_cache:' . $server['Server']['id'])) {
|
||||
|
|
|
@ -326,7 +326,6 @@ class Log extends AppModel
|
|||
$elasticSearchClient = $this->getElasticSearchTool();
|
||||
$elasticSearchClient->pushDocument($logIndex, "log", $data);
|
||||
}
|
||||
|
||||
if (Configure::read('Security.syslog')) {
|
||||
// write to syslogd as well
|
||||
$syslog = new SysLog();
|
||||
|
@ -341,8 +340,17 @@ class Log extends AppModel
|
|||
}
|
||||
|
||||
$entry = $data['Log']['action'];
|
||||
if (!empty($data['Log']['title'])) {
|
||||
$entry .= sprintf(
|
||||
' -- %s',
|
||||
$data['Log']['title']
|
||||
);
|
||||
}
|
||||
if (!empty($data['Log']['description'])) {
|
||||
$entry .= sprintf(' -- %s', $data['Log']['description']);
|
||||
$entry .= sprintf(
|
||||
' -- %s',
|
||||
$data['Log']['description']
|
||||
);
|
||||
}
|
||||
$syslog->write($action, $entry);
|
||||
}
|
||||
|
|
|
@ -1234,7 +1234,7 @@ class MispObject extends AppModel
|
|||
return $toReturn;
|
||||
}
|
||||
|
||||
public function reviseObject($revised_object, $object) {
|
||||
public function reviseObject($revised_object, $object, $template) {
|
||||
$revised_object = json_decode(base64_decode($revised_object), true);
|
||||
$revised_object_both = array('mergeable' => array(), 'notMergeable' => array());
|
||||
|
||||
|
|
|
@ -512,7 +512,7 @@ class Server extends AppModel
|
|||
'description' => __('Enables the use of MISP\'s background processing.'),
|
||||
'value' => '',
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'test' => 'testBoolTrue',
|
||||
'type' => 'boolean',
|
||||
),
|
||||
'attachments_dir' => array(
|
||||
|
@ -642,6 +642,15 @@ class Server extends AppModel
|
|||
'type' => 'numeric',
|
||||
'optionsSource' => 'TagCollections',
|
||||
),
|
||||
'default_publish_alert' => array(
|
||||
'level' => 0,
|
||||
'description' => __('The default setting for publish alerts when creating users.'),
|
||||
'value' => true,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'tagging' => array(
|
||||
'level' => 1,
|
||||
'description' => __('Enable the tagging feature of MISP. This is highly recommended.'),
|
||||
|
@ -1304,6 +1313,16 @@ class Server extends AppModel
|
|||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'disable_local_feed_access' => array(
|
||||
'level' => 0,
|
||||
'description' => __('Disabling this setting will allow the creation/modification of local feeds (as opposed to network feeds). Enabling this setting will restrict feed sources to be network based only. When disabled, keep in mind that a malicious site administrator could get access to any arbitrary file on the system that the apache user has access to. Make sure that proper safe-guards are in place. This setting can only be modified via the CLI.'),
|
||||
'value' => false,
|
||||
'errorMessage' => '',
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true,
|
||||
'cli_only' => 1
|
||||
),
|
||||
'allow_unsafe_apikey_named_param' => array(
|
||||
'level' => 0,
|
||||
'description' => __('Allows passing the API key via the named url parameter "apikey" - highly recommended not to enable this, but if you have some dodgy legacy tools that cannot pass the authorization header it can work as a workaround. Again, only use this as a last resort.'),
|
||||
|
@ -2645,6 +2664,23 @@ class Server extends AppModel
|
|||
return $final;
|
||||
}
|
||||
|
||||
private function __orgRuleDowngrade($HttpSocket, $request, $server, $filter_rules)
|
||||
{
|
||||
$uri = $server['Server']['url'] . '/servers/getVersion';
|
||||
try {
|
||||
$version_response = $HttpSocket->get($uri, false, $request);
|
||||
$body = $version_response->body;
|
||||
$version_response = json_decode($body, true);
|
||||
$version = $version_response['version'];
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
$version = explode('.', $version);
|
||||
if ($version[0] <= 2 && $version[1] <= 4 && $version[0] <= 123) {
|
||||
$filter_rules['org'] = implode('|', $filter_rules['org']);
|
||||
}
|
||||
return $filter_rules;
|
||||
}
|
||||
|
||||
// Get an array of event_ids that are present on the remote server
|
||||
public function getEventIdsFromServer($server, $all = false, $HttpSocket=null, $force_uuid=false, $ignoreFilterRules = false, $scope = 'events')
|
||||
|
@ -2657,6 +2693,9 @@ class Server extends AppModel
|
|||
}
|
||||
$HttpSocket = $this->setupHttpSocket($server, $HttpSocket);
|
||||
$request = $this->setupSyncRequest($server);
|
||||
if (!empty($filter_rules['org'])) {
|
||||
$filter_rules = $this->__orgRuleDowngrade($HttpSocket, $request, $server, $filter_rules);
|
||||
}
|
||||
$uri = $url . '/events/index';
|
||||
$filter_rules['minimal'] = 1;
|
||||
$filter_rules['published'] = 1;
|
||||
|
@ -2747,6 +2786,7 @@ class Server extends AppModel
|
|||
} catch (SocketException $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
// error, so return error message, since that is handled and everything is expecting an array
|
||||
return "Error: got response code " . $response->code;
|
||||
}
|
||||
|
@ -3506,6 +3546,21 @@ class Server extends AppModel
|
|||
return true;
|
||||
}
|
||||
|
||||
public function testBoolTrue($value, $errorMessage = false)
|
||||
{
|
||||
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 enabled. Make sure you understand the impact of having this setting turned off.';
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function testBoolFalse($value, $errorMessage = false)
|
||||
{
|
||||
if ($this->testBool($value, $errorMessage) !== true) {
|
||||
|
@ -4474,7 +4529,10 @@ class Server extends AppModel
|
|||
if (isset($field['error_type'])) {
|
||||
$length = false;
|
||||
if (in_array($field['error_type'], array('missing_column', 'column_different'))) {
|
||||
if ($field['expected']['data_type'] === 'int') {
|
||||
preg_match('/([a-z]+)(?:\((?<dw>[0-9,]+)\))?\s*([a-z]+)?/i', $field['expected']['column_type'], $displayWidthMatches);
|
||||
if (isset($displayWidthMatches['dw'])) {
|
||||
$length = $displayWidthMatches[2];
|
||||
} elseif ($field['expected']['data_type'] === 'int') {
|
||||
$length = 11;
|
||||
} elseif ($field['expected']['data_type'] === 'tinyint') {
|
||||
$length = 1;
|
||||
|
@ -4580,6 +4638,7 @@ class Server extends AppModel
|
|||
'numeric_precision',
|
||||
// 'datetime_precision', -- Only available on MySQL 5.6+
|
||||
'collation_name',
|
||||
'column_type',
|
||||
'column_default'
|
||||
)
|
||||
){
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
|
||||
$('#AttributeCategory').change(function() {
|
||||
formCategoryChanged('Attribute');
|
||||
$('#AttributeType').chosen('destroy').chosen();
|
||||
if ($(this).val() === 'Internal reference') {
|
||||
$("#AttributeDistribution").val('0');
|
||||
checkSharingGroup('Attribute');
|
||||
|
@ -166,6 +167,16 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
<?php if (!$ajax): ?>
|
||||
$('#AttributeType').chosen();
|
||||
$('#AttributeCategory').chosen();
|
||||
<?php else: ?>
|
||||
$('#genericModal').on('shown', function() {
|
||||
$('#AttributeType').chosen();
|
||||
$('#AttributeCategory').chosen();
|
||||
})
|
||||
<?php endif; ?>
|
||||
});
|
||||
</script>
|
||||
<?php echo $this->element('form_seen_input'); ?>
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
'label' => __('For Intrusion Detection System'),
|
||||
'selected' => 2,
|
||||
));
|
||||
echo $this->Form->input('is_proposal', array(
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Create proposals'),
|
||||
'checked' => true
|
||||
));
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ if (typeof d3 === "undefined") { // load d3.js once. This is necessary as d3.js
|
|||
init<?= $seed ?>();
|
||||
})
|
||||
} else { // d3.js is already loaded or is loading
|
||||
runInitWhenReady()
|
||||
runInitWhenReady<?= $seed ?>()
|
||||
}
|
||||
|
||||
function runInitWhenReady() {
|
||||
function runInitWhenReady<?= $seed ?>() {
|
||||
if (d3.version === undefined) { // d3.js not loaded yet
|
||||
setTimeout(function() {
|
||||
runInitWhenReady();
|
||||
runInitWhenReady<?= $seed ?>();
|
||||
}, 50);
|
||||
} else {
|
||||
init<?= $seed ?>();
|
||||
|
@ -30,7 +30,6 @@ function runInitWhenReady() {
|
|||
|
||||
function init<?= $seed ?>() { // variables and functions have their own scope (no override)
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
*
|
||||
* Data expected format: Array({
|
||||
|
@ -455,9 +454,6 @@ function init<?= $seed ?>() { // variables and functions have their own scope (n
|
|||
.on('mouseover', function(d) {
|
||||
tooltipDate(true, this, d);
|
||||
})
|
||||
.on('mouseout', function() {
|
||||
tooltipDate(false);
|
||||
})
|
||||
.on('click', function(d) {
|
||||
handleMarkerClick(d);
|
||||
})
|
||||
|
@ -516,48 +512,30 @@ function init<?= $seed ?>() { // variables and functions have their own scope (n
|
|||
}
|
||||
|
||||
function tooltipDate(show, d3Element, datum) {
|
||||
var tooltip = _toggleTooltip(show, d3Element);
|
||||
if (show) {
|
||||
tooltip.html(_generate_tooltip(datum));
|
||||
var tooltipBR = tooltip.node().getBoundingClientRect();
|
||||
var tooltipHeight = tooltipBR.height;
|
||||
var tooltipWidth = tooltipBR.width;
|
||||
var tooltipcx = parseInt(d3.select(d3Element).attr('cx'));
|
||||
var dcx = 17;
|
||||
// Flip tooltip position if necessary
|
||||
if (width < options.margin.right + tooltipcx - dcx + tooltipWidth) {
|
||||
var tooltipLeft = parseInt(tooltip.style('left').split('px')[0]);
|
||||
tooltip.style('left', (tooltipLeft - (dcx + tooltipWidth + 15)) + 'px')
|
||||
}
|
||||
var tooltipTop = parseInt(tooltip.style('top').split('px')[0]);
|
||||
tooltip.style('top', (tooltipTop - tooltipHeight/2) + 'px')
|
||||
}
|
||||
}
|
||||
|
||||
function _toggleTooltip(show, d3Element) {
|
||||
if (show) {
|
||||
tooltip_container
|
||||
.style('display', 'block')
|
||||
.style('left', (d3.event.pageX + 17) + 'px')
|
||||
.style('top', (d3.event.pageY) + 'px')
|
||||
.transition()
|
||||
.duration(options.animation_short_duration)
|
||||
.delay(options.animation_short_duration/2)
|
||||
.style('opacity', '0.7');
|
||||
} else {
|
||||
tooltip_container.transition()
|
||||
.duration(options.animation_short_duration)
|
||||
.style('opacity', 0)
|
||||
.delay(options.animation_short_duration)
|
||||
.style('display', 'none');
|
||||
}
|
||||
return tooltip_container;
|
||||
var $d3Element = $(d3Element);
|
||||
$d3Element.tooltip({
|
||||
html: true,
|
||||
container: 'body',
|
||||
title: _generate_tooltip(datum)
|
||||
}).tooltip('show')
|
||||
}
|
||||
|
||||
function _generate_tooltip(datum) {
|
||||
var formated_date = d3.time.format(options.time_format)(datum.date);
|
||||
var html = $('<p></p>').text(datum.name).html() + ' (' + formated_date + ', <strong>' + $('<p></p>').text(datum.count).html() + '</strong>) ';
|
||||
return html;
|
||||
var formated_x = options.abscissa_linear ? datum.index : d3.time.format(options.time_format)(datum.date);
|
||||
return $('<div></div>').append(
|
||||
$('<h6></h6>').text(formated_x).css({'margin': 0}),
|
||||
$('<h6></h6>').append(
|
||||
$('<span></span>').text(datum.name).css({'margin-right': '1em'}).prepend(
|
||||
$('<svg height="10px" width="15px"></svg>').append($('<circle></circle>')
|
||||
.attr('cx', 5)
|
||||
.attr('cy', 5)
|
||||
.attr('r', 5)
|
||||
.css('fill', colors(datum.name))
|
||||
)
|
||||
),
|
||||
$('<span></span>').text(datum.count)
|
||||
).css({'margin': 0})
|
||||
)[0].outerHTML
|
||||
}
|
||||
|
||||
function handleMarkerClick(datum) {
|
||||
|
@ -610,7 +588,7 @@ function init<?= $seed ?>() { // variables and functions have their own scope (n
|
|||
var left = (overlayLeftBCR.width - overlayRightBCR.width > 0 ?
|
||||
overlayLeftBCR.left + overlayLeftBCR.width/2 :
|
||||
overlayRightBCR.left + overlayRightBCR.width/2) - tooltipBCR.width / 2;
|
||||
var top = overlayLeftBCR.top + 30;
|
||||
var top = overlayLeftBCR.top + window.scrollY + 30;
|
||||
|
||||
tooltipPickedNodes
|
||||
.style('left', left + 'px')
|
||||
|
|
|
@ -85,7 +85,8 @@
|
|||
);
|
||||
$rows = '';
|
||||
foreach ($dbSchemaDiagnostics as $tableName => $tableDiagnostic) {
|
||||
$rows .= sprintf('<tr data-tablename="%s">', $tableName);
|
||||
$tableContainsCritical = array_filter(Hash::extract($tableDiagnostic, '{n}.is_critical'));
|
||||
$rows .= sprintf('<tr class="%s" data-tablename="%s">', $tableContainsCritical ? '' : 'noncritical', $tableName);
|
||||
$rows .= sprintf('<td rowspan="%s" colspan="0" class="bold">%s</td>', count($tableDiagnostic)+1, h($tableName));
|
||||
$rows .= '</tr>';
|
||||
|
||||
|
|
|
@ -6,9 +6,19 @@
|
|||
<strong><?php echo __('Make sure you keep your API key secret as it gives access to the all of the data that you normally have access to in MISP.');?></strong>
|
||||
<?php echo __('To view the old MISP automation page, click <a href="automation/1">here</a>.');?>
|
||||
</p>
|
||||
<p><?php echo __('Your current key is: <code>%s</code>.
|
||||
You can %s this key.', $me['authkey'], $this->Html->link(__('reset'), array('controller' => 'users', 'action' => 'resetauthkey', 'me')));?>
|
||||
</p>
|
||||
<span>
|
||||
<?php
|
||||
echo __(
|
||||
'Your current key is: <code>%s</code>. You can %s this key.',
|
||||
$me['authkey'],
|
||||
$this->Form->postLink(
|
||||
__('reset'),
|
||||
array('controller' => 'users', 'action' => 'resetauthkey', 'me'),
|
||||
array('div' => false)
|
||||
)
|
||||
);
|
||||
?>
|
||||
</span>
|
||||
<?php
|
||||
$data = array(
|
||||
'title' => __('Search'),
|
||||
|
|
|
@ -379,7 +379,7 @@
|
|||
$count++;
|
||||
if ($count == $display_threshold+1 && $total > $display_threshold):
|
||||
?>
|
||||
<div class="no-side-padding correlation-expand-button useCursorPointer linkButton blue"><?php echo __('Show (%s more)', $total - $count);?></div>
|
||||
<div class="no-side-padding correlation-expand-button useCursorPointer linkButton blue"><?php echo __('Show (%s more)', $total - ($count-1));?></div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
|
|
@ -2,10 +2,16 @@
|
|||
<?php echo $this->Form->create('Feed');?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Add MISP Feed');?></legend>
|
||||
<p><?php echo __('Add a new MISP feed source.');?></p>
|
||||
<?php
|
||||
echo $this->Form->input('enabled', array());
|
||||
echo $this->Form->input('caching_enabled', array('label' => __('Caching enabled')));
|
||||
<?php
|
||||
if (!empty(Configure::read('Security.disable_local_feed_access'))) {
|
||||
echo sprintf(
|
||||
'<p class="red bold">%s</p>',
|
||||
__('Warning: local feeds are currently disabled by policy, to re-enable the feature, set the Security.allow_local_feed_access flag in the server settings. This setting can only be set via the CLI.')
|
||||
);
|
||||
}
|
||||
echo '<p>' . __('Add a new MISP feed source.') . '</p>';
|
||||
echo $this->Form->input('enabled', array());
|
||||
echo $this->Form->input('caching_enabled', array('label' => __('Caching enabled')));
|
||||
?>
|
||||
<div class="input clear"></div>
|
||||
<?php
|
||||
|
@ -21,10 +27,14 @@
|
|||
'placeholder' => __('Name of the content provider'),
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
$options = array('network' => 'Network');
|
||||
if (empty(Configure::read('Security.disable_local_feed_access'))) {
|
||||
$options['local'] = 'Local';
|
||||
}
|
||||
echo $this->Form->input('input_source', array(
|
||||
'label' => __('Input Source'),
|
||||
'div' => 'input clear',
|
||||
'options' => array('network' => 'Network', 'local' => 'Local'),
|
||||
'options' => $options,
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
?>
|
||||
|
|
|
@ -2,8 +2,14 @@
|
|||
<?php echo $this->Form->create('Feed');?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Edit MISP Feed');?></legend>
|
||||
<p><?php echo __('Edit a new MISP feed source.');?></p>
|
||||
<?php
|
||||
<?php
|
||||
if (!empty(Configure::read('Security.disable_local_feed_access'))) {
|
||||
echo sprintf(
|
||||
'<p class="red bold">%s</p>',
|
||||
__('Warning: local feeds are currently disabled by policy, to re-enable the feature, set the Security.allow_local_feed_access flag in the server settings. This setting can only be set via the CLI.')
|
||||
);
|
||||
}
|
||||
echo '<p>' . __('Edit a new MISP feed source.') . '</p>';
|
||||
echo $this->Form->input('enabled', array(
|
||||
'type' => 'checkbox'
|
||||
));
|
||||
|
@ -26,9 +32,13 @@
|
|||
'placeholder' => __('Name of the content provider'),
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
$options = array('network' => 'Network');
|
||||
if (empty(Configure::read('Security.disable_local_feed_access'))) {
|
||||
$options['local'] = 'Local';
|
||||
}
|
||||
echo $this->Form->input('input_source', array(
|
||||
'div' => 'input clear',
|
||||
'options' => array('network' => 'Network', 'local' => 'Local'),
|
||||
'options' => $options,
|
||||
'class' => 'form-control span6'
|
||||
));
|
||||
?>
|
||||
|
|
|
@ -72,10 +72,11 @@
|
|||
<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.')));
|
||||
$default_publish_alert = Configure::check('MISP.default_publish_alert') ? Configure::read('MISP.default_publish_alert') : true;
|
||||
echo $this->Form->input('autoalert', array(
|
||||
'label' => __('Receive alerts when events are published'),
|
||||
'type' => 'checkbox',
|
||||
'checked' => isset($this->request->data['User']['autoalert']) ? $this->request->data['User']['autoalert'] : true
|
||||
'checked' => isset($this->request->data['User']['autoalert']) ? $this->request->data['User']['autoalert'] : $default_publish_alert
|
||||
));
|
||||
echo $this->Form->input('contactalert', array(
|
||||
'label' => __('Receive alerts from "contact reporter" requests'),
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 777c3188db6fd1f04fc81106a6c2eb293bb19d12
|
||||
Subproject commit c7104e8819d6b789b24a45655aa28625a8c4c346
|
|
@ -39,6 +39,8 @@ threat_actor_galaxies_list = ('threat-actor', 'microsoft-activity-group')
|
|||
tool_galaxies_list = ('botnet', 'rat', 'exploit-kit', 'tds', 'tool', 'mitre-tool',
|
||||
'mitre-enterprise-attack-tool', 'mitre-mobile-attack-tool')
|
||||
_MISP_event_tags = ['Threat-Report', 'misp:tool="misp2stix2"']
|
||||
_time_fields = {'indicator': ('valid_from', 'valid_until'),
|
||||
'observed-data': ('first_observed', 'last_observed')}
|
||||
|
||||
class StixBuilder():
|
||||
def __init__(self):
|
||||
|
@ -73,6 +75,7 @@ class StixBuilder():
|
|||
report_args = {'type': 'report', 'id': self.report_id, 'name': self.misp_event['info'],
|
||||
'created_by_ref': self.identity_id, 'created': self.misp_event['date'],
|
||||
'published': self.get_datetime_from_timestamp(self.misp_event['publish_timestamp']),
|
||||
'modified': self.get_datetime_from_timestamp(self.misp_event['timestamp']),
|
||||
'interoperability': True}
|
||||
labels = [tag for tag in _MISP_event_tags]
|
||||
if self.misp_event.get('Tag'):
|
||||
|
@ -377,8 +380,7 @@ class StixBuilder():
|
|||
self.galaxies.append(galaxy_uuid)
|
||||
self.relationships['defined'][source_id].append("{}--{}".format(stix_type, galaxy_uuid))
|
||||
|
||||
@staticmethod
|
||||
def generate_galaxy_args(galaxy, b_killchain, b_alias, sdo_type):
|
||||
def generate_galaxy_args(self, galaxy, b_killchain, b_alias, sdo_type):
|
||||
cluster = galaxy['GalaxyCluster'][0]
|
||||
try:
|
||||
cluster_uuid = cluster['collection_uuid']
|
||||
|
@ -387,8 +389,9 @@ class StixBuilder():
|
|||
sdo_id = "{}--{}".format(sdo_type, cluster_uuid)
|
||||
description = "{} | {}".format(galaxy['description'], cluster['description'])
|
||||
labels = ['misp:name=\"{}\"'.format(galaxy['name'])]
|
||||
sdo_args = {'id': sdo_id, 'type': sdo_type, 'name': cluster['value'],
|
||||
'description': description, 'interoperability': True}
|
||||
sdo_args = {'id': sdo_id, 'type': sdo_type, 'created': self.misp_event['date'],
|
||||
'modified': self.get_datetime_from_timestamp(self.misp_event['timestamp']),
|
||||
'name': cluster['value'], 'description': description, 'interoperability': True}
|
||||
if b_killchain:
|
||||
killchain = [{'kill_chain_name': 'misp-category',
|
||||
'phase_name': galaxy['type']}]
|
||||
|
@ -452,8 +455,9 @@ class StixBuilder():
|
|||
custom_object_id = "x-misp-object-{}--{}".format(attribute_type, attribute['uuid'])
|
||||
custom_object_type = "x-misp-object-{}".format(attribute_type)
|
||||
labels, markings = self.create_labels(attribute)
|
||||
custom_object_args = {'id': custom_object_id, 'x_misp_category': attribute['category'], 'labels': labels,
|
||||
'x_misp_timestamp': self.get_datetime_from_timestamp(attribute['timestamp']),
|
||||
timestamp = self.get_datetime_from_timestamp(attribute['timestamp'])
|
||||
custom_object_args = {'id': custom_object_id, 'x_misp_category': attribute['category'],
|
||||
'created': timestamp, 'modified': timestamp, 'labels': labels,
|
||||
'x_misp_value': attribute['value'], 'created_by_ref': self.identity_id}
|
||||
if attribute.get('comment'):
|
||||
custom_object_args['x_misp_comment'] = attribute['comment']
|
||||
|
@ -461,14 +465,15 @@ class StixBuilder():
|
|||
markings = self.handle_tags(markings)
|
||||
custom_object_args['object_marking_refs'] = markings
|
||||
@CustomObject(custom_object_type, [('id', properties.StringProperty(required=True)),
|
||||
('x_misp_timestamp', properties.StringProperty(required=True)),
|
||||
('labels', properties.ListProperty(labels, required=True)),
|
||||
('x_misp_value', properties.StringProperty(required=True)),
|
||||
('created_by_ref', properties.StringProperty(required=True)),
|
||||
('object_marking_refs', properties.ListProperty(markings)),
|
||||
('x_misp_comment', properties.StringProperty()),
|
||||
('x_misp_category', properties.StringProperty())
|
||||
])
|
||||
('labels', properties.ListProperty(labels, required=True)),
|
||||
('x_misp_value', properties.StringProperty(required=True)),
|
||||
('created', properties.TimestampProperty(required=True, precision='millisecond')),
|
||||
('modified', properties.TimestampProperty(required=True, precision='millisecond')),
|
||||
('created_by_ref', properties.StringProperty(required=True)),
|
||||
('object_marking_refs', properties.ListProperty(markings)),
|
||||
('x_misp_comment', properties.StringProperty()),
|
||||
('x_misp_category', properties.StringProperty())
|
||||
])
|
||||
class Custom(object):
|
||||
def __init__(self, **kwargs):
|
||||
return
|
||||
|
@ -498,14 +503,11 @@ class StixBuilder():
|
|||
labels, markings = self.create_labels(attribute)
|
||||
attribute_value = attribute['value'] if attribute_type != "AS" else self.define_attribute_value(attribute['value'], attribute['comment'])
|
||||
pattern = mispTypesMapping[attribute_type]['pattern'](attribute_type, attribute_value, attribute['data']) if attribute.get('data') else self.define_pattern(attribute_type, attribute_value)
|
||||
indicator_args = {'id': indicator_id, 'type': 'indicator', 'labels': labels, 'kill_chain_phases': killchain,
|
||||
'valid_from': self.misp_event['date'], 'created_by_ref': self.identity_id,
|
||||
'pattern': pattern, 'interoperability': True}
|
||||
if hasattr(attribute, 'Sighting'):
|
||||
for sighting in attribute['Sighting']:
|
||||
if sighting['Organisation']['name'] == self.misp_event['Orgc']['name'] and sighting['type'] == "2":
|
||||
indicator_args['valid_until'] = self.get_datetime_from_timestamp(sighting['date_sighting'])
|
||||
break
|
||||
timestamp = self.get_datetime_from_timestamp(attribute['timestamp'])
|
||||
indicator_args = {'id': indicator_id, 'type': 'indicator', 'labels': labels,
|
||||
'kill_chain_phases': killchain, 'created_by_ref': self.identity_id,
|
||||
'pattern': pattern, 'interoperability': True}
|
||||
indicator_args.update(self.handle_time_fields(attribute, timestamp, 'indicator'))
|
||||
if attribute.get('comment'):
|
||||
indicator_args['description'] = attribute['comment']
|
||||
if markings:
|
||||
|
@ -534,8 +536,9 @@ class StixBuilder():
|
|||
attribute_value = attribute['value'] if attribute_type != "AS" else self.define_attribute_value(attribute['value'], attribute['comment'])
|
||||
observable = mispTypesMapping[attribute_type]['observable'](attribute_type, attribute_value, attribute['data']) if attribute.get('data') else self.define_observable(attribute_type, attribute_value)
|
||||
observed_data_args = {'id': observed_data_id, 'type': 'observed-data', 'number_observed': 1,
|
||||
'first_observed': timestamp, 'last_observed': timestamp, 'labels': labels,
|
||||
'created_by_ref': self.identity_id, 'objects': observable, 'interoperability': True}
|
||||
'objects': observable, 'created_by_ref': self.identity_id,
|
||||
'labels': labels, 'interoperability': True}
|
||||
observed_data_args.update(self.handle_time_fields(attribute, timestamp, 'observed-data'))
|
||||
if markings:
|
||||
observed_data_args['object_marking_refs'] = self.handle_tags(markings)
|
||||
observed_data = ObservedData(**observed_data_args)
|
||||
|
@ -593,15 +596,17 @@ class StixBuilder():
|
|||
category = misp_object.get('meta-category')
|
||||
labels = self.create_object_labels(name, category, to_ids)
|
||||
values = self.fetch_custom_values(misp_object['Attribute'], custom_object_id)
|
||||
custom_object_args = {'id': custom_object_id, 'x_misp_values': values, 'labels': labels,
|
||||
'x_misp_category': category, 'created_by_ref': self.identity_id,
|
||||
'x_misp_timestamp': self.get_datetime_from_timestamp(misp_object['timestamp'])}
|
||||
timestamp = self.get_datetime_from_timestamp(misp_object['timestamp'])
|
||||
custom_object_args = {'id': custom_object_id, 'x_misp_values': values,
|
||||
'created': timestamp, 'modified': timestamp, 'labels': labels,
|
||||
'x_misp_category': category, 'created_by_ref': self.identity_id}
|
||||
if hasattr(misp_object, 'comment') and misp_object.get('comment'):
|
||||
custom_object_args['x_misp_comment'] = misp_object['comment']
|
||||
@CustomObject(custom_object_type, [('id', properties.StringProperty(required=True)),
|
||||
('x_misp_timestamp', properties.StringProperty(required=True)),
|
||||
('labels', properties.ListProperty(labels, required=True)),
|
||||
('x_misp_values', properties.DictionaryProperty(required=True)),
|
||||
('created', properties.TimestampProperty(required=True, precision='millisecond')),
|
||||
('modified', properties.TimestampProperty(required=True, precision='millisecond')),
|
||||
('created_by_ref', properties.StringProperty(required=True)),
|
||||
('x_misp_comment', properties.StringProperty()),
|
||||
('x_misp_category', properties.StringProperty())
|
||||
|
@ -623,11 +628,13 @@ class StixBuilder():
|
|||
category = misp_object.get('meta-category')
|
||||
killchain = self.create_killchain(category)
|
||||
labels = self.create_object_labels(name, category, True)
|
||||
indicator_args = {'id': indicator_id, 'valid_from': self.misp_event['date'],
|
||||
'type': 'indicator', 'labels': labels, 'pattern': pattern,
|
||||
timestamp = self.get_datetime_from_timestamp(misp_object['timestamp'])
|
||||
indicator_args = {'id': indicator_id, 'type': 'indicator',
|
||||
'labels': labels, 'pattern': pattern,
|
||||
'description': misp_object['description'], 'allow_custom': True,
|
||||
'kill_chain_phases': killchain, 'interoperability': True,
|
||||
'created_by_ref': self.identity_id}
|
||||
indicator_args.update(self.handle_time_fields(misp_object, timestamp, 'indicator'))
|
||||
indicator = Indicator(**indicator_args)
|
||||
self.append_object(indicator)
|
||||
|
||||
|
@ -644,8 +651,8 @@ class StixBuilder():
|
|||
timestamp = self.get_datetime_from_timestamp(misp_object['timestamp'])
|
||||
observed_data_args = {'id': observed_data_id, 'type': 'observed-data', 'labels': labels,
|
||||
'number_observed': 1, 'objects': observable_objects, 'allow_custom': True,
|
||||
'first_observed': timestamp, 'last_observed': timestamp,
|
||||
'created_by_ref': self.identity_id, 'interoperability': True}
|
||||
observed_data_args.update(self.handle_time_fields(misp_object, timestamp, 'observed-data'))
|
||||
try:
|
||||
observed_data = ObservedData(**observed_data_args)
|
||||
except exceptions.InvalidValueError:
|
||||
|
@ -1417,6 +1424,13 @@ class StixBuilder():
|
|||
def get_datetime_from_timestamp(timestamp):
|
||||
return datetime.datetime.utcfromtimestamp(int(timestamp))
|
||||
|
||||
@staticmethod
|
||||
def handle_time_fields(attribute, timestamp, stix_type):
|
||||
to_return = {'created': timestamp, 'modified': timestamp}
|
||||
for misp_field, stix_field in zip(('first_seen', 'last_seen'), _time_fields[stix_type]):
|
||||
to_return[stix_field] = attribute[misp_field] if attribute[misp_field] else timestamp
|
||||
return to_return
|
||||
|
||||
def main(args):
|
||||
stix_builder = StixBuilder()
|
||||
stix_builder.loadEvent(args)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 00b6fafdff7c5242115f0f97be6247dc25fd1f09
|
||||
Subproject commit 28687d90d575332776480cd5d683361e7485033c
|
|
@ -766,7 +766,7 @@ class EventGraph {
|
|||
group: group,
|
||||
mass: 5,
|
||||
};
|
||||
if (node.type == 'attachment' && isPicture(node.value)) {
|
||||
if (node.type == 'attachment' && isPicture(node.label)) {
|
||||
// fetch picture via attributes/viewPicture
|
||||
node_conf.group = 'attribute_image';
|
||||
node_conf.size = $('#slider_display_picture_size').val();
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 77ca5ae2f9742652cd90a53f1b83308a8343f2cc
|
||||
Subproject commit 65a943d8929c578041f789665b05810ea68986cb
|
738
db_schema.json
738
db_schema.json
File diff suppressed because it is too large
Load Diff
|
@ -29,7 +29,8 @@ if [ "$1" = "configure" ] ; then
|
|||
|
||||
cd /usr/share/misp/app
|
||||
sudo -u www-data composer dump-autoload
|
||||
|
||||
sudo -u www-data composer install --ignore-platform-reqs
|
||||
|
||||
phpenmod redis
|
||||
phpenmod gnupg
|
||||
|
||||
|
@ -55,9 +56,8 @@ if [ "$1" = "configure" ] ; then
|
|||
mysql -h$HOST -uroot -p$ROOTPWD -e "CREATE USER IF NOT EXISTS '$MISPDBUSER'@'localhost' IDENTIFIED BY '$MISPDBUSERPWD';"
|
||||
mysql -h$HOST -uroot -p$ROOTPWD -e "GRANT ALL PRIVILEGES ON misp.* TO '$MISPDBUSER'@'localhost';"
|
||||
mysql -h$HOST -uroot -p$ROOTPWD -e "FLUSH PRIVILEGES;"
|
||||
mysql -h$HOST -uroot -p$ROOTPWD -e "CREATE DATABASE $MISPDB;"
|
||||
echo "Creating MISP Database..."
|
||||
gunzip < /usr/share/doc/misp/MYSQL.sql.gz | mysql -h$HOST -u$MISPDBUSER -p$MISPDBUSERPWD $MISPDB
|
||||
mysql -h$HOST -uroot -p$ROOTPWD -e "CREATE DATABASE $MISPDB;" && gunzip < /usr/share/doc/misp/MYSQL.sql.gz | mysql -h$HOST -u$MISPDBUSER -p$MISPDBUSERPWD $MISPDB || true
|
||||
|
||||
# /usr/share/misp/app/Config/database.php
|
||||
echo "Updating salt..."
|
||||
|
@ -69,11 +69,18 @@ if [ "$1" = "configure" ] ; then
|
|||
sed -i -E "s/'password'\s=>\s'db password'/'password' => '$MISPDBUSERPWD'/" /usr/share/misp/app/Config/database.php
|
||||
sed -i -E "s/'database'\s=>\s'misp'/'database' => '$MISPDB'/" /usr/share/misp/app/Config/database.php
|
||||
|
||||
composer require resque/php-resque || true
|
||||
# composer require resque/php-resque || true
|
||||
# No composer.json in current directory, do you want to use the one at /usr/share/misp/app? [Y,n]? Y
|
||||
|
||||
|
||||
sudo -u www-data /usr/share/misp/app/Console/cake admin setSetting MISP.baseurl "$BASEURL"
|
||||
|
||||
echo "{\"major\":2, \"minor\":4, \"hotfix\":221}" > /usr/share/misp/VERSION.json
|
||||
|
||||
#
|
||||
# Starting MISP Workers at every boot
|
||||
#
|
||||
chmod +x /usr/share/misp/app/Console/worker/start.sh
|
||||
cat /usr/share/doc/misp/misp-workers.service > /etc/systemd/system/misp-workers.service
|
||||
sed -i -E "s/\/var\/www\/MISP/\/usr\/share\/misp/" /etc/systemd/system/misp-workers.service
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable --now misp-workers
|
||||
fi
|
||||
|
||||
|
|
Loading…
Reference in New Issue