Skip to content

HowTo CorrelationDetector

Max Landauer edited this page Feb 3, 2022 · 9 revisions

HowTo EventCorrelationDetector

Events in system logs usually form specific sequences that are often recurring. The reason for this is that the logic of the monitored application produces log events in patterns that reflect the underlying workflows. However, since these workflows depend on specific circumstances, e.g., user input, and are subject to delays and concurrent processes, it is not always guaranteed that events occur in precisely the same order, but rather involve swapped, additional, or missing events. Nonetheless, given a sufficiently long time for training, it is possible to extract dependencies between log events that are expected to hold with a certain probability. Violations of these patterns occurring during normal operation represent anomalies that should be reported.

In this tutorial, we apply the EventCorrelationDetector (ECD) on two types of log data to automatically extract correlations and use them to disclose anomalies as violations of these rules. For this, we use data from a mail server which runs Horde webmail and Exim. Whenever a user sends a mail on the Horde platform, we expect that events are generated both by the Horde and Exim service - these events therefore correlate. Let's see if we can derive this rule without any manual coding of event dependencies.

For the following demonstration, we use the ecd_demo_data.txt log file. For convenience, the file contains logs from both the messages file as well as Exim mainlog file. This makes it easier to process logs that appear simultaneously (i.e., in the same second according to the timestamp in the event) in the correct order. The data looks like this:

Jan 14 10:29:16 mail HORDE: [horde] Login success for taylor.johnson to horde (172.21.129.224) [pid 11970 on line 163 of "/usr/share/horde/login.php"]
Jan 14 10:29:16 mail HORDE: [imp] Login success for taylor.johnson (172.21.129.224) (forwarded for [192.168.104.81]) to {imap://mailserver.smith.santos.com/} [pid 11970 on line 156 of "/usr/share/horde/imp/lib/Auth.php"]
Jan 14 10:29:35 mail HORDE: [imp] Message sent to amanda.watson@smith.santos.com from danny.jarvis (192.168.104.95) [pid 12035 on line 970 of "/usr/share/horde/imp/lib/Compose.php"]
2022-01-14 10:29:35 1n8Jpv-000388-Id <= danny.jarvis@smith.santos.com H=mailserver.smith.santos.com (mail) [172.21.131.50] P=esmtps X=TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 CV=no S=191130 id=20220114102935.Horde.3853jf0G860sRIhjdXxd0zi@mail.dmz.smith.santos.com
2022-01-14 10:29:35 1n8Jpv-000388-Id => amanda.watson <amanda.watson@smith.santos.com> R=local_user T=maildir_home
2022-01-14 10:29:35 1n8Jpv-000388-Id Completed
Jan 14 10:30:01 mail HORDE: [nag] PHP ERROR: Declaration of Horde_Form_Type_country::init($prompt = NULL) should be compatible with Horde_Form_Type_enum::init($values, $prompt = NULL) [pid 11972 on line 0 of "/usr/share/php/Horde/Form/Type.php"]
Jan 14 10:30:01 mail HORDE: [nag] PHP ERROR: Declaration of Nag_Form_Task::renderActive() should be compatible with Horde_Form::renderActive($renderer = NULL, $vars = NULL, $action = '', $method = 'get', $enctype = NULL, $focus = true) [pid 11972 on line 17 of "/usr/share/horde/nag/lib/Form/Task.php"]
Jan 14 10:30:17 mail HORDE: [nag] PHP ERROR: Declaration of Horde_Form_Type_country::init($prompt = NULL) should be compatible with Horde_Form_Type_enum::init($values, $prompt = NULL) [pid 12007 on line 0 of "/usr/share/php/Horde/Form/Type.php"]
Jan 14 10:30:17 mail HORDE: [nag] PHP ERROR: Declaration of Nag_Form_Task::renderActive() should be compatible with Horde_Form::renderActive($renderer = NULL, $vars = NULL, $action = '', $method = 'get', $enctype = NULL, $focus = true) [pid 12007 on line 17 of "/usr/share/horde/nag/lib/Form/Task.php"]
Jan 14 10:30:29 hayes-mail HORDE: [horde] User jamie.walsh logged out of Horde (10.229.1.182) [pid 6827 on line 106 of "/usr/share/horde/login.php"]
Jan 14 10:30:37 mail HORDE: [imp] Message sent to andrew.pierce@smith.santos.com, jennifer.villegas@rogersturnbull.santos.com from cindy.turner (192.168.104.98) [pid 11971 on line 970 of "/usr/share/horde/imp/lib/Compose.php"]
2022-01-14 10:30:37 1n8Jqv-00038G-PV <= cindy.turner@smith.santos.com H=mailserver.smith.santos.com (mail) [172.21.131.50] P=esmtps X=TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 CV=no S=1311 id=20220114103037.Horde.lAVZfd42wFnZf9BIx6JWJaY@mail.dmz.smith.santos.com
2022-01-14 10:30:37 1n8Jqv-00038G-PV => andrew.pierce <andrew.pierce@smith.santos.com> R=local_user T=maildir_home
2022-01-14 10:30:38 1n8Jqv-00038G-PV => jennifer.villegas@rogersturnbull.santos.com R=dnslookup T=remote_smtp H=mailserver.rogersturnbull.santos.com [10.229.0.32] X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=yes DN="C=UK,ST=England,L=London,O=ROGERSTURNBULL LLC,CN=mailserver.rogersturnbull.santos.com" C="250 OK id=1n8Jqw-00016q-0b"
2022-01-14 10:30:38 1n8Jqv-00038G-PV Completed

There is a lot going on in these logs: We see events that are generated when users log in or out, some error logs, events that are generated when emails are sent by Horde (i.e., HORDE: [imp] Message sent to ...), and sent (<=) or received (=>) mails logged by the Exim service. Just by looking at the logs, it is not easy to find some correlations that should always hold. Note that our log file contains messages from multiple servers (e.g., mail, hayes-mail) and therefore not every Message sent to event is followed by a corresponding <= event. In addition, some users send mails to multiple recepients and therefore there is no direct relationship between <= and => events.

But let's just do the AMiner this kind of reasoning. In the configuration of the AMiner we add an EventCorrelationDetector and do not specify any paths (which would only be useful if we want to find correlations between values or value combinations that occur in a specific event parameter) in order to detect correlations between event types. Since mails are sent relatively infrequently, we use sufficiently long delta times of 28800 seconds. For testing whether correlations hold, we use samples of size 300 and test them with p0 = 0.99 and alpha = 0.01. Moreover, we set both check_rules_flag as well as learn_mode to true so that we simultaneously learn correlations and use them for detection. For more details on the functioning of this detection approach, we refer to this paper. Other analysis components include the NewMatchPathDetector with suppress set to true to skip anomalies about new events as they are not relevant for this demonstration, as well as a ParserCount component that allows us to determine whether all lines are parsed.

LearnMode: True

LogResourceList:
        - 'file:///home/ubuntu/ecd_demo_data.txt'

Parser:
        - id: 'syslogModel'
          type: SyslogParsingModel
          name: 'syslog'

        - id: 'eximModel'
          type: EximParsingModel
          name: 'exim'

        - id: 'START'
          start: True
          type: FirstMatchModelElement
          name: 'parser'
          args:
            - 'syslogModel'
            - 'eximModel'

Input:
        timestamp_paths:
         - '/parser/model/time'

Analysis:
        - type: 'EventCorrelationDetector'
          id: 'ecd'
          hypothesis_max_delta_time: 3
          hypotheses_eval_delta_time: 28800
          delta_time_to_discard_hypothesis: 28800
          max_observations: 300
          p0: 0.99
          alpha: 0.01
          candidates_size: 100
          check_rules_flag: True
          learn_mode: True

        - type: 'NewMatchPathDetector'
          id: 'npd'
          suppress: True

        - type: "ParserCount"
          report_interval: 5

EventHandlers:
        - id: "stpe"
          type: "StreamPrinterEventHandler"
          json: True

As visible in the config, we use parsers for syslog and exim. Import the parsers from the ait-lds2 directory as follows.

root@user-0:/home/ubuntu# ln -s /etc/aminer/conf-available/ait-lds2/* /etc/aminer/conf-enabled/

And that's all we need to do to run the AMiner with this configuration. Use the following command to start the AMiner.

root@user-0:/home/ubuntu# aminer -C -c config.yml

It is only a matter of seconds until all of the 19,318 log events are parsed; there should not be any unparsed events. With this configuration, three anomalies should be reported. The first anomaly looks as follows.

{
  "RuleInfo": {
    "Rule": "('/parser/model', '/parser/model/time', '/parser/model/sp1', '/parser/model/host', '/parser/model/service/horde', '/parser/model/service/horde/horde_str', '/parser/model/service/horde/horde/imp', '/parser/model/service/horde/to_str', '/parser/model/service/horde/pid', '/parser/model/service/horde/line_str', '/parser/model/service/horde/line', '/parser/model/service/horde/of_str', '/parser/model/service/horde/path', '/parser/model/service/horde/brack_str', '/parser/model/service/horde/horde/imp/succ_str', '/parser/model/service/horde/horde/imp/imp/message_sent', '/parser/model/service/horde/horde/imp/imp/message_sent/message_sent_str', '/parser/model/service/horde/horde/imp/imp/message_sent/recepients', '/parser/model/service/horde/horde/imp/imp/message_sent/from_str', '/parser/model/service/horde/horde/imp/imp/message_sent/user', '/parser/model/service/horde/horde/imp/imp/message_sent/brack_str1', '/parser/model/service/horde/horde/imp/imp/message_sent/ip', '/parser/model/service/horde/horde/imp/imp/message_sent/brack_str2')<-('/parser/model', '/parser/model/time', '/parser/model/sp', '/parser/model/fm/mail', '/parser/model/fm/mail/id', '/parser/model/fm/mail/dir/dir_in', '/parser/model/fm/mail/dir/dir_in/in', '/parser/model/fm/mail/dir/dir_in/fm/remainder')",
    "Expected": "300/300",
    "Observed": "299/300"
  },
  "LogData": {
    "RawLogData": [
      "2022-01-16 09:09:53 1n91Xt-0001U1-Nw <= danny.jarvis@smith.santos.com H=mailserver.smith.santos.com (mail) [172.21.131.50] P=esmtps X=TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 CV=no S=1482 id=20220116090953.Horde.S095HGoTxAXukEKq07z2uLu@mail.dmz.smith.santos.com"
    ],
    "Timestamps": [
      1642324193
    ],
    "DetectionTimestamp": 1643894953.64,
    "LogLinesCount": 1
  },
  "AnalysisComponent": {
    "AnalysisComponentIdentifier": 1,
    "AnalysisComponentType": "EventCorrelationDetector",
    "AnalysisComponentName": "ecd",
    "Message": "Correlation rule violated! Event b'Jan 16 09:09:18 hayes-mail HORDE: [imp] Message sent to danny.jarvis@smith.santos.com from norman.humphries (10.229.0.23) [pid 27187 on line 970 of \"/usr/share/horde/imp/lib/Compose.php\"]' is missing, but should precede event b'2022-01-16 09:09:53 1n91Xt-0001U1-Nw <= danny.jarvis@smith.santos.com H=mailserver.smith.santos.com (mail) [172.21.131.50] P=esmtps X=TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 CV=no S=1482 id=20220116090953.Horde.S095HGoTxAXukEKq07z2uLu@mail.dmz.smith.santos.com'",
    "PersistenceFileName": "Default",
    "TrainingMode": true
  }
}

As stated in the Message field, the Message sent to event should have occurred before the <= event, but failed to do so. In other words, the ECD learned a correlation rule that up to this point every time the <= events occurs, there occurs also a Message sent to event at most 3 seconds before - and this rule was apparently violated. This rule needs to be fulfilled in 100% of all cases as it held in all 300 observation as visible in the Expected field. Looking at the affected logs, we see that this is indeed the case: The Message sent to event occurred with a 4 seconds delay. Most likely, this is just a randomly delayed event.

2022-01-16 09:09:53 1n91Xt-0001U1-Nw <= danny.jarvis@smith.santos.com H=mailserver.smith.santos.com (mail) [172.21.131.50] P=esmtps X=TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128 CV=no S=1482 id=20220116090953.Horde.S095HGoTxAXukEKq07z2uLu@mail.dmz.smith.santos.com
2022-01-16 09:09:53 1n91Xt-0001U1-Nw => katelyn.clayton@rogersturnbull.santos.com R=dnslookup T=remote_smtp H=mailserver.rogersturnbull.santos.com [10.229.0.32] X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=yes DN="C=UK,ST=England,L=London,O=ROGERSTURNBULL LLC,CN=mailserver.rogersturnbull.santos.com" C="250 OK id=1n91Xt-0005cu-U3"
2022-01-16 09:09:53 1n91Xt-0001U1-Nw Completed
Jan 16 09:09:57 mail HORDE: [imp] Message sent to katelyn.clayton@rogersturnbull.santos.com from danny.jarvis (192.168.104.95) [pid 5695 on line 970 of "/usr/share/horde/imp/lib/Compose.php"]

The next anomaly is a forward rule, i.e., it specifies that some events needs to occur at most 3 seconds after a particular event.

{
  "RuleInfo": {
    "Rule": "('/parser/model', '/parser/model/time', '/parser/model/sp', '/parser/model/fm/mail', '/parser/model/fm/mail/id', '/parser/model/fm/mail/dir/dir_in', '/parser/model/fm/mail/dir/dir_in/in', '/parser/model/fm/mail/dir/dir_in/fm/remainder')->('/parser/model', '/parser/model/time', '/parser/model/sp', '/parser/model/fm/mail', '/parser/model/fm/mail/id', '/parser/model/fm/mail/dir/completed')",
    "Expected": "300/300",
    "Observed": "299/300"
  },
  "LogData": {
    "RawLogData": [
      "2022-01-16 10:48:16 1n9351-0001wc-2F => danny.jarvis <danny.jarvis@smith.santos.com> R=local_user T=maildir_home"
    ],
    "Timestamps": [
      1642330096
    ],
    "DetectionTimestamp": 1643894953.83,
    "LogLinesCount": 1
  },
  "AnalysisComponent": {
    "AnalysisComponentIdentifier": 1,
    "AnalysisComponentType": "EventCorrelationDetector",
    "AnalysisComponentName": "ecd",
    "Message": "Correlation rule violated! Event b'2022-01-16 10:44:14 1n931C-0001wH-Lz Completed' is missing, but should follow event b'2022-01-16 10:48:11 1n9351-0001wc-2F <= jamie.walsh@hayes.santos.com H=smtp.hayes.santos.com (hayes-mail.novalocal) [10.229.2.25] P=esmtps X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=no PRDR S=1234 id=20220116104810.Horde.pgaLR4IHNlI3HR-5FgIVnPq@smtp.hayes.santos.com'",
    "PersistenceFileName": "Default",
    "TrainingMode": true
  }
}

This time, the Completed event should have occurred after the <= event. However, the logs confirm once more that ther was a delay of 5 seconds:

2022-01-16 10:48:11 1n9351-0001wc-2F <= jamie.walsh@hayes.santos.com H=smtp.hayes.santos.com (hayes-mail.novalocal) [10.229.2.25] P=esmtps X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=no PRDR S=1234 id=20220116104810.Horde.pgaLR4IHNlI3HR-5FgIVnPq@smtp.hayes.santos.com
2022-01-16 10:48:16 1n9351-0001wc-2F => danny.jarvis <danny.jarvis@smith.santos.com> R=local_user T=maildir_home
2022-01-16 10:48:16 1n9351-0001wc-2F => amanda.watson <amanda.watson@smith.santos.com> R=local_user T=maildir_home
2022-01-16 10:48:16 1n9351-0001wc-2F Completed

Now we come to the last anomaly, which looks like this:

{
  "RuleInfo": {
    "Rule": "('/parser/model', '/parser/model/time', '/parser/model/sp1', '/parser/model/host', '/parser/model/service/horde', '/parser/model/service/horde/horde_str', '/parser/model/service/horde/horde/imp', '/parser/model/service/horde/to_str', '/parser/model/service/horde/pid', '/parser/model/service/horde/line_str', '/parser/model/service/horde/line', '/parser/model/service/horde/of_str', '/parser/model/service/horde/path', '/parser/model/service/horde/brack_str', '/parser/model/service/horde/horde/imp/succ_str', '/parser/model/service/horde/horde/imp/imp/message_sent', '/parser/model/service/horde/horde/imp/imp/message_sent/message_sent_str', '/parser/model/service/horde/horde/imp/imp/message_sent/recepients', '/parser/model/service/horde/horde/imp/imp/message_sent/from_str', '/parser/model/service/horde/horde/imp/imp/message_sent/user', '/parser/model/service/horde/horde/imp/imp/message_sent/brack_str1', '/parser/model/service/horde/horde/imp/imp/message_sent/ip', '/parser/model/service/horde/horde/imp/imp/message_sent/brack_str2')<-('/parser/model', '/parser/model/time', '/parser/model/sp', '/parser/model/fm/mail', '/parser/model/fm/mail/id', '/parser/model/fm/mail/dir/dir_in', '/parser/model/fm/mail/dir/dir_in/in', '/parser/model/fm/mail/dir/dir_in/fm/remainder')",
    "Expected": "300/300",
    "Observed": "299/300"
  },
  "LogData": {
    "RawLogData": [
      "2022-01-17 20:44:48 1n9Yrw-0007GI-PY <= katy.martin@hayes.santos.com H=smtp.hayes.santos.com (hayes-mail.novalocal) [10.229.2.25] P=esmtps X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=no S=1272 id=20220117204448.Horde.qoL7XleRykqtBa-_RSzveri@smtp.hayes.santos.com"
    ],
    "Timestamps": [
      1642452288
    ],
    "DetectionTimestamp": 1643894955.78,
    "LogLinesCount": 1
  },
  "AnalysisComponent": {
    "AnalysisComponentIdentifier": 1,
    "AnalysisComponentType": "EventCorrelationDetector",
    "AnalysisComponentName": "ecd",
    "Message": "Correlation rule violated! Event b'Jan 17 20:43:23 hayes-mail HORDE: [imp] Message sent to brian.thomas@smith.santos.com from katy.martin (10.229.2.234) [pid 11105 on line 970 of \"/usr/share/horde/imp/lib/Compose.php\"]' is missing, but should precede event b'2022-01-17 20:44:48 1n9Yrw-0007GI-PY <= katy.martin@hayes.santos.com H=smtp.hayes.santos.com (hayes-mail.novalocal) [10.229.2.25] P=esmtps X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=no S=1272 id=20220117204448.Horde.qoL7XleRykqtBa-_RSzveri@smtp.hayes.santos.com'",
    "PersistenceFileName": "Default",
    "TrainingMode": true
  }
}

Looks very similar to the first anomaly, right? Well, yes, but looking at the logs, we see that this time the Message sent to event is actually missing!

2022-01-17 20:43:23 1n9YqZ-0007G9-PT Completed
2022-01-17 20:44:48 1n9Yrw-0007GI-PY <= katy.martin@hayes.santos.com H=smtp.hayes.santos.com (hayes-mail.novalocal) [10.229.2.25] P=esmtps X=TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256 CV=no S=1272 id=20220117204448.Horde.qoL7XleRykqtBa-_RSzveri@smtp.hayes.santos.com
2022-01-17 20:44:48 1n9Yrw-0007GI-PY => amanda.watson <amanda.watson@smith.santos.com> R=local_user T=maildir_home
2022-01-17 20:44:48 1n9Yrw-0007GI-PY Completed
Jan 17 20:45:51 hayes-mail HORDE: [imp] Message sent to brian.thomas@smith.santos.com from katy.martin (10.229.2.234) [pid 9708 on line 970 of "/usr/share/horde/imp/lib/Compose.php"]

This means that for some reason, the user bypassed the Horde logging framework. In fact, this could be caused by an attacker sending a mail without using the Horde platform, e.g., as part of a vulnerability exploit. In any way, this suspicious behavior deviates the normal user behavior and is therefore correctly detected as an anomaly.

In order to see which other rules were learned by the ECD, open the persistency file as follows:

root@user-0:/home/ubuntu# cat /var/lib/aminer/EventCorrelationDetector/Default
[["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/completed"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_in", "string:/parser/model/fm/mail/dir/dir_in/in", "string:/parser/model/fm/mail/dir/dir_in/fm/remainder"], 300, 294], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_in", "string:/parser/model/fm/mail/dir/dir_in/in", "string:/parser/model/fm/mail/dir/dir_in/fm/remainder"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/imp", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/imp/succ_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent", "string:/parser/model/service/horde/horde/imp/imp/message_sent/message_sent_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/recepients", "string:/parser/model/service/horde/horde/imp/imp/message_sent/from_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/user", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str1", "string:/parser/model/service/horde/horde/imp/imp/message_sent/ip", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str2"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/function", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/function/horde_function", "string:/parser/model/service/horde/horde/function/nag_str", "string:/parser/model/service/horde/horde/function/php_error/declaration", "string:/parser/model/service/horde/horde/function/php_error/declaration/declaration_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name1", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str1", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1", "string:/parser/model/service/horde/horde/function/php_error/declaration/failed_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str3", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2/arg2"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/function", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/function/horde_function", "string:/parser/model/service/horde/horde/function/nag_str", "string:/parser/model/service/horde/horde/function/php_error/declaration", "string:/parser/model/service/horde/horde/function/php_error/declaration/declaration_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name1", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str1", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1", "string:/parser/model/service/horde/horde/function/php_error/declaration/failed_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str3", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1/arg1"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_in", "string:/parser/model/fm/mail/dir/dir_in/in", "string:/parser/model/fm/mail/dir/dir_in/fm/remainder"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_in", "string:/parser/model/fm/mail/dir/dir_in/in", "string:/parser/model/fm/mail/dir/dir_in/fm/remainder"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/horde", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/horde/succ_str", "string:/parser/model/service/horde/horde/horde/horde/success", "string:/parser/model/service/horde/horde/horde/horde/success/success_str", "string:/parser/model/service/horde/horde/horde/horde/success/user", "string:/parser/model/service/horde/horde/horde/horde/success/brack_str1", "string:/parser/model/service/horde/horde/horde/horde/success/ip", "string:/parser/model/service/horde/horde/horde/horde/success/brack_str2"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/horde", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/horde/succ_str", "string:/parser/model/service/horde/horde/horde/horde/success", "string:/parser/model/service/horde/horde/horde/horde/success/success_str", "string:/parser/model/service/horde/horde/horde/horde/success/user", "string:/parser/model/service/horde/horde/horde/horde/success/brack_str1", "string:/parser/model/service/horde/horde/horde/horde/success/ip", "string:/parser/model/service/horde/horde/horde/horde/success/brack_str2"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/completed"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/imp", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/imp/succ_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent", "string:/parser/model/service/horde/horde/imp/imp/message_sent/message_sent_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/recepients", "string:/parser/model/service/horde/horde/imp/imp/message_sent/from_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/user", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str1", "string:/parser/model/service/horde/horde/imp/imp/message_sent/ip", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str2"], 300, 294], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/function", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/function/horde_function", "string:/parser/model/service/horde/horde/function/nag_str", "string:/parser/model/service/horde/horde/function/php_error/declaration", "string:/parser/model/service/horde/horde/function/php_error/declaration/declaration_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name1", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str1", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1", "string:/parser/model/service/horde/horde/function/php_error/declaration/failed_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str3", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1/arg1"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/function", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/function/horde_function", "string:/parser/model/service/horde/horde/function/nag_str", "string:/parser/model/service/horde/horde/function/php_error/declaration", "string:/parser/model/service/horde/horde/function/php_error/declaration/declaration_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name1", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str1", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1", "string:/parser/model/service/horde/horde/function/php_error/declaration/failed_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str3", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1/arg1"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/function", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/function/horde_function", "string:/parser/model/service/horde/horde/function/nag_str", "string:/parser/model/service/horde/horde/function/php_error/declaration", "string:/parser/model/service/horde/horde/function/php_error/declaration/declaration_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name1", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str1", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1", "string:/parser/model/service/horde/horde/function/php_error/declaration/failed_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str3", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2/arg2"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/function", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/function/horde_function", "string:/parser/model/service/horde/horde/function/nag_str", "string:/parser/model/service/horde/horde/function/php_error/declaration", "string:/parser/model/service/horde/horde/function/php_error/declaration/declaration_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name1", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str1", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg1", "string:/parser/model/service/horde/horde/function/php_error/declaration/failed_str", "string:/parser/model/service/horde/horde/function/php_error/declaration/function_name2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str2", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2", "string:/parser/model/service/horde/horde/function/php_error/declaration/brack_str3", "string:/parser/model/service/horde/horde/function/php_error/declaration/arg2/arg2"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/completed"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/completed"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_out", "string:/parser/model/fm/mail/dir/dir_out/in", "string:/parser/model/fm/mail/dir/dir_out/name", "string:/parser/model/fm/mail/dir/dir_out/fm/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/sp1", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/mail_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq/sp2", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq/mail", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq/closing_brack"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_out", "string:/parser/model/fm/mail/dir/dir_out/in", "string:/parser/model/fm/mail/dir/dir_out/name", "string:/parser/model/fm/mail/dir/dir_out/fm/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/sp1", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/mail_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq/sp2", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq/mail", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt/seq/closing_brack"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_out", "string:/parser/model/fm/mail/dir/dir_out/in", "string:/parser/model/fm/mail/dir/dir_out/name", "string:/parser/model/fm/mail/dir/dir_out/fm/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/sp1", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/mail_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/h_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/h", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/x_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/x", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/cv_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/cv", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/dn_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/dn", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/c"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_out", "string:/parser/model/fm/mail/dir/dir_out/in", "string:/parser/model/fm/mail/dir/dir_out/name", "string:/parser/model/fm/mail/dir/dir_out/fm/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/sp1", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/mail_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/r", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/t", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/h_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/h", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/x_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/x", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/cv_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/cv", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/dn_str", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/dn", "string:/parser/model/fm/mail/dir/dir_out/fm/seq/param_opt/seq/c"], 300, 300], ["string:forward", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/dir_in", "string:/parser/model/fm/mail/dir/dir_in/in", "string:/parser/model/fm/mail/dir/dir_in/fm/remainder"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp", "string:/parser/model/fm/mail", "string:/parser/model/fm/mail/id", "string:/parser/model/fm/mail/dir/completed"], 300, 300], ["string:back", ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/imp", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/imp/succ_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent", "string:/parser/model/service/horde/horde/imp/imp/message_sent/message_sent_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/recepients", "string:/parser/model/service/horde/horde/imp/imp/message_sent/from_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/user", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str1", "string:/parser/model/service/horde/horde/imp/imp/message_sent/ip", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str2"], ["string:/parser/model", "string:/parser/model/time", "string:/parser/model/sp1", "string:/parser/model/host", "string:/parser/model/service/horde", "string:/parser/model/service/horde/horde_str", "string:/parser/model/service/horde/horde/imp", "string:/parser/model/service/horde/to_str", "string:/parser/model/service/horde/pid", "string:/parser/model/service/horde/line_str", "string:/parser/model/service/horde/line", "string:/parser/model/service/horde/of_str", "string:/parser/model/service/horde/path", "string:/parser/model/service/horde/brack_str", "string:/parser/model/service/horde/horde/imp/succ_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent", "string:/parser/model/service/horde/horde/imp/imp/message_sent/message_sent_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/recepients", "string:/parser/model/service/horde/horde/imp/imp/message_sent/from_str", "string:/parser/model/service/horde/horde/imp/imp/message_sent/user", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str1", "string:/parser/model/service/horde/horde/imp/imp/message_sent/ip", "string:/parser/model/service/horde/horde/imp/imp/message_sent/brack_str2"], 300, 300]]

This will show you how many forward rules (where correlated events follow a particular event) and back rules (where correlated events must occur before a particular event) were generated. In our case, there are 12 back rules and a single forward rule. Note that not all of them necessarily occur with 100% probability, which is determined by the number of successful evaluations when generating the rule and considered when checking whether a learned rule holds. Note that the exact number of rules may be different when running the ECD multiple times as the detector uses random search for correlation rules.

This concludes the demonstration of the ECD. In case that anything is unclear, it is worth checking out this try-it-out where the ECD is applied on Apache access logs.