Merge branch '2.4' into feature/bro-export

Conflicts:
	app/Model/Event.php
pull/1544/head
Iglocska 2016-09-15 18:00:25 +02:00
commit 2cede15e68
76 changed files with 2412 additions and 817 deletions

View File

@ -45,6 +45,8 @@ pear channel-update pear.php.net
pear install Crypt_GPG # we need version >1.3.0
NOTE: if using rh-php56 the command needs to be run through its terminal: /usr/bin/scl enable rh-php56 "pear list | grep Crypt_GPG"
# GPG needs lots of entropy, haveged provides entropy
yum install haveged
systemctl enable haveged.service
@ -111,6 +113,8 @@ echo "extension=redis.so" > /etc/opt/rh/rh-php56/php-fpm.d/redis.ini
ln -s ../php-fpm.d/redis.ini /etc/opt/rh/rh-php56/php.d/99-redis.ini
systemctl restart rh-php56-php-fpm.service
Note: if using rh-php56 redis needs to be installed through its terminal: /usr/bin/scl enable rh-php56 "pecl install redis-2.2.8"
# If you have not yet set a timezone in php.ini
echo 'date.timezone = "Europe/Amsterdam"' > /etc/opt/rh/rh-php56/php-fpm.d/timezone.ini
ln -s ../php-fpm.d/timezone.ini /etc/opt/rh/rh-php56/php.d/99-timezone.ini
@ -167,13 +171,13 @@ mysql -u misp -p misp < INSTALL/MYSQL.sql
cp /var/www/MISP/INSTALL/apache.misp.centos7 /etc/httpd/conf.d/misp.conf
# Since SELinux is enabled, we need to allow httpd to write to certain directories
chcon -t httpd_sys_content_rw_t /var/www/MISP/app/files
chcon -t httpd_sys_content_rw_t /var/www/MISP/app/files/terms
chcon -t httpd_sys_content_rw_t /var/www/MISP/app/files/scripts/tmp
chcon -t httpd_sys_content_rw_t /var/www/MISP/app/Plugin/CakeResque/tmp
chcon -R -t httpd_sys_content_rw_t /var/www/MISP/app/tmp
chcon -R -t httpd_sys_content_rw_t /var/www/MISP/app/webroot/img/orgs
chcon -R -t httpd_sys_content_rw_t /var/www/MISP/app/webroot/img/custom
chcon -t httpd_sys_rw_content_t /var/www/MISP/app/files
chcon -t httpd_sys_rw_content_t /var/www/MISP/app/files/terms
chcon -t httpd_sys_rw_content_t /var/www/MISP/app/files/scripts/tmp
chcon -t httpd_sys_rw_content_t /var/www/MISP/app/Plugin/CakeResque/tmp
chcon -R -t httpd_sys_rw_content_t /var/www/MISP/app/tmp
chcon -R -t httpd_sys_rw_content_t /var/www/MISP/app/webroot/img/orgs
chcon -R -t httpd_sys_rw_content_t /var/www/MISP/app/webroot/img/custom
# Allow httpd to connect to the redis server and php-fpm over tcp/ip
setsebool -P httpd_can_network_connect on
@ -210,7 +214,7 @@ cp -a config.default.php config.php
# If you want to be able to change configuration parameters from the webinterface:
chown apache:apache /var/www/MISP/app/Config/config.php
chcon -t httpd_sys_content_rw_t /var/www/MISP/app/Config/config.php
chcon -t httpd_sys_rw_content_t /var/www/MISP/app/Config/config.php
# Generate a GPG encryption key.
# If the following command gives an error message, try it as root from the console

View File

@ -0,0 +1,100 @@
INSTALLATION INSTRUCTIONS
------------------------- for Debian 8 "jessie" server + PostgreSQL
######### WARNING #########
PostgreSQL support in MISP is experimental.
We strongly discourage you from use on production systems.
Testing & development: most recent MISP codebase on Debian 8 "jessie" (PHP 5.6 & PostgreSQL 9.4).
There may be serious bugs!
We also don't support updates (e.g. 2.4.49 -> 2.4.50) on PostgreSQL yet, so your installation may break.
If you want to help improving PostgreSQL-support,
Please make sure you have tried the newest commit from GitHub first.
Also, please activate debug mode.
After that, you may open an issue on Github and provide us with as much information on the issue as possible.
###########################
please follow Debian 8 install instructions - INSTALL.debian8.txt
-------------------------
# when it comes to installing mariadb in step 2, skip that part, instead:
sudo apt-get install postgresql
# instead of installing the php5-mysql package in step 2, install php5-pgsql
sudo apt-get install php5-pgsql
# activate the module
sudo php5enmod pgsql
# restart apache
sudo service apache2 restart
# in step 6 of the Debian install, you skip creating a mysql user, instead:
# create user
sudo -u postgres createuser misp
# create database
sudo -u postgres createdb -O misp misp
# set password
sudo -u postgres psql -U postgres
postgres=# ALTER USER misp with password 'XXXXXXXXX';
postgres=# \q
# after that, load the basic database structure
psql -U misp -d misp -f /var/www/MISP/INSTALL/POSTGRESQL-structure.sql -h localhost -W
# ATTENTION: skip this step if you want to migrate from MySQL/MariaDB!
# and load initial data
psql -U misp -d misp -f /var/www/MISP/INSTALL/POSTGRESQL-data-initial.sql -h localhost -W
# in step 8 of the Debian install, you configure Postgres instead of MySQL
# the necessary lines are already there, you just have to activate them instead of the MySQL-lines
# file: /var/www/MISP/app/Config/database.php
# necessary changes:
# 'datasource' => 'Database/Postgres',
# 'port' => 5432,
# ATTENTION: skip this step if you want to migrate from MySQL/MariaDB!
# perhaps you accidently installed MySQL/MariaDB, too - but you can clean it up like this
sudo apt-get remove mysql-server mysql-client mariadb-client mariadb-server php5-mysql
### MIGRATION from MySQL/MariaDB
# migration of data is done using latest "pgloader" release (3.2.2 at the time of writing)
# add official postgres repository to apt sources
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
# make sure packages from official postgres repository aren't used by default, only when explicitly specifying it
sudo cat <<EOF > /etc/apt/preferences.d/pgdg.pref
Package: *
Pin: release o=apt.postgresql.org
Pin-Priority: 200
EOF
# install some dependencies
sudo apt-get install wget ca-certificates
# add repository signing key
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# update cache
sudo apt-get update
# install pgloader
sudo apt-get -t $(lsb_release -cs)-pgdg install pgloader
# migrate data (replace XXX and YYY with the correct passwords)
pgloader --type mysql --with "reset sequences" --with "data only" --set "maintenance_work_mem = '128MB'" --set "work_mem = '12MB'" --cast "type tinyint when (= precision 1) to smallint" mysql://misp:XXX@localhost/misp postgresql://misp:YYY@localhost/misp
# afterwards, you have to change your MISP database configuration (see above)
# maybe you want to remove mysql (see command above) in the end
# if you only want to stop&disable it:
systemctl stop mysql
systemctl disable mysql

View File

@ -121,11 +121,11 @@ CREATE TABLE IF NOT EXISTS `events` (
`publish_timestamp` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE INDEX `uuid` (`uuid`),
FULLTEXT INDEX `info` (`info`),
INDEX `info` (`info`(255)),
INDEX `sharing_group_id` (`sharing_group_id`),
INDEX `org_id` (`org_id`),
INDEX `orgc_id` (`orgc_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- -------------------------------------------------------
@ -339,6 +339,7 @@ CREATE TABLE IF NOT EXISTS `roles` (
`perm_template` tinyint(1) NOT NULL DEFAULT 0,
`perm_sharing_group` tinyint(1) NOT NULL DEFAULT 0,
`perm_tag_editor` tinyint(1) NOT NULL DEFAULT 0,
`default_role` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
@ -364,6 +365,8 @@ CREATE TABLE IF NOT EXISTS `servers` (
`pull_rules` text COLLATE utf8_bin NOT NULL,
`push_rules` text COLLATE utf8_bin NOT NULL,
`cert_file` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`client_cert_file` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`internal` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
INDEX `org_id` (`org_id`),
INDEX `remote_org_id` (`remote_org_id`)
@ -799,7 +802,7 @@ CREATE TABLE IF NOT EXISTS `whitelist` (
--
INSERT INTO `admin_settings` (`id`, `setting`, `value`) VALUES
(1, 'db_version', '2.4.49');
(1, 'db_version', '2.4.51');
INSERT INTO `feeds` (`id`, `provider`, `name`, `url`, `distribution`, `default`, `enabled`) VALUES
(1, 'CIRCL', 'CIRCL OSINT Feed', 'https://www.circl.lu/doc/misp/feed-osint', 3, 1, 0),
@ -850,26 +853,26 @@ INSERT INTO `feeds` (`id`, `provider`, `name`, `url`, `distribution`, `default`,
-- 7. Read Only - read
--
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (1, 'admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (1, 'admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (2, 'Org Admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (2, 'Org Admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (3, 'User', NOW(), NOW(), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (3, 'User', NOW(), NOW(), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (4, 'Publisher', NOW(), NOW(), 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (4, 'Publisher', NOW(), NOW(), 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (5, 'Sync user', NOW(), NOW(), 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (5, 'Sync user', NOW(), NOW(), 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (6, 'Automation user', NOW(), NOW(), 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (6, 'Automation user', NOW(), NOW(), 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`)
VALUES (7, 'Read Only', NOW(), NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO `roles` (`id`, `name`, `created`, `modified`, `perm_add`, `perm_modify`, `perm_modify_org`, `perm_publish`, `perm_sync`, `perm_admin`, `perm_audit`, `perm_full`, `perm_auth`, `perm_regexp_access`, `perm_tagger`, `perm_site_admin`, `perm_template`, `perm_sharing_group`, `perm_tag_editor`, `perm_delegate`, `default_role`)
VALUES (7, 'Read Only', NOW(), NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-- --------------------------------------------------------

View File

@ -0,0 +1,212 @@
-- --------------------------------------------------------
--
-- Default values for initial installation
--
INSERT INTO admin_settings (id, setting, value) VALUES
(1, 'db_version', '2.4.51');
SELECT SETVAL('admin_settings_id_seq', (SELECT MAX(id) FROM admin_settings));
INSERT INTO feeds (id, provider, name, url, distribution, "default", enabled) VALUES
(1, 'CIRCL', 'CIRCL OSINT Feed', 'https://www.circl.lu/doc/misp/feed-osint', 3, 1, 0),
(2, 'Botvrij.eu', 'The Botvrij.eu Data', 'http://www.botvrij.eu/data/feed-osint', 3, 1, 0);
SELECT SETVAL('feeds_id_seq', (SELECT MAX(id) FROM feeds));
INSERT INTO regexp (id, regexp, replacement, type) VALUES
(1, '/.:.ProgramData./i', '%ALLUSERSPROFILE%\\\\', 'ALL'),
(2, '/.:.Documents and Settings.All Users./i', '%ALLUSERSPROFILE%\\\\', 'ALL'),
(3, '/.:.Program Files.Common Files./i', '%COMMONPROGRAMFILES%\\\\', 'ALL'),
(4, '/.:.Program Files (x86).Common Files./i', '%COMMONPROGRAMFILES(x86)%\\\\', 'ALL'),
(5, '/.:.Users\\\\(.*?)\\\\AppData.Local.Temp./i', '%TEMP%\\\\', 'ALL'),
(6, '/.:.ProgramData./i', '%PROGRAMDATA%\\\\', 'ALL'),
(7, '/.:.Program Files./i', '%PROGRAMFILES%\\\\', 'ALL'),
(8, '/.:.Program Files (x86)./i', '%PROGRAMFILES(X86)%\\\\', 'ALL'),
(9, '/.:.Users.Public./i', '%PUBLIC%\\\\', 'ALL'),
(10, '/.:.Documents and Settings\\\\(.*?)\\\\Local Settings.Temp./i', '%TEMP%\\\\', 'ALL'),
(11, '/.:.Users\\\\(.*?)\\\\AppData.Local.Temp./i', '%TEMP%\\\\', 'ALL'),
(12, '/.:.Users\\\\(.*?)\\\\AppData.Local./i', '%LOCALAPPDATA%\\\\', 'ALL'),
(13, '/.:.Users\\\\(.*?)\\\\AppData.Roaming./i', '%APPDATA%\\\\', 'ALL'),
(14, '/.:.Users\\\\(.*?)\\\\Application Data./i', '%APPDATA%\\\\', 'ALL'),
(15, '/.:.Windows\\\\(.*?)\\\\Application Data./i', '%APPDATA%\\\\', 'ALL'),
(16, '/.:.Users\\\\(.*?)\\\\/i', '%USERPROFILE%\\\\', 'ALL'),
(17, '/.:.DOCUME~1.\\\\(.*?)\\\\/i', '%USERPROFILE%\\\\', 'ALL'),
(18, '/.:.Documents and Settings\\\\(.*?)\\\\/i', '%USERPROFILE%\\\\', 'ALL'),
(19, '/.:.Windows./i', '%WINDIR%\\\\', 'ALL'),
(20, '/.:.Windows./i', '%WINDIR%\\\\', 'ALL'),
(21, '/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{9}){1}(-[0-9]{10}){1}-[0-9]{9}-[0-9]{4}/i', 'HKCU', 'ALL'),
(22, '/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{10}){2}-[0-9]{9}-[0-9]{4}/i', 'HKCU', 'ALL'),
(23, '/.REGISTRY.USER.S(-[0-9]{1}){2}-[0-9]{2}(-[0-9]{10}){3}-[0-9]{4}/i', 'HKCU', 'ALL'),
(24, '/.REGISTRY.MACHINE./i', 'HKLM\\\\', 'ALL'),
(25, '/.Registry.Machine./i', 'HKLM\\\\', 'ALL'),
(26, '/%USERPROFILE%.Application Data.Microsoft.UProof/i', '', 'ALL'),
(27, '/%USERPROFILE%.Local Settings.History/i', '', 'ALL'),
(28, '/%APPDATA%.Microsoft.UProof/i ', '', 'ALL'),
(29, '/%LOCALAPPDATA%.Microsoft.Windows.Temporary Internet Files/i', '', 'ALL');
SELECT SETVAL('regexp_id_seq', (SELECT MAX(id) FROM regexp));
-- --------------------------------------------------------
--
-- Creating initial roles
--
-- 1. Admin - has full access
-- 2. Org Admin - read/write/publish/audit/admin/sync/auth/tagger
-- 3. User - User - Read / Write, no other permissions (default)
-- 4. Publisher
-- 5. Sync user - read/write/publish/sync/auth
-- 6. Automation user - read/write/publish/auth
-- 7. Read Only - read
--
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES (1, 'admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0);
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES ('2', 'Org Admin', NOW(), NOW(), 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0);
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES ('3', 'User', NOW(), NOW(), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES ('4', 'Publisher', NOW(), NOW(), 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES ('5', 'Sync user', NOW(), NOW(), 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0);
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES ('6', 'Automation user', NOW(), NOW(), 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0);
INSERT INTO roles (id, name, created, modified, perm_add, perm_modify, perm_modify_org, perm_publish, perm_sync, perm_admin, perm_audit, perm_full, perm_auth, perm_regexp_access, perm_tagger, perm_site_admin, perm_template, perm_sharing_group, perm_tag_editor, perm_delegate, default_role)
VALUES ('7', 'Read Only', NOW(), NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
SELECT SETVAL('roles_id_seq', (SELECT MAX(id) FROM roles));
-- --------------------------------------------------------
--
-- Initial threat levels
--
INSERT INTO threat_levels (id, name, description, form_description)
VALUES
(1, 'High', '*high* means sophisticated APT malware or 0-day attack', 'Sophisticated APT malware or 0-day attack'),
(2, 'Medium', '*medium* means APT malware', 'APT malware'),
(3, 'Low', '*low* means mass-malware', 'Mass-malware'),
(4, 'Undefined', '*undefined* no risk', 'No risk');
SELECT SETVAL('threat_levels_id_seq', (SELECT MAX(id) FROM threat_levels));
-- --------------------------------------------------------
--
-- Default templates
--
INSERT INTO templates (id, name, description, org, share) VALUES
(1, 'Phishing E-mail', 'Create a MISP event about a Phishing E-mail.', 'MISP', 1),
(2, 'Phishing E-mail with malicious attachment', 'A MISP event based on Spear-phishing containing a malicious attachment. This event can include anything from the description of the e-mail itself, the malicious attachment and its description as well as the results of the analysis done on the malicious f', 'MISP', 1),
(3, 'Malware Report', 'This is a template for a generic malware report. ', 'MISP', 1),
(4, 'Indicator List', 'A simple template for indicator lists.', 'MISP', 1);
SELECT SETVAL('templates_id_seq', (SELECT MAX(id) FROM templates));
INSERT INTO template_elements (id, template_id, position, element_definition) VALUES
(1, 1, 2, 'attribute'),
(2, 1, 3, 'attribute'),
(3, 1, 1, 'text'),
(4, 1, 4, 'attribute'),
(5, 1, 5, 'text'),
(6, 1, 6, 'attribute'),
(7, 1, 7, 'attribute'),
(8, 1, 8, 'attribute'),
(11, 2, 1, 'text'),
(12, 2, 2, 'attribute'),
(13, 2, 3, 'text'),
(14, 2, 4, 'file'),
(15, 2, 5, 'attribute'),
(16, 2, 10, 'text'),
(17, 2, 6, 'attribute'),
(18, 2, 7, 'attribute'),
(19, 2, 8, 'attribute'),
(20, 2, 9, 'attribute'),
(21, 2, 11, 'file'),
(22, 2, 12, 'attribute'),
(23, 2, 13, 'attribute'),
(24, 2, 14, 'attribute'),
(25, 2, 15, 'attribute'),
(26, 2, 16, 'attribute'),
(27, 2, 17, 'attribute'),
(28, 2, 18, 'attribute'),
(29, 3, 1, 'text'),
(30, 3, 2, 'file'),
(31, 3, 4, 'text'),
(32, 3, 9, 'text'),
(33, 3, 11, 'text'),
(34, 3, 10, 'attribute'),
(35, 3, 12, 'attribute'),
(36, 3, 3, 'attribute'),
(37, 3, 5, 'attribute'),
(38, 3, 6, 'attribute'),
(39, 3, 7, 'attribute'),
(40, 3, 8, 'file'),
(41, 3, 13, 'text'),
(42, 3, 14, 'attribute'),
(43, 3, 15, 'attribute'),
(44, 3, 16, 'attribute'),
(45, 4, 1, 'text'),
(46, 4, 2, 'attribute'),
(47, 4, 3, 'attribute');
SELECT SETVAL('template_elements_id_seq', (SELECT MAX(id) FROM template_elements));
INSERT INTO template_element_attributes (id, template_element_id, name, description, to_ids, category, complex, type, mandatory, batch) VALUES
(1, 1, 'From address', 'The source address from which the e-mail was sent.', 1, 'Payload delivery', 0, 'email-src', 1, 1),
(2, 2, 'Malicious url', 'The malicious url in the e-mail body.', 1, 'Payload delivery', 0, 'url', 1, 1),
(3, 4, 'E-mail subject', 'The subject line of the e-mail.', 0, 'Payload delivery', 0, 'email-subject', 1, 0),
(4, 6, 'Spoofed source address', 'If an e-mail address was spoofed, specify which.', 1, 'Payload delivery', 0, 'email-src', 0, 0),
(5, 7, 'Source IP', 'The source IP from which the e-mail was sent', 1, 'Payload delivery', 0, 'ip-src', 0, 1),
(6, 8, 'X-mailer header', 'It could be useful to capture which application and which version thereof was used to send the message, as described by the X-mailer header.', 1, 'Payload delivery', 0, 'text', 0, 1),
(7, 12, 'From address', 'The source address from which the e-mail was sent', 1, 'Payload delivery', 0, 'email-src', 1, 1),
(8, 15, 'Spoofed From Address', 'The spoofed source address from which the e-mail appears to be sent.', 1, 'Payload delivery', 0, 'email-src', 0, 1),
(9, 17, 'E-mail Source IP', 'The IP address from which the e-mail was sent.', 1, 'Payload delivery', 0, 'ip-src', 0, 1),
(10, 18, 'X-mailer header', 'It could be useful to capture which application and which version thereof was used to send the message, as described by the X-mailer header.', 1, 'Payload delivery', 0, 'text', 0, 0),
(11, 19, 'Malicious URL in the e-mail', 'If there was a malicious URL (or several), please specify it here', 1, 'Payload delivery', 0, 'ip-dst', 0, 1),
(12, 20, 'Exploited vulnerablity', 'The vulnerabilities exploited during the payload delivery.', 0, 'Payload delivery', 0, 'vulnerability', 0, 1),
(13, 22, 'C2 information', 'Command and Control information detected during the analysis.', 1, 'Network activity', 1, 'CnC', 0, 1),
(14, 23, 'Artifacts dropped (File)', 'Any information about the files dropped during the analysis', 1, 'Artifacts dropped', 1, 'File', 0, 1),
(15, 24, 'Artifacts dropped (Registry key)', 'Any registry keys touched during the analysis', 1, 'Artifacts dropped', 0, 'regkey', 0, 1),
(16, 25, 'Artifacts dropped (Registry key + value)', 'Any registry keys created or altered together with the value.', 1, 'Artifacts dropped', 0, 'regkey|value', 0, 1),
(17, 26, 'Persistance mechanism (filename)', 'Filenames (or filenames with filepaths) used as a persistence mechanism', 1, 'Persistence mechanism', 0, 'regkey|value', 0, 1),
(18, 27, 'Persistence mechanism (Registry key)', 'Any registry keys touched as part of the persistence mechanism during the analysis ', 1, 'Persistence mechanism', 0, 'regkey', 0, 1),
(19, 28, 'Persistence mechanism (Registry key + value)', 'Any registry keys created or modified together with their values used by the persistence mechanism', 1, 'Persistence mechanism', 0, 'regkey|value', 0, 1),
(20, 34, 'C2 Information', 'You can drop any urls, domains, hostnames or IP addresses that were detected as the Command and Control during the analysis here. ', 1, 'Network activity', 1, 'CnC', 0, 1),
(21, 35, 'Other Network Activity', 'Drop any applicable information about other network activity here. The attributes created here will NOT be marked for IDS exports.', 0, 'Network activity', 1, 'CnC', 0, 1),
(22, 36, 'Vulnerability', 'The vulnerability or vulnerabilities that the sample exploits', 0, 'Payload delivery', 0, 'vulnerability', 0, 1),
(23, 37, 'Artifacts Dropped (File)', 'Insert any data you have on dropped files here.', 1, 'Artifacts dropped', 1, 'File', 0, 1),
(24, 38, 'Artifacts dropped (Registry key)', 'Any registry keys touched during the analysis', 1, 'Artifacts dropped', 0, 'regkey', 0, 1),
(25, 39, 'Artifacts dropped (Registry key + value)', 'Any registry keys created or altered together with the value.', 1, 'Artifacts dropped', 0, 'regkey|value', 0, 1),
(26, 42, 'Persistence mechanism (filename)', 'Insert any filenames used by the persistence mechanism.', 1, 'Persistence mechanism', 0, 'filename', 0, 1),
(27, 43, 'Persistence Mechanism (Registry key)', 'Paste any registry keys that were created or modified as part of the persistence mechanism', 1, 'Persistence mechanism', 0, 'regkey', 0, 1),
(28, 44, 'Persistence Mechanism (Registry key and value)', 'Paste any registry keys together with the values contained within created or modified by the persistence mechanism', 1, 'Persistence mechanism', 0, 'regkey|value', 0, 1),
(29, 46, 'Network Indicators', 'Paste any combination of IP addresses, hostnames, domains or URL', 1, 'Network activity', 1, 'CnC', 0, 1),
(30, 47, 'File Indicators', 'Paste any file hashes that you have (MD5, SHA1, SHA256) or filenames below. You can also add filename and hash pairs by using the following syntax for each applicable column: filename|hash ', 1, 'Payload installation', 1, 'File', 0, 1);
SELECT SETVAL('template_element_attributes_id_seq', (SELECT MAX(id) FROM template_element_attributes));
INSERT INTO template_element_files (id, template_element_id, name, description, category, malware, mandatory, batch) VALUES
(1, 14, 'Malicious Attachment', 'The file (or files) that was (were) attached to the e-mail itself.', 'Payload delivery', 1, 0, 1),
(2, 21, 'Payload installation', 'Payload installation detected during the analysis', 'Payload installation', 1, 0, 1),
(3, 30, 'Malware sample', 'The sample that the report is based on', 'Payload delivery', 1, 0, 0),
(4, 40, 'Artifacts dropped (Sample)', 'Upload any files that were dropped during the analysis.', 'Artifacts dropped', 1, 0, 1);
SELECT SETVAL('template_element_files_id_seq', (SELECT MAX(id) FROM template_element_files));
INSERT INTO template_element_texts (id, name, template_element_id, text) VALUES
(1, 'Required fields', 3, 'The fields below are mandatory.'),
(2, 'Optional information', 5, 'All of the fields below are optional, please fill out anything that''s applicable.'),
(4, 'Required Fields', 11, 'The following fields are mandatory'),
(5, 'Optional information about the payload delivery', 13, 'All of the fields below are optional, please fill out anything that''s applicable. This section describes the payload delivery, including the e-mail itself, the attached file, the vulnerability it is exploiting and any malicious urls in the e-mail.'),
(6, 'Optional information obtained from analysing the malicious file', 16, 'Information about the analysis of the malware (if applicable). This can include C2 information, artifacts dropped during the analysis, persistance mechanism, etc.'),
(7, 'Malware Sample', 29, 'If you can, please upload the sample that the report revolves around.'),
(8, 'Dropped Artifacts', 31, 'Describe any dropped artifacts that you have encountered during your analysis'),
(9, 'C2 Information', 32, 'The following field deals with Command and Control information obtained during the analysis. All fields are optional.'),
(10, 'Other Network Activity', 33, 'If any other Network activity (such as an internet connection test) was detected during the analysis, please specify it using the following fields'),
(11, 'Persistence mechanism', 41, 'The following fields allow you to describe the persistence mechanism used by the malware'),
(12, 'Indicators', 45, 'Just paste your list of indicators based on type into the appropriate field. All of the fields are optional, so inputting a list of IP addresses into the Network indicator field for example is sufficient to complete this template.');
SELECT SETVAL('template_element_texts_id_seq', (SELECT MAX(id) FROM template_element_texts));

View File

@ -0,0 +1,797 @@
-- --------------------------------------------------------
--
-- Table structure for table admin_settings
--
CREATE TABLE IF NOT EXISTS admin_settings (
id bigserial NOT NULL,
setting varchar(255) NOT NULL,
value text NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table attributes
--
CREATE TABLE IF NOT EXISTS attributes (
id bigserial NOT NULL,
event_id bigint NOT NULL,
category varchar(255) NOT NULL,
type varchar(100) NOT NULL,
value1 text NOT NULL,
value2 text NOT NULL,
to_ids smallint NOT NULL DEFAULT 1,
uuid varchar(40) NOT NULL,
timestamp bigint NOT NULL DEFAULT 0,
distribution smallint NOT NULL DEFAULT 0,
sharing_group_id bigint NOT NULL,
comment text NOT NULL,
deleted smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE (uuid)
);
CREATE INDEX idx_attributes_event_id ON attributes (event_id);
CREATE INDEX idx_attributes_sharing_group_id ON attributes (sharing_group_id);
CREATE INDEX idx_attributes_value1 ON attributes (value1);
CREATE INDEX idx_attributes_value2 ON attributes (value2);
-- --------------------------------------------------------
--
-- Table structure for table bruteforces
--
CREATE TABLE IF NOT EXISTS bruteforces (
ip varchar(255) NOT NULL,
username varchar(255) NOT NULL,
expire timestamp NOT NULL
);
-- --------------------------------------------------------
--
-- Table structure for table cake_sessions
--
CREATE TABLE IF NOT EXISTS cake_sessions (
id varchar(255) NOT NULL DEFAULT '',
data text NOT NULL,
expires bigint NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_cake_sessions_expires ON cake_sessions (expires);
-- --------------------------------------------------------
--
-- Table structure for table correlations
--
CREATE TABLE IF NOT EXISTS correlations (
id bigserial NOT NULL,
value text NOT NULL,
"1_event_id" bigint NOT NULL,
"1_attribute_id" bigint NOT NULL,
event_id bigint NOT NULL,
attribute_id bigint NOT NULL,
org_id bigint NOT NULL,
distribution smallint NOT NULL,
a_distribution smallint NOT NULL,
sharing_group_id bigint NOT NULL,
a_sharing_group_id bigint NOT NULL,
date date NOT NULL,
info text NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_correlations_event_id ON correlations (event_id);
CREATE INDEX idx_correlations_1_event_id ON correlations ("1_event_id");
CREATE INDEX idx_correlations_attribute_id ON correlations (attribute_id);
CREATE INDEX idx_correlations_1_attribute_id ON correlations ("1_attribute_id");
CREATE INDEX idx_correlations_org_id ON correlations (org_id);
CREATE INDEX idx_correlations_sharing_group_id ON correlations (sharing_group_id);
CREATE INDEX idx_correlations_a_sharing_group_id ON correlations (a_sharing_group_id);
-- --------------------------------------------------------
--
-- Table structure for table events
--
CREATE TABLE IF NOT EXISTS events (
id bigserial NOT NULL,
org_id bigint NOT NULL,
date date NOT NULL,
info text NOT NULL,
user_id bigint NOT NULL,
uuid varchar(40) NOT NULL,
published smallint NOT NULL DEFAULT 0,
analysis smallint NOT NULL,
attribute_count bigint CHECK (attribute_count >= 0) DEFAULT NULL,
orgc_id bigint NOT NULL,
timestamp bigint NOT NULL DEFAULT 0,
distribution smallint NOT NULL DEFAULT 0,
sharing_group_id bigint NOT NULL,
proposal_email_lock smallint NOT NULL DEFAULT 0,
locked smallint NOT NULL DEFAULT 0,
threat_level_id bigint NOT NULL,
publish_timestamp bigint NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE (uuid)
);
CREATE INDEX idx_events_info ON events (info);
CREATE INDEX idx_events_sharing_group_id ON events (sharing_group_id);
CREATE INDEX idx_events_org_id ON events (org_id);
CREATE INDEX idx_events_orgc_id ON events (orgc_id);
-- -------------------------------------------------------
--
-- Table structure for event_delegations
--
CREATE TABLE IF NOT EXISTS event_delegations (
id bigserial NOT NULL,
org_id bigint NOT NULL,
requester_org_id bigint NOT NULL,
event_id bigint NOT NULL,
message text,
distribution smallint NOT NULL DEFAULT -1,
sharing_group_id bigint,
PRIMARY KEY (id)
);
CREATE INDEX idx_event_delegations_org_id ON event_delegations (org_id);
CREATE INDEX idx_event_delegations_event_id ON event_delegations (event_id);
-- -------------------------------------------------------
--
-- Table structure for event_tags
--
CREATE TABLE IF NOT EXISTS event_tags (
id bigserial NOT NULL,
event_id bigint NOT NULL,
tag_id bigint NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_event_tags_event_id ON event_tags (event_id);
CREATE INDEX idx_event_tags_tag_id ON event_tags (tag_id);
-- -------------------------------------------------------
--
-- Table structure for favourite_tags
--
CREATE TABLE IF NOT EXISTS favourite_tags (
id bigserial NOT NULL,
tag_id bigint NOT NULL,
user_id bigint NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_favourite_tags_user_id ON favourite_tags (user_id);
CREATE INDEX idx_favourite_tags_tag_id ON favourite_tags (tag_id);
-- -------------------------------------------------------
--
-- Table structure for feeds
--
CREATE TABLE IF NOT EXISTS feeds (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
provider varchar(255) NOT NULL,
url varchar(255) NOT NULL,
rules text DEFAULT NULL,
enabled smallint NOT NULL,
distribution smallint NOT NULL,
sharing_group_id bigint NOT NULL DEFAULT 0,
tag_id bigint NOT NULL DEFAULT 0,
"default" smallint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table jobs
--
CREATE TABLE IF NOT EXISTS jobs (
id bigserial NOT NULL,
worker varchar(32) NOT NULL,
job_type varchar(32) NOT NULL,
job_input text NOT NULL,
status smallint NOT NULL DEFAULT 0,
retries bigint NOT NULL DEFAULT 0,
message text NOT NULL,
progress bigint NOT NULL DEFAULT 0,
org_id bigint NOT NULL DEFAULT 0,
process_id varchar(32) DEFAULT NULL,
date_created timestamp NOT NULL,
date_modified timestamp NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table logs
--
CREATE TABLE IF NOT EXISTS logs (
id bigserial NOT NULL,
title text DEFAULT NULL,
created timestamp NOT NULL,
model varchar(20) NOT NULL,
model_id bigint NOT NULL,
action varchar(20) NOT NULL,
user_id bigint NOT NULL,
change text DEFAULT NULL,
email varchar(255) NOT NULL,
org varchar(255) NOT NULL,
description text DEFAULT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table news
--
CREATE TABLE IF NOT EXISTS news (
id bigserial NOT NULL,
message text NOT NULL,
title text NOT NULL,
user_id bigint NOT NULL,
date_created bigint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table organisations
--
CREATE TABLE organisations (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
date_created timestamp NOT NULL,
date_modified timestamp NOT NULL,
description text,
type varchar(255),
nationality varchar(255),
sector varchar(255),
created_by bigint NOT NULL DEFAULT 0,
uuid varchar(40) DEFAULT NULL,
contacts text,
local smallint NOT NULL DEFAULT 0,
landingpage text,
PRIMARY KEY (id)
);
CREATE INDEX idx_organisations_uuid ON organisations (uuid);
CREATE INDEX idx_organisations_name ON organisations (name);
-- --------------------------------------------------------
--
-- Table structure for table posts
--
CREATE TABLE IF NOT EXISTS posts (
id bigserial NOT NULL,
date_created timestamp NOT NULL,
date_modified timestamp NOT NULL,
user_id bigint NOT NULL,
contents text NOT NULL,
post_id bigint NOT NULL DEFAULT 0,
thread_id bigint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
CREATE INDEX idx_posts_post_id ON posts (post_id);
CREATE INDEX idx_posts_thread_id ON posts (thread_id);
-- --------------------------------------------------------
--
-- Table structure for table regexp
--
CREATE TABLE IF NOT EXISTS regexp (
id bigserial NOT NULL,
regexp varchar(255) NOT NULL,
replacement varchar(255) NOT NULL,
type varchar(100) NOT NULL DEFAULT 'ALL',
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table roles
--
CREATE TABLE IF NOT EXISTS roles (
id bigserial NOT NULL,
name varchar(100) NOT NULL,
created timestamp DEFAULT NULL,
modified timestamp DEFAULT NULL,
perm_add smallint DEFAULT NULL,
perm_modify smallint DEFAULT NULL,
perm_modify_org smallint DEFAULT NULL,
perm_publish smallint DEFAULT NULL,
perm_delegate smallint NOT NULL DEFAULT 0,
perm_sync smallint DEFAULT NULL,
perm_admin smallint DEFAULT NULL,
perm_audit smallint DEFAULT NULL,
perm_full smallint DEFAULT NULL,
perm_auth smallint NOT NULL DEFAULT 0,
perm_site_admin smallint NOT NULL DEFAULT 0,
perm_regexp_access smallint NOT NULL DEFAULT 0,
perm_tagger smallint NOT NULL DEFAULT 0,
perm_template smallint NOT NULL DEFAULT 0,
perm_sharing_group smallint NOT NULL DEFAULT 0,
perm_tag_editor smallint NOT NULL DEFAULT 0,
default_role smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table servers
--
CREATE TABLE IF NOT EXISTS servers (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
url varchar(255) NOT NULL,
authkey varchar(40) NOT NULL,
org_id bigint NOT NULL,
push smallint NOT NULL,
pull smallint NOT NULL,
lastpulledid bigint DEFAULT NULL,
lastpushedid bigint DEFAULT NULL,
organization varchar(10) DEFAULT NULL,
remote_org_id bigint NOT NULL,
self_signed smallint NOT NULL,
pull_rules text NOT NULL,
push_rules text NOT NULL,
cert_file varchar(255) DEFAULT NULL,
client_cert_file varchar(255) DEFAULT NULL,
internal smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
CREATE INDEX idx_servers_org_id ON servers (org_id);
CREATE INDEX idx_servers_remote_org_id ON servers (remote_org_id);
-- --------------------------------------------------------
--
-- Table structure for table shadow_attributes
--
CREATE TABLE IF NOT EXISTS shadow_attributes (
id bigserial NOT NULL,
old_id bigint NOT NULL,
event_id bigint NOT NULL,
type varchar(100) NOT NULL,
category varchar(255) NOT NULL,
value1 text,
to_ids smallint NOT NULL DEFAULT 1,
uuid varchar(40) NOT NULL,
value2 text,
org_id bigint NOT NULL,
email varchar(255) DEFAULT NULL,
event_org_id bigint NOT NULL,
comment text NOT NULL,
event_uuid varchar(40) NOT NULL,
deleted smallint NOT NULL DEFAULT 0,
timestamp bigint NOT NULL DEFAULT 0,
proposal_to_delete BOOLEAN NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_shadow_attributes_event_id ON shadow_attributes (event_id);
CREATE INDEX idx_shadow_attributes_event_uuid ON shadow_attributes (event_uuid);
CREATE INDEX idx_shadow_attributes_event_org_id ON shadow_attributes (event_org_id);
CREATE INDEX idx_shadow_attributes_uuid ON shadow_attributes (uuid);
CREATE INDEX idx_shadow_attributes_old_id ON shadow_attributes (old_id);
CREATE INDEX idx_shadow_attributes_value1 ON shadow_attributes (value1);
CREATE INDEX idx_shadow_attributes_value2 ON shadow_attributes (value2);
-- --------------------------------------------------------
--
-- Table structure for table shadow_attribute_correlations
--
CREATE TABLE IF NOT EXISTS shadow_attribute_correlations (
id bigserial NOT NULL,
org_id bigint NOT NULL,
value text NOT NULL,
distribution smallint NOT NULL,
a_distribution smallint NOT NULL,
sharing_group_id bigint,
a_sharing_group_id bigint,
attribute_id bigint NOT NULL,
"1_shadow_attribute_id" bigint NOT NULL,
event_id bigint NOT NULL,
"1_event_id" bigint NOT NULL,
info text NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_shadow_attribute_correlations_org_id ON shadow_attribute_correlations (org_id);
CREATE INDEX idx_shadow_attribute_correlations_attribute_id ON shadow_attribute_correlations (attribute_id);
CREATE INDEX idx_shadow_attribute_correlations_a_sharing_group_id ON shadow_attribute_correlations (a_sharing_group_id);
CREATE INDEX idx_shadow_attribute_correlations_event_id ON shadow_attribute_correlations (event_id);
CREATE INDEX idx_shadow_attribute_correlations_1_event_id ON shadow_attribute_correlations ("1_event_id");
CREATE INDEX idx_shadow_attribute_correlations_sharing_group_id ON shadow_attribute_correlations (sharing_group_id);
CREATE INDEX idx_shadow_attribute_correlations_1_shadow_attribute_id ON shadow_attribute_correlations ("1_shadow_attribute_id");
-- --------------------------------------------------------
--
-- Table structure for table sharing_group_orgs
--
CREATE TABLE sharing_group_orgs (
id bigserial NOT NULL,
sharing_group_id bigint NOT NULL,
org_id bigint NOT NULL,
extend smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
CREATE INDEX idx_sharing_group_orgs_org_id ON sharing_group_orgs (org_id);
CREATE INDEX idx_sharing_group_orgs_sharing_group_id ON sharing_group_orgs (sharing_group_id);
-- --------------------------------------------------------
--
-- Table structure for table sharing_group_servers
--
CREATE TABLE sharing_group_servers (
id bigserial NOT NULL,
sharing_group_id bigint NOT NULL,
server_id bigint NOT NULL,
all_orgs smallint NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_sharing_group_servers_server_id ON sharing_group_servers (server_id);
CREATE INDEX idx_sharing_group_servers_sharing_group_id ON sharing_group_servers (sharing_group_id);
-- --------------------------------------------------------
--
-- Table structure for table sharing_groups
--
CREATE TABLE sharing_groups (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
releasability text NOT NULL,
description text NOT NULL,
uuid varchar(40) NOT NULL,
organisation_uuid varchar(40) NOT NULL,
org_id bigint NOT NULL,
sync_user_id bigint NOT NULL DEFAULT 0,
active smallint NOT NULL,
created timestamp NOT NULL,
modified timestamp NOT NULL,
local smallint NOT NULL,
roaming smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE (uuid)
);
CREATE INDEX idx_sharing_groups_org_id ON sharing_groups (org_id);
CREATE INDEX idx_sharing_groups_sync_user_id ON sharing_groups (sync_user_id);
CREATE INDEX idx_sharing_groups_organisation_uuid ON sharing_groups (organisation_uuid);
-- --------------------------------------------------------
--
-- Table structure for table tags
--
CREATE TABLE IF NOT EXISTS tags (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
colour varchar(7) NOT NULL,
exportable smallint NOT NULL,
org_id smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
CREATE INDEX idx_tags_org_id ON tags (org_id);
-- --------------------------------------------------------
--
-- Table structure for table tasks
--
CREATE TABLE IF NOT EXISTS tasks (
id bigserial NOT NULL,
type varchar(100) NOT NULL,
timer bigint NOT NULL,
scheduled_time varchar(8) NOT NULL DEFAULT '6:00',
process_id varchar(32) DEFAULT NULL,
description varchar(255) NOT NULL,
next_execution_time bigint NOT NULL,
message varchar(255) NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table taxonomies
--
CREATE TABLE IF NOT EXISTS taxonomies (
id bigserial NOT NULL,
namespace varchar(255) NOT NULL,
description text NOT NULL,
version bigint NOT NULL,
enabled smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table taxonomy_entries
--
CREATE TABLE IF NOT EXISTS taxonomy_entries (
id bigserial NOT NULL,
taxonomy_predicate_id bigint NOT NULL,
value text NOT NULL,
expanded text,
PRIMARY KEY (id)
);
CREATE INDEX idx_taxonomy_entries_taxonomy_predicate_id ON taxonomy_entries (taxonomy_predicate_id);
-- --------------------------------------------------------
--
-- Table structure for table taxonomy_predicates
--
CREATE TABLE IF NOT EXISTS taxonomy_predicates (
id bigserial NOT NULL,
taxonomy_id bigint NOT NULL,
value text NOT NULL,
expanded text,
PRIMARY KEY (id)
);
CREATE INDEX idx_taxonomy_predicates_taxonomy_id ON taxonomy_predicates (taxonomy_id);
-- --------------------------------------------------------
--
-- Table structure for table templates
--
CREATE TABLE IF NOT EXISTS templates (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
description varchar(255) NOT NULL,
org varchar(255) NOT NULL,
share smallint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table template_elements
--
CREATE TABLE IF NOT EXISTS template_elements (
id bigserial NOT NULL,
template_id bigint NOT NULL,
position bigint NOT NULL,
element_definition varchar(255) NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table template_element_attributes
--
CREATE TABLE IF NOT EXISTS template_element_attributes (
id bigserial NOT NULL,
template_element_id bigint NOT NULL,
name varchar(255) NOT NULL,
description text NOT NULL,
to_ids smallint NOT NULL DEFAULT 1,
category varchar(255) NOT NULL,
complex smallint NOT NULL,
type varchar(255) NOT NULL,
mandatory smallint NOT NULL,
batch smallint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table template_element_files
--
CREATE TABLE IF NOT EXISTS template_element_files (
id bigserial NOT NULL,
template_element_id bigint NOT NULL,
name varchar(255) NOT NULL,
description text NOT NULL,
category varchar(255) NOT NULL,
malware smallint NOT NULL,
mandatory smallint NOT NULL,
batch smallint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table template_element_texts
--
CREATE TABLE IF NOT EXISTS template_element_texts (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
template_element_id bigint NOT NULL,
text text NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table template_tags
--
CREATE TABLE IF NOT EXISTS template_tags (
id bigserial NOT NULL,
template_id bigint NOT NULL,
tag_id bigint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table threads
--
CREATE TABLE IF NOT EXISTS threads (
id bigserial NOT NULL,
date_created timestamp NOT NULL,
date_modified timestamp NOT NULL,
distribution smallint NOT NULL,
user_id bigint NOT NULL,
post_count bigint NOT NULL,
event_id bigint NOT NULL,
title varchar(255) NOT NULL,
org_id bigint NOT NULL,
sharing_group_id bigint NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_threads_user_id ON threads (user_id);
CREATE INDEX idx_threads_event_id ON threads (event_id);
CREATE INDEX idx_threads_org_id ON threads (org_id);
CREATE INDEX idx_threads_sharing_group_id ON threads (sharing_group_id);
-- --------------------------------------------------------
--
-- Table structure for table threat_levels
--
CREATE TABLE IF NOT EXISTS threat_levels (
id bigserial NOT NULL,
name varchar(50) NOT NULL,
description varchar(255) DEFAULT NULL,
form_description varchar(255) NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table users
--
CREATE TABLE IF NOT EXISTS users (
id bigserial NOT NULL,
password varchar(40) NOT NULL,
org_id bigint NOT NULL,
server_id bigint NOT NULL DEFAULT 0,
email varchar(255) NOT NULL,
autoalert smallint NOT NULL DEFAULT 0,
authkey varchar(40) DEFAULT NULL,
invited_by bigint NOT NULL DEFAULT 0,
gpgkey text,
certif_public text,
nids_sid bigint NOT NULL DEFAULT 0,
termsaccepted smallint NOT NULL DEFAULT 0,
newsread bigint DEFAULT 0,
role_id bigint NOT NULL DEFAULT 0,
change_pw smallint NOT NULL DEFAULT 0,
contactalert smallint NOT NULL DEFAULT 0,
disabled BOOLEAN NOT NULL DEFAULT false,
expiration timestamp DEFAULT NULL,
current_login bigint DEFAULT 0,
last_login bigint DEFAULT 0,
force_logout smallint NOT NULL DEFAULT 0,
PRIMARY KEY (id)
);
CREATE INDEX idx_users_email ON users (email);
CREATE INDEX idx_users_org_id ON users (org_id);
CREATE INDEX idx_users_server_id ON users (server_id);
-- --------------------------------------------------------
--
-- Table structure for table warninglists
--
CREATE TABLE IF NOT EXISTS warninglists (
id bigserial NOT NULL,
name varchar(255) NOT NULL,
type varchar(255) NOT NULL DEFAULT 'string',
description text NOT NULL,
version bigint NOT NULL DEFAULT '1',
enabled smallint NOT NULL DEFAULT 0,
warninglist_entry_count bigint DEFAULT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table warninglist_entries
--
CREATE TABLE IF NOT EXISTS warninglist_entries (
id bigserial NOT NULL,
value text NOT NULL,
warninglist_id bigint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table warninglist_types
--
CREATE TABLE IF NOT EXISTS warninglist_types (
id bigserial NOT NULL,
type varchar(255) NOT NULL,
warninglist_id bigint NOT NULL,
PRIMARY KEY (id)
);
-- --------------------------------------------------------
--
-- Table structure for table whitelist
--
CREATE TABLE IF NOT EXISTS whitelist (
id bigserial NOT NULL,
name text NOT NULL,
PRIMARY KEY (id)
);

2
PyMISP

@ -1 +1 @@
Subproject commit 8059ead9cf451f2081f43e88e77938844cde72d5
Subproject commit e70cc7a985b84605145cbe7a760304c86bcdef1b

View File

@ -1 +1 @@
{"major":2, "minor":4, "hotfix":50}
{"major":2, "minor":4, "hotfix":51}

View File

@ -1,68 +0,0 @@
;<?php exit() ?>
;/**
; * ACL Configuration
; *
; *
; * PHP 5
; *
; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
; * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; * @link http://cakephp.org CakePHP(tm) Project
; * @package app.Config
; * @since CakePHP(tm) v 0.10.0.1076
; * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
; */
; acl.ini.php - Cake ACL Configuration
; ---------------------------------------------------------------------
; Use this file to specify user permissions.
; aco = access control object (something in your application)
; aro = access request object (something requesting access)
;
; User records are added as follows:
;
; [uid]
; groups = group1, group2, group3
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; Group records are added in a similar manner:
;
; [gid]
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; The allow, deny, and groups sections are all optional.
; NOTE: groups names *cannot* ever be the same as usernames!
;
; ACL permissions are checked in the following order:
; 1. Check for user denies (and DENY if specified)
; 2. Check for user allows (and ALLOW if specified)
; 3. Gather user's groups
; 4. Check group denies (and DENY if specified)
; 5. Check group allows (and ALLOW if specified)
; 6. If no aro, aco, or group information is found, DENY
;
; ---------------------------------------------------------------------
;-------------------------------------
;Users
;-------------------------------------
[username-goes-here]
groups = group1, group2
deny = aco1, aco2
allow = aco3, aco4
;-------------------------------------
;Groups
;-------------------------------------
[groupname-goes-here]
deny = aco5, aco6
allow = aco7, aco8

View File

@ -1,134 +0,0 @@
<?php
/**
* This is the PHP base ACL configuration file.
*
* Use it to configure access control of your Cake application.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 2.1
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Example
* -------
*
* Assumptions:
*
* 1. In your application you created a User model with the following properties:
* username, group_id, password, email, firstname, lastname and so on.
* 2. You configured AuthComponent to authorize actions via
* $this->Auth->authorize = array('Actions' => array('actionPath' => 'controllers/'),...)
*
* Now, when a user (i.e. jeff) authenticates successfully and requests a controller action (i.e. /invoices/delete)
* that is not allowed by default (e.g. via $this->Auth->allow('edit') in the Invoices controller) then AuthComponent
* will ask the configured ACL interface if access is granted. Under the assumptions 1. and 2. this will be
* done via a call to Acl->check() with
*
* array('User' => array('username' => 'jeff', 'group_id' => 4, ...))
*
* as ARO and
*
* '/controllers/invoices/delete'
*
* as ACO.
*
* If the configured map looks like
*
* $config['map'] = array(
* 'User' => 'User/username',
* 'Role' => 'User/group_id',
* );
*
* then PhpAcl will lookup if we defined a role like User/jeff. If that role is not found, PhpAcl will try to
* find a definition for Role/4. If the definition isn't found then a default role (Role/default) will be used to
* check rules for the given ACO. The search can be expanded by defining aliases in the alias configuration.
* E.g. if you want to use a more readable name than Role/4 in your definitions you can define an alias like
*
* $config['alias'] = array(
* 'Role/4' => 'Role/editor',
* );
*
* In the roles configuration you can define roles on the lhs and inherited roles on the rhs:
*
* $config['roles'] = array(
* 'Role/admin' => null,
* 'Role/accountant' => null,
* 'Role/editor' => null,
* 'Role/manager' => 'Role/editor, Role/accountant',
* 'User/jeff' => 'Role/manager',
* );
*
* In this example manager inherits all rules from editor and accountant. Role/admin doesn't inherit from any role.
* Lets define some rules:
*
* $config['rules'] = array(
* 'allow' => array(
* '*' => 'Role/admin',
* 'controllers/users/(dashboard|profile)' => 'Role/default',
* 'controllers/invoices/*' => 'Role/accountant',
* 'controllers/articles/*' => 'Role/editor',
* 'controllers/users/*' => 'Role/manager',
* 'controllers/invoices/delete' => 'Role/manager',
* ),
* 'deny' => array(
* 'controllers/invoices/delete' => 'Role/accountant, User/jeff',
* 'controllers/articles/(delete|publish)' => 'Role/editor',
* ),
* );
*
* Ok, so as jeff inherits from Role/manager he's matched every rule that references User/jeff, Role/manager,
* Role/editor, Role/accountant and Role/default. However, for jeff, rules for User/jeff are more specific than
* rules for Role/manager, rules for Role/manager are more specific than rules for Role/editor and so on.
* This is important when allow and deny rules match for a role. E.g. Role/accountant is allowed
* controllers/invoices/* but at the same time controllers/invoices/delete is denied. But there is a more
* specific rule defined for Role/manager which is allowed controllers/invoices/delete. However, the most specific
* rule denies access to the delete action explicitly for User/jeff, so he'll be denied access to the resource.
*
* If we would remove the role definition for User/jeff, then jeff would be granted access as he would be resolved
* to Role/manager and Role/manager has an allow rule.
*/
/**
* The role map defines how to resolve the user record from your application
* to the roles you defined in the roles configuration.
*/
$config['map'] = array(
'User' => 'User/username',
'Role' => 'User/group_id',
);
/**
* define aliases to map your model information to
* the roles defined in your role configuration.
*/
$config['alias'] = array(
'Role/4' => 'Role/editor',
);
/**
* role configuration
*/
$config['roles'] = array(
'Role/admin' => null,
);
/**
* rule configuration
*/
$config['rules'] = array(
'allow' => array(
'*' => 'Role/admin',
),
'deny' => array(),
);

View File

@ -61,10 +61,12 @@ class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
//'datasource' => 'Database/Postgres',
'persistent' => false,
'host' => 'localhost',
'login' => 'db login',
'port' => 3306,
'port' => 3306, // MySQL & MariaDB
//'port' => 5432, // PostgreSQL
'password' => 'db password',
'database' => 'misp',
'prefix' => '',

View File

@ -28,28 +28,11 @@
Router::connect('/', array('controller' => 'events', 'action' => 'index'));
// admin Paginator
//Router::connect('/whitelists/admin_add/*', array('controller' => 'whitelists', 'action' => 'add', 'admin' => true));
Router::connect('/whitelists/admin_index/*', array('controller' => 'whitelists', 'action' => 'index', 'admin' => true));
//Router::connect('/whitelists/admin_edit/*', array('controller' => 'whitelists', 'action' => 'edit', 'admin' => true));
//Router::connect('/whitelists/admin_delete/*', array('controller' => 'whitelists', 'action' => 'delete', 'admin' => true));
// Router::connect('/regexp/admin_index/*', array('controller' => 'regexp', 'action' => 'index', 'admin' => true));
Router::connect('/users/admin_index/*', array('controller' => 'users', 'action' => 'index', 'admin' => true));
Router::connect('/roles/admin_index/*', array('controller' => 'roles', 'action' => 'index', 'admin' => true));
Router::connect('/logs/admin_search/*', array('controller' => 'logs', 'action' => 'search', 'admin' => true));
// Router::connect('/roles/admin_add/*', array('controller' => 'roles', 'action' => 'add', 'admin' => true));
// Router::connect('/roles/admin_edit/*', array('controller' => 'roles', 'action' => 'edit', 'admin' => true));
Router::connect('/logs/admin_index/*', array('controller' => 'logs', 'action' => 'index', 'admin' => true));
// Router::connect('/logs/admin_search/*', array('controller' => 'logs', 'action' => 'search', 'admin' => true));
// Router::connect('/admin/users/terms', array('controller' => 'users', 'action' => 'terms'));
//Router::connect('/admin/users/login', array('controller' => 'users', 'action' => 'login', 'admin' => false));
//Router::connect('/admin/users/routeafterlogin', array('controller' => 'users', 'action' => 'routeafterlogin'));
// Router::connect('/admin/users/edit/:id', array('controller' => 'users', 'action' => 'edit'), array('pass' => array('field', 'id')));
// Router::connect('/admin/users/view/:id', array('controller' => 'users', 'action' => 'view'), array('pass' => array('field', 'id')));
// Router::connect('/:controller/:field/:newValue/:oldValue', array('action' => 'call'), array('pass' => array('field', 'newValue', 'oldValue')));
// Activate REST
Router::mapResources(array('events', 'attributes'));

View File

@ -100,6 +100,34 @@ class EventShell extends AppShell
$this->Job->saveField('date_modified', date("y-m-d H:i:s"));
}
public function cachestix() {
$timeStart = time();
$userId = $this->args[0];
$id = $this->args[1];
$user = $this->User->getAuthUser($userId);
$this->Job->id = $id;
$dir = new Folder(APP . 'tmp/cached_exports/stix', true, 0750);
if ($user['Role']['perm_site_admin']) {
$stixFile = new File($dir->pwd() . DS . 'misp.stix' . '.ADMIN.xml');
} else {
$stixFile = new File($dir->pwd() . DS . 'misp.stix' . '.' . $user['Organisation']['name'] . '.xml');
}
$result = $this->Event->stix(false, false, Configure::read('MISP.cached_attachments'), $user, 'xml', false, false, false, $id);
$timeDelta = (time()-$timeStart);
$this->Job->saveField('date_modified', date("y-m-d H:i:s"));
if ($result['success']) {
$stixFile->write($result['data']);
$stixFile->close();
$this->Job->saveField('progress', 100);
$this->Job->saveField('message', 'Job done. (in '.$timeDelta.'s)');
} else {
$log = ClassRegistry::init('Log');
$log->create();
$log->createLogEntry($user, 'export', 'STIX export failed', $result['message']);
throw new InternalErrorException();
}
}
private function __recursiveEcho($array) {
$text = "";
foreach ($array as $k => $v) {
@ -432,6 +460,7 @@ class EventShell extends AppShell
$i = 0;
foreach ($users as $user) {
foreach ($this->Event->export_types as $k => $type) {
if ($k == 'stix') continue;
$this->Job->cache($k, $user['User']);
$i++;
}
@ -459,7 +488,7 @@ class EventShell extends AppShell
$this->Job->save($job);
$log = ClassRegistry::init('Log');
$log->create();
$log->createLogEntry($user, 'publish', 'Event (' . $id . '): published.', 'publised () => (1)');
$log->createLogEntry($user, 'publish', 'Event', $id, 'Event (' . $id . '): published.', 'publised () => (1)');
}
}

View File

@ -1,11 +1,13 @@
<?php
class UserInitShell extends AppShell {
public $uses = array('User', 'Role', 'Organisation', 'Server');
public $uses = array('User', 'Role', 'Organisation', 'Server', 'ConnectionManager');
public function main() {
if (!Configure::read('Security.salt')) {
$this->loadModel('Server');
$this->Server->serverSettingsSaveValue('Security.salt', $this->User->generateRandomPassword(32));
}
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
$this->Role->Behaviors->unload('SysLogLogable.SysLogLogable');
$this->User->Behaviors->unload('SysLogLogable.SysLogLogable');
// populate the DB with the first role (site admin) if it's empty
@ -29,6 +31,11 @@ class UserInitShell extends AppShell {
'perm_template' => 1
));
$this->Role->save($siteAdmin);
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
if ($dataSource == 'Database/Postgres') {
$sql = "SELECT setval('roles_id_seq', (SELECT MAX(id) FROM roles));";
$this->Role->query($sql);
}
}
if ($this->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
@ -41,6 +48,11 @@ class UserInitShell extends AppShell {
'local' => 1
));
$this->Organisation->save($org);
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
if ($dataSource == 'Database/Postgres') {
$sql = "SELECT setval('organisations_id_seq', (SELECT MAX(id) FROM organisations));";
$this->Organisation->query($sql);
}
$org_id = $this->Organisation->id;
} else {
$hostOrg = $this->Organisation->find('first', array('conditions' => array('Organisation.name' => Configure::read('MISP.org')), 'recursive' => -1));
@ -69,6 +81,11 @@ class UserInitShell extends AppShell {
));
$this->User->validator()->remove('password'); // password is to simple, remove validation
$this->User->save($admin);
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
if ($dataSource == 'Database/Postgres') {
$sql = "SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));";
$this->User->query($sql);
}
echo $authkey . PHP_EOL;
} else {
echo 'Script aborted: MISP instance already initialised.' . PHP_EOL;

View File

@ -22,6 +22,7 @@
// TODO GPG encryption has issues when keys are expired
App::uses('ConnectionManager', 'Model');
App::uses('Controller', 'Controller');
App::uses('File', 'Utility');
App::uses('RequestRearrangeTool', 'Tools');
@ -45,14 +46,14 @@ class AppController extends Controller {
public $helpers = array('Utility');
private $__jsVersion = '2.4.50';
private $__jsVersion = '2.4.51';
public $phpmin = '5.5.9';
public $phprec = '5.6.0';
// Used for _isAutomation(), a check that returns true if the controller & action combo matches an action that is a non-xml and non-json automation method
// This is used to allow authentication via headers for methods not covered by _isRest() - as that only checks for JSON and XML formats
public $automationArray = array(
'events' => array('csv', 'nids', 'hids', 'xml', 'restSearch', 'stix', 'updateGraph'),
'events' => array('csv', 'nids', 'hids', 'xml', 'restSearch', 'stix', 'updateGraph', 'downloadOpenIOCEvent'),
'attributes' => array('text', 'downloadAttachment', 'returnAttributes', 'restSearch', 'rpz'),
);
@ -71,14 +72,19 @@ class AppController extends Controller {
'authError' => 'Unauthorised access.',
'loginRedirect' => array('controller' => 'users', 'action' => 'routeafterlogin'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login', 'admin' => false),
//'authorize' => array('Controller', // Added this line
//'Actions' => array('actionPath' => 'controllers')) // TODO ACL, 4: tell actionPath
),
),
'Security',
'ACL'
);
public function beforeFilter() {
// check for a supported datasource configuration
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
if ($dataSource != 'Database/Mysql' && $dataSource != 'Database/Postgres') {
throw new Exception('datasource not supported: ' . $dataSource);
}
$this->set('jsVersion', $this->__jsVersion);
$this->loadModel('User');
$auth_user_fields = $this->User->describeAuthFields();
@ -100,7 +106,6 @@ class AppController extends Controller {
)
);
} else {
$this->Auth->className = 'SecureAuth';
$this->Auth->authenticate = array(
'Form' => array(
'fields' => array('username' => 'email'),
@ -130,7 +135,6 @@ class AppController extends Controller {
$userLoggedIn = false;
if (Configure::read('Plugin.CustomAuth_enable')) $userLoggedIn = $this->__customAuthentication($_SERVER);
if (!$userLoggedIn) {
// REST authentication
if ($this->_isRest() || $this->_isAutomation()) {
@ -153,8 +157,8 @@ class AppController extends Controller {
if ($user) {
unset($user['User']['gpgkey']);
unset($user['User']['certif_public']);
// User found in the db, add the user info to the session
if (Configure::read('MISP.log_auth')) {
// User found in the db, add the user info to the session
if (Configure::read('MISP.log_auth')) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$log = array(
@ -167,9 +171,9 @@ class AppController extends Controller {
'change' => 'HTTP method: ' . $_SERVER['REQUEST_METHOD'] . PHP_EOL . 'Target: ' . $this->here,
);
$this->Log->save($log);
}
$this->Session->renew();
$this->Session->write(AuthComponent::$sessionKey, $user['User']);
}
$this->Session->renew();
$this->Session->write(AuthComponent::$sessionKey, $user['User']);
} else {
// User not authenticated correctly
// reset the session information
@ -323,7 +327,7 @@ class AppController extends Controller {
$this->set('me', false);
}
if ($this->_isSiteAdmin()) {
if (Configure::read('Session.defaults') !== 'database') {
if (Configure::read('Session.defaults') == 'database') {
$db = ConnectionManager::getDataSource('default');
$sqlResult = $db->query('SELECT COUNT(id) AS session_count FROM cake_sessions WHERE expires < ' . time() . ';');
if (isset($sqlResult[0][0]['session_count']) && $sqlResult[0][0]['session_count'] > 1000) {
@ -652,8 +656,4 @@ class AppController extends Controller {
$this->Session->setFlash('Caches cleared.');
$this->redirect(array('controller' => 'servers', 'action' => 'serverSettings', 'diagnostics'));
}
public function checkFilename($filename) {
return preg_match('@^([a-z0-9_.]+[a-z0-9_.\- ]*[a-z0-9_.\-]|[a-z0-9_.])+$@i', $filename);
}
}

View File

@ -473,13 +473,13 @@ class AttributesController extends AppController {
// Check if there were problems with the file upload
$tmpfile = new File($this->request->data['Attribute']['value']['tmp_name']);
if ((isset($this->request->data['Attribute']['value']['error']) && $this->request->data['Attribute']['value']['error'] == 0) ||
(!empty( $this->request->data['Attribute']['value']['tmp_name']) && $this->request->data['Attribute']['value']['tmp_name'] != 'none')
(!empty( $this->request->data['Attribute']['value']['tmp_name']) && $this->request->data['Attribute']['value']['tmp_name'] != 'none')
) {
if (!is_uploaded_file($tmpfile->path))
throw new InternalErrorException('PHP says file was not uploaded. Are you attacking me?');
if (!is_uploaded_file($tmpfile->path))
throw new InternalErrorException('PHP says file was not uploaded. Are you attacking me?');
} else {
$this->Session->setFlash(__('There was a problem to upload the file.', true), 'default', array(), 'error');
$this->redirect(array('controller' => 'attributes', 'action' => 'add_threatconnect', $this->request->data['Attribute']['event_id']));
$this->Session->setFlash(__('There was a problem to upload the file.', true), 'default', array(), 'error');
$this->redirect(array('controller' => 'attributes', 'action' => 'add_threatconnect', $this->request->data['Attribute']['event_id']));
}
// verify mime type
$file_info = $tmpfile->info();
@ -546,9 +546,9 @@ class AttributesController extends AppController {
if (preg_match("#^[0-9a-f]{32}$#", $attribute['value']))
$attribute['type'] = 'md5';
else if (preg_match("#^[0-9a-f]{40}$#", $attribute['value']))
$attribute['type'] = 'sha1';
$attribute['type'] = 'sha1';
else if (preg_match("#^[0-9a-f]{64}$#", $attribute['value']))
$attribute['type'] = 'sha256';
$attribute['type'] = 'sha256';
else
// do not keep attributes that do not have a match
$attribute=NULL;
@ -1247,8 +1247,8 @@ class AttributesController extends AppController {
else $include[] = $tagname;
}
$this->loadModel('Tag');
if (!empty($include)) $conditions['AND'][] = array('OR' => array('Attribute.event_id' => $this->Tag->findTags($include)));
if (!empty($exclude)) $conditions['AND'][] = array('Attribute.event_id !=' => $this->Tag->findTags($exclude));
if (!empty($include)) $conditions['AND'][] = array('OR' => array('Attribute.event_id' => $this->Tag->findEventIdsByTagNames($include)));
if (!empty($exclude)) $conditions['AND'][] = array('Attribute.event_id !=' => $this->Tag->findEventIdsByTagNames($exclude));
}
if ($type != 'ALL') {
$conditions['Attribute.type ='] = $type;
@ -2307,8 +2307,6 @@ class AttributesController extends AppController {
}
$url = Configure::read('Plugin.Enrichment_services_url') ? Configure::read('Plugin.Enrichment_services_url') : $this->Server->serverSettings['Plugin']['Enrichment_services_url']['value'];
$port = Configure::read('Plugin.Enrichment_services_port') ? Configure::read('Plugin.Enrichment_services_port') : $this->Server->serverSettings['Plugin']['Enrichment_services_port']['value'];
App::uses('HttpSocket', 'Network/Http');
$httpSocket = new HttpSocket();
$resultArray = array();
foreach ($validTypes as &$type) {
$options = array();

View File

@ -199,6 +199,7 @@ class ACLComponent extends Component {
'admin_delete' => array(),
'admin_edit' => array(),
'admin_index' => array('perm_admin'),
'admin_set_default' => array(),
'index' => array('*'),
'view' => array('*'),
),
@ -333,6 +334,7 @@ class ACLComponent extends Component {
'logout' => array('*'),
'attributehistogram' => array('*'),
'resetauthkey' => array('*'),
'request_API' => array('*'),
'routeafterlogin' => array('*'),
'statistics' => array('*'),
'terms' => array('*'),

View File

@ -1,65 +0,0 @@
<?php
App::uses('AuthComponent', 'Controller/Component');
class SecureAuthComponent extends AuthComponent {
/**
* Log a user in using anti-brute-force protection.
* If a $user is provided that data will be stored as the logged in user. If `$user` is empty or not
* specified, the request will be used to identify a user. If the identification was successful,
* the user record is written to the session key specified in AuthComponent::$sessionKey. Logging in
* will also change the session id in order to help mitigate session replays.
*
* @param mixed $user Either an array of user data, or null to identify a user using the current request.
* @return boolean True on login success, false on failure
* @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#identifying-users-and-logging-them-in
* @throws ForbiddenException
*/
public function login($user = null) {
$this->_setDefaults();
if (empty($user)) {
$this->Bruteforce = ClassRegistry::init('Bruteforce');
// do the anti-bruteforce checks
$usernameField = $this->authenticate['Form']['fields']['username'];
if (isset($this->request->data['User'][$usernameField])) {
$username = $this->request->data['User'][$usernameField];
if (!$this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $username)) {
// user - ip combination is not blacklisted
// check if the user credentials are valid
$user = $this->identify($this->request, $this->response);
unset($user['gpgkey']);
unset($user['certif_public']);
if ($user === false) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$log = array(
'org' => 'SYSTEM',
'model' => 'User',
'model_id' => 0,
'email' => $username,
'action' => 'login_fail',
'title' => 'Failed login attempt',
'change' => null,
);
$this->Log->save($log);
// insert row in Bruteforce table
$this->Bruteforce->insert($_SERVER['REMOTE_ADDR'], $username);
// do nothing as user is not logged in
}
} else {
// user - ip combination has reached the amount of maximum attempts in the timeframe
throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
}
} else {
// user didn't fill in all the form fields, nothing to do
}
}
if ($user) {
$this->Session->renew();
$this->Session->write(self::$sessionKey, $user);
}
return $this->loggedIn();
}
}

View File

@ -40,7 +40,6 @@ class EventsController extends AppController {
$this->Auth->allow('hids_md5');
$this->Auth->allow('hids_sha1');
$this->Auth->allow('text');
$this->Auth->allow('dot');
$this->Auth->allow('restSearch');
$this->Auth->allow('stix');
@ -504,12 +503,6 @@ class EventsController extends AppController {
}
if (Configure::read('MISP.tagging') && !$this->_isRest()) {
$this->Event->contain(array('User.email', 'EventTag' => array('Tag')));
$tags = $this->Event->EventTag->Tag->find('all', array('recursive' => -1));
$tagNames = array('None');
foreach ($tags as $k => $v) {
$tagNames[$v['Tag']['id']] = $v['Tag']['name'];
}
$this->set('tags', $tagNames);
} else {
$this->Event->contain('User.email');
}
@ -538,6 +531,9 @@ class EventsController extends AppController {
if (isset($passedArgs['limit'])) {
$rules['limit'] = intval($passedArgs['limit']);
}
if (isset($passedArgs['page'])) {
$rules['page'] = intval($passedArgs['page']);
}
$rules['contain'] = $this->paginate['contain'];
if (Configure::read('MISP.tagging')) {
$rules['contain']['EventTag'] = array('Tag' => array('fields' => array('id', 'name', 'colour', 'exportable'), 'conditions' => array('Tag.exportable' => true)));
@ -560,23 +556,23 @@ class EventsController extends AppController {
$this->set('events', $events);
}
if (!$this->Event->User->getPGP($this->Auth->user('id')) && Configure::read('GnuPG.onlyencrypted')) {
// No GPG
if (Configure::read('SMIME.enabled') && !$this->Event->User->getCertificate($this->Auth->user('id'))) {
// No GPG and No SMIME
$this->Session->setFlash(__('No x509 certificate or GPG key set in your profile. To receive emails, submit your public certificate or GPG key in your profile.'));
} else if (!Configure::read('SMIME.enabled')) {
$this->Session->setFlash(__('No GPG key set in your profile. To receive emails, submit your public key in your profile.'));
}
} else if ($this->Auth->user('autoalert') && !$this->Event->User->getPGP($this->Auth->user('id')) && Configure::read('GnuPG.bodyonlyencrypted')) {
// No GPG & autoalert
if ($this->Auth->user('autoalert') && Configure::read('SMIME.enabled') && !$this->Event->User->getCertificate($this->Auth->user('id'))) {
// No GPG and No SMIME & autoalert
$this->Session->setFlash(__('No x509 certificate or GPG key set in your profile. To receive attributes in emails, submit your public certificate or GPG key in your profile.'));
} else if (!Configure::read('SMIME.enabled')) {
$this->Session->setFlash(__('No GPG key set in your profile. To receive attributes in emails, submit your public key in your profile.'));
}
}
if (!$this->Event->User->getPGP($this->Auth->user('id')) && Configure::read('GnuPG.onlyencrypted')) {
// No GPG
if (Configure::read('SMIME.enabled') && !$this->Event->User->getCertificate($this->Auth->user('id'))) {
// No GPG and No SMIME
$this->Session->setFlash(__('No x509 certificate or GPG key set in your profile. To receive emails, submit your public certificate or GPG key in your profile.'));
} else if (!Configure::read('SMIME.enabled')) {
$this->Session->setFlash(__('No GPG key set in your profile. To receive emails, submit your public key in your profile.'));
}
} else if ($this->Auth->user('autoalert') && !$this->Event->User->getPGP($this->Auth->user('id')) && Configure::read('GnuPG.bodyonlyencrypted')) {
// No GPG & autoalert
if ($this->Auth->user('autoalert') && Configure::read('SMIME.enabled') && !$this->Event->User->getCertificate($this->Auth->user('id'))) {
// No GPG and No SMIME & autoalert
$this->Session->setFlash(__('No x509 certificate or GPG key set in your profile. To receive attributes in emails, submit your public certificate or GPG key in your profile.'));
} else if (!Configure::read('SMIME.enabled')) {
$this->Session->setFlash(__('No GPG key set in your profile. To receive attributes in emails, submit your public key in your profile.'));
}
}
$this->set('eventDescriptions', $this->Event->fieldDescriptions);
$this->set('analysisLevels', $this->Event->analysisLevels);
$this->set('distributionLevels', $this->Event->distributionLevels);
@ -861,6 +857,10 @@ class EventsController extends AppController {
}
$results = $this->Event->fetchEvent($this->Auth->user(), $conditions);
if (empty($results)) throw new NotFoundException('Invalid event');
//if the current user is an org admin AND event belongs to his/her org, fetch also the event creator info
if ($this->userRole['perm_admin'] && !$this->_isSiteAdmin() && ($results[0]['Org']['id'] == $this->Auth->user('org_id'))) {
$results[0]['User']['email'] = $this->User->field('email', array('id' , $results[0]['Event']['user_id']));
}
$event = &$results[0];
if ($this->_isRest()) {
$this->set('event', $event);
@ -1886,7 +1886,7 @@ class EventsController extends AppController {
$rootDir = APP . "files" . DS . $id . DS;
App::uses('Folder', 'Utility');
$dir = new Folder($rootDir, true);
if (!$this->checkFilename($this->data['Event']['submittedgfi']['name'])) {
if (!$this->Event->checkFilename($this->data['Event']['submittedgfi']['name'])) {
throw new Exception ('Filename not allowed.');
}
$zipFile = new File($rootDir . $this->data['Event']['submittedgfi']['name']);
@ -1914,7 +1914,7 @@ class EventsController extends AppController {
public function _addIOCFile($id) {
if (!empty($this->data) && $this->data['Event']['submittedioc']['size'] > 0 &&
is_uploaded_file($this->data['Event']['submittedioc']['tmp_name'])) {
if (!$this->checkFilename($this->data['Event']['submittedioc']['name'])) {
if (!$this->Event->checkFilename($this->data['Event']['submittedioc']['name'])) {
throw new Exception ('Filename not allowed.');
}
@ -2262,17 +2262,15 @@ class EventsController extends AppController {
// the last 4 fields accept the following operators:
// && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two.
// ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't.
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $searchall = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false) {
if ($key!='download') {
$user = $this->checkAuthUser($key);
public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $searchall = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $metadata = false) {
if ($key != 'download') {
if (!$this->checkAuthUser($key)) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
} else {
if (!$this->Auth->user()) {
throw new UnauthorizedException('You are not authorized. Please send the Authorization header with your auth key along with an Accept header for application/xml.');
}
$user = $this->checkAuthUser($this->Auth->user('authkey'));
}
if (!$user) {
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
if (!is_array($value)) $value = str_replace('|', '/', $value);
// request handler for POSTed queries. If the request is a post, the parameters (apart from the key) will be ignored and replaced by the terms defined in the posted json or xml object.
@ -2288,7 +2286,7 @@ class EventsController extends AppController {
} else {
throw new BadRequestException('Either specify the search terms in the url, or POST a json array / xml (with the root element being "request" and specify the correct headers based on content type.');
}
$paramArray = array('value', 'type', 'category', 'org', 'tags', 'searchall', 'from', 'to', 'last', 'eventid', 'withAttachments');
$paramArray = array('value', 'type', 'category', 'org', 'tags', 'searchall', 'from', 'to', 'last', 'eventid', 'withAttachments', 'metadata');
foreach ($paramArray as $p) {
if (isset($data['request'][$p])) ${$p} = $data['request'][$p];
else ${$p} = null;
@ -2414,7 +2412,7 @@ class EventsController extends AppController {
$final = "";
$final .= '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<response>' . PHP_EOL;
foreach ($eventIds as $currentEventId) {
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $currentEventId, 'includeAttachments' => $withAttachments));
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $currentEventId, 'includeAttachments' => $withAttachments, 'metadata' => $metadata));
if (!empty($result)) {
$result = $this->Whitelist->removeWhitelistedFromArray($result, false);
$final .= $converter->event2XML($result[0]) . PHP_EOL;
@ -2430,7 +2428,7 @@ class EventsController extends AppController {
$converter = new JSONConverterTool();
$final = '{"response":[';
foreach ($eventIds as $k => $currentEventId) {
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $currentEventId, 'includeAttachments' => $withAttachments));
$result = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $currentEventId, 'includeAttachments' => $withAttachments, 'metadata' => $metadata));
$final .= $converter->event2JSON($result[0]);
if ($k < count($eventIds) -1 ) $final .= ',';
}
@ -2446,7 +2444,7 @@ class EventsController extends AppController {
return $this->response;
}
public function downloadOpenIOCEvent($eventid) {
public function downloadOpenIOCEvent($key, $eventid) {
// return a downloadable text file called misp.openIOC.<eventId>.ioc for individual events
// TODO implement mass download of all events - maybe in a zip file?
$this->response->type('text'); // set the content type
@ -2457,6 +2455,17 @@ class EventsController extends AppController {
}
$this->layout = 'text/default';
if ($key != 'download'){
$user = $this->checkAuthUser($key);
if (!$user){
throw new UnauthorizedException('This authentication key is not authorized to be used for exports. Contact your administrator.');
}
} else {
if (!$this->Auth->user('id')){
throw new UnauthorizedException('You have to be logged in to do that.');
}
}
// get the event if it exists and load it together with its attributes
$this->Event->id = $eventid;
if (!$this->Event->exists()) {
@ -2665,7 +2674,7 @@ class EventsController extends AppController {
if (empty($tag)) return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200));
$tag_id = $tag['Tag']['id'];
}
$this->Event->recurisve = -1;
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution', 'sharing_group_id'), $id);
if (!$this->_isSiteAdmin() && !$this->userRole['perm_sync']) {
@ -2723,7 +2732,7 @@ class EventsController extends AppController {
$tag_id = $tag['Tag']['id'];
}
if (!is_numeric($id)) $id = $this->request->data['Event']['id'];
$this->Event->recurisve = -1;
$this->Event->recursive = -1;
$event = $this->Event->read(array('id', 'org_id', 'orgc_id', 'distribution'), $id);
// org should allow to tag too, so that an event that gets pushed can be tagged locally by the owning org
if ((($this->Auth->user('org_id') !== $event['Event']['org_id'] && $this->Auth->user('org_id') !== $event['Event']['orgc_id'] && $event['Event']['distribution'] == 0) || (!$this->userRole['perm_tagger'])) && !$this->_isSiteAdmin()) {
@ -2837,7 +2846,7 @@ class EventsController extends AppController {
App::uses('FileAccessTool', 'Tools');
$tmpdir = Configure::read('MISP.tmpdir') ? Configure::read('MISP.tmpdir') : '/tmp';
$tempFile = explode('|', $attribute['data']);
if (!$this->checkFilename($tempFile[0])) {
if (!$this->Event->checkFilename($tempFile[0])) {
throw new Exception('Invalid filename.');
}
$attribute['data'] = (new FileAccessTool())->readFromFile($tmpdir . '/' . $tempFile[0], $tempFile[1]);
@ -3093,7 +3102,7 @@ class EventsController extends AppController {
'checkbox_default' => true
),
'openIOC' => array(
'url' => '/events/downloadOpenIOCEvent/' . $id,
'url' => '/events/downloadOpenIOCEvent/download/' . $id,
'text' => 'OpenIOC (all indicators marked to IDS)',
'requiresPublished' => true,
'checkbox' => false,
@ -3654,10 +3663,8 @@ class EventsController extends AppController {
$modules = $this->Module->getEnabledModules();
if (!is_array($modules) || empty($modules)) throw new MethodNotAllowedException('No valid enrichment options found for this attribute.');
$options = array();
$found = false;
foreach ($modules['modules'] as &$temp) {
if ($temp['name'] == $module) {
$found = true;
if (isset($temp['meta']['config'])) {
foreach ($temp['meta']['config'] as $conf) {
$options[$conf] = Configure::read('Plugin.Enrichment_' . $module . '_' . $conf);

View File

@ -62,6 +62,8 @@ class RolesController extends AppController {
public function admin_index() {
if (!$this->_isSiteAdmin()) $this->redirect(array('controller' => 'roles', 'action' => 'index', 'admin' => false));
$this->AdminCrud->adminIndex();
$this->loadModel('AdminSetting');
$this->set('default_role_id', $this->AdminSetting->getSetting('default_role'));
$this->set('permFlags', $this->Role->permFlags);
$this->set('options', $this->options);
}
@ -83,6 +85,21 @@ class RolesController extends AppController {
$this->recursive = 0;
$this->set('permFlags', $this->Role->permFlags);
$this->set('list', $this->paginate());
$this->loadModel('AdminSetting');
$this->set('default_role_id', $this->AdminSetting->getSetting('default_role'));
$this->set('options', $this->options);
}
public function admin_set_default($role_id = false) {
if (!is_numeric($role_id) && $role_id !== false) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid role.')),'status'=>200));
}
$this->loadModel('AdminSetting');
$result = $this->AdminSetting->changeSetting('default_role', $role_id);
if ($result === true) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $role_id ? 'Default role set.' : 'Default role unset.')),'status'=>200));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $result)),'status'=>200));
}
}
}

View File

@ -157,7 +157,7 @@ class ServersController extends AppController {
$json = json_decode($this->request->data['Server']['json'], true);
$fail = false;
if (empty(Configure::read('MISP.host_org_id'))) $this->request->data['Server']['internal'] = 0;
// test the filter fields
if (!empty($this->request->data['Server']['pull_rules']) && !$this->Server->isJson($this->request->data['Server']['pull_rules'])) {
$fail = true;
@ -203,11 +203,17 @@ class ServersController extends AppController {
}
}
}
if (Configure::read('MISP.host_org_id') == 0 || $this->request->data['Server']['remote_org_id'] != Configure::read('MISP.host_org_id')) {
$this->request->data['Server']['internal'] = 0;
}
if (!$fail) {
$this->request->data['Server']['org_id'] = $this->Auth->user('org_id');
if ($this->Server->save($this->request->data)) {
if (isset($this->request->data['Server']['submitted_cert']) && $this->request->data['Server']['submitted_cert']['size'] != 0) {
$this->__saveCert($this->request->data, $this->Server->id);
$this->__saveCert($this->request->data, $this->Server->id, false);
}
if (isset($this->request->data['Server']['submitted_client_cert']) && $this->request->data['Server']['submitted_client_cert']['size'] != 0) {
$this->__saveCert($this->request->data, $this->Server->id, true);
}
$this->Session->setFlash(__('The server has been saved'));
$this->redirect(array('action' => 'index'));
@ -239,7 +245,7 @@ class ServersController extends AppController {
$externalOrganisations[$o['Organisation']['id']] = $o['Organisation']['name'];
$allOrgs[] = array('id' => $o['Organisation']['id'], 'name' => $o['Organisation']['name']);
}
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
$this->set('organisationOptions', $organisationOptions);
$this->set('localOrganisations', $localOrganisations);
$this->set('externalOrganisations', $externalOrganisations);
@ -251,6 +257,7 @@ class ServersController extends AppController {
$allTags = array();
foreach ($temp as $t) $allTags[] = array('id' => $t['Tag']['id'], 'name' => $t['Tag']['name']);
$this->set('allTags', $allTags);
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
}
public function edit($id = null) {
@ -261,6 +268,7 @@ class ServersController extends AppController {
$s = $this->Server->read(null, $id);
if (!$this->_isSiteAdmin()) $this->redirect(array('controller' => 'servers', 'action' => 'index'));
if ($this->request->is('post') || $this->request->is('put')) {
if (empty(Configure::read('MISP.host_org_id'))) $this->request->data['Server']['internal'] = 0;
$json = json_decode($this->request->data['Server']['json'], true);
$fail = false;
@ -276,7 +284,7 @@ class ServersController extends AppController {
}
if (!$fail) {
// say what fields are to be updated
$fieldList = array('id', 'url', 'push', 'pull', 'remote_org_id', 'name' ,'self_signed', 'cert_file', 'push_rules', 'pull_rules');
$fieldList = array('id', 'url', 'push', 'pull', 'remote_org_id', 'name' ,'self_signed', 'cert_file', 'client_cert_file', 'push_rules', 'pull_rules', 'internal');
$this->request->data['Server']['id'] = $id;
if ("" != $this->request->data['Server']['authkey']) $fieldList[] = 'authkey';
if ($this->request->data['Server']['organisation_type'] < 2) $this->request->data['Server']['remote_org_id'] = $json['id'];
@ -310,15 +318,22 @@ class ServersController extends AppController {
}
}
}
if (empty(Configure::read('MISP.host_org_id')) || $this->request->data['Server']['remote_org_id'] != Configure::read('MISP.host_org_id')) {
$this->request->data['Server']['internal'] = 0;
}
}
if (!$fail) {
// Save the data
if ($this->Server->save($this->request->data, true, $fieldList)) {
if (isset($this->request->data['Server']['submitted_cert']) && $this->request->data['Server']['submitted_cert']['size'] != 0 && !$this->request->data['Server']['delete_cert']) {
$this->__saveCert($this->request->data, $this->Server->id);
$this->__saveCert($this->request->data, $this->Server->id, false);
} else {
if ($this->request->data['Server']['delete_cert']) $this->__saveCert($this->request->data, $this->Server->id, true);
if ($this->request->data['Server']['delete_cert']) $this->__saveCert($this->request->data, $this->Server->id, false, true);
}
if (isset($this->request->data['Server']['submitted_client_cert']) && $this->request->data['Server']['submitted_client_cert']['size'] != 0 && !$this->request->data['Server']['delete_client_cert']) {
$this->__saveCert($this->request->data, $this->Server->id, true);
} else {
if ($this->request->data['Server']['delete_client_cert']) $this->__saveCert($this->request->data, $this->Server->id, true, true);
}
$this->Session->setFlash(__('The server has been saved'));
$this->redirect(array('action' => 'index'));
@ -356,7 +371,7 @@ class ServersController extends AppController {
$oldRemoteSetting = 0;
if (!$this->Server->data['RemoteOrg']['local']) $oldRemoteSetting = 1;
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
$this->set('oldRemoteSetting', $oldRemoteSetting);
$this->set('oldRemoteOrg', $this->Server->data['RemoteOrg']['id']);
@ -372,6 +387,7 @@ class ServersController extends AppController {
foreach ($temp as $t) $allTags[] = array('id' => $t['Tag']['id'], 'name' => $t['Tag']['name']);
$this->set('allTags', $allTags);
$this->set('server', $s);
$this->set('host_org_id', Configure::read('MISP.host_org_id'));
}
public function delete($id = null) {
@ -509,35 +525,44 @@ class ServersController extends AppController {
}
}
private function __saveCert($server, $id, $delete = false) {
private function __saveCert($server, $id, $client = false, $delete = false) {
if ($client) {
$subm = 'submitted_client_cert';
$attr = 'client_cert_file';
$ins = '_client';
} else {
$subm = 'submitted_cert';
$attr = 'cert_file';
$ins = '';
}
if (!$delete) {
$ext = '';
App::uses('File', 'Utility');
App::uses('Folder', 'Utility');
App::uses('FileAccessTool', 'Tools');
if (!$this->checkFilename($server['Server']['submitted_cert']['name'])) {
if (!$this->Server->checkFilename($server['Server'][$subm]['name'])) {
throw new Exception ('Filename not allowed');
}
$file = new File($server['Server']['submitted_cert']['name']);
$file = new File($server['Server'][$subm]['name']);
$ext = $file->ext();
if (($ext != 'pem') || !$server['Server']['submitted_cert']['size'] > 0) {
if (($ext != 'pem') || !$server['Server'][$subm]['size'] > 0) {
$this->Session->setFlash('Incorrect extension or empty file.');
$this->redirect(array('action' => 'index'));
}
// read pem file data
$pemData = (new FileAccessTool())->readFromFile($server['Server']['submitted_cert']['tmp_name'], $server['Server']['submitted_cert']['size']);
$pemData = (new FileAccessTool())->readFromFile($server['Server'][$subm]['tmp_name'], $server['Server'][$subm]['size']);
$destpath = APP . "files" . DS . "certs" . DS;
$dir = new Folder(APP . "files" . DS . "certs", true);
$pemfile = new File($destpath . $id . '.' . $ext);
$pemfile = new File($destpath . $id . $ins . '.' . $ext);
$result = $pemfile->write($pemData);
$s = $this->Server->read(null, $id);
$s['Server']['cert_file'] = $s['Server']['id'] . '.' . $ext;
$s['Server'][$attr] = $s['Server']['id'] . $ins . '.' . $ext;
if ($result) $this->Server->save($s);
} else {
$s = $this->Server->read(null, $id);
$s['Server']['cert_file'] = '';
$s['Server'][$attr] = '';
$this->Server->save($s);
}
}
@ -564,6 +589,16 @@ class ServersController extends AppController {
$this->render('/Elements/healthElements/settings_row');
}
private function __loadLocalOrgs() {
$this->loadModel('Organisation');
$local_orgs = $this->Organisation->find('list', array(
'conditions' => array('local' => 1),
'recursive' => -1,
'fields' => array('Organisation.id', 'Organisation.name')
));
return array_replace(array(0 => 'No organisation selected.'), $local_orgs);
}
public function serverSettings($tab=false) {
if (!$this->_isSiteAdmin()) throw new MethodNotAllowedException();
if ($this->request->is('Get')) {
@ -614,6 +649,9 @@ class ServersController extends AppController {
$tabs[$result['tab']]['errors']++;
if ($result['level'] < $tabs[$result['tab']]['severity']) $tabs[$result['tab']]['severity'] = $result['level'];
}
if (isset($result['optionsSource']) && !empty($result['optionsSource'])) {
$result['options'] = $this->{'__load' . $result['optionsSource']}();
}
$dumpResults[] = $result;
if ($result['tab'] == $tab) {
if (isset($result['subGroup'])) $tempArray[$result['subGroup']][] = $result;
@ -805,6 +843,9 @@ class ServersController extends AppController {
if ($value) $found['value'] = $value;
$found['setting'] = $setting;
}
if (isset($found['optionsSource']) && !empty($found['optionsSource'])) {
$found['options'] = $this->{'__load' . $found['optionsSource']}();
}
$subGroup = 'general';
$subGroup = explode('.', $setting);
if ($subGroup[0] === 'Plugin') {

View File

@ -35,6 +35,12 @@ class TasksController extends AppController {
if (!in_array($taskName, $existingTasks)) {
$this->Task->create();
$this->Task->save($taskData);
} else {
$existingTask = $this->Task->find('first', array('recursive' => -1, 'conditions' => array('Task.type' => $taskName)));
if ($taskData['description'] != $existingTask['Task']['description']) {
$existingTask['Task']['description'] = $taskData['description'];
$this->Task->save($existingTask);
}
}
}
}

View File

@ -327,7 +327,7 @@ class TemplatesController extends AppController {
$this->loadModel('Attribute');
$fails = 0;
foreach ($attributes as $k => &$attribute) {
if (isset($attribute['data']) && $this->checkFilename($attribute['data'])) {
if (isset($attribute['data']) && $this->Template->checkFilename($attribute['data'])) {
$file = new File(APP . 'tmp/files/' . $attribute['data']);
$content = $file->read();
$attribute['data'] = base64_encode($content);
@ -370,7 +370,7 @@ class TemplatesController extends AppController {
// filename checks
foreach ($this->request->data['Template']['file'] as $k => $file) {
if ($file['size'] > 0 && $file['error'] == 0) {
if ($this->checkFilename($file['name'])) {
if ($this->Template->checkFilename($file['name'])) {
$fn = $this->Template->generateRandomFileName();
move_uploaded_file($file['tmp_name'], APP . 'tmp/files/' . $fn);
$filenames[] = $file['name'];
@ -400,7 +400,7 @@ class TemplatesController extends AppController {
if (!$this->request->is('post')) throw new MethodNotAllowedException('This action is restricted to accepting POST requests only.');
if (!$this->request->is('ajax')) throw new MethodNotAllowedException('This action is only accessible through AJAX.');
$this->autoRender = false;
if ($this->checkFilename($filename)) {
if ($this->Template->checkFilename($filename)) {
$file = new File(APP . 'tmp/files/' . $filename);
if ($file->exists()) {
$file->delete();

View File

@ -36,12 +36,32 @@ class UsersController extends AppController {
}
$this->User->id = $id;
$this->User->recursive = 0;
if (!$this->User->exists()) {
throw new NotFoundException(__('Invalid user'));
}
$this->set('user', $this->User->read(null, $id));
}
public function request_API(){
if (Configure::read('MISP.disable_emailing')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'API access request failed. E-mailing is currently disabled on this instance.')),'status'=>200));
}
$responsibleAdmin = $this->User->findAdminsResponsibleForUser($this->Auth->user());
$message = "Something went wrong, please try again later.";
if (isset($responsibleAdmin['email']) && !empty($responsibleAdmin['email'])) {
$subject = "[MISP ".Configure::read('MISP.org')."] User requesting API access";
$body = "A user (".$this->Auth->user('email').") has sent you a request to enable his/her API key access.<br/>";
$body .= "Click <a href=\"".Configure::read('MISP.baseurl')."\">here</a> to edit his profile to change his role.";
$user = $this->User->find('first', array('conditions' => array('User.id' => $this->Auth->user('id'))));
$result = $this->User->sendEmail($user, $body, false, $subject);
if ($result) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'API access requested.')),'status'=>200));
}
}
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Something went wrong, please try again later.')),'status'=>200));
}
public function edit($id = null) {
if (!$this->_isAdmin() && Configure::read('MISP.disableUserSelfManagement')) throw new MethodNotAllowedException('User self-management has been disabled on this instance.');
$me = false;
@ -365,6 +385,8 @@ class UsersController extends AppController {
if (!empty($t['Server']['name'])) $servers[$t['Server']['id']] = $t['Server']['name'];
else $servers[$t['Server']['id']] = $t['Server']['url'];
}
$this->loadModel('AdminSetting');
$this->set('default_role_id', $this->AdminSetting->getSetting('default_role'));
$this->set('servers', $servers);
$this->set(compact('roles'));
$this->set(compact('syncRoles'));
@ -543,6 +565,12 @@ class UsersController extends AppController {
}
public function login() {
$this->Bruteforce = ClassRegistry::init('Bruteforce');
if ($this->request->is('post') && isset($this->request->data['User']['email'])) {
if ($this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
}
}
if ($this->Auth->login()) {
$this->__extralog("login"); // TODO Audit, __extralog, check: customLog i.s.o. __extralog, no auth user?: $this->User->customLog('login', $this->Auth->user('id'), array('title' => '','user_id' => $this->Auth->user('id'),'email' => $this->Auth->user('email'),'org' => 'IN2'));
$this->User->Behaviors->disable('SysLogLogable.SysLogLogable');
@ -554,6 +582,8 @@ class UsersController extends AppController {
// $this->redirect($this->Auth->redirectUrl());
$this->redirect(array('controller' => 'events', 'action' => 'index'));
} else {
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
// don't display authError before first login attempt
if (str_replace("//","/",$this->webroot . $this->Session->read('Auth.redirect')) == $this->webroot && $this->Session->read('Message.auth.message') == $this->Auth->authError) {
$this->Session->delete('Message.auth');
@ -561,6 +591,9 @@ class UsersController extends AppController {
// don't display "invalid user" before first login attempt
if ($this->request->is('post')) {
$this->Session->setFlash(__('Invalid username or password, try again'));
if (isset($this->request->data['User']['email'])) {
$this->Bruteforce->insert($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email']);
}
}
// populate the DB with the first role (site admin) if it's empty
$this->loadModel('Role');
@ -584,6 +617,11 @@ class UsersController extends AppController {
'perm_tagger' => 1,
));
$this->Role->save($siteAdmin);
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
if ($dataSource == 'Database/Postgres') {
$sql = "SELECT setval('roles_id_seq', (SELECT MAX(id) FROM roles));";
$this->Role->query($sql);
}
}
if ($this->User->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
$org = array('Organisation' => array(
@ -597,6 +635,11 @@ class UsersController extends AppController {
'nationality' => ''
));
$this->User->Organisation->save($org);
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
if ($dataSource == 'Database/Postgres') {
$sql = "SELECT setval('organisations_id_seq', (SELECT MAX(id) FROM organisations));";
$this->User->Organisation->query($sql);
}
$org_id = $this->User->Organisation->id;
} else {
$hostOrg = $this->User->Organisation->find('first', array('conditions' => array('Organisation.name' => Configure::read('MISP.org'), 'Organisation.local' => true), 'recursive' => -1));
@ -623,6 +666,11 @@ class UsersController extends AppController {
));
$this->User->validator()->remove('password'); // password is too simple, remove validation
$this->User->save($admin);
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
if ($dataSource == 'Database/Postgres') {
$sql = "SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));";
$this->User->query($sql);
}
}
}
}
@ -652,6 +700,10 @@ class UsersController extends AppController {
$this->Session->setFlash(__('Invalid id for user', true), 'default', array(), 'error');
$this->redirect(array('action' => 'view', $this->Auth->user('id')));
}
if (!$this->userRole['perm_auth']) {
$this->Session->setFlash(__('Invalid action', true), 'default', array(), 'error');
$this->redirect(array('action' => 'view', $this->Auth->user('id')));
}
// reset the key
$this->User->id = $id;
if (!$this->User->exists($id)) {
@ -676,7 +728,7 @@ class UsersController extends AppController {
}
public function attributehistogram() {
//all code is called via JS
//all code is called via JS
}
public function histogram($selected = null) {
@ -691,6 +743,7 @@ class UsersController extends AppController {
));
$orgs = array();
foreach ($temp as $t) {
if (!isset($t['Event'])) $t['Event'] = $t[0]; // Postgres workaround, array element has index 0 instead of Event
$orgs[$t['Event']['orgc_id']] = $t['Orgc']['name'];
}
// What org posted what type of attribute
@ -976,8 +1029,13 @@ class UsersController extends AppController {
$this->Auth->login($newUser['User']);
}
public function fetchPGPKey($email) {
if (!$this->_isAdmin()) throw new Exception('Administrators only.');
public function fetchPGPKey($email = false) {
if (!$this->_isAdmin()) {
throw new Exception('Administrators only.');
}
if ($email == false) {
throw new NotFoundException('No email provided.');
}
$keys = $this->User->fetchPGPKey($email);
if (is_numeric($keys)) {
throw new NotFoundException('Could not retrieved any keys from the key server.');

View File

@ -483,4 +483,4 @@ class NidsExport {
}
return false;
}
}
}

View File

@ -12,124 +12,124 @@ class NidsSuricataExport extends NidsExport {
// below overwrite functions from NidsExport
public function hostnameRule($ruleFormat, $attribute, &$sid) {
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'dns_query; content:"'.$attribute['value'].'"; nocase; pcre: "/(^|[^A-Za-z0-9-\.])' . preg_quote($attribute['value']) . '$/i";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'dns', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
// also do http requests
// warning: only suricata compatible
$content = 'flow:to_server,established; content: "Host|3a| ' . $attribute['value'] . '"; fast_pattern; nocase; http_header; pcre: "/(^|[^A-Za-z0-9-\.])' . preg_quote($attribute['value']) . '[^A-Za-z0-9-\.]/Hi";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'dns_query; content:"'.$attribute['value'].'"; nocase; pcre: "/(^|[^A-Za-z0-9-\.])' . preg_quote($attribute['value']) . '$/i";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'dns', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
// also do http requests
// warning: only suricata compatible
$content = 'flow:to_server,established; content: "Host|3a| ' . $attribute['value'] . '"; fast_pattern; nocase; http_header; pcre: "/(^|[^A-Za-z0-9-\.])' . preg_quote($attribute['value']) . '[^A-Za-z0-9-\.]/Hi";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP Hostname: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
public function domainRule($ruleFormat, $attribute, &$sid) {
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'dns_query; content:"'.$attribute['value'].'"; nocase; pcre: "/(^|[^A-Za-z0-9-])' . preg_quote($attribute['value']) . '$/i";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'dns', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Domain: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
// also do http requests,
// warning: only suricata compatible
$content = 'flow:to_server,established; content: "Host|3a|"; nocase; http_header; content:"' . $attribute['value'] . '"; fast_pattern; nocase; http_header; pcre: "/(^|[^A-Za-z0-9-])' . preg_quote($attribute['value']) . '[^A-Za-z0-9-\.]/Hi";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP Domain: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'dns_query; content:"'.$attribute['value'].'"; nocase; pcre: "/(^|[^A-Za-z0-9-])' . preg_quote($attribute['value']) . '$/i";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'dns', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Domain: ' . $attribute['value'], // msg
$content, // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
// also do http requests,
// warning: only suricata compatible
$content = 'flow:to_server,established; content: "Host|3a|"; nocase; http_header; content:"' . $attribute['value'] . '"; fast_pattern; nocase; http_header; pcre: "/(^|[^A-Za-z0-9-])' . preg_quote($attribute['value']) . '[^A-Za-z0-9-\.]/Hi";';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP Domain: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
public function urlRule($ruleFormat, $attribute, &$sid) {
// TODO in hindsight, an url should not be excluded given a host or domain name.
//$hostpart = parse_url($attribute['value'], PHP_URL_HOST);
//$overruled = $this->checkNames($hostpart);
// warning: only suricata compatible
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'flow:to_server,established; content:"' . $attribute['value'] . '"; fast_pattern; nocase; http_uri;';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP URL: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
// TODO in hindsight, an url should not be excluded given a host or domain name.
//$hostpart = parse_url($attribute['value'], PHP_URL_HOST);
//$overruled = $this->checkNames($hostpart);
// warning: only suricata compatible
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
$content = 'flow:to_server,established; content:"' . $attribute['value'] . '"; fast_pattern; nocase; http_uri;';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing HTTP URL: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
public function userAgentRule($ruleFormat, $attribute, &$sid) {
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
// warning: only suricata compatible
$content = 'flow:to_server,established; content:"' . $attribute['value'] . '"; fast_pattern; http_user_agent;';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing User-Agent: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
$overruled = $this->checkWhitelist($attribute['value']);
$attribute['value'] = NidsExport::replaceIllegalChars($attribute['value']); // substitute chars not allowed in rule
// warning: only suricata compatible
$content = 'flow:to_server,established; content:"' . $attribute['value'] . '"; fast_pattern; http_user_agent;';
$this->rules[] = sprintf($ruleFormat,
($overruled) ? '#OVERRULED BY WHITELIST# ' : '',
'http', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'any', // dst_port
'Outgoing User-Agent: ' . $attribute['value'], // msg
$content, // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
}
}

View File

@ -1,21 +1,20 @@
<?php
class JSONConverterTool {
public function event2JSON($event, $isSiteAdmin=false) {
$event['Event']['Org'] = $event['Org'];
$event['Event']['Orgc'] = $event['Orgc'];
if (isset($event['SharingGroup'])) $event['Event']['SharingGroup'] = $event['SharingGroup'];
$event['Event']['Attribute'] = $event['Attribute'];
$event['Event']['ShadowAttribute'] = $event['ShadowAttribute'];
$event['Event']['RelatedEvent'] = $event['RelatedEvent'];
$toRearrange = array('Org', 'Orgc', 'SharingGroup', 'Attribute', 'ShadowAttribute', 'RelatedAttribute', 'RelatedEvent');
foreach ($toRearrange as $object) {
if (isset($event[$object])) {
$event['Event'][$object] = $event[$object];
unset($event[$object]);
}
}
if (isset($event['EventTag'])) {
foreach ($event['EventTag'] as $k => $tag) {
$event['Event']['Tag'][$k] = $tag['Tag'];
}
}
if (isset($event['RelatedAttribute'])) $event['Event']['RelatedAttribute'] = $event['RelatedAttribute'];
else $event['Event']['RelatedAttribute'] = array();
//
// cleanup the array from things we do not want to expose
//

View File

@ -7,6 +7,7 @@ class SyncTool {
App::uses('HttpSocket', 'Network/Http');
if (!empty($server)) {
if ($server['Server']['cert_file']) $params['ssl_cafile'] = APP . "files" . DS . "certs" . DS . $server['Server']['id'] . '.pem';
if ($server['Server']['client_cert_file']) $params['ssl_local_cert'] = APP . "files" . DS . "certs" . DS . $server['Server']['id'] . '_client.pem';
if ($server['Server']['self_signed']) $params['ssl_allow_self_signed'] = $server['Server']['self_signed'];
}
$HttpSocket = new HttpSocket($params);

@ -1 +1 @@
Subproject commit 0a22058e356b7346221f26d3be47a6c93e12c2f5
Subproject commit d0041f155dcc70a76d0d6e36343a514e9540cbd3

View File

@ -0,0 +1,46 @@
<?php
App::uses('AppModel', 'Model');
class AdminSetting extends AppModel {
public $useTable = 'admin_settings';
public $actsAs = array(
'SysLogLogable.SysLogLogable' => array(
'userModel' => 'User',
'userKey' => 'user_id',
'change' => 'full'
),
'Containable'
);
public $validate = array('setting' => 'isUnique');
public function changeSetting($setting, $value = false) {
$setting_object = $this->find('first', array(
'conditions' => array('setting' => $setting)
));
if (!empty($setting_object)) {
$setting_object['AdminSetting']['value'] = $value;
} else {
$this->create();
$setting_object['AdminSetting'] = array('setting' => $setting, 'value' => $value);
}
if ($this->save($setting_object)) {
return true;
} else {
return $this->validationErrors;
}
}
public function getSetting($setting) {
$setting_object = $this->find('first', array(
'conditions' => array('setting' => $setting)
));
if (!empty($setting_object)) {
return $setting_object['AdminSetting']['value'];
} else {
return false;
}
}
}

View File

@ -1,9 +0,0 @@
<?php
App::uses('AppModel', 'Model');
class AdminSetting extends AppModel {
public $actsAs = array('Containable');
public $validate = array('setting' => 'isUnique');
}

View File

@ -36,7 +36,7 @@ class AppModel extends Model {
// major -> minor -> hotfix -> requires_logout
public $db_changes = array(
2 => array(
4 => array(18 => false, 19 => false, 20 => false, 25 => false, 27 => false, 32 => false, 33 => true, 38 => true, 39 => true, 40 => false, 42 => false, 44 => false, 45 => false, 49 => true, 50 => false)
4 => array(18 => false, 19 => false, 20 => false, 25 => false, 27 => false, 32 => false, 33 => true, 38 => true, 39 => true, 40 => false, 42 => false, 44 => false, 45 => false, 49 => true, 50 => false, 51 => false)
)
);
@ -427,6 +427,10 @@ class AppModel extends Model {
$sqlArray[] = "ALTER TABLE `users` ADD `certif_public` longtext COLLATE utf8_bin AFTER `gpgkey`;";
$sqlArray[] = "ALTER TABLE `servers` ADD `client_cert_file` varchar(255) COLLATE utf8_bin DEFAULT NULL;";
break;
case '2.4.51':
$sqlArray[] = 'ALTER TABLE `servers` ADD `internal` tinyint(1) NOT NULL DEFAULT 0;';
$sqlArray[] = 'ALTER TABLE `roles` ADD `default_role` tinyint(1) NOT NULL DEFAULT 0;';
break;
case 'fixNonEmptySharingGroupID':
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';

View File

@ -165,7 +165,7 @@ class Attribute extends AppModel {
public $categoryDefinitions = array(
'Internal reference' => array(
'desc' => 'Reference used by the publishing party (e.g. ticket number)',
'types' => array('link', 'comment', 'text', 'other')
'types' => array('text', 'link', 'comment', 'other')
),
'Targeting data' => array(
'desc' => 'Internal Attack Targeting and Compromise Information',
@ -484,7 +484,7 @@ class Attribute extends AppModel {
// set to_ids if it doesn't exist
if (empty($this->data['Attribute']['to_ids'])) {
$this->data['Attribute']['to_ids'] = 0;
$this->data['Attribute']['to_ids'] = 0;
}
// generate UUID if it doesn't exist
if (empty($this->data['Attribute']['uuid'])) {
@ -620,7 +620,7 @@ class Attribute extends AppModel {
break;
case 'http-method':
if (preg_match("#(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|PROPFIND|PROPPATCH|MKCOL|COPY|MOVE|LOCK|UNLOCK|VERSION-CONTROL|REPORT|CHECKOUT|CHECKIN|UNCHECKOUT|MKWORKSPACE|UPDATE|LABEL|MERGE|BASELINE-CONTROL|MKACTIVITY|ORDERPATCH|ACL|PATCH|SEARCH)#", $value)) {
$returnValue = true;
$returnValue = true;
} else {
$returnValue = 'Unknown HTTP method.';
}
@ -1096,7 +1096,6 @@ class Attribute extends AppModel {
));
}
$this->Correlation = ClassRegistry::init('Correlation');
$correlations = array();
$correlatingValues = array($a['value1']);
if (!empty($a['value2'])) $correlatingValues[] = $a['value2'];
foreach ($correlatingValues as $k => $cV) {

View File

@ -1,31 +1,45 @@
<?php
App::uses('AppModel', 'Model');
App::uses('ConnectionManager', 'Model');
App::uses('Sanitize', 'Utility');
class Bruteforce extends AppModel {
public function insert($ip, $username) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$expire = time() + Configure::read('SecureAuth.expire');
// sanitize fields
$ip = Sanitize::clean($ip);
$username = Sanitize::clean($username);
$this->query("INSERT INTO bruteforces (ip, username, `expire`) VALUES ('$ip', '$username', '$expire');");
$expire = date('Y-m-d H:i:s', $expire);
$bruteforceEntry = array(
'ip' => $ip,
'username' => $username,
'expire' => $expire
);
$this->save($bruteforceEntry);
$title = 'Failed login attempt using username ' . $username . ' from IP: ' . $_SERVER['REMOTE_ADDR'] . '.';
if ($this->isBlacklisted($ip, $username)) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
$title .= 'This has tripped the bruteforce protection after ' . Configure::read('SecureAuth.amount') . ' failed attempts. The user is now blacklisted for ' . Configure::read('SecureAuth.expire') . ' seconds.';
}
$log = array(
'org' => 'SYSTEM',
'model' => 'Blacklist',
'model' => 'User',
'model_id' => 0,
'email' => $username,
'action' => 'blacklist',
'title' => 'User from ' . $ip . ' claiming to be ' . $username . ' has been blacklisted after ' . Configure::read('SecureAuth.amount') . ' failed attempts'
));
}
'action' => 'login_fail',
'title' => $title
);
$this->Log->save($log);
}
public function clean() {
$this->query("DELETE FROM bruteforces WHERE `expire` <= NOW();");
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
if ($dataSource == 'Database/Mysql') {
$sql = 'DELETE FROM bruteforces WHERE `expire` <= NOW();';
} else if ($dataSource == 'Database/Postgres') {
$sql = 'DELETE FROM bruteforces WHERE expire <= NOW();';
}
$this->query($sql);
}
public function isBlacklisted($ip,$username) {

View File

@ -10,7 +10,7 @@ class Dns extends AppModel {
public $useTable = false;
// Checks for a valid internet name
// Returns true if the name is an existing domain name, false otherwise
// Returns true if the name is an existing domain name, false otherwise
public function testipaddress($nametotest) {
if (intval($nametotest) > 0) {
return true;

View File

@ -104,6 +104,13 @@ class Event extends AppModel {
'canHaveAttachments' => false,
'description' => 'Click this to download all network related attributes that you have access to under the Bro rule format. Only published events and attributes marked as IDS Signature are exported. Administration is able to maintain a whitelist containing host, domain name and IP numbers to exclude from the NIDS export.',
),
'stix' => array(
'extension' => '.xml',
'type' => 'STIX',
'requiresPublished' => 1,
'canHaveAttachments' => true,
'description' => 'Click this to download an a STIX document containing the STIX version of all events and attributes that you have access to.'
),
'rpz' => array(
'extension' => '.txt',
'type' => 'RPZ',
@ -353,15 +360,15 @@ class Event extends AppModel {
// TODO refactor analysis into an Enum (in the database)
if (isset($this->data['Event']['analysis'])) {
switch ($this->data['Event']['analysis']) {
case 'Initial':
$this->data['Event']['analysis'] = 0;
break;
case 'Ongoing':
$this->data['Event']['analysis'] = 1;
break;
case 'Completed':
$this->data['Event']['analysis'] = 2;
break;
case 'Initial':
$this->data['Event']['analysis'] = 0;
break;
case 'Ongoing':
$this->data['Event']['analysis'] = 1;
break;
case 'Completed':
$this->data['Event']['analysis'] = 2;
break;
}
}
if (!isset($this->data['Event']['threat_level_id'])) $this->data['Event']['threat_level_id'] = Configure::read('MISP.default_event_threat_level') ? Configure::read('MISP.default_event_threat_level') : '1';
@ -490,10 +497,10 @@ class Event extends AppModel {
// iii. Attribute has a sharing group that the user is accessible to view
$conditionsCorrelation = $this->__buildEventConditionsCorrelation($user, $eventId, $sgids);
$correlations = $this->Correlation->find('all',array(
'fields' => 'Correlation.event_id',
'conditions' => $conditionsCorrelation,
'recursive' => 0,
'order' => array('Correlation.event_id DESC')));
'fields' => 'Correlation.event_id',
'conditions' => $conditionsCorrelation,
'recursive' => 0,
'order' => array('Correlation.event_id DESC')));
$relatedEventIds = array();
foreach ($correlations as $correlation) {
@ -856,18 +863,18 @@ class Event extends AppModel {
if (isset($event['Event']['Attribute'])) {
foreach ($event['Event']['Attribute'] as $key => &$attribute) {
// do not keep attributes that are private, nor cluster
if ($attribute['distribution'] < 2) {
if (!$server['Server']['internal'] && $attribute['distribution'] < 2) {
unset($event['Event']['Attribute'][$key]);
continue; // stop processing this
}
// Downgrade the attribute from connected communities to community only
if ($attribute['distribution'] == 2) {
if (!$server['Server']['internal'] && $attribute['distribution'] == 2) {
$attribute['distribution'] = 1;
}
// If the attribute has a sharing group attached, make sure it can be transfered
if ($attribute['distribution'] == 4) {
if ($this->checkDistributionForPush(array('Attribute' => $attribute), $server, 'Attribute') === false) {
if (!$server['Server']['internal'] && $this->checkDistributionForPush(array('Attribute' => $attribute), $server, 'Attribute') === false) {
unset($event['Event']['Attribute'][$key]);
continue;
}
@ -929,7 +936,7 @@ class Event extends AppModel {
}
// Downgrade the event from connected communities to community only
if ($event['Event']['distribution'] == 2) {
if (!$server['Server']['internal'] && $event['Event']['distribution'] == 2) {
$event['Event']['distribution'] = 1;
}
return $event;
@ -1088,7 +1095,7 @@ class Event extends AppModel {
// includeAttachments: true will attach the attachments to the attributes in the data field
public function fetchEvent($user, $options = array()) {
if (isset($options['Event.id'])) $options['eventid'] = $options['Event.id'];
$possibleOptions = array('eventid', 'idList', 'tags', 'from', 'to', 'last', 'to_ids', 'includeAllTags', 'includeAttachments', 'event_uuid', 'distribution', 'sharing_group_id', 'disableSiteAdmin');
$possibleOptions = array('eventid', 'idList', 'tags', 'from', 'to', 'last', 'to_ids', 'includeAllTags', 'includeAttachments', 'event_uuid', 'distribution', 'sharing_group_id', 'disableSiteAdmin', 'metadata');
foreach ($possibleOptions as &$opt) if (!isset($options[$opt])) $options[$opt] = false;
if ($options['eventid']) {
$conditions['AND'][] = array("Event.id" => $options['eventid']);
@ -1248,6 +1255,10 @@ class Event extends AppModel {
),
)
);
if ($options['metadata']) {
unset($params['contain']['Attribute']);
unset($params['contain']['ShadowAttribute']);
}
if ($user['Role']['perm_site_admin']) {
$params['contain']['User'] = array('fields' => 'email');
}
@ -1286,28 +1297,30 @@ class Event extends AppModel {
}
}
}
foreach ($event['Attribute'] as $key => &$attribute) {
if (isset($options['includeAttachments']) && $options['includeAttachments']) {
if ($this->Attribute->typeIsAttachment($attribute['type'])) {
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
$attribute['data'] = $encodedFile;
}
}
if (isset($attribute['SharingGroup']['SharingGroupServer'])) {
foreach ($attribute['SharingGroup']['SharingGroupServer'] as &$sgs) {
if ($sgs['server_id'] == 0) {
$sgs['Server'] = array('id' => '0', 'url' => Configure::read('MISP.baseurl'), 'name' => Configure::read('MISP.baseurl'));
if (isset($event['Attribute'])) {
foreach ($event['Attribute'] as $key => &$attribute) {
if (isset($options['includeAttachments']) && $options['includeAttachments']) {
if ($this->Attribute->typeIsAttachment($attribute['type'])) {
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
$attribute['data'] = $encodedFile;
}
}
}
$attribute['ShadowAttribute'] = array();
// If a shadowattribute can be linked to an attribute, link it to it then remove it from the event
// This is to differentiate between proposals that were made to an attribute for modification and between proposals for new attributes
foreach ($event['ShadowAttribute'] as $k => &$sa) {
if (!empty($sa['old_id'])) {
if ($sa['old_id'] == $attribute['id']) {
$results[$eventKey]['Attribute'][$key]['ShadowAttribute'][] = $sa;
unset($results[$eventKey]['ShadowAttribute'][$k]);
if (isset($attribute['SharingGroup']['SharingGroupServer'])) {
foreach ($attribute['SharingGroup']['SharingGroupServer'] as &$sgs) {
if ($sgs['server_id'] == 0) {
$sgs['Server'] = array('id' => '0', 'url' => Configure::read('MISP.baseurl'), 'name' => Configure::read('MISP.baseurl'));
}
}
}
$attribute['ShadowAttribute'] = array();
// If a shadowattribute can be linked to an attribute, link it to it then remove it from the event
// This is to differentiate between proposals that were made to an attribute for modification and between proposals for new attributes
foreach ($event['ShadowAttribute'] as $k => &$sa) {
if (!empty($sa['old_id'])) {
if ($sa['old_id'] == $attribute['id']) {
$results[$eventKey]['Attribute'][$key]['ShadowAttribute'][] = $sa;
unset($results[$eventKey]['ShadowAttribute'][$k]);
}
}
}
}
@ -1317,8 +1330,10 @@ class Event extends AppModel {
}
// remove proposals to attributes that we cannot see
// if the shadow attribute wasn't moved within an attribute before, this is the case
foreach ($event['ShadowAttribute'] as $k => &$sa) {
if (!empty($sa['old_id'])) unset($event['ShadowAttribute'][$k]);
if (isset($event['ShadowAttribute'])) {
foreach ($event['ShadowAttribute'] as $k => &$sa) {
if (!empty($sa['old_id'])) unset($event['ShadowAttribute'][$k]);
}
}
}
return $results;
@ -1422,6 +1437,20 @@ class Event extends AppModel {
if (empty($event)) return false;
if (strtotime($event['Event']['date']) < $oldest) return true;
}
if (Configure::read('MISP.disable_emailing')) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Event',
'model_id' => $id,
'email' => $user['email'],
'action' => 'publish',
'title' => 'E-mail alerts not sent out during publishing. Reason: Emailing is currently disabled on this instance.',
'change' => null,
));
return true;
}
if (Configure::read('MISP.background_jobs')) {
$job = ClassRegistry::init('Job');
$job->create();
@ -1546,7 +1575,7 @@ class Event extends AppModel {
$ids = '';
if ($attribute['to_ids']) $ids = ' (IDS)';
if (isset($event['Event']['publish_timestamp']) && isset($attribute['timestamp']) && $attribute['timestamp'] > $event['Event']['publish_timestamp']) {
$line = '*' . $attribute['type'] . str_repeat(' ', $appendlen - 2 - strlen($attribute['type'])) . ': ' . $attribute['value'] . $ids . "\n";
$line = '* ' . $attribute['type'] . str_repeat(' ', $appendlen - 2 - strlen($attribute['type'])) . ': ' . $attribute['value'] . $ids . " *\n";
} else {
$line = $attribute['type'] . str_repeat(' ', $appendlen - 2 - strlen($attribute['type'])) . ': ' . $attribute['value'] . $ids . "\n";
}
@ -2043,7 +2072,9 @@ class Event extends AppModel {
// If the distribution is org only / comm only, return false
// If the distribution is sharing group only, check if the sync user is in the sharing group or not, return true if yes, false if no
public function checkDistributionForPush($object, $server, $context = 'Event') {
if ($object[$context]['distribution'] < 2) return false;
if (empty(Configure::read('MISP.host_org_id')) || !$server['Server']['internal'] || Configure::read('MISP.host_org_id') != $server['Server']['remote_org_id']) {
if ($object[$context]['distribution'] < 2) return false;
}
if ($object[$context]['distribution'] == 4) {
if ($context === 'Event') {
return $this->SharingGroup->checkIfServerInSG($object['SharingGroup'], $server);
@ -2101,8 +2132,6 @@ class Event extends AppModel {
),
));
if (empty($event)) return true;
if ($event['Event']['distribution'] < 2) return true;
$event['Event']['locked'] = 1;
// get a list of the servers
$this->Server = ClassRegistry::init('Server');
@ -2117,6 +2146,9 @@ class Event extends AppModel {
$failedServers = array();
App::uses('SyncTool', 'Tools');
foreach ($servers as &$server) {
if ((!isset($server['Server']['internal']) || !$server['Server']['internal']) && $event['Event']['distribution'] < 2) {
continue;
}
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
// Skip servers where the event has come from.
@ -2132,6 +2164,9 @@ class Event extends AppModel {
}
}
if (!$uploaded) {
if (empty($failedServers)) {
return true;
}
return $failedServers;
} else {
return true;
@ -2201,11 +2236,7 @@ class Event extends AppModel {
if (!empty($fullEvent)) $pubSubTool->publishEvent($fullEvent[0]);
}
}
if ($event['Event']['distribution'] > 1) {
$uploaded = $this->uploadEventToServersRouter($id, $passAlong);
} else {
return true;
}
$uploaded = $this->uploadEventToServersRouter($id, $passAlong);
return $uploaded;
}
@ -2402,56 +2433,97 @@ class Event extends AppModel {
}
}
public function stix($id, $tags, $attachments, $user, $returnType, $from = false, $to = false, $last = false) {
public function stix($id, $tags, $attachments, $user, $returnType = 'xml', $from = false, $to = false, $last = false, $jobId = false) {
$eventIDs = $this->Attribute->dissectArgs($id);
$tagIDs = $this->Attribute->dissectArgs($tags);
$idList = $this->getAccessibleEventIds($eventIDs[0], $eventIDs[1], $tagIDs[0], $tagIDs[1]);
if (empty($idList)) throw new Exception('No matching events found to export.');
$events = $this->fetchEvent($user, array('idList' => $idList, 'last' => $last, 'from' => $from, 'to' => $to));
if (empty($events)) throw new Exception('No matching events found to export.');
// If a second argument is passed (and it is either "yes", "true", or 1) base64 encode all of the attachments
if ($attachments == "yes" || $attachments == "true" || $attachments == 1) {
foreach ($events as &$event) {
foreach ($event['Attribute'] as &$attribute) {
if (empty($idList)) {
return array('success' => 0, 'message' => 'No matching events found to export.');
}
$event_ids = $this->fetchEventIds($user, $from, $to, $last, true);
$event_ids = array_intersect($event_ids, $idList);
if (empty($event_ids)) {
return array('success' => 0, 'message' => 'No matching events found to export.');
}
$randomFileName = $this->generateRandomFileName();
$tmpDir = APP . "files" . DS . "scripts" . DS . "tmp";
$stixFile = new File($tmpDir . DS . $randomFileName . ".stix");
$stix_framing = shell_exec('python ' . APP . "files" . DS . "scripts" . DS . 'misp2stix_framing.py ' . escapeshellarg(Configure::read('MISP.baseurl')) . ' ' . escapeshellarg(Configure::read('MISP.org')) . ' ' . escapeshellarg($returnType));
if (empty($stix_framing)) {
$stixFile->delete();
return array('success' => 0, 'message' => 'There was an issue generating the STIX export.');
}
$stixFile->write(substr($stix_framing, 0, -1));
$result = array();
if ($jobId) {
$this->Job = ClassRegistry::init('Job');
$this->Job->id = $jobId;
if (!$this->Job->exists()) $jobId = false;
}
$i = 0;
$eventCount = count($event_ids);
foreach ($event_ids as $event_id) {
$tempFile = new File($tmpDir . DS . $randomFileName, true, 0644);
$event = $this->fetchEvent($user, array('eventid' => $event_id));
if (empty($event)) continue;
if ($attachments == "yes" || $attachments == "true" || $attachments == 1) {
foreach ($event[0]['Attribute'] as &$attribute) {
if ($this->Attribute->typeIsAttachment($attribute['type'])) {
$encodedFile = $this->Attribute->base64EncodeAttachment($attribute);
$attribute['data'] = $encodedFile;
}
}
}
}
if (Configure::read('MISP.tagging')) {
foreach ($events as &$event) {
$event['Tag'] = $this->EventTag->Tag->findEventTags($event['Event']['id']);
$event[0]['Tag'] = array();
foreach ($event[0]['EventTag'] as $tag) {
$event[0]['Tag'][] = $tag['Tag'];
}
$tempFile->write(json_encode($event[0]));
unset($event);
$scriptFile = APP . "files" . DS . "scripts" . DS . "misp2stix.py";
$result = shell_exec('python ' . $scriptFile . ' ' . $randomFileName . ' ' . escapeshellarg($returnType) . ' ' . escapeshellarg(Configure::read('MISP.baseurl')) . ' ' . escapeshellarg(Configure::read('MISP.org')));
// The result of the script will be a returned JSON object with 2 variables: success (boolean) and message
// If success = 1 then the temporary output file was successfully written, otherwise an error message is passed along
$decoded = json_decode($result, true);
if (!isset($decoded['success']) || !$decoded['success']) {
$tempFile->delete();
$stixFile->delete();
return array('success' => 0, 'message' => $decoded['message']);
}
}
// generate a randomised filename for the temporary file that will be passed to the python script
$randomFileName = $this->generateRandomFileName();
$tempFile = new File(APP . "files" . DS . "scripts" . DS . "tmp" . DS . $randomFileName, true, 0644);
// save the json_encoded event(s) to the temporary file
$result = $tempFile->write(json_encode($events));
$scriptFile = APP . "files" . DS . "scripts" . DS . "misp2stix.py";
// Execute the python script and point it to the temporary filename
$result = shell_exec('python ' . $scriptFile . ' ' . $randomFileName . ' ' . $returnType . ' ' . Configure::read('MISP.baseurl') . ' "' . Configure::read('MISP.org') . '"');
// The result of the script will be a returned JSON object with 2 variables: success (boolean) and message
// If success = 1 then the temporary output file was successfully written, otherwise an error message is passed along
$decoded = json_decode($result);
$result = array();
$result['success'] = $decoded->success;
$result['message'] = $decoded->message;
if ($result['success'] == 1) {
$file = new File(APP . "files" . DS . "scripts" . DS . "tmp" . DS . $randomFileName . ".out");
$result['data'] = $file->read();
if ($returnType == 'xml') {
$stix_event = ' ' . substr($file->read(), 0, -1);
$stix_event = str_replace("\n", "\n ", $stix_event) . "\n";
} else {
$stix_event = $file->read() . (($i + 1) != $eventCount ? ',' : '');
}
$stixFile->append($stix_event);
$file->close();
$file->delete();
$i++;
if ($jobId) {
$this->Job->saveField('message', 'Event ' . $i . '/' . $eventCount);
if ($i % 10 == 0) {
$this->Job->saveField('progress', $i * 80 / $eventCount);
}
}
$tempFile->close();
}
if ($returnType == 'xml') {
$stixFile->append("</stix:STIX_Package>\n\n");
} else {
$stixFile->append("]}\n");
}
if ($i == 0) {
$tempFile->delete();
$stixFile->delete();
return array('success' => 0, 'message' => 'No matching events found to export.');
}
$data = $stixFile->read();
$tempFile->delete();
$file = new File(APP . "files" . DS . "scripts" . DS . "tmp" . DS . $randomFileName . ".out");
$file->delete();
return $result;
$stixFile->delete();
return array('success' => 1, 'data' => $data);
}
public function getAccessibleEventIds($include, $exclude, $includedTags, $excludedTags) {

View File

@ -42,7 +42,8 @@ class Log extends AppModel {
'request_delegation',
'merge',
'undelete',
'file_upload'
'file_upload',
'export'
)),
'message' => 'Options : ...'
)
@ -81,6 +82,8 @@ class Log extends AppModel {
}
public function returnDates($org = 'all') {
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
$conditions = array();
$this->Organisation = ClassRegistry::init('Organisation');
if ($org !== 'all') {
@ -89,12 +92,27 @@ class Log extends AppModel {
$conditions['org'] = $org['Organisation']['name'];
}
$conditions['AND']['NOT'] = array('action' => array('login', 'logout', 'changepw'));
$validDates = $this->find('all', array(
'fields' => array('DISTINCT UNIX_TIMESTAMP(DATE(created)) AS Date', 'count(id) AS count'),
'conditions' => $conditions,
'group' => array('Date'),
'order' => array('Date')
));
if ($dataSource == 'Database/Mysql') {
$validDates = $this->find('all', array(
'fields' => array('DISTINCT UNIX_TIMESTAMP(DATE(created)) AS Date', 'count(id) AS count'),
'conditions' => $conditions,
'group' => array('Date'),
'order' => array('Date')
));
} else if ($dataSource == 'Database/Postgres') {
// manually generate the query for Postgres
// cakephp ORM would escape "DATE" datatype in CAST expression
$condnotinaction = "'" . implode("', '", $conditions['AND']['NOT']['action']) . "'";
if (!empty($conditions['org'])) $condOrg = ' AND org = "' . $conditions['org'] . '"';
else $condOrg = '';
$sql = 'SELECT DISTINCT EXTRACT(EPOCH FROM CAST(created AS DATE)) AS "Date",
COUNT(id) AS count
FROM logs
WHERE action NOT IN (' . $condnotinaction . ')
' . $condOrg . '
GROUP BY "Date" ORDER BY "Date"';
$validDates = $this->query($sql);
}
$data = array();
foreach ($validDates as $k => $date) {
$data[$date[0]['Date']] = intval($date[0]['count']);

View File

@ -1,5 +1,6 @@
<?php
App::uses('AppModel', 'Model');
App::uses('ConnectionManager', 'Model');
class Organisation extends AppModel{
public $useTable = 'organisations';
@ -192,13 +193,20 @@ class Organisation extends AppModel{
if (empty($currentOrg) || empty($targetOrg)) throw new MethodNotAllowedException('Something went wrong with the organisation merge. Organisation not found.');
$dir = new Folder();
$this->Log = ClassRegistry::init('Log');
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
$dataSource = $dataSourceConfig['datasource'];
$dirPath = APP . 'tmp' . DS . 'logs' . DS . 'merges';
if (!$dir->create($dirPath)) throw new MethodNotAllowedException('Merge halted because the log directory (default: /var/www/MISP/app/tmp/logs/merges) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
$logFile = new File($dirPath . DS . 'merge_' . $currentOrg['Organisation']['id'] . '_' . $targetOrg['Organisation']['id'] . '_' . time() . '.log');
if (!$logFile->create()) throw new MethodNotAllowedException('Merge halted because the log file (default location: /var/www/MISP/app/tmp/logs/merges/[old_org_id]_[new_org_id]_timestamp.log) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
$backupFile = new File($dirPath . DS . 'merge_' . $currentOrg['Organisation']['id'] . '_' . $targetOrg['Organisation']['id'] . '_' . time() . '.sql');
if (!$backupFile->create()) throw new MethodNotAllowedException('Merge halted because the backup script file (default location: /var/www/MISP/app/tmp/logs/merges/[old_org_id]_[new_org_id]_timestamp.sql) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
$backupFile->append('INSERT INTO organisations (`' . implode('`, `', array_keys($currentOrg['Organisation'])) . '`) VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');' . PHP_EOL);
if ($dataSource == 'Database/Mysql') {
$sql = 'INSERT INTO organisations (`' . implode('`, `', array_keys($currentOrg['Organisation'])) . '`) VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');';
} else if ($dataSource == 'Database/Postgres') {
$sql = 'INSERT INTO organisations ("' . implode('", "', array_keys($currentOrg['Organisation'])) . '") VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');';
}
$backupFile->append($sql . PHP_EOL);
$this->Log->create();
$this->Log->save(array(
'org' => $user['Organisation']['name'],
@ -214,14 +222,29 @@ class Organisation extends AppModel{
$success = true;
foreach ($this->organisationAssociations as $model => $data) {
foreach ($data['fields'] as $field) {
$temp = $this->query('SELECT `id` FROM `' . $data['table'] . '` WHERE `' . $field . '` = "' . $currentOrg['Organisation']['id'] . '"');
if ($dataSource == 'Database/Mysql') {
$sql = 'SELECT `id` FROM `' . $data['table'] . '` WHERE `' . $field . '` = "' . $currentOrg['Organisation']['id'] . '"';
} else if ($dataSource == 'Database/Postgres') {
$sql = 'SELECT "id" FROM "' . $data['table'] . '" WHERE "' . $field . '" = "' . $currentOrg['Organisation']['id'] . '"';
}
$temp = $this->query($sql);
if (!empty($temp)) {
$dataMoved['values_changed'][$model][$field] = Set::extract('/' . $data['table'] . '/id', $temp);
if (!empty($dataMoved['values_changed'][$model][$field])) {
$this->Log->create();
try {
$result = $this->query('UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $targetOrg['Organisation']['id'] . ' WHERE `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ';');
$backupFile->append('UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ' WHERE `id` IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');' . PHP_EOL);
if ($dataSource == 'Database/Mysql') {
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $targetOrg['Organisation']['id'] . ' WHERE `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ';';
} else if ($dataSource == 'Database/Postgres') {
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $targetOrg['Organisation']['id'] . ' WHERE "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ';';
}
$result = $this->query($sql);
if ($dataSource == 'Database/Mysql') {
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ' WHERE `id` IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
} else if ($dataSource == 'Database/Postgres') {
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ' WHERE "id" IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
}
$backupFile->append($sql . PHP_EOL);
$this->Log->save(array(
'org' => $user['Organisation']['name'],
'model' => 'Organisation',

View File

@ -240,6 +240,15 @@ class Server extends AppModel {
'test' => 'testForEmpty',
'type' => 'string',
),
'host_org_id' => array(
'level' => 0,
'description' => 'The hosting organisation of this instance. If this is not selected then replication instances cannot be added.',
'value' => '0',
'errorMessage' => '',
'test' => 'testLocalOrg',
'type' => 'numeric',
'optionsSource' => 'LocalOrgs',
),
'logo' => array(
'level' => 3,
'description' => 'This setting is deprecated and can be safely removed.',
@ -1270,25 +1279,27 @@ class Server extends AppModel {
$event['Event']['distribution'] = '1';
}
// Distribution
switch ($event['Event']['distribution']) {
case 1:
// if community only, downgrade to org only after pull
$event['Event']['distribution'] = '0';
break;
case 2:
// if connected communities downgrade to community only
$event['Event']['distribution'] = '1';
break;
}
if (isset($event['Event']['Attribute']) && !empty($event['Event']['Attribute'])) {
foreach ($event['Event']['Attribute'] as &$a) {
switch ($a['distribution']) {
case '1':
$a['distribution'] = '0';
break;
case '2':
$a['distribution'] = '1';
break;
if (empty(Configure::read('MISP.host_org_id')) || !$server['Server']['internal'] || Configure::read('MISP.host_org_id') != $server['Server']['org_id']) {
switch ($event['Event']['distribution']) {
case 1:
// if community only, downgrade to org only after pull
$event['Event']['distribution'] = '0';
break;
case 2:
// if connected communities downgrade to community only
$event['Event']['distribution'] = '1';
break;
}
if (isset($event['Event']['Attribute']) && !empty($event['Event']['Attribute'])) {
foreach ($event['Event']['Attribute'] as &$a) {
switch ($a['distribution']) {
case '1':
$a['distribution'] = '0';
break;
case '2':
$a['distribution'] = '1';
break;
}
}
}
}
@ -1936,6 +1947,18 @@ class Server extends AppModel {
return true;
}
public function testLocalOrg($value) {
$this->Organisation = ClassRegistry::init('Organisation');
if ($value == 0) return 'No organisation selected';
$local_orgs = $this->Organisation->find('list', array(
'conditions' => array('local' => 1),
'recursive' => -1,
'fields' => array('Organisation.id', 'Organisation.name')
));
if (in_array($value, array_keys($local_orgs))) return true;
return 'Invalid organisation';
}
public function testForEmpty($value) {
if ($value === '') return 'Value not set.';
return true;
@ -2882,6 +2905,35 @@ class Server extends AppModel {
}
}
/* returns the version string of a connected instance
* error codes:
* 1: received non json response
* 2: no route to host
* 3: empty result set
*/
public function getRemoteVersion($id) {
$server = $this->find('first', array(
'conditions' => array('Server.id' => $id),
));
if (empty($server)) {
return 2;
}
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
$response = $HttpSocket->get($server['Server']['url'] . '/servers/getVersion', $data = '', $request);
if ($response->code == 200) {
try {
$data = json_decode($response->body, true);
} catch (Exception $e) {
return 1;
}
if (isset($data['version']) && !empty($data['version'])) {
return $data['version'];
} else return 3;
} return 2;
}
/* returns an array with the events
* error codes:
@ -2893,6 +2945,9 @@ class Server extends AppModel {
$server = $this->find('first', array(
'conditions' => array('Server.id' => $id),
));
if (empty($server)) {
return 2;
}
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);
@ -2937,6 +2992,9 @@ class Server extends AppModel {
$server = $this->find('first', array(
'conditions' => array('Server.id' => $serverId),
));
if (empty($server)) {
return 2;
}
App::uses('SyncTool', 'Tools');
$syncTool = new SyncTool();
$HttpSocket = $syncTool->setupHttpSocket($server);

View File

@ -365,11 +365,7 @@ class SharingGroup extends AppModel {
$sgids = $existingSG['SharingGroup']['id'];
$editedSG = $existingSG['SharingGroup'];
$attributes = array('name', 'releasability', 'description', 'created', 'modified');
$different = false;
foreach ($attributes as &$a) {
if (!in_array($a, array('created', 'modified')) && $editedSG[$a] !== $sg[$a]) {
$different = true;
}
foreach ($attributes as $a) {
$editedSG[$a] = $sg[$a];
}
$this->save($editedSG);

View File

@ -40,6 +40,7 @@ class Tag extends AppModel {
public $hasMany = array(
'EventTag' => array(
'className' => 'EventTag',
'dependent' => true
),
'TemplateTag',
'FavouriteTag' => array(
@ -54,11 +55,6 @@ class Tag extends AppModel {
)
);
public function beforeDelete($cascade = true) {
$this->EventTag->deleteAll(array('EventTag.tag_id' => $this->id));
}
public function validateColour($fields) {
if (!preg_match('/^#[0-9a-f]{6}$/i', $fields['colour'])) return false;
return true;
@ -69,17 +65,16 @@ class Tag extends AppModel {
$acceptIds = array();
$rejectIds = array();
if (!empty($accept)) {
$acceptIds = $this->findTags($accept);
$acceptIds = $this->findEventIdsByTagNames($accept);
if (empty($acceptIds)) $acceptIds[] = -1;
}
if (!empty($reject)) {
$rejectIds = $this->findTags($reject);
$rejectIds = $this->findEventIdsByTagNames($reject);
}
return array($acceptIds, $rejectIds);
}
// find all of the event Ids that belong to tags with certain names
public function findTags($array) {
public function findEventIdsByTagNames($array) {
$ids = array();
foreach ($array as $a) {
$conditions['OR'][] = array('LOWER(name) like' => strtolower($a));
@ -87,7 +82,6 @@ class Tag extends AppModel {
$params = array(
'recursive' => 1,
'contain' => 'EventTag',
//'fields' => array('id', 'name'),
'conditions' => $conditions
);
$result = $this->find('all', $params);

View File

@ -9,7 +9,7 @@ class Task extends AppModel {
'timer' => 0,
'scheduled_time' => '12:00',
'process_id' => '',
'description' => 'Generates export caches for every export type and for every organisation. This process is heavy, schedule so it might be a good idea to schedule this outside of working hours and before your daily automatic imports on connected services are scheduled.',
'description' => 'Generates export caches for every export type and for every organisation. This process is heavy and it is highly advised to leave export cache generation as an on-demand function for users. STIX export not included.',
'next_execution_time' => 1391601600,
'message' => 'Not scheduled yet.'

View File

@ -898,4 +898,34 @@ class User extends AppModel {
}
return $usersPerOrg;
}
public function findAdminsResponsibleForUser($user){
$admin = $this->find('first', array(
'recursive' => -1,
'conditions' => array(
'Role.perm_admin' => 1,
'User.disabled' => 0,
'User.org_id' => $user['org_id']
),
'contain' => array(
'Role' => array('fields' => array('perm_admin', 'perm_site_admin'))
),
'fields' => array('User.id', 'User.email', 'User.org_id')
));
if (count($admin) == 0) {
$admin = $this->find('first', array(
'recursive' => -1,
'conditions' => array(
'Role.perm_site_admin' => 1,
'User.disabled' => 0,
),
'contain' => array(
'Role' => array('fields' => array('perm_site_admin'))
),
'fields' => array('User.id', 'User.email', 'User.org_id')
));
}
return $admin['User'];
}
}

View File

@ -88,12 +88,14 @@ class Whitelist extends AppModel {
} else {
// if !$isAttributeArray, we know that we have an array of events that we need to parse through
foreach ($data as $ke => $event) {
// loop through each attribute and unset the ones that are whitelisted
foreach ($event['Attribute'] as $k => $attribute) {
// loop through each whitelist item and run a preg match against the attribute value. If it matches, unset the attribute
foreach ($whitelists as $wlitem) {
if (preg_match($wlitem, $attribute['value'])) {
unset($data[$ke]['Attribute'][$k]);
if (isset($event['Attribute'])) {
// loop through each attribute and unset the ones that are whitelisted
foreach ($event['Attribute'] as $k => $attribute) {
// loop through each whitelist item and run a preg match against the attribute value. If it matches, unset the attribute
foreach ($whitelists as $wlitem) {
if (preg_match($wlitem, $attribute['value'])) {
unset($data[$ke]['Attribute'][$k]);
}
}
}
}

View File

@ -27,8 +27,6 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
*
* 'ApacheShibbAuth' => // Configuration for shibboleth authentication
* array(
* 'apacheEnv' => 'REMOTE_USER', // If proxy variable = HTTP_REMOTE_USER
* 'ssoAuth' => 'AUTH_TYPE', // NOT to modify
* 'MailTag' => 'EMAIL_TAG',
* 'OrgTag' => 'FEDERATION_TAG',
* 'GroupTag' => 'GROUP_TAG',
@ -38,7 +36,6 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
* 'group_two' => 2,
* 'group_one' => 1,
* ),
* 'DefaultRoleId' => 3,
* 'DefaultOrg' => 'MY_ORG',
* ),
* @param CakeRequest $request The request that contains login information.
@ -58,13 +55,13 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
{
//If the url contains sso=disable we return false so the main misp authentication form is used to log in
if (array_key_exists('sso', $request->query) && $request->query['sso'] == 'disable' || $_SESSION["sso_disable"] === True) {
if (array_key_exists('sso', $request->query) && $request->query['sso'] == 'disable' || (isset($_SESSION["sso_disable"]) && $_SESSION["sso_disable"] === True)) {
$_SESSION["sso_disable"]=True;
return false;
}
// Get Default parameters
$roleId = Configure::read('ApacheShibbAuth.DefaultRoleId');
$roleId = -1;
$org = Configure::read('ApacheShibbAuth.DefaultOrg');
// Get tags from SSO config
$mailTag = Configure::read('ApacheShibbAuth.MailTag');
@ -73,9 +70,13 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
$groupRoleMatching = Configure::read('ApacheShibbAuth.GroupRoleMatching');
// Get user values
if (!isset($_SERVER[$mailTag])) return false;
if (!isset($_SERVER[$mailTag]) || filter_var($_SERVER[$mailTag], FILTER_VALIDATE_EMAIL) === FALSE) {
CakeLog::write('error', 'Mail tag is not given by the SSO SP. Not processing login.');
return false;
}
$mispUsername = $_SERVER[$mailTag];
CakeLog::write('info', "Trying login of user: ${mispUsername}.");
//Change username column for email (username in shibboleth attributes corresponds to the email in MISPs DB)
$this->settings['fields'] = array('username' => 'email');
@ -92,19 +93,28 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
//Get user role from its list of groups
list($roleChanged, $roleId) = $this->getUserRoleFromGroup($groupTag, $groupRoleMatching, $roleId);
if($roleId < 0) return false; //Deny if the user is not in any egroup
// Database model object
$userModel = ClassRegistry::init($this->settings['userModel']);
if ($user) { // User already exists
CakeLog::write('info', "User ${mispUsername} found in database.");
$user = $this->updateUserRole($roleChanged, $user, $roleId, $userModel);
$user = $this->updateUserOrg($org, $user, $userModel);
CakeLog::write('info', "User ${mispUsername} logged in.");
return $user;
}
CakeLog::write('info', "User ${mispUsername} not found in database.");
//Insert user in database if not existent
//Generate random password
$password = $this->randPasswordGen(40);
// get maximum nids value
$nidsMax = $userModel->find('all', array(
'fields' => array('MAX(User.nids_sid) AS nidsMax'),
)
);
// create user
$userData = array('User' => array(
'email' => $mispUsername,
@ -112,7 +122,7 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
'password' => $password, //Since it is done via shibboleth the password will be a random 40 character string
'confirm_password' => $password,
'authkey' => $userModel->generateAuthKey(),
'nids_sid' => 4000000,
'nids_sid' => ((int)$nidsMax[0][0]['nidsMax'])+1,
'newsread' => date('Y-m-d'),
'role_id' => $roleId,
'change_pw' => 0
@ -120,7 +130,8 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
// save user
$userModel->save($userData, false);
CakeLog::write('info', "User ${mispUsername} saved in database.");
CakeLog::write('info', "User ${mispUsername} logged in.");
return $this->_findUser(
$mispUsername
);
@ -147,6 +158,7 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
public function updateUserRole($roleChanged, $user, $roleId, $userModel)
{
if ($roleChanged && $user['role_id'] != $roleId) {
CakeLog::write('warning', "User role changed from ${user['role_id']} to ${roleId}.");
$user['role_id'] = $roleId; // Different role either increase or decrease permissions
$userUpdatedData = array('User' => $user);
$userModel->set(array(
@ -176,11 +188,13 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
foreach ($groupList as $group) {
//TODO: Can be optimized inverting the search group and using only array_key_exists
if (array_key_exists($group, $groupRoleMatching)) { //In case there is an group not defined in the config.php file
CakeLog::write('info', "User group ${group} found.");
$roleVal = $groupRoleMatching[$group];
if ($roleVal <= $roleId) {
if ($roleVal <= $roleId || $roleId == -1) {
$roleId = $roleVal;
$roleChanged = true;
}
CakeLog::write('info', "User role ${roleId} assigned.");
}
}
return array($roleChanged, $roleId);
@ -207,6 +221,9 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
$orgUserId = 1; //By default created by the admin
if ($user) $orgUserId = $user['id'];
$orgId = $organisations->createOrgFromName($org, $orgUserId, 0); //Created with local set to 0 by default
CakeLog::write('info', "User organisation ${org} created with id ${orgId}.");
} else {
CakeLog::write('info', "User organisation ${org} found with id ${orgId}.");
}
return $orgId;
}
@ -214,6 +231,7 @@ class ApacheShibbAuthenticate extends BaseAuthenticate {
private function updateUserOrg($org, $user, $userModel)
{
if ($user['org_id'] != $org) {
CakeLog::write('warning', "User organisation ${org} changed.");
$user['org_id'] = $org; // Different role either increase or decrease permissions
$userUpdatedData = array('User' => $user);
$userModel->set(array(

View File

@ -63,7 +63,7 @@ class UrlCacheManager {
public static function init(View $View) {
$params = $View->request->params;
if (Configure::read('UrlCache.pageFiles')) {
$cachePageKey = '_misc';
$cachePageKey = '_misc';
if (is_object($View)) {
$path = $View->request->here;
if ($path == '/') {
@ -115,10 +115,10 @@ class UrlCacheManager {
public static function get($url, $full) {
$keyUrl = $url;
if (is_array($keyUrl)) {
$keyUrl += self::$extras;
# prevent different hashs on different orders
ksort($keyUrl, SORT_STRING);
# prevent different hashs on different types (int/string/bool)
$keyUrl += self::$extras;
# prevent different hashs on different orders
ksort($keyUrl, SORT_STRING);
# prevent different hashs on different types (int/string/bool)
foreach ($keyUrl as $key => $val) {
$keyUrl[$key] = (String) $val;
}

View File

@ -23,8 +23,8 @@ class OrphansProtectableBehavior extends ModelBehavior {
function setup(&$model, $settings) {
$Model->_deletionError = null; // Stores the deletion error message
$Model->orphansProtectableOptions = array_merge(array(
'listPossibleOrphans' => true,
'htmlError' => false
'listPossibleOrphans' => true,
'htmlError' => false
), $settings);
}
@ -50,7 +50,7 @@ class OrphansProtectableBehavior extends ModelBehavior {
$possibleOrphans = array();
foreach ($Model->hasMany as $model => $settings) {
// Is relationship is dependent?
// Is relationship is dependent?
if ($settings['dependent']) { // Yes! Possible orphans are deleted, too!
// Do nothing
} else { // No! Possible orphans should be protected!
@ -114,11 +114,11 @@ class OrphansProtectableBehavior extends ModelBehavior {
function createDeletionErrorIds(&$model, $orphanModel, $ids) {
$messageParts = array();
if ($Model->orphansProtectableOptions['htmlError']) {
foreach ($ids as $id) {
$messageParts[] = '<a href="'.Inflector::pluralize(strtolower($orphanModel)).'/view/'.$id.'">'.$id.'</a>'; // TODO: Noch unschön! --zivi-muh
}
foreach ($ids as $id) {
$messageParts[] = '<a href="'.Inflector::pluralize(strtolower($orphanModel)).'/view/'.$id.'">'.$id.'</a>'; // TODO: Noch unschön! --zivi-muh
}
} else {
$messageParts = $ids;
$messageParts = $ids;
}
return implode($messageParts, ', ');
}

View File

@ -484,7 +484,7 @@ attributes or the appropriate distribution level. If you think there is a mistak
</div>
<?php endif;?>
<div class="pagination">
<ul>
<ul>
<?php
$url = array_merge(array('controller' => 'events', 'action' => 'viewEventAttributes', $event['Event']['id']), $this->request->named);
$this->Paginator->options(array(

View File

@ -493,11 +493,11 @@ Accept: application/json
Content-type: application/json
</pre>
<b>Body</b>:
<code>{"searchinfo":"Locky", "searchpublished":1, "searchdistribution":!0}</code><br /><br />
<code>{"searcheventinfo":"Locky", "searchpublished":1, "searchdistribution":!0}</code><br /><br />
<p>The above would return any event that is published, not restricted to your organisation only that has the term "Locky" in its event description. You can use exclamation marks to negate a value wherever appropriate.</p>
<p><b>The list of valid parameters:</b></p>
<p><b>searchpublished</b>: Filters on published or unpulished events [0,1] - negatable<br />
<b>searchinfo</b>: Filters on strings found in the event info - negatable<br />
<b>searcheventinfo</b>: Filters on strings found in the event info - negatable<br />
<b>searchtag</b>: Filters on attached tag names - negatable<br />
<b>searcheventid</b>: Filters on specific event IDs - negatable<br />
<b>searchthreatlevel</b>: Filters on a given event threat level [1,2,3,4] - negatable<br />

View File

@ -174,12 +174,12 @@ var typeArray = {
{"id" : "2", "value" : "Medium"},
{"id" : "3", "value" : "Low"},
{"id" : "4", "value" : "Undefined"}
],
],
'analysis' : [
{"id" : "0", "value" : "Initial"},
{"id" : "1", "value" : "Ongoing"},
{"id" : "2", "value" : "Completed"}
]
{"id" : "0", "value" : "Initial"},
{"id" : "1", "value" : "Ongoing"},
{"id" : "2", "value" : "Completed"}
]
};
var filterContext = "event";

View File

@ -92,7 +92,7 @@
<ul>
<?php
$this->Paginator->options(array(
'url' => array($feed['Feed']['id'], $event['Event']['uuid']),
'url' => array($feed['Feed']['id'], $event['Event']['uuid']),
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
@ -115,7 +115,7 @@
</ul>
</div>
<div id="attributeList" class="attributeListContainer">
<table class="table table-striped table-condensed">
<table class="table table-striped table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('date');?></th>
<th><?php echo $this->Paginator->sort('category');?></th>

View File

@ -3,9 +3,9 @@
<div class="pagination">
<ul>
<?php
$eventViewURL = '/feeds/previewEvent/' . h($id) . '/';
$eventViewURL = '/feeds/previewEvent/' . h($id) . '/';
$this->Paginator->options(array(
'url' => $id,
'url' => $id,
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',

View File

@ -41,7 +41,7 @@ class AppHelper extends UrlCacheAppHelper {
if (is_array($url) && !isset($url['admin'])) {
$url['admin'] = false;
}
return parent::url($url, $full);
return parent::url($url, $full);
}
}

View File

@ -18,15 +18,15 @@ App::uses('AppHelper', 'View/Helper');
$keywordArray = array($keywordArray);
}
foreach ($keywordArray as $k => &$keywordArrayElement) {
$keywordArrayElement = trim($keywordArrayElement);
if ("" == $keywordArrayElement) {
unset($keywordArray[$k]);
continue;
}
$replacementArray[] = '<span style="color:red">'.$keywordArrayElement.'</span>';
$keywordArrayElement = trim($keywordArrayElement);
if ("" == $keywordArrayElement) {
unset($keywordArray[$k]);
continue;
}
$replacementArray[] = '<span style="color:red">'.$keywordArrayElement.'</span>';
}
if (!empty($replacementArray))
return array_combine($keywordArray, $replacementArray);
return array_combine($keywordArray, $replacementArray);
}
public function highlighter($str, $replacePairs) {

View File

@ -0,0 +1,55 @@
<div class="confirmation">
<legend>Background Job Error Browser</legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<div>
<?php
if (!empty($response)):
$stackTrace = "";
if (isset($response['backtrace']) && !empty($response['backtrace'])) {
foreach ($response['backtrace'] as $line) {
$stackTrace .= h($line) . '</br>';
}
}
foreach ($fields as $name => $content):
if (isset($response[$content])):
?>
<span class="bold red"><?php echo h($name); ?></span>: <?php echo h($response[$content]); ?><br />
<?php
endif;
endforeach;
?>
<a href="#" id="show_stacktrace">(Click to show stack trace)</a>
<a href="#" id="hide_stacktrace" class="hidden">(Click to hide stack trace)</a>
<div id="stacktrace" class="hidden">
<?php echo $stackTrace; ?>
</div>
<?php
else:
?>
<p>No error data found. Generally job error data is purged from Redis after 24 hours, however, you can still view the errors in the log files in "/app/tmp/logs".</p>
<?php
endif;
?>
</div>
<span class="btn btn-inverse" id="PromptNoButton" onClick="cancelPopoverForm();">Close</span>
</div>
</div>
<script type="text/javascript">
$("#show_stacktrace").click(function() {
$("#show_stacktrace").hide();
$("#hide_stacktrace").show();
$("#stacktrace").show();
});
$("#hide_stacktrace").click(function() {
$("#hide_stacktrace").hide();
$("#show_stacktrace").show();
$("#stacktrace").hide();
});
$(document).ready(function() {
resizePopoverBody();
});
$(window).resize(function() {
resizePopoverBody();
});
</script>

View File

@ -71,7 +71,7 @@
$progress_bar_type = 'progress progress-striped progress-warning active';
} else if ($item['Job']['progress'] == 0) {
$progress_bar_type = 'progress progress-striped progress-queued active';
$progress_message = 'Queued';
$progress_message = $item['Job']['status'] === 'Running' ? 'Running' : 'Queued';
} else {
$progress = h($item['Job']['progress']);
if ($item['Job']['progress'] == 100) {

View File

@ -26,7 +26,7 @@
echo $this->Form->input('anonymise', array(
'type' => 'checkbox',
'checked' => $newsItem['News']['user_id'] == 0,
'label' => 'Create anonymously',
'label' => 'Create anonymously',
));
?>
</fieldset>

View File

@ -35,11 +35,11 @@ echo $this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escap
</div>
<div class="tabMenuFixedContainer" style="display:inline-block;">
<?php
foreach (array('local', 'external', 'all') as $scopeChoice):
foreach (array('local', 'external', 'all') as $scopeChoice):
?>
<span class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php if ($scope === $scopeChoice) echo 'tabMenuActive';?>" onClick="window.location='/organisations/index/scope:<?php echo h($scopeChoice);?>'"><?php echo $texts[$scopeChoice]['text'];?></span>
<span class="tabMenuFixed tabMenuFixedCenter tabMenuSides useCursorPointer <?php if ($scope === $scopeChoice) echo 'tabMenuActive';?>" onClick="window.location='/organisations/index/scope:<?php echo h($scopeChoice);?>'"><?php echo $texts[$scopeChoice]['text'];?></span>
<?php
endforeach;
endforeach;
?>
<span id="quickFilterButton" class="tabMenuFilterFieldButton useCursorPointer" onClick="quickFilter(<?php echo h($passedArgs); ?>, '<?php echo $baseurl . '/organisations/index'; ?>');">Filter</span>
<input class="tabMenuFilterField" type="text" id="quickFilterField"></input>

View File

@ -19,6 +19,7 @@
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th>Default</th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('permission', 'Permission');?></th>
<?php
@ -32,9 +33,10 @@
</tr><?php
foreach ($list as $item): ?>
<tr>
<td class="short"><?php echo $this->Html->link(h($item['Role']['id']), array('admin' => true, 'action' => 'edit', $item['Role']['id'])); ?>&nbsp;</td>
<td><?php echo $this->Html->link(h($item['Role']['id']), array('admin' => true, 'action' => 'edit', $item['Role']['id'])); ?>&nbsp;</td>
<td class="short" style="text-align:center;width:20px;"><input class="servers_default_role_checkbox" type="checkbox" data-id="<?php echo h($item['Role']['id']); ?>" <?php if ($default_role_id && $default_role_id == $item['Role']['id']) echo 'checked'; ?>></td>
<td><?php echo h($item['Role']['name']); ?>&nbsp;</td>
<td class="short"><?php echo h($options[$item['Role']['permission']]); ?>&nbsp;</td>
<td><?php echo h($options[$item['Role']['permission']]); ?>&nbsp;</td>
<?php foreach ($permFlags as $k => $flags): ?>
<td class="short"><span class="<?php if ($item['Role'][$k]) echo 'icon-ok'; ?>"></span>&nbsp;</td>
<?php endforeach; ?>
@ -61,7 +63,6 @@ endforeach; ?>
?>
</ul>
</div>
</div>
<?php
echo $this->element('side_menu', array('menuList' => 'admin', 'menuItem' => 'indexRole'));

View File

@ -19,6 +19,7 @@
<table class="table table-striped table-hover table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th>Default</th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th><?php echo $this->Paginator->sort('permission', 'Permission');?></th>
<?php
@ -32,6 +33,7 @@
foreach ($list as $item): ?>
<tr>
<td class="short"><?php echo h($item['Role']['id']); ?>&nbsp;</td>
<td class="short" style="text-align:center;width:20px;"><div class="icon-<?php echo $default_role_id == $item['Role']['id'] ? 'ok' : 'remove' ?>"></div></td>
<td><?php echo h($item['Role']['name']); ?>&nbsp;</td>
<td class="short"><?php echo h($options[$item['Role']['permission']]); ?>&nbsp;</td>
<?php foreach ($permFlags as $k => $flags): ?>

View File

@ -9,6 +9,20 @@
echo $this->Form->input('name', array(
'label' => 'Instance name',
));
if (!empty($host_org_id)):
?>
<div id="InternalDiv" class = "input clear" style="width:100%;">
<hr />
<p class="red" style="width:50%;">You can set this instance up as an internal instance by checking the checkbox below. This means that any synchronisation between this instance and the remote will not be automatically degraded as it would in a normal synchronisation scenario. Please make sure that you own both instances and that you are OK with this otherwise dangerous change.</p>
<?php
echo $this->Form->input('internal', array(
'label' => 'Internal instance',
'type' => 'checkbox',
));
?>
</div>
<?php
endif;
?>
<div class="input clear" style="width:100%;">
<hr />
@ -16,7 +30,7 @@
</div>
<div class = "input clear"></div>
<?php
if ($isSiteAdmin) :
if ($isSiteAdmin):
echo $this->Form->input('organisation_type', array(
'label' => 'Remote Sync Organisation Type',
'options' => $organisationOptions,
@ -64,7 +78,13 @@
));
echo $this->Form->input('Server.submitted_cert', array(
'label' => '<b>Certificate file</b>',
'label' => '<b>Server certificate file</b>',
'type' => 'file',
'div' => 'clear'
));
echo $this->Form->input('Server.submitted_client_cert', array(
'label' => '<b>Client certificate file</b>',
'type' => 'file',
'div' => 'clear'
));
@ -119,6 +139,7 @@ var validOptions = ['pull', 'push'];
var validFields = ['tags', 'orgs'];
var tags = <?php echo json_encode($allTags); ?>;
var orgs = <?php echo json_encode($allOrganisations); ?>;
var host_org_id = "<?php echo h($host_org_id); ?>";
var modelContext = 'Server';
$(document).ready(function() {
@ -148,5 +169,9 @@ $(document).ready(function() {
$("#pull_modify").click(function() {
serverRuleFormActivate('pull');
});
$('#ServerOrganisationType, #ServerLocal').change(function() {
serverOwnerOrganisationChange(host_org_id);
});
});
</script>

View File

@ -9,6 +9,20 @@
echo $this->Form->input('name', array(
'label' => 'Instance name',
));
if (!empty($host_org_id) && $this->request->data['Server']['remote_org_id'] == $host_org_id):
?>
<div id="InternalDiv" class = "input clear" style="width:100%;">
<hr />
<p class="red" style="width:50%;">You can set this instance up as an internal instance by checking the checkbox below. This means that any synchronisation between this instance and the remote will not be automatically degraded as it would in a normal synchronisation scenario. Please make sure that you own both instances and that you are OK with this otherwise dangerous change. This also requires that the current instance's host organisation and the remote sync organisation are the same.</p>
<?php
echo $this->Form->input('internal', array(
'label' => 'Internal instance',
'type' => 'checkbox',
));
?>
</div>
<?php
endif;
?>
<div class="input clear"></div>
@ -71,7 +85,7 @@
?>
<div class="clear">
<p>
<span class="bold">Ceritificate file: </span>
<span class="bold">Server ceritificate file: </span>
<span id="serverEditCertValue">
<?php
if (isset($server['Server']['cert_file']) && !empty($server['Server']['cert_file'])) echo h($server['Server']['cert_file']);
@ -85,7 +99,29 @@
<div style="width: 0px;height: 0px;overflow: hidden;">
<?php
echo $this->Form->input('Server.submitted_cert', array(
'label' => false,
'label' => 'submitted_cert',
'type' => 'file',
'div' => false
));
?>
</div>
<div class="clear">
<p>
<span class="bold">Client ceritificate file: </span>
<span id="serverEditClientCertValue">
<?php
if (isset($server['Server']['client_cert_file']) && !empty($server['Server']['client_cert_file'])) echo h($server['Server']['client_cert_file']);
else echo '<span class="green bold">Not set.</span>';
?>
</span>
<br />
<span id="add_client_cert_file" class="btn btn-inverse" style="line-height:10px; padding: 4px 4px;">Add certificate file</span>
<span id="remove_client_cert_file" class="btn btn-inverse" style="line-height:10px; padding: 4px 4px;">Remove certificate file</span>
</p>
<div style="width: 0px;height: 0px;overflow: hidden;">
<?php
echo $this->Form->input('Server.submitted_client_cert', array(
'label' => 'submitted_client_cert',
'type' => 'file',
'div' => false
));
@ -109,6 +145,7 @@
echo $this->Form->input('pull_rules', array('style' => 'display:none;', 'label' => false, 'div' => false));
echo $this->Form->input('json', array('style' => 'display:none;', 'label' => false, 'div' => false));
echo $this->Form->checkbox('delete_cert', array('style' => 'display:none;', 'label' => false, 'div' => false));
echo $this->Form->checkbox('delete_client_cert', array('style' => 'display:none;', 'label' => false, 'div' => false));
?>
</fieldset>
<span class="btn btn-primary" onClick="serverSubmitForm('Edit');">Submit</span>
@ -135,6 +172,7 @@ var formInfoValues = {
'ServerPush' : "Allow the upload of events and their attributes.",
'ServerPull' : "Allow the download of events and their attributes from the server.",
'ServerSubmittedCert' : "You can also upload a certificate file if the instance you are trying to connect to has its own signing authority.",
'ServerSubmittedClientCert' : "You can also upload a client certificate file if the instance you are trying to connect requires this.",
'ServerSelfSigned' : "Click this, if you would like to allow a connection despite the other instance using a self-signed certificate (not recommended)."
};
@ -144,6 +182,8 @@ var validFields = ['tags', 'orgs'];
var tags = <?php echo json_encode($allTags); ?>;
var orgs = <?php echo json_encode($allOrganisations); ?>;
var delete_cert = false;
var delete_client_cert = false;
var host_org_id = "<?php echo h($host_org_id); ?>";
var modelContext = 'Server';
$(document).ready(function() {
@ -152,11 +192,11 @@ $(document).ready(function() {
serverOrgTypeChange();
});
$("#ServerUrl, #ServerOrganization, #ServerName, #ServerAuthkey, #ServerPush, #ServerPull, #ServerSubmittedCert, #ServerSelfSigned").on('mouseleave', function(e) {
$("#ServerUrl, #ServerOrganization, #ServerName, #ServerAuthkey, #ServerPush, #ServerPull, #ServerSubmittedCert, #ServerSubmittedClientCert, #ServerSelfSigned").on('mouseleave', function(e) {
$('#'+e.currentTarget.id).popover('destroy');
});
$("#ServerUrl, #ServerOrganization, #ServerName, #ServerAuthkey, #ServerPush, #ServerPull, #ServerSubmittedCert, #ServerSelfSigned").on('mouseover', function(e) {
$("#ServerUrl, #ServerOrganization, #ServerName, #ServerAuthkey, #ServerPush, #ServerPull, #ServerSubmittedCert, #ServerSubmittedClientCert, #ServerSelfSigned").on('mouseover', function(e) {
var $e = $(e.target);
$('#'+e.currentTarget.id).popover('destroy');
$('#'+e.currentTarget.id).popover({
@ -177,14 +217,28 @@ $(document).ready(function() {
$('#add_cert_file').click(function() {
$('#ServerSubmittedCert').trigger('click');
});
$('input[type=file]').change(function() {
$('#serverEditCertValue').text($('input[type=file]').val());
$('#add_client_cert_file').click(function() {
$('#ServerSubmittedClientCert').trigger('click');
});
$('input[label=submitted_cert]').change(function() {
$('#serverEditCertValue').text($('input[label=submitted_cert]').val());
$('#ServerDeleteCert').prop('checked', false);
});
$('input[label=submitted_client_cert]').change(function() {
$('#serverEditClientCertValue').text($('input[label=submitted_client_cert]').val());
$('#ServerDeleteClientCert').prop('checked', false);
});
$('#remove_cert_file').click(function() {
$('#serverEditCertValue').html('<span class="green bold">Not set.</span>');
$('#ServerDeleteCert').prop('checked', true);
});
$('#remove_client_cert_file').click(function() {
$('#serverEditClientCertValue').html('<span class="green bold">Not set.</span>');
$('#ServerDeleteClientCert').prop('checked', true);
});
$('#ServerOrganisationType, #ServerLocal').change(function() {
serverOwnerOrganisationChange(host_org_id);
});
});
</script>

View File

@ -20,11 +20,13 @@
<tr>
<th><?php echo $this->Paginator->sort('name');?></th>
<th>Connection test</th>
<th><?php echo $this->Paginator->sort('internal');?></th>
<th><?php echo $this->Paginator->sort('push');?></th>
<th><?php echo $this->Paginator->sort('pull');?></th>
<th><?php echo $this->Paginator->sort('url');?></th>
<th>Remote Organisation</th>
<th><?php echo $this->Paginator->sort('cert_file');?></th>
<th><?php echo $this->Paginator->sort('client_cert_file');?></th>
<th><?php echo $this->Paginator->sort('self_signed');?></th>
<th><?php echo $this->Paginator->sort('org');?></th>
<th class="actions">Actions</th>
@ -62,12 +64,13 @@ foreach ($servers as $server):
?>
</td>
<td id="connection_test_<?php echo $server['Server']['id'];?>"><span class="btn btn-primary" style="line-height:10px; padding: 4px 4px;" onClick="testConnection('<?php echo $server['Server']['id'];?>');">Run</span></td>
<td><span class="<?php echo ($server['Server']['internal']? 'icon-ok' : 'icon-remove'); ?>" title="<?php echo ($server['Server']['internal']? 'Internal instance that ignores distribution level degradation *WARNING: Only use this setting if you have several insternal instances and the sync link is to an internal extension of the current MISP community*' : 'Normal sync link to an external MISP instance. Distribution degradation will follow the normal rules.'); ?>"></span></td>
<td><span class="<?php echo ($server['Server']['push']? 'icon-ok' : 'icon-remove'); ?>"></span><span class="short <?php if (!$server['Server']['push'] || empty($ruleDescription['push'])) echo "hidden"; ?>" data-toggle="popover" title="Distribution List" data-content="<?php echo $ruleDescription['push']; ?>"> (Rules)</span></td>
<td><span class="<?php echo ($server['Server']['pull']? 'icon-ok' : 'icon-remove'); ?>"></span><span class="short <?php if (!$server['Server']['pull'] || empty($ruleDescription['pull'])) echo "hidden"; ?>" data-toggle="popover" title="Distribution List" data-content="<?php echo $ruleDescription['pull']; ?>"> (Rules)</span>
<td><?php echo h($server['Server']['url']); ?>&nbsp;</td>
<td><a href="/organisations/view/<?php echo h($server['RemoteOrg']['id']); ?>"><?php echo h($server['RemoteOrg']['name']); ?></a></td>
<td class="short"><?php echo h($server['Server']['cert_file']); ?>&nbsp;</td>
<td class="short"><?php echo h($server['Server']['client_cert_file']); ?>&nbsp;</td>
<td class="short"><span class="<?php echo ($server['Server']['self_signed'] ? 'icon-ok' : 'icon-remove'); ?>"></span></td>
<td class="short"><a href="/organisations/view/<?php echo h($server['Organisation']['id']); ?>"><?php echo h($server['Organisation']['name']); ?></a></td>
<td class="short action-links">

View File

@ -116,7 +116,7 @@
<ul>
<?php
$this->Paginator->options(array(
'url' => array($server['Server']['id'], $event['Event']['id']),
'url' => array($server['Server']['id'], $event['Event']['id']),
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
@ -139,7 +139,7 @@
</ul>
</div>
<div id="attributeList" class="attributeListContainer">
<table class="table table-striped table-condensed">
<table class="table table-striped table-condensed">
<tr>
<th><?php echo $this->Paginator->sort('date');?></th>
<th><?php echo $this->Paginator->sort('category');?></th>
@ -213,7 +213,7 @@
<ul>
<?php
$this->Paginator->options(array(
'url' => array($server['Server']['id'], $event['Event']['id']),
'url' => array($server['Server']['id'], $event['Event']['id']),
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',

View File

@ -4,9 +4,9 @@
<div class="pagination">
<ul>
<?php
$eventViewURL = '/servers/previewEvent/' . h($id) . '/';
$eventViewURL = '/servers/previewEvent/' . h($id) . '/';
$this->Paginator->options(array(
'url' => $id,
'url' => $id,
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',

View File

@ -58,7 +58,7 @@
</div>
<div id="attributeList" class="attributeListContainer">
<div class="tabMenuFixedContainer">
<div class="tabMenu tabMenuEditBlock noPrint mass-select" style="float:left;top:-1px;">
<div class="tabMenu tabMenuEditBlock noPrint mass-select" style="float:left;top:-1px;">
<span id="multi-edit-button" title="Create / update selected tags" class="icon-plus useCursorPointer" onClick="addSelectedTaxonomies(<?php echo $taxonomy['id']; ?>);"></span>
</div>
<div style="float:right !important;overflow:hidden;border:0px;padding:0px;padding-right:200px;">

View File

@ -48,7 +48,12 @@
'empty' => 'Choose organisation',
));
}
echo $this->Form->input('role_id', array('label' => 'Role'));
$roleOptions = array('label' => 'Role');
// We need to make sure that the default role is actually available to the admin (for an org admin it might not be)
if (!empty($default_role_id) && isset($roles[intval($default_role_id)])) {
$roleOptions['default'] = $default_role_id;
}
echo $this->Form->input('role_id', $roleOptions);
echo $this->Form->input('authkey', array('value' => $authkey, 'readonly' => 'readonly', 'div' => 'input clear'));
echo $this->Form->input('nids_sid');
?>
@ -58,11 +63,11 @@
?>
</div>
<?php
echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => 'Paste the user\'s PGP key here or try to retrieve it from the MIT key server by clicking on "Fetch GPG key" below.'));
?>
<div class="clear"><span onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;">Fetch GPG key</span></div>
<?php
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => 'Public certificate (Encryption -- PEM format)', 'div' => 'clear', 'class' => 'input-xxlarge'));
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => 'SMIME key', 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => 'Paste the user\'s SMIME public key in PEM format here.'));
echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published', 'type' => 'checkbox'));
echo $this->Form->input('contactalert', array('label' => 'Receive alerts from "contact reporter" requests', 'type' => 'checkbox'));
?>
@ -72,7 +77,8 @@
?>
</fieldset>
<?php echo $this->Form->button(__('Submit'), array('class' => 'btn btn-primary'));
<?php
echo $this->Form->button(__('Submit'), array('class' => 'btn btn-primary'));
echo $this->Form->end();?>
</div>
<?php

View File

@ -57,11 +57,11 @@
?>
</div>
<?php
echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge'));
echo $this->Form->input('gpgkey', array('label' => 'GPG key', 'div' => 'clear', 'class' => 'input-xxlarge', 'placeholder' => 'Paste the user\'s PGP key here or try to retrieve it from the MIT key server by clicking on "Fetch GPG key" below.'));
?>
<div class="clear"><span onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;">Fetch GPG key</span></div>
<div class="clear"><span onClick="lookupPGPKey('UserEmail');" class="btn btn-inverse" style="margin-bottom:10px;">Fetch GPG key</span></div>
<?php
if (Configure::read('SMIME.enabled')) echo $this->Form->input('certif_public', array('label' => 'SMIME Public certificate (PEM format)', 'div' => 'clear', 'class' => 'input-xxlarge'));
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('change_pw', array('type' => 'checkbox', 'label' => 'Change Password'));
echo $this->Form->input('autoalert', array('label' => 'Receive alerts when events are published', 'type' => 'checkbox'));

View File

@ -1,7 +1,8 @@
<div class="events form">
<h2>Contact User(s)</h2>
<?php echo $this->Form->create('User');?>
<fieldset>
<legend><?php echo __('Contact User(s)', true); ?></legend>
<h4>Messaging - here's a quick guide on how this feature works</h4>
You can use this view to send messages to your current or future users or send them a temporary password.
<ul>

View File

@ -115,7 +115,7 @@
<?php
if (($isAclAdmin && (($user['User']['org_id'] == $me['org_id'])) || ('1' == $me['id'])) || ($isSiteAdmin)) {
?>
<span class="icon-refresh useCursorPointer" onClick="initiatePasswordReset('<?php echo $user['User']['id']; ?>');"></span>
<span class="icon-refresh useCursorPointer" onClick="initiatePasswordReset('<?php echo $user['User']['id']; ?>');" title="Inform user"></span>
<?php
echo $this->Html->link('', array('admin' => true, 'action' => 'edit', $user['User']['id']), array('class' => 'icon-edit', 'title' => 'Edit'));
echo $this->Form->postLink('', array('admin' => true, 'action' => 'delete', $user['User']['id']), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete # %s? It is highly recommended to never delete users but to disable them instead.', $user['User']['id']));

View File

@ -34,9 +34,13 @@
<dt><?php echo __('Authkey'); ?></dt>
<dd>
<?php
echo h($user['User']['authkey']);
if (!Configure::read('MISP.disableUserSelfManagement') || $isAdmin) {
echo '(' . $this->Html->link('reset', array('controller' => 'users', 'action' => 'resetauthkey', $user['User']['id'])) . ')';
if ($user['Role']['perm_auth']) {
echo h($user['User']['authkey']);
if (!Configure::read('MISP.disableUserSelfManagement') || $isAdmin) {
echo '(' . $this->Html->link('reset', array('controller' => 'users', 'action' => 'resetauthkey', $user['User']['id'])) . ')';
}
} else {
echo "<a onclick=\"requestAPIAccess()\" style=\"cursor:pointer;\">Request API access</a>";
}
?>
&nbsp;

View File

@ -17,7 +17,7 @@ def resolveIdentityAttribute(incident, attribute, namespace):
identity_spec.add_electronic_address_identifier(ElectronicAddressIdentifier(value = attribute["value"]))
ciq_identity.specification = identity_spec
ciq_identity.id_ = "example:Identity-" + attribute["uuid"]
ciq_identity.id_ = namespace + ":Identity-" + attribute["uuid"]
# is this a good idea?
ciq_identity.name = attribute["type"] + ": " + attribute["value"] + " (MISP Attribute #" + attribute["id"] + ")"

View File

@ -35,6 +35,7 @@ simple_type_to_method.update(dict.fromkeys(["pattern-in-file", "pattern-in-traff
misp_cybox_name = {"domain" : "DomainName", "hostname" : "Hostname", "url" : "URI", "AS" : "AutonomousSystem", "mutex" : "Mutex", "named pipe" : "Pipe", "link" : "URI"}
cybox_name_attribute = {"DomainName" : "value", "Hostname" : "hostname_value", "URI" : "value", "AutonomousSystem" : "number", "Pipe" : "name", "Mutex" : "name"}
misp_indicator_type = {"domain" : "Domain Watchlist", "hostname" : "Domain Watchlist", "url" : "URL Watchlist", "AS" : "", "mutex" : "Host Characteristics", "named pipe" : "Host Characteristics", "link" : ""}
cybox_validation = {"AutonomousSystem": "isInt"}
# mapping Windows Registry Hives and their abbreviations
# see https://cybox.mitre.org/language/version2.1/xsddocs/objects/Win_Registry_Key_Object_xsd.html#RegistryHiveEnum
@ -72,7 +73,9 @@ def generateObservable(indicator, attribute):
action = getattr(this_module, simple_type_to_method[attribute["type"]], None)
if (action != None):
property = action(indicator, attribute)
property.condition = "Equals"
if property is False:
return False
property.condition = "Equals"
object = Object(property)
object.id_ = cybox.utils.idgen.__generator.namespace.prefix + ":" + property.__class__.__name__ + "-" + attribute["uuid"]
observable = Observable(object)
@ -180,6 +183,10 @@ def generateRegkeyObservable(indicator, attribute):
def generateSimpleObservable(indicator, attribute):
cyboxName = misp_cybox_name[attribute["type"]]
if cyboxName in cybox_validation:
validator = getattr(this_module, cybox_validation[cyboxName], None)
if not (validator(attribute["value"])):
return False
constructor = getattr(this_module, cyboxName, None)
indicatorType = misp_indicator_type[attribute["type"]]
if (indicatorType != ""):
@ -192,6 +199,7 @@ def generateSimpleObservable(indicator, attribute):
def generateTM(indicator, attribute):
if (attribute["type"] == "snort"):
tm = SnortTestMechanism()
attribute["value"] = attribute["value"].encode('utf-8')
tm.rules = [attribute["value"]]
else:
# remove the following line and uncomment the code below once yara test mechanisms get added to python-stix
@ -301,3 +309,9 @@ def resolveRegHive(regStr):
if regStrU.startswith(hive):
return misp_reghive[hive], regStr[len(hive):]
return None, regStr
def isInt(var):
if var.isdigit():
return True
return False

View File

@ -54,44 +54,12 @@ NS_DICT = {
"urn:oasis:names:tc:ciq:xpil:3" : 'xpil',
}
SCHEMALOC_DICT = {
'http://cybox.mitre.org/common-2': 'http://cybox.mitre.org/XMLSchema/common/2.1/cybox_common.xsd',
'http://cybox.mitre.org/cybox-2': 'http://cybox.mitre.org/XMLSchema/core/2.1/cybox_core.xsd',
'http://cybox.mitre.org/default_vocabularies-2': 'http://cybox.mitre.org/XMLSchema/default_vocabularies/2.1/cybox_default_vocabularies.xsd',
'http://cybox.mitre.org/objects#ASObject-1': 'http://cybox.mitre.org/XMLSchema/objects/AS/1.0/AS_Object.xsd',
'http://cybox.mitre.org/objects#AddressObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Address/2.1/Address_Object.xsd',
'http://cybox.mitre.org/objects#DomainNameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Domain_Name/1.0/Domain_Name_Object.xsd',
'http://cybox.mitre.org/objects#EmailMessageObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Email_Message/2.1/Email_Message_Object.xsd',
'http://cybox.mitre.org/objects#FileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/File/2.1/File_Object.xsd',
'http://cybox.mitre.org/objects#HTTPSessionObject-2': 'http://cybox.mitre.org/XMLSchema/objects/HTTP_Session/2.1/HTTP_Session_Object.xsd',
'http://cybox.mitre.org/objects#HostnameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Hostname/1.0/Hostname_Object.xsd',
'http://cybox.mitre.org/objects#MutexObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Mutex/2.1/Mutex_Object.xsd',
'http://cybox.mitre.org/objects#PipeObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Pipe/2.1/Pipe_Object.xsd',
'http://cybox.mitre.org/objects#URIObject-2': 'http://cybox.mitre.org/XMLSchema/objects/URI/2.1/URI_Object.xsd',
'http://cybox.mitre.org/objects#WinRegistryKeyObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Registry_Key/2.1/Win_Registry_Key_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/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',
'http://stix.mitre.org/default_vocabularies-1': 'http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd',
'http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1': 'http://stix.mitre.org/XMLSchema/extensions/identity/ciq_3.0/1.1.1/ciq_3.0_identity.xsd',
'http://stix.mitre.org/extensions/TestMechanism#Snort-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/snort/1.1.1/snort_test_mechanism.xsd',
'http://stix.mitre.org/stix-1': 'http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd',
'urn:oasis:names:tc:ciq:xal:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xAL.xsd',
'urn:oasis:names:tc:ciq:xnl:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xNL.xsd',
'urn:oasis:names:tc:ciq:xpil:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xPIL.xsd',
}
# mappings
status_mapping = {'0' : 'New', '1' : 'Open', '2' : 'Closed'}
TLP_mapping = {'0' : 'AMBER', '1' : 'GREEN', '2' : 'GREEN', '3' : 'GREEN'}
confidence_mapping = {False : 'None', True : 'High'}
not_implemented_attributes = ['yara', 'pattern-in-traffic', 'pattern-in-memory']
not_implemented_attributes = ['yara', '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', 'email-target', 'vulnerability', 'attachment']
@ -99,25 +67,23 @@ non_indicator_attributes = ['text', 'comment', 'other', 'link', 'target-user', '
def loadEvent(args, pathname):
try:
filename = pathname + "/tmp/" + args[1]
#filename = "tmp/" + args[1]
tempFile = open(filename, 'r')
events = json.loads(tempFile.read())
return events
except:
print json.dumps({'success' : 0, 'message' : 'The temporary MISP export file could not be read'})
print(json.dumps({'success' : 0, 'message' : 'The temporary MISP export file could not be read'}))
sys.exit(1)
def saveFile(args, pathname, package):
try:
filename = pathname + "/tmp/" + args[1] + ".out"
#filename = "test.out"
with open(filename, 'w') as f:
if args[2] == 'json':
f.write(package.to_json())
f.write('{"package": ' + package.to_json() + "}")
else:
f.write(package.to_xml(auto_namespace=False, ns_dict=NS_DICT, schemaloc_dict=SCHEMALOC_DICT))
f.write(package.to_xml(include_namespaces=False, include_schemalocs=False))
except:
print json.dumps({'success' : 0, 'message' : 'The STIX file could not be written'})
print(json.dumps({'success' : 0, 'message' : 'The STIX file could not be written'}))
sys.exit(1)
#generate a package that will contain all of the event-packages
@ -350,13 +316,10 @@ def main(args):
NS_DICT[namespace[0]]=namespace[1]
cybox.utils.idgen.set_id_namespace(Namespace(namespace[0], namespace[1]))
stix.utils.idgen.set_id_namespace({namespace[0]: namespace[1]})
events = loadEvent(args, pathname)
stix_package = generateMainPackage(events)
for event in events:
sub_package = generateEventPackage(event)
stix_package.related_packages.append(sub_package)
event = loadEvent(args, pathname)
stix_package = generateEventPackage(event)
saveFile(args, pathname, stix_package)
print json.dumps({'success' : 1, 'message' : ''})
print(json.dumps({'success' : 1, 'message' : ''}))
if __name__ == "__main__":
main(sys.argv)

View File

@ -0,0 +1,108 @@
import sys, json, uuid, os, time, datetime, re
from misp2cybox import *
from dateutil.tz import tzutc
from stix.indicator import Indicator
from stix.indicator.valid_time import ValidTime
from stix.ttp import TTP, Behavior
from stix.ttp.malware_instance import MalwareInstance
from stix.incident import Incident, Time, ImpactAssessment, ExternalID, AffectedAsset
from stix.exploit_target import ExploitTarget, Vulnerability
from stix.incident.history import JournalEntry, History, HistoryItem
from stix.threat_actor import ThreatActor
from stix.core import STIXPackage, STIXHeader
from stix.common import InformationSource, Identity, Confidence
from stix.data_marking import Marking, MarkingSpecification
from stix.extensions.marking.tlp import TLPMarkingStructure
from stix.common.related import *
from stix.common.confidence import Confidence
from stix.common.vocabs import IncidentStatus
from cybox.utils import Namespace
NS_DICT = {
"http://cybox.mitre.org/common-2" : 'cyboxCommon',
"http://cybox.mitre.org/cybox-2" : 'cybox',
"http://cybox.mitre.org/default_vocabularies-2" : 'cyboxVocabs',
"http://cybox.mitre.org/objects#ASObject-1" : 'ASObj',
"http://cybox.mitre.org/objects#AddressObject-2" : 'AddressObj',
"http://cybox.mitre.org/objects#DomainNameObject-1" : 'DomainNameObj',
"http://cybox.mitre.org/objects#EmailMessageObject-2" : 'EmailMessageObj',
"http://cybox.mitre.org/objects#FileObject-2" : 'FileObj',
"http://cybox.mitre.org/objects#HTTPSessionObject-2" : 'HTTPSessionObj',
"http://cybox.mitre.org/objects#HostnameObject-1" : 'HostnameObj',
"http://cybox.mitre.org/objects#MutexObject-2" : 'MutexObj',
"http://cybox.mitre.org/objects#PipeObject-2" : 'PipeObj',
"http://cybox.mitre.org/objects#URIObject-2" : 'URIObj',
"http://cybox.mitre.org/objects#WinRegistryKeyObject-2" : 'WinRegistryKeyObj',
"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/TTP-1" : 'ttp',
"http://stix.mitre.org/ThreatActor-1" : 'ta',
"http://stix.mitre.org/common-1" : 'stixCommon',
"http://stix.mitre.org/default_vocabularies-1" : 'stixVocabs',
"http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1" : 'stix-ciqidentity',
"http://stix.mitre.org/extensions/TestMechanism#Snort-1" : 'snortTM',
"http://stix.mitre.org/stix-1" : 'stix',
"http://www.w3.org/2001/XMLSchema-instance" : 'xsi',
"urn:oasis:names:tc:ciq:xal:3" : 'xal',
"urn:oasis:names:tc:ciq:xnl:3" : 'xnl',
"urn:oasis:names:tc:ciq:xpil:3" : 'xpil',
}
SCHEMALOC_DICT = {
'http://cybox.mitre.org/common-2': 'http://cybox.mitre.org/XMLSchema/common/2.1/cybox_common.xsd',
'http://cybox.mitre.org/cybox-2': 'http://cybox.mitre.org/XMLSchema/core/2.1/cybox_core.xsd',
'http://cybox.mitre.org/default_vocabularies-2': 'http://cybox.mitre.org/XMLSchema/default_vocabularies/2.1/cybox_default_vocabularies.xsd',
'http://cybox.mitre.org/objects#ASObject-1': 'http://cybox.mitre.org/XMLSchema/objects/AS/1.0/AS_Object.xsd',
'http://cybox.mitre.org/objects#AddressObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Address/2.1/Address_Object.xsd',
'http://cybox.mitre.org/objects#DomainNameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Domain_Name/1.0/Domain_Name_Object.xsd',
'http://cybox.mitre.org/objects#EmailMessageObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Email_Message/2.1/Email_Message_Object.xsd',
'http://cybox.mitre.org/objects#FileObject-2': 'http://cybox.mitre.org/XMLSchema/objects/File/2.1/File_Object.xsd',
'http://cybox.mitre.org/objects#HTTPSessionObject-2': 'http://cybox.mitre.org/XMLSchema/objects/HTTP_Session/2.1/HTTP_Session_Object.xsd',
'http://cybox.mitre.org/objects#HostnameObject-1': 'http://cybox.mitre.org/XMLSchema/objects/Hostname/1.0/Hostname_Object.xsd',
'http://cybox.mitre.org/objects#MutexObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Mutex/2.1/Mutex_Object.xsd',
'http://cybox.mitre.org/objects#PipeObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Pipe/2.1/Pipe_Object.xsd',
'http://cybox.mitre.org/objects#URIObject-2': 'http://cybox.mitre.org/XMLSchema/objects/URI/2.1/URI_Object.xsd',
'http://cybox.mitre.org/objects#WinRegistryKeyObject-2': 'http://cybox.mitre.org/XMLSchema/objects/Win_Registry_Key/2.1/Win_Registry_Key_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/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',
'http://stix.mitre.org/default_vocabularies-1': 'http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd',
'http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1': 'http://stix.mitre.org/XMLSchema/extensions/identity/ciq_3.0/1.1.1/ciq_3.0_identity.xsd',
'http://stix.mitre.org/extensions/TestMechanism#Snort-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/snort/1.1.1/snort_test_mechanism.xsd',
'http://stix.mitre.org/stix-1': 'http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd',
'urn:oasis:names:tc:ciq:xal:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xAL.xsd',
'urn:oasis:names:tc:ciq:xnl:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xNL.xsd',
'urn:oasis:names:tc:ciq:xpil:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xPIL.xsd',
}
def main(args):
if len(sys.argv) < 4:
sys.exit("Invalid parameters")
namespace = [sys.argv[1], sys.argv[2]]
NS_DICT[namespace[0]]=namespace[1]
cybox.utils.idgen.set_id_namespace(Namespace(namespace[0], namespace[1]))
stix.utils.idgen.set_id_namespace({namespace[0]: namespace[1]})
stix_package = STIXPackage()
stix_header = STIXHeader()
stix_header.title="Export from " + namespace[1] + " MISP"
stix_header.package_intents="Threat Report"
stix_package.stix_header = stix_header
if sys.argv[3] == 'json':
stix_string = stix_package.to_json()[:-1]
stix_string += ', "related_packages": ['
else:
stix_string = stix_package.to_xml(auto_namespace=False, ns_dict=NS_DICT, schemaloc_dict=SCHEMALOC_DICT)
stix_string = stix_string.replace("</stix:STIX_Package>\n", "");
print(stix_string)
if __name__ == "__main__":
main(sys.argv)

View File

@ -2489,3 +2489,49 @@ $(".queryPopover").click(function() {
});
});
function serverOwnerOrganisationChange(host_org_id) {
if ($('#ServerOrganisationType').val() == "0" && $('#ServerLocal').val() == host_org_id) {
$('#InternalDiv').show();
} else {
$('#ServerInternal').prop("checked", false);
$('#InternalDiv').hide();
}
}
function requestAPIAccess() {
url = "/users/request_API/";
$.ajax({
type:"get",
url:url,
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data) {
$(".loading").hide();
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Something went wrong - could not request API access.');
}
});
}
$('.servers_default_role_checkbox').click(function() {
var id = $(this).data("id");
var state = $(this).is(":checked");
$(".servers_default_role_checkbox").not(this).attr('checked', false);
$.ajax({
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
handleGenericAjaxResponse(data);
},
complete:function() {
$(".loading").hide();
},
type:"get",
cache: false,
url: '/admin/roles/set_default/' + (state ? id : ""),
});
});

View File

@ -0,0 +1,39 @@
#!/usr/bin/python
'''
Example file on how to get the exported IDS data from MISP
Add your API key and SSL client certificate file,
set the MISP host and define the output file.
'''
import urllib2, httplib
MISP_HOST="http:/"
API_KEY=""
CERT_FILE="/path/to/file.pem"
EXPORT_DATA="events/nids/suricata/download"
OUTPUT_FILE="misp-suricata"
class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
def __init__(self, key, cert):
urllib2.HTTPSHandler.__init__(self)
self.key = key
self.cert = cert
def https_open(self, req):
# Rather than pass in a reference to a connection class, we pass in
# a reference to a function which, for all intents and purposes,
# will behave as a constructor
return self.do_open(self.getConnection, req)
def getConnection(self, host, timeout=300):
return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert)
URL="%s/%s" % (MISP_HOST, EXPORT_DATA)
opener = urllib2.build_opener(HTTPSClientAuthHandler(CERT_FILE, CERT_FILE))
opener.addheaders = [('Authorization', API_KEY)]
data = opener.open(URL).read()
f = open(OUTPUT_FILE,'w')
f.write(data)
f.close()