From 6135468c41f9c1ffe3d7fcc30b6805522156fb56 Mon Sep 17 00:00:00 2001 From: iglocska Date: Fri, 24 Nov 2017 12:00:50 +0100 Subject: [PATCH] new: Added full audit logging to ZMQ and Syslog, fixes #2635 - syslog now includes all audit log entries and it's separated into proper severity levels - ZMQ logging and syslog logging are both optional features --- app/Lib/Tools/PubSubTool.php | 5 +++ app/Model/Log.php | 39 ++++++++++++++++++- app/Model/Server.php | 17 ++++++++ .../Model/Behavior/SysLogLogableBehavior.php | 12 +----- app/files/scripts/mispzmq/mispzmq.py | 6 +-- 5 files changed, 64 insertions(+), 15 deletions(-) diff --git a/app/Lib/Tools/PubSubTool.php b/app/Lib/Tools/PubSubTool.php index 87aa9e917..bca4454ed 100644 --- a/app/Lib/Tools/PubSubTool.php +++ b/app/Lib/Tools/PubSubTool.php @@ -129,6 +129,11 @@ class PubSubTool { return $this->__pushToRedis(':data:misp_json_' . $type, json_encode($data, JSON_PRETTY_PRINT)); } + public function publish($data, $type, $action = false) { + if (!empty($action)) $data['action'] = $action; + return $this->__pushToRedis(':data:misp_json_' . $type, json_encode($data, JSON_PRETTY_PRINT)); + } + public function killService($settings = false) { $redis = new Redis(); if ($this->checkIfRunning()) { diff --git a/app/Model/Log.php b/app/Model/Log.php index a023b4a67..18b4f7d7a 100644 --- a/app/Model/Log.php +++ b/app/Model/Log.php @@ -3,7 +3,16 @@ App::uses('AppModel', 'Model'); class Log extends AppModel { - + public $warningActions = array( + 'warning', + 'change_pw', + 'login_fail', + 'version_warning', + 'auth_fail' + ); + public $errorActions = array( + 'error' + ); public $validate = array( 'action' => array( 'rule' => array('inList', array( @@ -94,6 +103,7 @@ class Log extends AppModel { $this->data['Log'][$tf] = substr($this->data['Log'][$tf], 0, 65532) . '...'; } } + $this->logData($this->data); return true; } @@ -223,4 +233,31 @@ class Log extends AppModel { return $result; } } + + function logData($data) { + if (Configure::read('Plugin.ZeroMQ_enable') && Configure::read('Plugin.ZeroMQ_user_notifications_enable')) { + $pubSubTool = $this->getPubSubTool(); + $pubSubTool->publish($data, 'audit', 'log'); + } + if (Configure::read('Security.syslog')) { + // write to syslogd as well + $syslog = new SysLog(); + $action = 'info'; + if (isset($data['Log']['action'])) { + if (in_array($data['Log']['action'], $this->errorActions)) { + $action = 'err'; + } + if (in_array($data['Log']['action'], $this->warningActions)) { + $action = 'warning'; + } + } + + $entry = $data['Log']['action']; + if (!empty($data['Log']['description'])) { + $entry .= sprintf(' -- %s', $data['Log']['description']); + } + $syslog->write($action, $entry); + } + return true; + } } diff --git a/app/Model/Server.php b/app/Model/Server.php index e32d10c9b..6aa55756a 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -952,6 +952,15 @@ class Server extends AppModel { 'type' => 'string', 'editable' => false, ), + 'syslog' => array( + 'level' => 0, + 'description' => 'Enable this setting to pass all audit log entries directly to syslog. Keep in mind, this is verbose and will include user, organisation, event data.', + 'value' => false, + 'errorMessage' => '', + 'test' => 'testBool', + 'type' => 'boolean', + 'null' => true + ), 'password_policy_length' => array( 'level' => 2, 'description' => 'Password length requirement. If it is not set or it is set to 0, then the default value is assumed (12).', @@ -1244,6 +1253,14 @@ class Server extends AppModel { 'test' => 'testBool', 'type' => 'boolean' ), + 'ZeroMQ_audit_notifications_enable' => array( + 'level' => 2, + 'description' => 'Enables or disables the publishing of log entries to the ZMQ pubsub feed. Keep in mind, this can get pretty verbose depending on your logging settings.', + 'value' => false, + 'errorMessage' => '', + 'test' => 'testBool', + 'type' => 'boolean' + ), 'Sightings_enable' => array( 'level' => 1, 'description' => 'Enables or disables the sighting functionality. When enabled, users can use the UI or the appropriate APIs to submit sightings data about indicators.', diff --git a/app/Plugin/SysLogLogable/Model/Behavior/SysLogLogableBehavior.php b/app/Plugin/SysLogLogable/Model/Behavior/SysLogLogableBehavior.php index 1ac306936..6e59cdcf6 100644 --- a/app/Plugin/SysLogLogable/Model/Behavior/SysLogLogableBehavior.php +++ b/app/Plugin/SysLogLogable/Model/Behavior/SysLogLogableBehavior.php @@ -249,20 +249,10 @@ class SysLogLogableBehavior extends LogableBehavior { } } $this->Log->create($logData); - $this->Log->save(null, array( - 'validate' => false)); - - // write to syslogd as well - $syslog = new SysLog(); - if (isset($logData['Log']['change'])) { - $syslog->write('notice', $logData['Log']['description'].' -- '.$logData['Log']['change']); - } else { - $syslog->write('notice', $logData['Log']['description']); - } + $this->Log->save(null, array('validate' => false)); } function setup(Model $Model, $config = array()) { - if (!is_array($config)) { $config = array(); } diff --git a/app/files/scripts/mispzmq/mispzmq.py b/app/files/scripts/mispzmq/mispzmq.py index 7f1fef0f6..32334eaf1 100644 --- a/app/files/scripts/mispzmq/mispzmq.py +++ b/app/files/scripts/mispzmq/mispzmq.py @@ -74,9 +74,9 @@ def main(args): command = r.lpop(namespace + ":command") if command is not None: handleCommand(command) - topics = ["misp_json", "misp_json_event", "misp_json_attribute", "misp_json_sighting", + topics = ["misp_json", "misp_json_event", "misp_json_attribute", "misp_json_sighting", "misp_json_organisation", "misp_json_user", "misp_json_conversation", - "misp_json_object", "misp_json_object_reference"] + "misp_json_object", "misp_json_object_reference", "misp_json_audit"] message_received = False for topic in topics: data = r.lpop(namespace + ":data:" + topic) @@ -84,7 +84,7 @@ def main(args): pubMessage(topic, data, socket) message_received = True if (message_received == False): - time.sleep(1) + time.sleep(0.2) if ((int(time.time()) - start_time) % 10 == 0): status_entry = int(((int(time.time()) - start_time)/10) % 5) status_message = {